免費論壇 繁體 | 簡體
Sclub交友聊天~加入聊天室當版主
分享
返回列表 发帖

XX游戏驱动保护代码书写 (B)

A、恢复NtOpenThread
     B、恢复NtOpenProcess函数   
     C、恢复NtReadVirtualMemory 让CE可读
     D、恢复NtWriteVirtualMemory让CE可写
     E、Ret指令详解
     F、Hook代码编写并测试
     G、过非法保护测试
课时:44+4

OpenProcess         //NtOpenProcess+0x21E  //SSDT 122
OpenThread          //NtOpenThread+0x214   //SSDT 128
ReadProcessMemory   //NtReadVirtualMemory+0   //SSDT 186
WriteProcessMemory  //NtWriteVirtualMemory+0  //SSDT 277
Ret指令详解
  ret相当于 jmp dword ptr[esp];add esp,4;//但并不等价哟
一、用 MmGetSystemRoutineAddress 取得
NtOpenProcess和NtOpenThread的地址 存放到
PNtOpenProcess和PNtOpenThread中;
二、通过特征码定位下边4个地址以增加兼容性
DWORD NtOpenProcess_21E=0x805cc61a; //jmp myNtOpenProcess
DWORD NtOpenThread_214=805cc89ch;   //jmp myNtOpenThread
DWORD NtOpenThread_214_B=805cc8a7h; //Call ret Addr
DWORD NtOpenProcess_21E_B=805cc625h;//Call ret Addr
三、写HOOK代码

===================================================

笔记:杂音好大啊!

A部分:将上节课代码复制过来修改一下,
//nt!NtReadVirtualMemory:
//805b528a 6a1c            push    1Ch
//805b528c 68e8ae4d80      push    offset nt!MmClaimParameterAdjustDownTime+0x90 (804daee8)
DWORD Real_NtReadVirtualMemory_7 =0x805b5291;
DWORD Real_NtWriteVirtualMemory_7=0x805b5394;
DWORD NtOpenProcess_21E=0x805cc61a; //myNtOpenProcess
DWORD NtOpenThread_214=0x805cc89c;   //myNtOpenThread

DWORD NtOpenThread_214_B=0x805cc8a7;
DWORD NtOpenProcess_21E_B=0x805cc625;
PVOID PObOpenObjectByPointer,PNtOpenProcess,PNtOpenThread;
DWORD ssdtaddr;
#pragma PAGECODE
__declspec(naked)VOID My_NtReadVirtualMemory()
{  
        //恢复前2条指令
        __asm
        {
                push    1Ch
            push    804daee8h
                jmp  Real_NtReadVirtualMemory_7
        }
}

#pragma PAGECODE
__declspec(naked)VOID My_NtWriteVirtualMemory()
{  
        //恢复前2条指令
//         nt!NtWriteVirtualMemory:
// 805b5394 6a1c            push    1Ch
// 805b5396 6800af4d80      push    offset nt!MmClaimParameterAdjustDownTime+0xa8 (804daf00)

        __asm
        {
                    push    1Ch
                        push    804daf00h
                        jmp  Real_NtWriteVirtualMemory_7
        }
}

// OpenProcess         //NtOpenProcess+0x21E  //SSDT 122
// nt!NtOpenProcess+0x21e:
// 805cc61a ff75c8          push    dword ptr [ebp-38h] //jmp My_NtOpenPrcoess
// 805cc61d ff75dc          push    dword ptr [ebp-24h]
// 805cc620 e84706ffff      call    nt!ObOpenObjectByPointer (805bcc6c)
// 805cc625 8bf8            mov     edi,eax
#pragma PAGECODE
__declspec(naked)VOID My_NtOpenPrcoess()
{  
        //恢复前2条指令
        //         nt!NtWriteVirtualMemory:
        // 805b5394 6a1c            push    1Ch
        // 805b5396 6800af4d80      push    offset nt!MmClaimParameterAdjustDownTime+0xa8 (804daf00)

        __asm
        {
                    push    dword ptr [ebp-38h]
                        push    dword ptr [ebp-24h]
                        push     NtOpenProcess_21E_B //DWORD NtOpenProcess_21E_B=805cc625h
                        jmp  DWORD ptr [ PObOpenObjectByPointer] //(805bcc6c)  ret c3 eip
                        ret
                        //jmp  NtOpenProcess_21E_B
        }
}

// OpenThread          //NtOpenThread+0x214   //SSDT 128
// 805cc89c ff75cc          push    dword ptr [ebp-34h] //jmp  DWORD NtOpenThread_214=805cc89ch;
// 805cc89f ff75e0          push    dword ptr [ebp-20h]
// 805cc8a2 e8c503ffff      call    nt!ObOpenObjectByPointer (805bcc6c)
// 805cc8a7 8bf8            mov     edi,eax

#pragma PAGECODE
__declspec(naked)VOID My_NtOpenThread()
{  
        //恢复前2条指令
        //         nt!NtWriteVirtualMemory:
        // 805b5394 6a1c            push    1Ch
        // 805b5396 6800af4d80      push    offset nt!MmClaimParameterAdjustDownTime+0xa8 (804daf00)

        __asm
        {
                push    dword ptr [ebp-34h]
                push    dword ptr [ebp-20h]
                push    NtOpenThread_214_B // DWORD NtOpenProcess_214_B=805cc8a7h
                jmp    PObOpenObjectByPointer /*(805bcc6c)*/
                        //jmp  NtOpenProcess_214_B
        }
}

#pragma  PAGECODE
VOID HOOK()
{
        UNICODE_STRING Us_ObOpenObjectByPointer, Us_NtOpenProcess, Us_NtOpenThread;//建立变量
        RtlInitUnicodeString(&Us_ObOpenObjectByPointer,L"ObOpenObjectByPointer");//初始化
        RtlInitUnicodeString(&Us_NtOpenProcess,L"NtOpenProcess");//初始化
        RtlInitUnicodeString(&Us_NtOpenThread,L"NtOpenThread");//初始化
        PObOpenObjectByPointer=MmGetSystemRoutineAddress(&Us_ObOpenObjectByPointer);
        PNtOpenProcess=MmGetSystemRoutineAddress(&Us_NtOpenProcess);//获得OP函数地址
        PNtOpenThread=MmGetSystemRoutineAddress(&Us_NtOpenThread);        //获得OT函数地址
        __asm
        {  
                Cli                                //内存保护
                        mov eax,cr0
                        and eax,not 10000h
                        mov cr0,eax
           _asm int 3
                // NtOpenProcess 还原
                mov ebx,NtOpenProcess_21E
                mov al,0xe9
                mov byte ptr [ebx+0],al
                lea eax,My_NtOpenPrcoess
                sub eax,NtOpenProcess_21E
                sub eax,5
                mov [ebx+1],eax
      // NtOpenThread 还原
          mov ebx,NtOpenThread_214
          mov byte ptr [ebx+0],0xe9
          lea eax,My_NtOpenThread //通过公式计算
          sub eax,NtOpenThread_214
          sub eax,5
          mov [ebx+1],eax
          //ReadProcessMemory   //NtReadVirtualMemory+0   //SSDT 186
          //WriteProcessMemory  //NtWriteVirtualMemory+0  //SSDT 277
                mov eax, KeServiceDescriptorTable
                mov eax,[eax]                     //address of KeServiceDescriptorTable
                mov ssdtaddr,eax

                mov eax,ssdtaddr
                add eax,2e8h                     //0xBA * 4   ntreadvirtualmemoryaddr ssdt186
                lea ebx, My_NtReadVirtualMemory        //建立自己地址写入
                mov ecx,[eax]
                add ecx,7
        mov Real_NtReadVirtualMemory_7,ecx//要跳回的地址
                mov [eax],ebx          //HOOK成我们自己的 SSDT 186 hook My_NtReadVirtualMemory
                 mov eax,ssdtaddr
                 add eax,454h                     //0x115*4    ntwritevirtualmemoryaddr ssdt227
                 lea ebx,My_NtWriteVirtualMemory
                 mov ecx,[eax]
                 add ecx,7
                 mov Real_NtWriteVirtualMemory_7,ecx//要跳回的地址
                 mov [eax],ebx
         //去掉内存保护
         mov eax,cr0
         or  eax,10000h
         mov cr0,eax
         sti
        }
}
写好代码后先虚拟机测试了一下没有成功,再次修改.这次好像正确了,用ME打开游戏扫描一下结果被检测到非法,那么将ME的SYS去掉再扫描一下.还是非法.


B部分:老师将passtp.h加进去修改好错误后进行编译,然后在本机里进行测试,在加载了驱动之后用另一款ME就可以搜索到数据了,但是用CE还是非法,因为游戏本身有针对CE的检测.

随记: 终于过了!老师功夫果然厉害!另外老师写代码也经常出错,我想我写代码出错就更多了,以后还是要一点一点的写,然后一点一点的测试,确保代码不出错的情况下再继续编写,否则出错真是闹心.
  1. DWORD ssdtaddr,
  2. oldreadaddr,readpush ,readjmpaddr,
  3. oldwriteaddr,writepush ,writejmpaddr  ,
  4. ntopenprcaddr  ,
  5. ntopentrdaddr  ,
  6. KiAttachProcessaddr,KeStackAttachProcess_jmpaddr,
  7. ObOpenObjectByPointeraddr/*,
  8. h1,h2,hr,hw*/;


  9. #pragma PAGECODE
  10. __declspec(naked) VOID yjxsoft_com_KeStackAttachProcess()
  11. {  
  12.         KdPrint(("yjxsoft_com_KeStackAttachProcess\n"));
  13.     //KeStackAttachProcess_jmpaddr+0xD
  14.         __asm
  15.         {
  16.                
  17.                 //还原jmp占用处指令字节指令
  18.         push    dword ptr [ebp+0ch]
  19.                 push    dword ptr [ebp+8]
  20.                 push    edi
  21.                 push    esi
  22.         //压入返回地址
  23.                 mov eax,KeStackAttachProcess_jmpaddr
  24.                 add eax,0xd //push    dword ptr [ebp+8] 至CALL KiAttachProcess后的距离
  25.                 push eax //返回地址
  26.                 //KiAttachProcess 前7字节
  27.                 mov edi,edi
  28.                 push    ebp
  29.                 mov     ebp,esp
  30.                 push    ebx
  31.                 push    esi
  32.                 //jmp 至KiAttachProcess+7位置执行,执行完返回至                KeStackAttachProcess_jmpaddr+D处继续执行
  33.                 mov eax,  KiAttachProcessaddr
  34.                 add eax,7
  35.                 jmp eax

  36.         }


  37. }
  38. #pragma PAGECODE
  39. __declspec(naked) VOID yjxsoft_com_KiAttachProcess()
  40. {  
  41.         //KdPrint(("yjxsoft_com_KiAttachProcess\n"));

  42.         __asm
  43.         {
  44.                 /*  804f9b5e ff7508          push    dword ptr [ebp+8]
  45.                     804f9b61 57              push    edi
  46.                         804f9b62 56              push    esi

  47.                         804f9b63 e890feffff      call    nt!KiAttachProcess (804f99f8)
  48.                         804f9b68 5f              pop     edi
  49.                         804f9b69 5e              pop     esi
  50.                         804f9b6a 5d              pop     ebp
  51.                         804f9b6b c20400          ret     4
  52.                         */
  53.                  push    dword ptr [ebp+8]
  54.                  push    edi
  55.                  push    esi

  56.                  //恢复 前7字节指令
  57.                 /* nt!KiAttachProcess:
  58.                  804f99f8 8bff                mov     edi,edi
  59.                          804f99fa 55              push    ebp
  60.                          804f99fb 8bec            mov     ebp,esp
  61.                          804f99fd 53              push    ebx
  62.                          804f99fe 56              push    esi
  63.                  */
  64.                  push endCall //压栈返回地址
  65.                  mov edi,edi
  66.                  push    ebp
  67.                  mov     ebp,esp
  68.                  push    ebx
  69.                  push    esi
  70.                  //               
  71.                  mov eax,  KiAttachProcessaddr
  72.                  add eax,7
  73.                  jmp eax
  74. endCall:
  75.                  pop edi
  76.                  pop esi
  77.                  pop ebp
  78.                  ret 4

  79.         }


  80. }

  81. #pragma PAGECODE
  82. __declspec(naked) VOID yjxsoft_com_NtReadVirtualMemory()
  83. {  
  84.         //KdPrint(("yjxsoft_com_NtReadVirtualMemory\n"));
  85.    
  86.         __asm
  87.         {
  88.                         //
  89.                         push 0x1c
  90.                                 push readpush ////压栈参数
  91.                                 //
  92.                                 jmp  readjmpaddr
  93.         }


  94. }
  95. //
  96. //;///////////////////////////////////////////////////////////////////
  97. //
  98. #pragma PAGECODE
  99. __declspec(naked)VOID yjxsoft_com_NtWriteVirtualMemory()
  100. {
  101.     // KdPrint(("yjxsoft_com_NtWriteVirtualMemory\n"));
  102.         __asm
  103.         {
  104.                         push 0x1c
  105.                         push writepush //压栈参数
  106.                         //  
  107.                         jmp  writejmpaddr
  108.         }

  109. }
  110. //
  111. //;/////////////////////////////////////////////////////////////////
  112. //805cc613 8d8548ffffff    lea     eax,[ebp-0B8h]
  113. //805cc619 50              push    eax

  114. //805cc61a ff75c8          push    dword ptr [ebp-38h]
  115. //805cc61d ff75dc          push    dword ptr [ebp-24h]
  116. //805cc620 e84706ffff      call    nt!ObOpenObjectByPointer (805bcc6c)
  117. //805cc625 8bf8            mov     edi,eax
  118. //805cc625-805cc61a= 0bh
  119. #pragma PAGECODE
  120. __declspec(naked)VOID yjxsoft_com_OpenProcess()
  121. {
  122.    
  123.         __asm
  124.         {
  125.                
  126.                 push dword ptr [ebp-38h]
  127.                 push dword ptr [ebp-24h]
  128.                 mov  eax,ntopenprcaddr
  129.                 add  eax,0bh
  130.                 push eax //CALL后返回的地址 非压栈参数
  131.                 //  
  132.                 jmp  ObOpenObjectByPointeraddr
  133.         }
  134. }
  135. //
  136. //;//////////////////////////////////////////////////////////////////
  137. //
  138. #pragma PAGECODE
  139. __declspec(naked)VOID yjxsoft_com_OpenTread()
  140. {
  141.         //KdPrint(("yjxsoft_com_OpenTread     \n"));
  142.         __asm
  143.         {
  144.                 push dword ptr [ebp-34h]
  145.                 push dword ptr [ebp-20h]
  146.                 mov  eax,ntopentrdaddr
  147.                 add  eax,0bh
  148.                 push eax
  149.                 //  
  150.                 jmp  ObOpenObjectByPointeraddr
  151.         }
  152. }

  153. //
  154. //;//////////////////////////////////////////////////////////////////
  155. //
  156. #pragma PAGECODE
  157. __declspec(naked)   DWORD __stdcall Findcodeaddr(DWORD code1,WORD code2,DWORD prcaddr)
  158. {
  159.          
  160.          __asm
  161.          {
  162.                 mov    edx,[esp+0x0c] //prcaddr
  163.                 mov    ecx,1000h
  164.                 //while( ecx>0)
  165.                 ////  
  166. start:
  167.                 sub ecx,1h
  168.                 add edx,1h
  169.                 mov ebx,dword ptr [edx]
  170.                 xor eax,eax
  171.                 mov ax,word ptr [edx+4h]
  172.                 test ecx,ecx
  173.                         jz end
  174.                 cmp ebx,[esp+4] //code1
  175.                         jnz start
  176.                 cmp ax,[esp+8] //code2
  177.                         jnz start
  178.                 /*if (ebx==code1 && ax==code2)  break  */
  179. end:
  180.                 mov    eax,edx
  181.                 ret 0x0c
  182.          }
  183. }
  184. //;////////////////////////////////////////////////////////////////
  185. //
  186. #pragma PAGECODE
  187. VOID   PassTPhook ()
  188. {     
  189.           UNICODE_STRING g_ProcessAddr,g_ThreadAddr,g_KeAttachAddr,g_PointerAddr,g_KeStackAttachProcess;
  190.            RtlInitUnicodeString(&g_ProcessAddr,L"NtOpenProcess");
  191.            RtlInitUnicodeString(&g_ThreadAddr,L"NtOpenThread");
  192.            RtlInitUnicodeString(&g_KeAttachAddr,L"KeAttachProcess");
  193.            RtlInitUnicodeString(&g_PointerAddr,L"ObOpenObjectByPointer");
  194.            RtlInitUnicodeString(&g_KeStackAttachProcess,L"KeStackAttachProcess");
  195. //           __asm //  
  196. //          __asm mov eax,eax
  197. //       ntopenprcaddr=(DWORD)MmGetSystemRoutineAddress(&g_ProcessAddr);
  198. //
  199. //       Findcodeaddr(0xffc875ff,0xdc75,ntopenprcaddr);
  200.         __asm
  201.         {
  202.                
  203.         //        pushad
  204.                     lea eax,g_KeStackAttachProcess
  205.                         push eax
  206.                         call DWORD ptr DS:[ MmGetSystemRoutineAddress]
  207.                         push eax                //传入 KeStackAttachProcess地址
  208.                         //push 0E856h   
  209.                         //push 570875FFh               
  210.                         push 0875h
  211.                         push 0FF0C75FFh
  212.                         call Findcodeaddr
  213.                         mov    KeStackAttachProcess_jmpaddr,eax //// KeStackAttachProcess里 CALL KiAttachProcess的地址 定位push dword ptr[ebp+8]
  214.                   //        hook KeStackAttachProcess+7d
  215.                         lea ebx,yjxsoft_com_KeStackAttachProcess
  216.                         sub ebx,eax
  217.                         sub ebx,5
  218.                         mov BYTE ptr [eax],0E9h
  219.                         mov dword ptr [eax+1],ebx

  220.                         //hook end

  221.                         /////////////
  222.                 lea eax,g_ProcessAddr
  223.                 push eax
  224.                 call DWORD ptr DS:[ MmGetSystemRoutineAddress]
  225.                 push eax                //传入 NtOpenProcess地址
  226.                 push 0dc75h
  227.                 push 0ffc875ffh               
  228.                 call Findcodeaddr
  229.                 mov    ntopenprcaddr,eax ///NtOpenProcess里 CALL ObOpenObjectByPointer的地址

  230.                 lea eax, g_ThreadAddr
  231.                 push eax
  232.                 call DWORD ptr DS:[ MmGetSystemRoutineAddress]
  233.                 push eax     ////传入 NtOpenThread地址
  234.                 push 0e075h
  235.                 push 0ffcc75ffh
  236.                 call Findcodeaddr
  237.                 mov    ntopentrdaddr,eax //////存放 NtOpenThread 里 CALL ObOpenObjectByPointer的地址

  238.                 lea eax,g_PointerAddr
  239.                 push eax
  240.                 call DWORD ptr DS:[ MmGetSystemRoutineAddress]
  241.                 mov    ObOpenObjectByPointeraddr,eax //存放 ObOpenObjectByPointer地址

  242.      //hook KiAttachProcess  begin
  243.                 lea eax,g_KeAttachAddr
  244.                 push eax
  245.                 call DWORD ptr DS:[ MmGetSystemRoutineAddress]
  246.                 push eax    // 传入KeAttachProcess
  247.                 push 0e856h
  248.                 push 570875ffh
  249.                 call Findcodeaddr //查找KiAttachProcess地址
  250.                 add    eax,6h //指向 804f9b64//     804f9b63 e890feffff      call    nt!KiAttachProcess (804f99f8)

  251.                 mov    ebx,dword ptr [eax] //取CALL 地址
  252.                 add    ebx,eax //当前地址+取出地址+4
  253.                 add    ebx,4h
  254.                 mov    KiAttachProcessaddr,ebx //计算出 KiAttachProcess 这个未导出函数地址
  255.                
  256.                 sub eax,6h //mov    KiAttachProcess -6
  257.                  
  258.                 // HOOK KeAttachProcessPush->KiAttachProcessPush-5
  259.                 mov dword ptr[eax],0xE9 //jmp
  260.                 lea ebx,yjxsoft_com_KiAttachProcess
  261.                 sub ebx,eax
  262.                 sub ebx,5
  263.                 mov dword ptr[eax+1],ebx

  264.        //hook KiAttachProcess end


  265.                 mov eax, KeServiceDescriptorTable
  266.                 mov eax,[eax]                     //address of KeServiceDescriptorTable
  267.                 mov ssdtaddr,eax

  268.                 mov eax,ssdtaddr
  269.                 add eax,2e8h                     //0xBA * 4   ntreadvirtualmemoryaddr ssdt186
  270.                 mov eax,DWORD PTR [eax]
  271.                 mov oldreadaddr,eax
  272.                 mov ebx,DWORD PTR [eax+3h]
  273.                 mov readpush,ebx
  274.                 add eax,7h
  275.                 mov readjmpaddr,eax

  276.                 mov eax,ssdtaddr
  277.                 add eax,454h                     //0x115*4    ntwritevirtualmemoryaddr ssdt227
  278.                 mov eax,DWORD PTR [eax]
  279.                 mov oldwriteaddr,eax
  280.                 mov ebx,DWORD PTR [eax+3h]
  281.                 mov writepush,ebx
  282.                 add eax,7h
  283.                 mov writejmpaddr,eax

  284.                 cli
  285.                 mov eax,cr0
  286.                 and eax,not 10000h
  287.                 mov cr0,eax

  288.                 mov ebx,ssdtaddr
  289.                 mov eax,yjxsoft_com_NtReadVirtualMemory
  290.                 mov DWORD ptr [ebx+2e8h],eax
  291. //                 lea ebx,DWORD ptr [ebx+2e8h]
  292. //                 mov hr,ebx
  293.                 mov eax,yjxsoft_com_NtWriteVirtualMemory
  294.                 mov DWORD ptr [ebx+454h],eax
  295. //                 lea ebx,DWORD ptr [ebx+454h]
  296. //                 mov hw,ebx

  297.                 mov ebx,ntopenprcaddr
  298.                 mov BYTE ptr [ebx],0e9h
  299.                 /*        int 3*/
  300.                 mov eax,offset yjxsoft_com_OpenProcess
  301.                 lea eax,yjxsoft_com_OpenProcess
  302.                 sub eax,ebx
  303.                 sub eax,5h
  304.                 mov DWORD ptr [ebx+1h],eax
  305.                 /*lea ebx,DWORD ptr[ebx+1h]
  306.                 mov h1,ebx*/

  307.                 mov ebx,ntopentrdaddr
  308.                 mov BYTE ptr [ebx],0e9h
  309.                 mov eax,offset yjxsoft_com_OpenTread
  310.                 sub eax,ebx
  311.                 sub eax,5h //计算跳转地址
  312.                 mov DWORD ptr [ebx+1h],eax //紧接着 E9后边写 跳转地址
  313.                 lea ebx,DWORD ptr[ebx+1h]
  314. //                 mov h2,ebx
  315. //                 mov eax,90h
  316. //                 mov BYTE ptr [ebx+4],al

  317.                 mov eax,cr0
  318.                 or  eax,10000h
  319.                 mov cr0,eax
  320.                 sti
  321.                
  322.                
  323. }
  324. }
  325. //
  326. //;/////////////////////////////////////////////////////////////////
  327. //
  328. void jxcom_UnHook()
  329. {
  330. __asm
  331. {
  332. pushad
  333. cli
  334. mov  eax,cr0
  335. and  eax,not 10000h
  336. mov  cr0,eax

  337. mov eax,ssdtaddr
  338. mov ebx,DWORD ptr [oldreadaddr]
  339. mov DWORD ptr [eax+2e8h],ebx
  340. mov ebx,DWORD ptr [oldwriteaddr]
  341. mov DWORD ptr [eax+454h],ebx

  342. mov  eax,ntopenprcaddr
  343. mov  dword PTR [eax],0ffc875ffh
  344. mov  WORD ptr [eax+4h],0dc75h

  345. mov  eax,ntopentrdaddr
  346. mov  dword PTR [eax],0ffcc75ffh
  347. mov  WORD ptr [eax+4h],0e075h

  348. mov  eax,cr0
  349. or   eax,10000h
  350. mov  cr0,eax
  351. sti
  352. popad
  353. }

  354. }
  355. //yjxsoft_com_UnHook end
  356. //;////////////////////////////////////////////////////////////////////
复制代码

返回列表