过TP保护的基本方案Word格式文档下载.docx
- 文档编号:3426642
- 上传时间:2023-05-01
- 格式:DOCX
- 页数:21
- 大小:307.46KB
过TP保护的基本方案Word格式文档下载.docx
《过TP保护的基本方案Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《过TP保护的基本方案Word格式文档下载.docx(21页珍藏版)》请在冰点文库上搜索。
KdSendPacket//主要用来方式别人双机调试
使用了KdDisableDebugger来禁用双机调试
代码:
[url=javascript:
1..text:
010025F0jzshortloc_1002622
.text:
010025F2callsub_10022A4
010025F7callds:
KdDisableDebugger
010025FDpushoffsetbyte_10022EC
01002602pushesi
01002603pushoffsetbyte_10022DC
01002608pushedi
01002609pushdword_100CF24
并对debugport进行了疯狂的清零操作
甚至还包括EPROCESS+70\+74\+78等几处位置
图片:
1.jpg
处理的手段通常都是向64端口写入FE导致计算机被重启
01001665moval,0FEh
01001667out64h,al;
ATKeyboardcontroller8042.
01001667;
Resendthelasttransmission
01001669popa
0100166Aretn
下面简单看下他关键的几个HOOK:
KiAttachProcess
2.jpg
NtReadVirtualMemory
3.jpg
NtWriteVirtualMemory
4.jpg
NtOpenThread
5.jpg
NtOpenProcess
6.jpg
引用:
其中,前3个直接恢复即可。
第4个有监视,直接恢复即刻重启
第5个和ring3有通信,直接恢复1分钟内SX非法模块
根据上面的分析,下面给出相应的解决方案
1.直接恢复第1、2、3处HOOK
2.绕过4、5处HOOK
3.将debugport清零的内核线程干掉
4.恢复硬件断点
但是要有一个先后的逻辑顺序
因为内核有一个线程负责监视几个地方,必须要先干掉它。
但是这个内容我写在了处理debugport清零的一起,也就是第3步。
所以大家在照搬源码的时候
注意代码执行次序
先从简单的工作讲起,恢复1、2、3处的HOOK
KiAttachProcess的处理
1.//////////////////////////////////////////////////////////////////////
//名称:
Nakd_KiAttachProcess
//功能:
My_RecoveryHook_KiAttachProcess的中继函数
//参数:
//返回:
//////////////////////////////////////////////////////////////////////
staticNAKEDVOIDNakd_KiAttachProcess()
{
__asm
movedi,edi
pushebp
movebp,esp
pushebx
pushesi
moveax,KiAttachProcessAddress//注意这个是全局变量BYTE*
addeax,7
jmpeax
}
RecoveryHook_KiAttachProcess
解除游戏保护对_KiAttachProcess函数的HOOK(DNF)
状态
NTSTATUSMy_RecoveryHook_KiAttachProcess()
BYTE*KeAttachProcessAddress=NULL;
//KeAttachProcess函数地址
BYTE*p;
BYTEMovEaxAddress[5]={0xB8,0,0,0,0};
//
BYTEJmpEax[2]={0xff,0xe0};
KIRQLIrql;
//特征码
BYTESignature1=0x56,//p-1
Signature2=0x57,//p-2
Signature3=0x5F,//p-3
Signature4=0x5E,//p+5
Signature5=0xE8;
//p第一个字节
//获得KeAttachProcess地址,然后通过特征码找到
//KiAttachProcess的地址
KeAttachProcessAddress=(BYTE*)MyGetFunAddress(L"
KeAttachProcess"
);
if(KeAttachProcessAddress==NULL)
KdPrint(("
KeAttachProcess地址获取失败\n"
));
returnFAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
//将p指向KeAttachProcess函数开始处
p=KeAttachProcessAddress;
while
(1)
if((*(p-1)==Signature1)&
&
(*(p-2)==Signature2)&
(*(p+5)==Signature3)&
(*(p+6)==Signature4)&
(*p==Signature5))
//定位成功后取地址
KiAttachProcessAddress=*(PULONG)(p+1)+(ULONG)(p+5);
break;
//推动指针
p++;
//计算中继函数地址
*(ULONG*)(MovEaxAddress+1)=(ULONG)Nakd_KiAttachProcess;
WPOFF();
//清除CR0
//提升IRQL中断级
Irql=KeRaiseIrqlToDpcLevel();
//写入
RtlCopyMemory(KiAttachProcessAddress,MovEaxAddress,5);
RtlCopyMemory(KiAttachProcessAddress+5,JmpEax,2);
//恢复Irql
KeLowerIrql(Irql);
WPON();
//恢复CR0
returnSTATUS_SUCCESS;
}
NtReadVirtualMemory和
NtWriteVirtualMemory的处理
注意这里,我对他们俩开头的第2句PUSH的处理
我直接写入了push0x78563412
大家可以根据自己的地址来硬编码一次。
或者干脆这样使用
My_RecoveryHook_NtReadAndWriteMemory
解除游戏保护对NtReadVirtualMemory和
//NtWriteVirtualMemory的HOOK
NTSTATUSMy_RecoveryHook_NtReadAndWriteMemory()
BYTEPush1Ch[2]={0x6a,0x1c};
//0~2字节
BYTEPushAdd[5]={0x68,0x12,0x34,0x56,0x78};
//NtReadVirtualMemory[物理机]
//BYTEPushAdd2[5]={0x68,0xf0,0x6f,0x4f,0x80};
//NtWriteVirtualMemory[物理机]
BYTE*NtReadVirtualMemoryAddress=NULL;
//NtReadVirtualMemory的地址
BYTE*NtWriteVirtualMemoryAddress=NULL;
//NtWriteVirtualMemory的地址
//从SSDT表中获取NtReadVirtualMemory函数地址
NtReadVirtualMemoryAddress=(BYTE*)myGetCurrentAddress(0xBA);
if(NtReadVirtualMemoryAddress==NULL)
NtReadVirtualMemory函数地址获取失败!
\n"
//从SSDT表中获取NtWriteVirtualMemory函数地址
NtWriteVirtualMemoryAddress=(BYTE*)myGetCurrentAddress(0x115);
if(NtWriteVirtualMemoryAddress==NULL)
NtWriteVirtualMemory函数地址获取失败!
RtlCopyMemory(NtReadVirtualMemoryAddress,Push1Ch,2);
RtlCopyMemory(NtReadVirtualMemoryAddress+2,PushAdd,5);
RtlCopyMemory(NtWriteVirtualMemoryAddress,Push1Ch,2);
RtlCopyMemory(NtWriteVirtualMemoryAddress+2,PushAdd,5);
好了,下面来处理
NtOpenProcess和
这两个函数的处理上不能太鲁莽了。
手法要风骚一点细腻一点了
介于篇幅的原因,我只贴出来前者的处理方法,后者雷同
细微之处大家自行修改。
我总不能真的给你方法又给你工具。
眼看着自己变成教唆犯
1.//NtOpenProcess用到的全局变量[为了方便堆栈平衡的处理使用全局变量]
PEPROCESSprocessEPROCESS=NULL;
//保存访问者的EPROCESS
ANSI_STRINGp_str1,p_str2;
//保存进程名称
BYTE*ObOpenObjectByPointerAddress=NULL;
//ObOpenObjectByPointer的地址
BYTE*p_TpHookAddress=NULL;
//TP的HOOK函数地址
BYTE*p_ReturnAddress=NULL;
//返回到的地址
BYTE*p_MyHookAddress=NULL;
//我们的HOOK函数在哪写入
#defineDNF_EXE"
DNF.exe"
//要检索的进程名
Nakd_NtOpenProcess
My_RecoveryHook_NtOpenProcess的中继函数
staticNAKEDVOIDNakd_NtOpenProcess()
//获得调用者的EPROCESS
processEPROCESS=IoGetCurrentProcess();
//将调用者的进程名保存到str1中
RtlInitAnsiString(&
p_str1,(ULONG)processEPROCESS+0x174);
//将我们要比对的进程名放入str2
p_str2,DNF_EXE);
if(RtlCompareString(&
p_str1,&
p_str2,TRUE)==0)
//说明是DNF进程访问了这里
pushdwordptr[ebp-38h]
pushdwordptr[ebp-24h]
pushp_ReturnAddress
moveax,p_TpHookAddress
else
moveax,ObOpenObjectByPointerAddress
My_RecoveryHook_NtOpenProcess
解除游戏保护对NtOpenProcess的HOOK
NTSTATUSMy_RecoveryHook_NtOpenProcess()
BYTE*NtOpenProcessAddress=NULL;
//NtOpenProcess的地址
BYTE*p=NULL;
//临时
TOP5CODE*top5code=NULL;
//保存5字节内容
BYTEJmpAddress[6]={0xE9,0,0,0,0,0x90};
//获取NtOpenProcess的地址
NtOpenProcessAddress=(BYTE*)MyGetFunAddress(L"
NtOpenProcess"
if(NtOpenProcessAddress==NULL)
NtOpenProcess地址获取失败\n"
//获取ObOpenObjectByPointer的地址
ObOpenObjectByPointerAddress=(BYTE*)MyGetFunAddress(L"
ObOpenObjectByPointer"
if(ObOpenObjectByPointerAddress==NULL)
ObOpenObjectByPointer地址获取失败\n"
//将p指向NtOpenProcess函数开始处
p=NtOpenProcessAddress;
//用一个无限循环来判断给定的特征码来确定被HOOK位置
if((*(p-7)==0x50)&
(*(p-0xE)==0x56)&
(*(p+0xd)==0x50)&
(*(p+0x16)==0x3b)&
(*(p+0x17)==0xce)&
(*p==0xE8)&
(*(p+5)==0x8b)&
(*(p+6)==0xf8))
%0X\n"
(ULONG)p));
//推动指针向前走
//将top5code指向p的当前处
//用以取出call[地址]这5字节里面的地址
top5code=(TOP5CODE*)p;
p_TpHookAddress=(BYTE*)((ULONG)p+5+top5code->
address);
//找到我们写入自定义函数的地址
p_MyHookAddress=p-6;
//保存调用ObOpenObjectByPointer函数以后的返回地址
p_ReturnAddress=p+5;
//将一条JMPNakd_NtOpenProcess写入到数组中
*(ULONG*)(JmpAddress+1)=(ULONG)Nakd_NtOpenProcess-((ULONG)p_MyHookAddress+5);
RtlCopyMemory(p_MyHookAddress,JmpAddress,6);
处理之后:
7.jpg
简而言之其原理就是,任何人调用了NtOpenProcess的时候会先进入
Nakd_NtOpenProcess函数,我们判断。
如果是游戏进程访问的话,就有可能是验证之类的
我们转到它自己的函数里面。
让它保持与ring3层的通信。
否则的话,嘿嘿……
接下来是第3步处理debugport清零的这块了。
我想绝大多数人关心的都是这里了
网络上能搜多到的办法几乎都失效了
有办法的人又不肯放出来,急眼了就自己想了个土办法
虽然不那么时尚。
但是绝对的奏效。
由于代码凌乱不堪,简单说下其原理。
我们定位内核模块TxxxSxxx.sys的首地址
然后根据特征码遍历整个模块找到我们需要的地方,然后干掉他们。
那么我们又如何能够通过人工的判断出来到底是哪里在作怪呢
利用syser或StartSoftICE对EPROCESS+BC处设置断点。
就可以一层一层的追溯上去了
到底如何用他们,我想大家自己多花点时间在看雪和GOOGLE或者BAIDU上面是不会吃亏的。
由于ZwQuerySystemInformation函数的使用非常繁琐。
而且篇幅有限。
所以我只给出关键代码,至于这个函数如何使用。
大家可以自己在搜索引擎找“枚举内核模块”
MyEnumKernelModule
枚举内核模块
str:
内核模块名称
//moduleadd:
该模块地址[传出]
//modulesie:
该模块大小[传出]
NTSTATUSMyEnumKernelModule(INCHAR*str,OUTULONG*moduleadd,OUTULONG*modulesie)
NTSTATUSstatus=STATUS_SUCCESS;
ULONGn
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TP 保护 基本 方案