- 注册时间
 - 2021-4-16
 
- 最后登录
 - 2024-3-13
 
- 在线时间
 - 1 小时
 
 
 
 
 
编程入门 
  
	- 龙马币
 - 96 
 
 
 
 
 | 
 
 
首先要提出的是,我现在所做的过 TP 驱动保护只支持 32 位 XP,在所有的 32 位 XP 上都可以正常运行, 
不过 Win7 的话还不行,因为里面用到了搜索特征码来定位未导出 API,而我只针对 XP 做了处理。 
 
首先我们先分析一下TP所做的保护: 
1、 NtOpenProcess 中的 Deep InLine Hook: 
2、 NtOpenThread 中的 Deep InLine Hook: 
3、 NtReadVirtualMemory 中的 InLine Hook: 
4、 NtWriteVirtualMemory 中的 InLine Hook: 
5、 KiAttachProcess和KeStackAttachProcess的 InLine Hook: 
6、 NtGetContextThread 中的 InLine Hook: 
7、 NtSetContextThread 中的 InLine Hook: 
8 、DebugPort清零: 
大概主要的函数就是以上这些了,一些小HOOK就不写了。 
 
我相信前7个函数的处理方法在网上应该已经被人讲过一遍又一遍了,所以我直接从DebugPort清零说起。 
 
首先我们又虚拟机进行双机调试 下游戏基址+0xbc 的访问断点 
可以发现现在最新的TP 有四处清零和一处检测 
他们分别是 
 
TesSafe基址:   B13AF000 
进程基址:        829FFDA0 
 
Breakpoint 0 hit 
<Unloaded_TesSafe.sys>+0x6ef1: 
b1117ef1 8b4624          mov     eax,dword ptr [esi+24h] 
 
Breakpoint 0 hit 
<Unloaded_TesSafe.sys>+0x22a2: 
b11132a2 8b09            mov     ecx,dword ptr [ecx] 
 
Breakpoint 0 hit 
<Unloaded_TesSafe.sys>+0xba4cc: 
b11cb4cc e9a8350000      jmp     <Unloaded_TesSafe.sys>+0xbda79 (b11cea79) 
 
Breakpoint 0 hit 
<Unloaded_TesSafe.sys>+0xbb0f2: 
b11cc0f2 e9c5f1ffff      jmp     <Unloaded_TesSafe.sys>+0xba2bc (b11cb2bc 
 
一处检测: TesSafe.sys +0x4082 
 
在处理清零之前我们要先处理掉检测,不然要是直接把清零函数ret掉了,检测函数发现后就会重启我们的电脑。 
我们要先通过IDA的逆向找出清零函数和检测函数的首地址 
 
第一处清零首地址:TesSafe+0x6ea8; 
第二处清零首地址:TesSafe+0x222e; 
 
以下是两处VM的清零代码的地址: 
 
第三处清零:TesSafe+0xbb0f0; 
第四处清零:TesSafe+0xba4ca; 
 
CRC检测首地址:TesSafe+0x4082; 
 
知道这些信息后我们就开始写代码过了他吧! 
- void HandleDebugZero(ULONG uImageBase) //主要清零处理函数
 
 - {
 
 -     ULONG uAddr_1=uImageBase + 0x4082;//清零CRC检测首地址
 
 -     ULONG uAddr_2=uImageBase + 0x6ea8;//清零处1首地址
 
 -     ULONG uAddr_3=uImageBase + 0x2228;//清零处2首地址
 
 -  
 
 -     GetDnfEprocessAddr(uImageBase);   //取得DNF 进程基址
 
 -     //这个进程基址在处理第三和第四处清零的时候用到
 
 -     if(uImageBase==0)
 
 -     {
 
 -         return;
 
 -     }
 
 -  
 
 -     DisableWP();   //清除CR0
 
 -  
 
 -      //由于这个检测函数没压入参数,所以直接ret
 
 -     *(PUSHORT)uAddr_1=0xc3;
 
 -      
 
 -     //0x6ea8 //第一处清零首地址,也是直接ret
 
 -     *(PUCHAR)(uAddr_2)=0xc3;
 
 -  
 
 -     //0x2228 //第二处清零首地址,还是直接ret
 
 -     *(PUCHAR)(uAddr_3)=0xc3;
 
 -  
 
 -     EnableWP();//恢复CR0
 
  
-     g_uDebugPortOffset=g_uDebugPortOffset+0xbc;
 
 -     //取到清零位置的地址
 
 -  
 
 -     HandleDebugPortPop(true,uImageBase);//处理第三处清零
 
 -     HandleDebugPortPush(true,uImageBase);//处理第四处清零
 
 - }
 
  复制代码 
 
 
打字打到手都累了,下面就不加那么清楚的注释了,各位自己看下吧 
 
- void HandleDebugPortPop(BOOLEAN bHook,ULONG uImageBase)
 
 - {
 
 -         if(bHook)
 
 -         {
 
 -                 //hook pop 
 
 -                 if(uImageBase==0)
 
 -                 {
 
 -                         return ;
 
 -                 }
 
 -                 g_uDebugPortPopHookAddr=uImageBase+0xbb0f0;//pop hook地址
 
  
-                 g_uDebugPortPopRetAddr=uImageBase+0xba2bc;//pop retn 地址
 
  
-                 if(g_uDebugPortPopHookAddr==0)
 
 -                 {
 
 -                         return;
 
 -                 }
 
 -                 RtlCopyMemory((PVOID)g_szBackupDebugPortPop,
 
 -                                   (PVOID)g_uDebugPortPopHookAddr,
 
 -                                          5);//保存hook地址,用于恢复
 
 -                 
 
 -                 InLineHookEngine(g_uDebugPortPopHookAddr,(int)FuckDebugPortPop);
 
 -                 //__asm int 3
 
 -         }
 
 -         else
 
 -         {
 
 -                 if(g_uDebugPortPopHookAddr==0)
 
 -                 {
 
 -                         return;
 
 -                 }
 
 -                 // 最好判断下 TP是否 已经卸载
 
 -                 int TesSafe=GetTesSafeBassAddr();
 
 -                 if(TesSafe!=0)
 
 -                 {
 
 -                 //KIRQL Irql=KeRaiseIrqlToDpcLevel();
 
 -                 DisableWP();
 
 -         RtlCopyMemory((PVOID)g_uDebugPortPopHookAddr,
 
 -                                   (PVOID)g_szBackupDebugPortPop,
 
 -                                          5);//保存hook地址,用于恢复
 
 -                 EnableWP();
 
 -                 }
 
 -         }
 
 - }
 
  
- void HandleDebugPortPush(BOOLEAN bHook,ULONG uImageBase)
 
 - {
 
 -         if(bHook)
 
 -         {
 
 -                 //hook pop 
 
 -                 if(uImageBase==0)
 
 -                 {
 
 -                         return ;
 
 -                 }
 
 -                 g_uDebugPortPushHookAddr=uImageBase+0xba4ca;//push hook地址
 
  
-                 g_uDebugPortPushRetAddr=uImageBase+0xba2bc;//push retn 地址
 
  
-                 if(g_uDebugPortPushHookAddr==0)
 
 -                 {
 
 -                         return;
 
 -                 }
 
 -                 RtlCopyMemory((PVOID)g_szBackupDebugPortPush,
 
 -                                   (PVOID)g_uDebugPortPushHookAddr,
 
 -                                          5);//保存hook地址,用于恢复
 
 -                 
 
 -                 InLineHookEngine(g_uDebugPortPushHookAddr,(int)FuckDebugPortPush);
 
 -                 //__asm int 3
 
 -         }
 
 -         else
 
 -         {
 
 -                 if(g_uDebugPortPushHookAddr==0)
 
 -                 {
 
 -                         return;
 
 -                 }
 
 -                 // 最好判断下 TP是否 已经卸载
 
 -                 int TesSafe=GetTesSafeBassAddr();
 
 -                 if(TesSafe!=0)
 
 -                 {
 
 -                 //KIRQL Irql=KeRaiseIrqlToDpcLevel();
 
 -                 DisableWP();
 
 -                                 RtlCopyMemory((PVOID)g_uDebugPortPushHookAddr,
 
 -                                   (PVOID)g_szBackupDebugPortPush,
 
 -                                          5);//保存hook地址,用于恢复
 
 -                 EnableWP();
 
 -                 }
 
 -         }
 
  
- }
 
  
- __declspec(naked)void FuckDebugPortPop()
 
 - {
 
 -         //DbgPrint("Pop");
 
 -         __asm
 
 -         {
 
 -                 pushfd
 
 -                 cmp edx,g_uDebugPortOffset //判断入栈的参数是否是清零位置的地址
 
 -                 jnz POPLABLE
 
 -                 popfd 
 
 -                 add esp,0x4
 
 -                 jmp g_uDebugPortPopRetAddr
 
 - POPLABLE:
 
 -                 popfd
 
 -                 pop dword ptr [edx]
 
 -                 jmp g_uDebugPortPopRetAddr
 
  
-         }
 
  
- }
 
  
- __declspec(naked)void FuckDebugPortPush()
 
 - {
 
 -         //DbgPrint("Push");
 
 -         __asm
 
 -         {
 
 -                 pushfd
 
 -                 cmp edx,g_uDebugPortOffset//判断入栈的参数是否是清零位置的地址
 
  
-                 jnz PUSHLABLE
 
 -                 popfd
 
 -                 push 0
 
 -                 jmp g_uDebugPortPushRetAddr
 
 - PUSHLABLE:
 
 -                 popfd
 
 -                 push dword ptr [edx]
 
 -                 jmp g_uDebugPortPushRetAddr
 
 -         }
 
  
- }
 
  复制代码 
 
最后提一点以下这两个函数要在驱动卸载的时候加到Unload函数中 
HandleDebugPortPop(false,0); 
HandleDebugPortPush(false,0); 
 
最后在自己的机子成功过了TP后,CE 可以读写内存,OD可以附加。 
 |   
 
 
 
 |