|
在做某神奇工程的时候,需要在驱动里使用到ZwProtectVirtualMemory,可惜这个函数没有被ntoskrnl.exe导出。于是这就涉及到一个定位的问题。
不知道是否有人在意到,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-32*index
3.假设你要获取N号函数的地址,那么地址计算公式就是:p0+32*N
简单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通用):
|
|