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

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

A、定位特征码函数FindCode_Address构建
     B、定位NtOpenThread
     C、定位NtOpenProcess
     D、定位NtReadVirtualMemory
     E、定位NtWriteVirtualMemory
     F、CALL与JMP指令的区别
     G、构建相应的替换函数
课时:39分

OpenProcess         //NtOpenProcess+0x21E  //SSDT 122
OpenThread          //NtOpenThread+0x214   //SSDT 128
ReadProcessMemory   //NtReadVirtualMemory+0   //SSDT 186
WriteProcessMemory  //NtWriteVirtualMemory+0  //SSDT 277

ReadProcessMemory   
mov eax,Proc
jmp eax
WriteProcessMemory  
mov eax,Proc2
jmp eax
WriteProcessMemory +7

#pragma PAGECODE
__declspec(naked)VOID My_ReadProcessMemory()
{  
  //恢复前2条指令
__asm
{
   push    1Ch

}

}


#pragma PAGECODE
__declspec(naked)VOID yjxsoft_com_OpenProcess()
{
   
        __asm
        {
               
                push dword ptr [ebp-38h]
                push dword ptr [ebp-24h]
                mov  eax,ntopenprcaddr
                add  eax,0bh
                push eax //CALL后返回的地址 非压栈参数
                //  
                jmp  ObOpenObjectByPointeraddr
        }
}

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

笔记:
上节课有个函数写错了,应该是NtDebugActiveProcess.将46课的源代码复制过来,新建一个49.H头文件.首先通过NtReadVirtualMemory函数,建立函数先恢复前面几个字节,然后再跳回到原函数.同理WriteProcessMemory 也写上恢复代码.再写nt!NtOpenProcess函数的恢复,但是这个不能在头部直接恢复,是要在后面偏移0X21E处修改. nt!NtOpenThread的方法也类似.怕有人不明白汇编又讲解call = push + jmp 的原理.
最终代码如下:

//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=805cc89ch;   //myNtOpenThread
DWORD NtOpenThread_214_B=805cc8a7h;
DWORD NtOpenProcess_21E_B=805cc625h;
#pragma PAGECODE
__declspec(naked)VOID My_NtReadVirtualMemory()
{  
        //恢复前2条指令
        __asm
        {
                push    1Ch
            puhs    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
                        puhs    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    ObOpenObjectByPointer /*(805bcc6c)*/ ret c3 eip
                        //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    NtOpenProcess_214_B // DWORD NtOpenProcess_214_B=805cc8a7h
                jmp    ObOpenObjectByPointer /*(805bcc6c)*/
                        //jmp  NtOpenProcess_214_B
        }
}

#pragma  PAGECODE
VOID HOOK()
{
        // SSDT 186 =My_NtReadVirtualMemory
        // SSDT 277 =My_NtWriteVirtualMemory
        //DWORD NtOpenProcess_21E=0x805cc61a; //myNtOpenProcess
        //DWORD NtOpenThread_214=805cc89ch;   //myNtOpenThread
        __asm
        {  // NtOpenProcess 还原
                lea ebx,NtOpenProcess_21E
                mov [ebx+0],E9h
                lea eax,myNtOpenProcess
                mov [ebx+1],eax
      // NtOpenThread 还原
          lea ebx,NtOpenThread_214
          mov [ebx+0],E9h
          lea eax,myNtOpenThread //通过公式计算
          mov [ebx+1],eax
        }
}

另外老师给出了另一个passtp.h源代码里面有更详细的过保护.
  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. void jxcom_UnHook()
  328. {
  329. __asm
  330. {
  331. pushad
  332. cli
  333. mov  eax,cr0
  334. and  eax,not 10000h
  335. mov  cr0,eax

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

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

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

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

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

返回列表