如题,我想调用内核的函数KeSuspendThread这样的函数,但是这个函数DDK是没有支持的,不能通过简单的编写原型Link的方式。
我怎样才能调用像这种类型的内核函数啊,只是一个方法问题。
ULONGKeSuspendThread ( __inout PKTHREAD Thread )
/*++
Routine Description:
This function suspends the execution of a thread. If the suspend count overflows the maximum suspend count, then a condition is raised.
Arguments:
Thread - Supplies a pointer to a dispatcher object of type thread.
Return Value:
The previous suspend count.
--*/
NTSTATUSPsSuspendThread ( IN PETHREAD Thread, OUT PULONG PreviousSuspendCount OPTIONAL )/*++
This function suspends the target thread, and optionally returns the previous suspend count.
ThreadHandle - Supplies a handle to the thread object to suspend.
PreviousSuspendCount - An optional parameter, that if specified points to a variable that receives the thread's previous suspend count.
NTSTATUS - Status of call
--*/利用结合反汇编的暴力搜索定位,比如:0: kd> u nt!NtSuspendThreadnt!NtSuspendThread:805d58b0 6a20 push 20h805d58b2 68f8b94d80 push offset nt!ObWatchHandles+0x79c (804db9f8)805d58b7 e8c472f6ff call nt!_SEH_prolog (8053cb80)805d58bc 33db xor ebx,ebx805d58be 895dfc mov dword ptr [ebp-4],ebx805d58c1 64a124010000 mov eax,dword ptr fs:[00000124h]805d58c7 8945d0 mov dword ptr [ebp-30h],eax805d58ca 8a8040010000 mov al,byte ptr [eax+140h]805d58d0 8845e0 mov byte ptr [ebp-20h],al805d58d3 8b750c mov esi,dword ptr [ebp+0Ch]805d58d6 3ac3 cmp al,bl805d58d8 7413 je nt!NtSuspendThread+0x3d (805d58ed)805d58da 3bf3 cmp esi,ebx805d58dc 740f je nt!NtSuspendThread+0x3d (805d58ed)805d58de a134315680 mov eax,dword ptr [nt!MmUserProbeAddress (80563134)]805d58e3 3bf0 cmp esi,eax805d58e5 7202 jb nt!NtSuspendThread+0x39 (805d58e9)805d58e7 8918 mov dword ptr [eax],ebx805d58e9 8b06 mov eax,dword ptr [esi]805d58eb 8906 mov dword ptr [esi],eax805d58ed 834dfcff or dword ptr [ebp-4],0FFFFFFFFh805d58f1 53 push ebx805d58f2 8d45e4 lea eax,[ebp-1Ch]805d58f5 50 push eax805d58f6 ff75e0 push dword ptr [ebp-20h]805d58f9 ff35bc495680 push dword ptr [nt!PsThreadType (805649bc)]805d58ff 6a02 push 2805d5901 ff7508 push dword ptr [ebp+8]805d5904 e8896bfeff call nt!ObReferenceObjectByHandle (805bc492)805d5909 3bc3 cmp eax,ebx805d590b 7c5c jl nt!NtSuspendThread+0xb9 (805d5969)805d590d 8d45dc lea eax,[ebp-24h]805d5910 50 push eax805d5911 ff75e4 push dword ptr [ebp-1Ch]805d5914 e869feffff call nt!PsSuspendThread (805d5782) // 第三个 E8 类型 call805d5919 8bf8 mov edi,eax805d591b 8b4de4 mov ecx,dword ptr [ebp-1Ch]0: kd> u nt!PsSuspendThreadnt!PsSuspendThread:805d5782 6a18 push 18h805d5784 68e0b94d80 push offset nt!ObWatchHandles+0x784 (804db9e0)805d5789 e8f273f6ff call nt!_SEH_prolog (8053cb80)805d578e 33f6 xor esi,esi805d5790 8975e4 mov dword ptr [ebp-1Ch],esi805d5793 64a124010000 mov eax,dword ptr fs:[00000124h]805d5799 8b7d08 mov edi,dword ptr [ebp+8]805d579c 3bf8 cmp edi,eax805d579e 752e jne nt!PsSuspendThread+0x4c (805d57ce)805d57a0 8975fc mov dword ptr [ebp-4],esi805d57a3 57 push edi805d57a4 e83f8df2ff call nt!KeSuspendThread (804fe4e8) // 第二个 E8 类型 call805d57a9 8945e4 mov dword ptr [ebp-1Ch],eax805d57ac 8975dc mov dword ptr [ebp-24h],esi805d57af 834dfcff or dword ptr [ebp-4],0FFFFFFFFh805d57b3 e98a000000 jmp nt!PsSuspendThread+0xc0 (805d5842)0: kd> u 804fe4e8nt!KeSuspendThread:804fe4e8 8bff mov edi,edi804fe4ea 55 push ebp804fe4eb 8bec mov ebp,esp804fe4ed 83ec0c sub esp,0Ch804fe4f0 53 push ebx804fe4f1 56 push esi804fe4f2 8b7508 mov esi,dword ptr [ebp+8]804fe4f5 57 push edi........最后,马甲同学的惯用手法就是:__asm{ mov ebx, g_Addr push xxx push xxx .... call ebx}1. 相对偏移需要自己计算一下 如果要 E8 类型 call hook 之类的话2. 我个人极不推荐这种做法
暴力不难呀。
nt!NtSuspendThread 是 SSDT 表里的 API:
0: kd> u nt!ZwSuspendThreadnt!ZwSuspendThread:80502104 b8fe000000 mov eax,0FEh80502109 8d542404 lea edx,[esp+4]8050210d 9c pushfd8050210e 6a08 push 880502110 e83c030400 call nt!KiSystemService (80542451)80502115 c20800 ret 8
0: kd> ?poi(80505450+0FE*4)Evaluate expression: -2141366096 = 805d58b0
0: kd> ln 805d58b0(805d58b0) nt!NtSuspendThread | (805d5976) nt!NtResumeThreadExact matches: nt!NtSuspendThread = <no type information>
如果怕取的不正确就自己Map一份内核取到正确的地址。
然后开始反汇编这个地址,类似于下面的代码:
TotalSize = SizeOfProc( pTarFunction );
while( TRUE ){ if( CodeSize >= TotalSize ) break;
Size = SizeOfCode( (PVOID) pTarget, &pOpcode );
pTarget += Size; CodeSize += Size;
if( EnpCodeAnalysis(pOpcode, Size, CodeSize, TotalSize, HookNumber) ) { if( !gs_TargetAnalysis.Types ) INLINE_DBGPRINT( ("[keenjoy95 's Inline Hook Engine] - ERROR CODE 0xA0000001.\n") );
break; }}
明眼人一看就知道我这段代码用的是 Ms-Rem 的 反汇编引擎 LDasm,当然我自己的反汇编引擎也在编写中。
连续三次分析到长度为 5字节、E8 开头的指令就说明找到了 nt!PsSuspendThread,接下来找 nt!KeSuspendThread 的过程雷同。跳过 E8 是偏移 fff28d3f,需要计算一下。
我之所以不推荐这种方法的问题之一是跨平台,我简单看了一下,WIN-XP/2003/VISTA 下第三个 call 均是 nt!PsSuspendThread。
Windows 2000 Kernel Version 2195 (Service Pack 4) MP (2 procs) Free x86 下第三个 call 直接就是 nt!KeSuspendThread:0: kd> u nt!NtSuspendThreadnt!NtSuspendThread:804e6462 55 push ebp804e6463 8bec mov ebp,esp804e6465 6aff push 0FFFFFFFFh804e6467 6828664080 push offset nt!GUID_DEVICE_BATTERY+0x4b0 (80406628)804e646c 68d00a4680 push offset nt!_except_handler3 (80460ad0)804e6471 64a100000000 mov eax,dword ptr fs:[00000000h]804e6477 50 push eax804e6478 64892500000000 mov dword ptr fs:[0],esp804e647f 51 push ecx804e6480 51 push ecx804e6481 83ec20 sub esp,20h804e6484 53 push ebx804e6485 56 push esi804e6486 57 push edi804e6487 8965e8 mov dword ptr [ebp-18h],esp804e648a 8365fc00 and dword ptr [ebp-4],0804e648e 64a124010000 mov eax,dword ptr fs:[00000124h]804e6494 8945cc mov dword ptr [ebp-34h],eax804e6497 8a8034010000 mov al,byte ptr [eax+134h]804e649d 8845d8 mov byte ptr [ebp-28h],al804e64a0 84c0 test al,al804e64a2 8b750c mov esi,dword ptr [ebp+0Ch]804e64a5 7417 je nt!NtSuspendThread+0x5c (804e64be)804e64a7 85f6 test esi,esi804e64a9 7413 je nt!NtSuspendThread+0x5c (804e64be)804e64ab a178474880 mov eax,dword ptr [nt!MmUserProbeAddress (80484778)]804e64b0 3bf0 cmp esi,eax804e64b2 7206 jb nt!NtSuspendThread+0x58 (804e64ba)804e64b4 c70000000000 mov dword ptr [eax],0804e64ba 8b06 mov eax,dword ptr [esi]804e64bc 8906 mov dword ptr [esi],eax804e64be 834dfcff or dword ptr [ebp-4],0FFFFFFFFh804e64c2 6a00 push 0804e64c4 8d45dc lea eax,[ebp-24h]804e64c7 50 push eax804e64c8 ff75d8 push dword ptr [ebp-28h]804e64cb ff35285c4880 push dword ptr [nt!PsThreadType (80485c28)]804e64d1 6a02 push 2804e64d3 ff7508 push dword ptr [ebp+8]804e64d6 e8e78ff6ff call nt!ObReferenceObjectByHandle (8044f4c2)804e64db 85c0 test eax,eax804e64dd 0f8c9a000000 jl nt!NtSuspendThread+0x11b (804e657d)804e64e3 c745fc01000000 mov dword ptr [ebp-4],1804e64ea 64a124010000 mov eax,dword ptr fs:[00000124h]804e64f0 8945c8 mov dword ptr [ebp-38h],eax804e64f3 8b4ddc mov ecx,dword ptr [ebp-24h]804e64f6 3bc8 cmp ecx,eax804e64f8 7419 je nt!NtSuspendThread+0xb1 (804e6513)804e64fa 83b92402000000 cmp dword ptr [ecx+224h],0804e6501 7410 je nt!NtSuspendThread+0xb1 (804e6513)804e6503 e89a92f6ff call nt!ObfDereferenceObject (8044f7a2)804e6508 834dfcff or dword ptr [ebp-4],0FFFFFFFFh804e650c b84b0000c0 mov eax,0C000004Bh804e6511 eb6a jmp nt!NtSuspendThread+0x11b (804e657d)804e6513 51 push ecx804e6514 e86980f4ff call nt!KeSuspendThread (8042e582)另外就是绕开入口函数直接调用 internal 实现有时往往会有一些问题。比如外层函数修改了某些标志位再 call 的 internal_xxx,那么我们就需要手动设置这些标志位 等。