0 2 0

WIN64系统上定位未导出的Zw函数

admin
757 0

本文共计5345个字,预计阅读时长20分钟。

WIN64(2003、7、8、8.1)系统上所有nt!Zw函数,都是32个字节:

2003
=======
lkd>u nt!zwopenfile l b
nt!ZwOpenFile:
fffff800`0102a4d0 488bc4          mov     rax,rsp
fffff800`0102a4d3 fa              cli
fffff800`0102a4d4 4883ec10        sub     rsp,10h
fffff800`0102a4d8 50              push    rax
fffff800`0102a4d9 9c              pushfq
fffff800`0102a4da 6a10            push    10h
fffff800`0102a4dc 488d051d430000  lea     rax,[nt!KiServiceLinkage (fffff800`0102e800)]
fffff800`0102a4e3 50              push    rax
fffff800`0102a4e4 b830000000      mov     eax,30h
fffff800`0102a4e9 e9d23b0000      jmp     nt!KiServiceInternal (fffff800`0102e0c0)
fffff800`0102a4ee 6690            xchg    ax,ax

WIN7
=======
lkd>u nt!zwopenfile l b
nt!ZwOpenFile:
fffff800`0188a240 488bc4          mov     rax,rsp
fffff800`0188a243 fa              cli
fffff800`0188a244 4883ec10        sub     rsp,10h
fffff800`0188a248 50              push    rax
fffff800`0188a249 9c              pushfq
fffff800`0188a24a 6a10            push    10h
fffff800`0188a24c 488d051d2c0000  lea     rax,[nt!KiServiceLinkage (fffff800`0188ce70)]
fffff800`0188a253 50              push    rax
fffff800`0188a254 b830000000      mov     eax,30h
fffff800`0188a259 e962630000      jmp     nt!KiServiceInternal (fffff800`018905c0)
fffff800`0188a25e 6690            xchg    ax,ax

WIN8
=======
lkd>u nt!zwopenfile l b
nt!ZwOpenFile:
fffff802`7768f260 488bc4          mov     rax,rsp
fffff802`7768f263 fa              cli
fffff802`7768f264 4883ec10        sub     rsp,10h
fffff802`7768f268 50              push    rax
fffff802`7768f269 9c              pushfq
fffff802`7768f26a 6a10            push    10h
fffff802`7768f26c 488d05bd2f0000  lea     rax,[nt!KiServiceLinkage (fffff802`77692230)]
fffff802`7768f273 50              push    rax
fffff802`7768f274 b831000000      mov     eax,31h
fffff802`7768f279 e9c2daffff      jmp     nt!KiServiceInternal (fffff802`7768cd40)
fffff802`7768f27e 6690            xchg    ax,ax

WIN8.1
=========
lkd>u nt!zwopenfile l c
nt!ZwOpenFile:
fffff801`1dbbf080 488bc4          mov     rax,rsp
fffff801`1dbbf083 fa              cli
fffff801`1dbbf084 4883ec10        sub     rsp,10h
fffff801`1dbbf088 50              push    rax
fffff801`1dbbf089 9c              pushfq
fffff801`1dbbf08a 6a10            push    10h
fffff801`1dbbf08c 488d056d6c0000  lea     rax,[nt!KiServiceLinkage (fffff801`1dbc5d00)]
fffff801`1dbbf093 50              push    rax
fffff801`1dbbf094 b832000000      mov     eax,32h
fffff801`1dbbf099 e9e2e40000      jmp     nt!KiServiceInternal (fffff801`1dbcd580)
fffff801`1dbbf09e c3              ret
fffff801`1dbbf09f 90              nop

这就为定位任意Zw函数提供了方便,只要知道它在SSDT上的INDEX即可。下面是详细步骤: 1.首先选取一个一定导出的函数,比如ZwClose,获得它的地址p 2.通过ZwClose的地址和序号index,获取0号函数的地址p0=p-32index 3.假设你要获取N号函数的地址,那么地址计算公式就是:p0+32N

简单WINDBG演示如下(基于WIN8.1):

lkd>u nt!zwclose l b
nt!ZwClose:
fffff801`1dbbec00 488bc4          mov     rax,rsp
fffff801`1dbbec03 fa              cli
fffff801`1dbbec04 4883ec10        sub     rsp,10h
fffff801`1dbbec08 50              push    rax
fffff801`1dbbec09 9c              pushfq
fffff801`1dbbec0a 6a10            push    10h
fffff801`1dbbec0c 488d05ed700000  lea     rax,[nt!KiServiceLinkage (fffff801`1dbc5d00)]
fffff801`1dbbec13 50              push    rax
fffff801`1dbbec14 b80e000000      mov     eax,0Eh    //<-这个是ZwClose的INDEX
fffff801`1dbbec19 e962e90000      jmp     nt!KiServiceInternal (fffff801`1dbcd580)
fffff801`1dbbec1e c3              ret

lkd>u nt!zwclose-e*20
nt!ZwWorkerFactoryWorkerReady:     //<-这个是0号函数(可以用WIN64AST验证)
fffff801`1dbbea40 488bc4          mov     rax,rsp
fffff801`1dbbea43 fa              cli
fffff801`1dbbea44 4883ec10        sub     rsp,10h
fffff801`1dbbea48 50              push    rax
fffff801`1dbbea49 9c              pushfq
fffff801`1dbbea4a 6a10            push    10h
fffff801`1dbbea4c 488d05ad720000  lea     rax,[nt!KiServiceLinkage (fffff801`1dbc5d00)]
fffff801`1dbbea53 50              push    rax

lkd>u fffff801`1dbbea40+20*100 l b
nt!ZwNotifyChangeKey:     //<-这个是0x100号函数了
fffff801`1dbc0a40 488bc4          mov     rax,rsp
fffff801`1dbc0a43 fa              cli
fffff801`1dbc0a44 4883ec10        sub     rsp,10h
fffff801`1dbc0a48 50              push    rax
fffff801`1dbc0a49 9c              pushfq
fffff801`1dbc0a4a 6a10            push    10h
fffff801`1dbc0a4c 488d05ad520000  lea     rax,[nt!KiServiceLinkage (fffff801`1dbc5d00)]
fffff801`1dbc0a53 50              push    rax
fffff801`1dbc0a54 b800010000      mov     eax,100h
fffff801`1dbc0a59 e922cb0000      jmp     nt!KiServiceInternal (fffff801`1dbcd580)
fffff801`1dbc0a5e c3              ret

代码如下(WIN32/WIN64通用):

SIZE_T GetNtosFunctionAddress(PCWSTR FunctionName)
{
        UNICODE_STRING UniCodeFunctionName;
        RtlInitUnicodeString(&UniCodeFunctionName, FunctionName);
        return (SIZE_T)MmGetSystemRoutineAddress(&UniCodeFunctionName);
}

SIZE_T GetZwFuncAddress(ULONG id)
{
        SIZE_T f0Addr=0,RetAddr=0,pZwClose=GetNtosFunctionAddress(L"ZwClose");
        ULONG ZwFunLen=0,ZwCloseIndex=0;
#ifdef AMD64
        ZwFunLen=32;
        memcpy(&ZwCloseIndex,(PUCHAR)pZwClose+21,4);
#else
        ZwFunLen=20;
        memcpy(&ZwCloseIndex,(PUCHAR)pZwClose+1,4);
#endif
        f0Addr=pZwClose-ZwCloseIndex*ZwFunLen;
        RetAddr=f0Addr+id*ZwFunLen;
        DbgPrint("%p\n",RetAddr);
        return RetAddr;
}

最新回复 ( 0 )
全部楼主