以PspExitThread为例介绍如何寻找未导出函数的函数地址

ntoskrnl.exe导出了很多内核例程供驱动开发人员方便的使用,它也隐藏了很多很强大的历程,防止驱动开发人员过于方便的用它们。比如PspExitThread,这个函数没什么特别的,但配合APC使用它就能杀死绝大多数的进程,包括一些杀毒软件在内。gussing.cnblogs.com

那么如何才能找到这些未导出的函数并使用它们呢?答案就是反汇编,借助强大的windbg,加上一点点汇编基础,操作系统在你面前就会变的很透明。还是以PspExitThread为例子,我们已经知道导出函数PsTerminateSystemThread会调用PspTerminateThreadByPointer()函数,PspTerminateThreadByPointer进而会调用PspExitThread,所谓的函数调用就是 call 指令加上一个函数地址,所以挖出PspExitThread的地址完全是有可能的。gussing.cnblogs.com

打开windbg的本地内核调试,把该加载的pdb都加载了,然后反汇编PsTerminateSystemThread:gussing.cnblogs.com

lkd> uf nt!PsTerminateSystemThread

nt!PsTerminateSystemThread:

805d2c36 8bff            mov     edi,edi

805d2c38 55              push    ebp

805d2c39 8bec            mov     ebp,esp

805d2c3b 64a124010000    mov     eax,dword ptr fs:[00000124h]

805d2c41 f6804802000010  test    byte ptr [eax+248h],10h

805d2c48 7507            jne     nt!PsTerminateSystemThread+0x1b (805d2c51)



nt!PsTerminateSystemThread+0x14:

805d2c4a b80d0000c0      mov     eax,0C000000Dh

805d2c4f eb09            jmp     nt!PsTerminateSystemThread+0x24 (805d2c5a)



nt!PsTerminateSystemThread+0x1b:

805d2c51 ff7508 push dword ptr [ebp+8]

805d2c54 50              push    eax

805d2c55 e828fcffff      call    nt!PspTerminateThreadByPointer (805d2882)



nt!PsTerminateSystemThread+0x24:

805d2c5a 5d              pop     ebp

805d2c5b c20400          ret     4

地址805d2c55处的call指令可以解析出PspTerminateThreadByPointer的地址。那么该call指令的地址又是如何得到的呢?看上面那行push dword ptr [ebp+8],也就是“ff7508”,这是PspTerminateThreadByPointer函数调用的“特征码”,从PsTerminateSystemThread函数开始到PspTerminateThreadByPointer函数调用为止,该特征码都只出现一次,所以搜索到ff7508串就能很方便的定位到PspTerminateThreadByPointer。gussing.cnblogs.com

再看PspTerminateThreadByPointer函数(805d2882)的反汇编:gussing.cnblogs.com

lkd> uf 805d2882

nt!PspTerminateThreadByPointer:

805d2882 8bff            mov     edi,edi

805d2884 55              push    ebp

805d2885 8bec            mov     ebp,esp

805d2887 83ec0c          sub     esp,0Ch

805d288a 834df8ff        or      dword ptr [ebp-8],0FFFFFFFFh

805d288e 56              push    esi

805d288f 57              push    edi

805d2890 8b7d08          mov     edi,dword ptr [ebp+8]

805d2893 8db748020000    lea     esi,[edi+248h]

805d2899 f60640          test    byte ptr [esi],40h

805d289c c745f4c0bdf0ff  mov     dword ptr [ebp-0Ch],0FFF0BDC0h

805d28a3 7417            je      nt!PspTerminateThreadByPointer+0x3a (805d28bc)



nt!PspTerminateThreadByPointer+0x23:

805d28a5 8b8720020000    mov     eax,dword ptr [edi+220h]

805d28ab 0574010000      add     eax,174h

805d28b0 50              push    eax

805d28b1 57              push    edi

805d28b2 6852285d80      push    offset nt!PspExitNormalApc+0x54 (805d2852)

805d28b7 e894f1ffff      call    nt!PspCatchCriticalBreak (805d1a50)



nt!PspTerminateThreadByPointer+0x3a:

805d28bc 64a124010000    mov     eax,dword ptr fs:[00000124h]

805d28c2 3bf8            cmp     edi,eax

805d28c4 750e            jne     nt!PspTerminateThreadByPointer+0x52 (805d28d4)



nt!PspTerminateThreadByPointer+0x44:

805d28c6 33c0            xor     eax,eax

805d28c8 40              inc     eax

805d28c9 f00906          lock or dword ptr [esi],eax

805d28cc ff750c push dword ptr [ebp+0Ch]

805d28cf e8bef7ffff      call    nt!PspExitThread (805d2092)
。。。

如之前所述,call PspExitThread之前有一串特征码ff750c,从PspTerminateThreadByPointer函数开始到PspExitThread函数调用间只出现一次,搜索到串ff750c就能很方便的找到PspExitThreadgussing.cnblogs.com

最后提供一个寻找PspExitThread的例子,部分代码来自网上,(忘了谁写的了,谁提醒下我马上改):

 

NTSTATUS PspTerminateThreadByPointer(PETHREAD Thread, NTSTATUS status);

typedef VOID (*MyPspExitThread)(NTSTATUS status);





ULONG GetPspTerminateThreadByPointer()

{

        char * PsTerminateSystemThreadAddr;

        int iLen;

        ULONG dwAddr;

        ULONG NtTerminateThreadAddr;

        char * pAddr;

gussing.cnblogs.com

                        PsTerminateSystemThreadAddr= (char *)PsTerminateSystemThread;

                        __asm

                        {

                                        __emit 0x90;

                                        __emit 0x90;

                        }

                        for (iLen=0;iLen<50;iLen++)

                        {

                                        if (*PsTerminateSystemThreadAddr == (char)0xff

                                                && *(PsTerminateSystemThreadAddr+1) == (char)0x75

                                                && *(PsTerminateSystemThreadAddr+2) == (char)0x08

                                                )

                                        {

                                                        __asm

                                                        {

                                                                        __emit 0x90;

                                                                        __emit 0x90;

                                                        }

                                                        PsTerminateSystemThreadAddr += 5;

                                                        dwAddr = *(ULONG *)PsTerminateSystemThreadAddr + (ULONG)PsTerminateSystemThreadAddr +4;



                                                        DbgPrint("[ring0] PspTerminateThreadByPointer:: 0x%x ",dwAddr);

                                                        return dwAddr;

                                                        //break;

                                        }

                                        PsTerminateSystemThreadAddr++;

                        }

        return FALSE;

}



gussing.cnblogs.com

PVOID GetPspExitThread()



{

#ifdef XP_SP3

        char* sPtr;

        ULONG end = (ULONG)GetPspTerminateThreadByPointer() + 0x60;

        sPtr = (char*)GetPspTerminateThreadByPointer();

        while ( (ULONG)sPtr <  end) //0x60 = ±??úé? PspTerminateThreadByPointer ·ê??3ì?è

        {

                //DbgPrint("[ring0] addr: 0x%x, val: 0x%x", sPtr, *(WORD*)sPtr);

                if ( *(WORD*)sPtr == 3189 )

                {gussing.cnblogs.com

                        return (PVOID)(*(ULONG*)(sPtr + 3) + sPtr + 7);        

                }

                sPtr ++;

        }gussing.cnblogs.com

        return NULL;

#else

        return NULL;

#endif



}

你可能感兴趣的:(thread)