之前提到过新奇迹世界用的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
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)