kernel-mode内联函数挂钩的简单实现
作者: CDrea, 出处:IT专家网, 责任编辑: 张帅,
2007-10-25 15:38
前段时间看了uty的《kernel inline hook 绕过vice检测》,思路很好但实现起来麻烦了点。这里以CmEnumerateKey为例介绍实现inline hook的简单方法……
前段时间看了uty的《kernel inline hook 绕过vice检测》,思路很好,但实现起来麻烦了点。这里以CmEnumerateKey为例介绍实现inline hook的简单方法,尽量依靠编译器做更多的事情。
1、编写fake_CmEnumerateKey,在其中对CmEnumerateKey的调用做后续处理。
| Code:[Copy to clipboard] NTSTATUS fake_CmEnumerateKey( IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength ) { NTSTATUS status = STATUS_SUCCESS; KdPrint(("[cmhook] nt!CmEnumerateKey() called.\n")); status = JMP_CmEnumerateKey(KeyControlBlock, Index, KeyInformationClass, KeyInformation, Length, ResultLength); return status; } |
2、取得CmEnumerateKey的地址,备份前7个字节,之后修改CmEnumerateKey的前5个字节为jmp xxxxxxxx(fake_CmEnumerateKey入口偏移地址)。
| Code:[Copy to clipboard] // 保存原始的7个字节代码 BYTE g_cOrigCode[7] = {0}; // JMP xxxxxxxx BYTE g_cHookCode[5] = { 0xe9, 0, 0, 0, 0 }; RtlCopyMemory(g_cOrigCode, (BYTE*)CmEnumerateKey, 7); // calc jmp offset *( (ULONG*)(g_cHookCode+1) ) = (ULONG)fake_CmEnumerateKey - (ULONG)CmEnumerateKey - 5; DisableWriteProtect(&ulAttr); RtlCopyMemory((BYTE*)CmEnumerateKey, g_cHookCode, 5); EnableWriteProtect(ulAttr); |
3、编写__declspec(naked) JMP_CmEnumerateKey,这个例程实现CmEnumerateKey被修改个7个字节的代码,并转入nt!CmEnumerateKey+7处开始执行。
| Code:[Copy to clipboard] __declspec(naked) NTSTATUS JMP_CmEnumerateKey( IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength ) { __asm { _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 } } |
JMP_CmEnumerateKey的主要实现代码在程序运行时进行填充,以下是实现代码:
| Code:[Copy to clipboard] BYTE jmp_orig_code[7] = { 0xEA, 0, 0, 0, 0, 0x08, 0x00 }; // jmp 0008:nt!CmEnumerateKey+7 *( (ULONG*)(jmp_orig_code+1) ) = (ULONG)((BYTE*)CmEnumerateKey + 7); DisableWriteProtect(&ulAttr); // // CmEnumerateKey修改之前的前7个字节的代码 // 6a18 push 18h // 68d0de4d80 push offset nt!`string'+0xf8 (804dded0) // RtlCopyMemory((BYTE*)JMP_CmEnumerateKey, g_cOrigCode, 7); // jmp 0008:nt!CmEnumerateKey+7 RtlCopyMemory((BYTE*)JMP_CmEnumerateKey+7, jmp_orig_code, 7); EnableWriteProtect(ulAttr); |
这里要注意一个细节,虽然只CmEnumerateKey修改了前5个字节,但这5个字节里面包含两条指令(共7个字节),因此要保存前7个字节。
修改前:
| Code:[Copy to clipboard] kd> u nt!CmEnumerateKey nt!CmEnumerateKey: 80605f54 6a18 push 18h 80605f56 68d0de4d80 push offset nt!`string'+0xf8 (804dded0) 80605f5b e80839f2ff call nt!_SEH_prolog (80529868) 80605f60 e829abffff call nt!CmpLockRegistry (80600a8e) 80605f65 8b4508 mov eax,dword ptr [ebp+8] 80605f68 f6400502 test byte ptr [eax+5],2 80605f6c 7407 je nt!CmEnumerateKey+0x21 (80605f75) 80605f6e be7c0100c0 mov esi,0C000017Ch |
修改后:
| Code:[Copy to clipboard] kd> u nt!CmEnumerateKey nt!CmEnumerateKey: 80605f54 e999143279 jmp cmhook+0x3f2 (f99273f2) 80605f59 4d dec ebp 80605f5a 80e808 sub al,8 80605f5d 39f2 cmp edx,esi 80605f5f ff ??? 80605f60 e829abffff call nt!CmpLockRegistry (80600a8e) 80605f65 8b4508 mov eax,dword ptr [ebp+8] 80605f68 f6400502 test byte ptr [eax+5],2 |
- 本文关键词:

