欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

绕过Hackshield的hook

绕过Hackshield的hook

之前提到过新奇迹世界用的Hackshield,用雪村看了下它的驱动,发现做一些hook,
有ssdt hook和inline函数hook:

我想恢复这些hook,参考了360安全卫士修改nt!KiFastCallEntry函数的思路,
可以参照下这个帖子 http://bbs.pediy.com/showthread.php?t=143364&highlight=
思路就是:在nt!KiFastCallEntry中,通过ssdt计算出内核函数后,调用内核函数前,先进入我的函数,根据索引号判断是否使用通过ssdt计算出的内核函数,还是原始的内核函数。
下面的代码我只做了NtWriteVirtualMemory、NtReadVirtualMemory、NtClose和NtOpenProcess的恢复,环境是win7 32bit,nt模块为ntkrnlpa.exe。此程序只为研究,所以代码中有些硬编码,请见谅。
#include "moniprocess.h"
#include "HookKiFastCallEntry.h"
 
ULONG g_uHookKiFastCallEntryCr0 = 0;
ULONG g_ulHookKiFastCallEntry = 0;          // 将要被hook的地址
ULONG g_ulJmpBackAddr = 0;              // 跳回的地址
JmpCode g_struOldValue_KiFastCallEntry;        

ULONG g_uIndexOfNtWriteVirtualMemory = 0x18f;    // NtWriteVirtualMemory在ssdt中的索引号
ULONG g_uAddrOfNtWriteVirtualMemory = 0;      // NtWriteVirtualMemory首地址  rva=0x26171C
ULONG g_uIndexOfNtReadVirtualMemory = 0x115;    // NtReadVirtualMemory在ssdt中的索引号
ULONG g_uAddrOfNtReadVirtualMemory = 0;        // NtReadVirtualMemory首地址  rva=0x26182C
 
ULONG g_uIndexOfNtClose = 0x32;            // NtClose在ssdt中的索引号
ULONG g_uAddrOfNtClose = 0;              // NtClose首地址  rva=0x24637A
ULONG g_uIndexOfNtOpenProcess = 0x0be;        // NtOpenProcess在ssdt中的索引号
ULONG g_uAddrOfPsOpenProcess = 0;          // PsOpenProcess首地址  rva=0x277E6C
 

__declspec(naked) int MyNtOpenProcess() // 由于NtOpenProcess被做了inline函数hook,所以这里我自己实现了这个函数,这里是直接拷贝的反汇编代码
{
  _asm
  {
    mov    edi, edi
    push   ebp
    mov    ebp, esp
    push   ecx
    push   ecx
    mov    eax, dword ptr fs:[0x124]
    mov    al, byte ptr [eax+0x13A]
    mov    ecx, dword ptr [ebp+0x14]
    mov    edx, dword ptr [ebp+0x10]
    mov    byte ptr [ebp-0x4], al
    push   dword ptr [ebp-0x4]
    push   dword ptr [ebp-0x4]
    push   dword ptr [ebp+0x0C]
    push   dword ptr [ebp+0x8]
    mov    eax, g_uAddrOfPsOpenProcess
    call   eax
    
    
    
    //leave ==
    mov    esp, ebp 
    pop    ebp

    retn   0x10
  }
}
 
__declspec(naked) int Jmp_KiFastCallEntry()
{
  // eax为ssdt的索引号
  // edi为ServiceTableBase地址
  // edx为得到的系统函数地址
  _asm
  {    
    //pushfd
    //pushad
                // 判断是否需要恢复
    cmp eax, g_uIndexOfNtWriteVirtualMemory
    je Goto_Set_NtWriteVirtualMemory
    
    cmp eax, g_uIndexOfNtReadVirtualMemory
    je Goto_Set_NtReadVirtualMemory
    cmp eax, g_uIndexOfNtOpenProcess
    je Goto_Set_NtOpenProcess
    cmp eax, g_uIndexOfNtClose
    je Goto_Set_NtClose
    jmp Goto_End
  }
Goto_Set_NtClose:
  _asm
  {
    mov edx, g_uAddrOfNtClose // 设置原始的内核函数地址
    jmp Goto_End
  }
Goto_Set_NtOpenProcess:
  _asm
  {
    mov edx, MyNtOpenProcess  // 设置原始的内核函数地址
    jmp Goto_End
  }
Goto_Set_NtReadVirtualMemory:
  _asm
  {
    mov edx, g_uAddrOfNtReadVirtualMemory  // 设置原始的内核函数地址
    jmp Goto_End
  }
Goto_Set_NtWriteVirtualMemory:
  _asm
  {
    mov edx, g_uAddrOfNtWriteVirtualMemory
  }
 
Goto_End:
  _asm
  {
    //popad
    //popfd
    sub esp, ecx
    shr ecx, 2
    jmp g_ulJmpBackAddr    
  }
}

NTSTATUS RealHookKiFastCallEntry()
{
  if( 0 != g_ulHookKiFastCallEntry )
  {
    ULONG ulMachineCode;
    ulMachineCode = GetMachineCode( g_ulHookKiFastCallEntry, Jmp_KiFastCallEntry );
 
    WPOFF( &g_uHookKiFastCallEntryCr0 );
    __asm
    {       
      // save  5字节
      mov eax, g_ulHookKiFastCallEntry
      mov ebx, dword ptr [ eax ]
      mov g_struOldValue_KiFastCallEntry.dwJmpCode[0], ebx 
      mov bl, byte ptr [ eax + 4 ]
      mov ecx, offset g_struOldValue_KiFastCallEntry
      mov byte ptr [ ecx + 4 ], bl
      // hook
      mov byte ptr [ eax ], 0x0e9
      add eax, 1
      mov ecx, ulMachineCode
      mov dword ptr [ eax ], ecx 
    }
    WPON( &g_uHookKiFastCallEntryCr0 );
    return STATUS_SUCCESS;
  }
  g_ulHookKiFastCallEntry = 0;
  return STATUS_ACCESS_DENIED;
}
NTSTATUS HookKiFastCallEntry( IN ULONG ulFunAddr )
{
  NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  if( 0 == ulFunAddr )
    return ntStatus;
  g_ulHookKiFastCallEntry = ulFunAddr;
  if( 0x0e9c1e12b == *( (PDWORD)g_ulHookKiFastCallEntry ) )
  {
    ntStatus = RealHookKiFastCallEntry();
    if( !NT_SUCCESS( ntStatus ) )
      g_ulHookKiFastCallEntry = 0;
  }
  return ntStatus; 
}
VOID UnHookKiFastCallEntry()
{
  if( 0 != g_ulHookKiFastCallEntry )
  {
    WPOFF( &g_uHookKiFastCallEntryCr0 );
    __asm
    {
      // 恢复  5字节
      mov eax, g_ulHookKiFastCallEntry
      mov ebx, g_struOldValue_KiFastCallEntry.dwJmpCode[0]
      mov dword ptr [ eax ], ebx
      mov ecx, offset g_struOldValue_KiFastCallEntry
      mov bl, byte ptr [ ecx + 4 ]
      mov byte ptr [ eax + 4 ], bl  
    }
    WPON( &g_uHookKiFastCallEntryCr0 );
    KeSleep( 1 );
  }
  g_ulHookKiFastCallEntry = 0;
}
BOOL GetKiFastCallEntryAddr_XP32_And_WIN732( OUT PULONG pFunAddr )
{
  BOOL bRet = FALSE;
  ULONG nModuleBase, nModuleSize;
  ULONG nCopyModuleBase = 0, nCopyModuleSize = 0;
  ULONG ulBuildNumber, ulMinorVersion, ulMajorVersion;
  ULONG ulArrayFeatures[ 16 ];
  ULONG ulOffset, ulTemp;
  UNICODE_STRING uniNtKrnlFileName;
  do 
  {
    if( NULL == pFunAddr )
      break;
    PsGetVersion( &ulMajorVersion, &ulMinorVersion, &ulBuildNumber, 0 );
    if( ulMajorVersion == 5 && ulMinorVersion == 1 ) // xp 32位
    { 
      ulOffset = 0x8053e553 - 0x8053e540;
    }
    else if( ulMajorVersion == 6 && ulMinorVersion == 1 ) // win7 32位
    {
      ulOffset = 0x8053e554 - 0x8053e540;
    }
    else
    {
      break;
    }
    bRet = GetModuleBaseAndSize( NameOfNT1, &nModuleBase, &nModuleSize, &uniNtKrnlFileName );
    if( !bRet )
    {
      bRet = GetModuleBaseAndSize( NameOfNT2, &nModuleBase, &nModuleSize, &uniNtKrnlFileName );
    }
    if( !bRet )
      break;
 
    bRet = FALSE;
    if( CopyModule( &uniNtKrnlFileName, &nCopyModuleBase, &nCopyModuleSize ) )
    {
      ulArrayFeatures[0] = 0x6a04618b;
      ulArrayFeatures[1] = 0x6a9c5223;
      ulArrayFeatures[2] = 0x08c28302;
      ulArrayFeatures[3] = 0x244c809d;
      ulArrayFeatures[4] = 0x1b6a0201;
      ulArrayFeatures[5] = 0x030435ff;
      ulArrayFeatures[6] = 0x006affdf;
      ulArrayFeatures[7] = 0x57565355;      
      ulTemp = GetUnDocApiAddr( nCopyModuleBase, nCopyModuleSize, ulArrayFeatures, 8 );
      if( 0 != ulTemp )
      { 
        ulTemp = ulTemp + nModuleBase - ulOffset;      
        if( 0 != ulTemp )
        { 
          *pFunAddr = ulTemp;
          g_uAddrOfNtWriteVirtualMemory = 0x26171C;
          g_uAddrOfNtReadVirtualMemory = 0x26182C;
          g_uAddrOfPsOpenProcess = 0x277E6C;
          g_uAddrOfNtClose = 0x24637A;
 
          g_uAddrOfNtWriteVirtualMemory += nModuleBase;
          g_uAddrOfNtReadVirtualMemory += nModuleBase;
          g_uAddrOfPsOpenProcess += nModuleBase;
          g_uAddrOfNtClose += nModuleBase;
  
          bRet = TRUE;
        }
      } 
    }
    RtlFreeUnicodeString( &uniNtKrnlFileName );
  } while (0);
  if( 0 != nCopyModuleBase )
  {
    ExFreePool( (PVOID)nCopyModuleBase );
  }
  return bRet;
}
BOOL InitKiFastCallEntry()
{
  BOOL bRet = FALSE;
  ULONG nTemp, nHookAddr, ulBuildNumber, ulMinorVersion, ulMajorVersion;  
  do 
  {
    if( !GetKiFastCallEntryAddr_XP32_And_WIN732( &nTemp ) )    // 获得nt!KiFastCallEntry的地址
      break;
    PsGetVersion( &ulMajorVersion, &ulMinorVersion, &ulBuildNumber, 0 );
    if( ulMajorVersion == 5 && ulMinorVersion == 1 ) // xp 32位
    { 
      nHookAddr = nTemp + 0x0e1;
      g_ulJmpBackAddr = nTemp + 0x0e6;
    }
    else if( ulMajorVersion == 6 && ulMinorVersion == 1 ) // win7 32位
    {
      nHookAddr = nTemp + 0x0e4;
      g_ulJmpBackAddr = nTemp + 0x0e9;
    }
    else
      break;
    if( NT_SUCCESS( HookKiFastCallEntry( nHookAddr ) ) )
      bRet = TRUE;
 
  } while (0);
 
  return bRet;
} 
通过以上的恢复,可以打开、杀掉游戏进程。
目前用od附加还是要失败,估计是NtGetContextThread之类的hook还没有恢复。
明天再搞,今天就这样了。
driver.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功