看流星社区

 找回密码
 注册账号
查看: 2605|回复: 1

绕过Hackshield的hook

[复制链接]

该用户从未签到

发表于 2013-4-26 08:56:38 | 显示全部楼层 |阅读模式
之前提到过新奇迹世界用的Hackshield,用雪村看了下它的驱动,发现做一些hook,
有ssdt hook和inline函数hook:

思路就是:在nt!KiFastCallEntry中,通过ssdt计算出内核函数后,调用内核函数前,先进入我的函数,根据索引号判断是否使用通过ssdt计算出的内核函数,还是原始的内核函数。
下面的代码我只做了NtWriteVirtualMemory、NtReadVirtualMemory、NtClose和NtOpenProcess的恢复,环境是win7 32bit,nt模块为ntkrnlpa.exe。此程序只为研究,所以代码中有些硬编码,请见谅。
  1. #include "moniprocess.h"
  2. #include "HookKiFastCallEntry.h"


  3. ULONG g_uHookKiFastCallEntryCr0 = 0;
  4. ULONG g_ulHookKiFastCallEntry = 0;          // 将要被hook的地址
  5. ULONG g_ulJmpBackAddr = 0;              // 跳回的地址
  6. JmpCode g_struOldValue_KiFastCallEntry;        


  7. ULONG g_uIndexOfNtWriteVirtualMemory = 0x18f;    // NtWriteVirtualMemory在ssdt中的索引号
  8. ULONG g_uAddrOfNtWriteVirtualMemory = 0;      // NtWriteVirtualMemory首地址  rva=0x26171C

  9. ULONG g_uIndexOfNtReadVirtualMemory = 0x115;    // NtReadVirtualMemory在ssdt中的索引号
  10. ULONG g_uAddrOfNtReadVirtualMemory = 0;        // NtReadVirtualMemory首地址  rva=0x26182C

  11. ULONG g_uIndexOfNtClose = 0x32;            // NtClose在ssdt中的索引号
  12. ULONG g_uAddrOfNtClose = 0;              // NtClose首地址  rva=0x24637A

  13. ULONG g_uIndexOfNtOpenProcess = 0x0be;        // NtOpenProcess在ssdt中的索引号
  14. ULONG g_uAddrOfPsOpenProcess = 0;          // PsOpenProcess首地址  rva=0x277E6C



  15. __declspec(naked) int MyNtOpenProcess() // 由于NtOpenProcess被做了inline函数hook,所以这里我自己实现了这个函数,这里是直接拷贝的反汇编代码
  16. {
  17.   _asm
  18.   {
  19.     mov    edi, edi
  20.     push   ebp
  21.     mov    ebp, esp
  22.     push   ecx
  23.     push   ecx
  24.     mov    eax, dword ptr fs:[0x124]
  25.     mov    al, byte ptr [eax+0x13A]
  26.     mov    ecx, dword ptr [ebp+0x14]
  27.     mov    edx, dword ptr [ebp+0x10]
  28.     mov    byte ptr [ebp-0x4], al
  29.     push   dword ptr [ebp-0x4]
  30.     push   dword ptr [ebp-0x4]
  31.     push   dword ptr [ebp+0x0C]
  32.     push   dword ptr [ebp+0x8]
  33.     mov    eax, g_uAddrOfPsOpenProcess
  34.     call   eax
  35.    
  36.    
  37.    
  38.     //leave ==

  39.     mov    esp, ebp
  40.     pop    ebp



  41.     retn   0x10
  42.   }
  43. }

  44. __declspec(naked) int Jmp_KiFastCallEntry()
  45. {
  46.   // eax为ssdt的索引号
  47.   // edi为ServiceTableBase地址
  48.   // edx为得到的系统函数地址

  49.   _asm
  50.   {   
  51.     //pushfd
  52.     //pushad

  53.                 // 判断是否需要恢复

  54.     cmp eax, g_uIndexOfNtWriteVirtualMemory
  55.     je Goto_Set_NtWriteVirtualMemory
  56.    
  57.     cmp eax, g_uIndexOfNtReadVirtualMemory
  58.     je Goto_Set_NtReadVirtualMemory

  59.     cmp eax, g_uIndexOfNtOpenProcess
  60.     je Goto_Set_NtOpenProcess

  61.     cmp eax, g_uIndexOfNtClose
  62.     je Goto_Set_NtClose

  63.     jmp Goto_End
  64.   }

  65. Goto_Set_NtClose:

  66.   _asm
  67.   {
  68.     mov edx, g_uAddrOfNtClose // 设置原始的内核函数地址
  69.     jmp Goto_End
  70.   }

  71. Goto_Set_NtOpenProcess:

  72.   _asm
  73.   {
  74.     mov edx, MyNtOpenProcess  // 设置原始的内核函数地址
  75.     jmp Goto_End
  76.   }

  77. Goto_Set_NtReadVirtualMemory:

  78.   _asm
  79.   {
  80.     mov edx, g_uAddrOfNtReadVirtualMemory  // 设置原始的内核函数地址
  81.     jmp Goto_End
  82.   }

  83. Goto_Set_NtWriteVirtualMemory:

  84.   _asm
  85.   {
  86.     mov edx, g_uAddrOfNtWriteVirtualMemory
  87.   }

  88. Goto_End:

  89.   _asm
  90.   {
  91.     //popad
  92.     //popfd

  93.     sub esp, ecx
  94.     shr ecx, 2

  95.     jmp g_ulJmpBackAddr   
  96.   }
  97. }

  98. NTSTATUS RealHookKiFastCallEntry()
  99. {
  100.   if( 0 != g_ulHookKiFastCallEntry )
  101.   {
  102.     ULONG ulMachineCode;
  103.     ulMachineCode = GetMachineCode( g_ulHookKiFastCallEntry, Jmp_KiFastCallEntry );

  104.     WPOFF( &g_uHookKiFastCallEntryCr0 );

  105.     __asm
  106.     {      
  107.       // save  5字节
  108.       mov eax, g_ulHookKiFastCallEntry
  109.       mov ebx, dword ptr [ eax ]
  110.       mov g_struOldValue_KiFastCallEntry.dwJmpCode[0], ebx

  111.       mov bl, byte ptr [ eax + 4 ]
  112.       mov ecx, offset g_struOldValue_KiFastCallEntry
  113.       mov byte ptr [ ecx + 4 ], bl

  114.       // hook
  115.       mov byte ptr [ eax ], 0x0e9

  116.       add eax, 1
  117.       mov ecx, ulMachineCode
  118.       mov dword ptr [ eax ], ecx
  119.     }

  120.     WPON( &g_uHookKiFastCallEntryCr0 );

  121.     return STATUS_SUCCESS;
  122.   }

  123.   g_ulHookKiFastCallEntry = 0;

  124.   return STATUS_ACCESS_DENIED;
  125. }

  126. NTSTATUS HookKiFastCallEntry( IN ULONG ulFunAddr )
  127. {
  128.   NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;

  129.   if( 0 == ulFunAddr )
  130.     return ntStatus;

  131.   g_ulHookKiFastCallEntry = ulFunAddr;
  132.   if( 0x0e9c1e12b == *( (PDWORD)g_ulHookKiFastCallEntry ) )
  133.   {
  134.     ntStatus = RealHookKiFastCallEntry();
  135.     if( !NT_SUCCESS( ntStatus ) )
  136.       g_ulHookKiFastCallEntry = 0;
  137.   }

  138.   return ntStatus;
  139. }

  140. VOID UnHookKiFastCallEntry()
  141. {
  142.   if( 0 != g_ulHookKiFastCallEntry )
  143.   {

  144.     WPOFF( &g_uHookKiFastCallEntryCr0 );

  145.     __asm
  146.     {
  147.       // 恢复  5字节
  148.       mov eax, g_ulHookKiFastCallEntry
  149.       mov ebx, g_struOldValue_KiFastCallEntry.dwJmpCode[0]
  150.       mov dword ptr [ eax ], ebx

  151.       mov ecx, offset g_struOldValue_KiFastCallEntry
  152.       mov bl, byte ptr [ ecx + 4 ]
  153.       mov byte ptr [ eax + 4 ], bl  
  154.     }

  155.     WPON( &g_uHookKiFastCallEntryCr0 );

  156.     KeSleep( 1 );
  157.   }

  158.   g_ulHookKiFastCallEntry = 0;
  159. }

  160. BOOL GetKiFastCallEntryAddr_XP32_And_WIN732( OUT PULONG pFunAddr )
  161. {
  162.   BOOL bRet = FALSE;
  163.   ULONG nModuleBase, nModuleSize;
  164.   ULONG nCopyModuleBase = 0, nCopyModuleSize = 0;
  165.   ULONG ulBuildNumber, ulMinorVersion, ulMajorVersion;
  166.   ULONG ulArrayFeatures[ 16 ];
  167.   ULONG ulOffset, ulTemp;
  168.   UNICODE_STRING uniNtKrnlFileName;

  169.   do
  170.   {
  171.     if( NULL == pFunAddr )
  172.       break;

  173.     PsGetVersion( &ulMajorVersion, &ulMinorVersion, &ulBuildNumber, 0 );
  174.     if( ulMajorVersion == 5 && ulMinorVersion == 1 ) // xp 32位
  175.     {
  176.       ulOffset = 0x8053e553 - 0x8053e540;
  177.     }
  178.     else if( ulMajorVersion == 6 && ulMinorVersion == 1 ) // win7 32位
  179.     {
  180.       ulOffset = 0x8053e554 - 0x8053e540;
  181.     }
  182.     else
  183.     {
  184.       break;
  185.     }

  186.     bRet = GetModuleBaseAndSize( NameOfNT1, &nModuleBase, &nModuleSize, &uniNtKrnlFileName );
  187.     if( !bRet )
  188.     {
  189.       bRet = GetModuleBaseAndSize( NameOfNT2, &nModuleBase, &nModuleSize, &uniNtKrnlFileName );
  190.     }

  191.     if( !bRet )
  192.       break;

  193.     bRet = FALSE;
  194.     if( CopyModule( &uniNtKrnlFileName, &nCopyModuleBase, &nCopyModuleSize ) )
  195.     {
  196.       ulArrayFeatures[0] = 0x6a04618b;
  197.       ulArrayFeatures[1] = 0x6a9c5223;
  198.       ulArrayFeatures[2] = 0x08c28302;
  199.       ulArrayFeatures[3] = 0x244c809d;

  200.       ulArrayFeatures[4] = 0x1b6a0201;
  201.       ulArrayFeatures[5] = 0x030435ff;
  202.       ulArrayFeatures[6] = 0x006affdf;
  203.       ulArrayFeatures[7] = 0x57565355;      

  204.       ulTemp = GetUnDocApiAddr( nCopyModuleBase, nCopyModuleSize, ulArrayFeatures, 8 );
  205.       if( 0 != ulTemp )
  206.       {
  207.         ulTemp = ulTemp + nModuleBase - ulOffset;      
  208.         if( 0 != ulTemp )
  209.         {
  210.           *pFunAddr = ulTemp;

  211.           g_uAddrOfNtWriteVirtualMemory = 0x26171C;
  212.           g_uAddrOfNtReadVirtualMemory = 0x26182C;
  213.           g_uAddrOfPsOpenProcess = 0x277E6C;
  214.           g_uAddrOfNtClose = 0x24637A;

  215.           g_uAddrOfNtWriteVirtualMemory += nModuleBase;
  216.           g_uAddrOfNtReadVirtualMemory += nModuleBase;
  217.           g_uAddrOfPsOpenProcess += nModuleBase;
  218.           g_uAddrOfNtClose += nModuleBase;
  219.   
  220.           bRet = TRUE;
  221.         }
  222.       }
  223.     }

  224.     RtlFreeUnicodeString( &uniNtKrnlFileName );

  225.   } while (0);

  226.   if( 0 != nCopyModuleBase )
  227.   {
  228.     ExFreePool( (PVOID)nCopyModuleBase );
  229.   }

  230.   return bRet;
  231. }

  232. BOOL InitKiFastCallEntry()
  233. {
  234.   BOOL bRet = FALSE;
  235.   ULONG nTemp, nHookAddr, ulBuildNumber, ulMinorVersion, ulMajorVersion;  

  236.   do
  237.   {
  238.     if( !GetKiFastCallEntryAddr_XP32_And_WIN732( &nTemp ) )    // 获得nt!KiFastCallEntry的地址
  239.       break;

  240.     PsGetVersion( &ulMajorVersion, &ulMinorVersion, &ulBuildNumber, 0 );
  241.     if( ulMajorVersion == 5 && ulMinorVersion == 1 ) // xp 32位
  242.     {
  243.       nHookAddr = nTemp + 0x0e1;
  244.       g_ulJmpBackAddr = nTemp + 0x0e6;
  245.     }
  246.     else if( ulMajorVersion == 6 && ulMinorVersion == 1 ) // win7 32位
  247.     {
  248.       nHookAddr = nTemp + 0x0e4;
  249.       g_ulJmpBackAddr = nTemp + 0x0e9;
  250.     }
  251.     else
  252.       break;

  253.     if( NT_SUCCESS( HookKiFastCallEntry( nHookAddr ) ) )
  254.       bRet = TRUE;

  255.   } while (0);

  256.   return bRet;
  257. }
复制代码
通过以上的恢复,可以打开、杀掉游戏进程。

目前用od附加还是要失败,估计是NtGetContextThread之类的hook还没有恢复。

明天再搞,今天就这样了。

该用户从未签到

发表于 2013-9-23 09:44:41 | 显示全部楼层
顶你个肺啊,这不是骂人哦。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-29 00:33

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表