逍遥公子 发表于 2013-4-26 08:56:38

绕过Hackshield的hook

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

思路就是:在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:
    mov    al, byte ptr
    mov    ecx, dword ptr
    mov    edx, dword ptr
    mov    byte ptr , al
    push   dword ptr
    push   dword ptr
    push   dword ptr
    push   dword ptr
    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
    {      
      // save5字节
      mov eax, g_ulHookKiFastCallEntry
      mov ebx, dword ptr [ eax ]
      mov g_struOldValue_KiFastCallEntry.dwJmpCode, 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
      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 = 0x6a04618b;
      ulArrayFeatures = 0x6a9c5223;
      ulArrayFeatures = 0x08c28302;
      ulArrayFeatures = 0x244c809d;

      ulArrayFeatures = 0x1b6a0201;
      ulArrayFeatures = 0x030435ff;
      ulArrayFeatures = 0x006affdf;
      ulArrayFeatures = 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还没有恢复。

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

cooby 发表于 2013-9-23 09:44:41

顶你个肺啊,这不是骂人哦。
页: [1]
查看完整版本: 绕过Hackshield的hook