Tesla.Angela 发表于 2014-5-13 15:53:59

[原创]在WIN64系统上定位未导出的Zw函数

在做某神奇工程的时候,需要在驱动里使用到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 488d051d430000lea   rax,
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 488d051d2c0000lea   rax,
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 488d05bd2f0000lea   rax,
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 488d056d6c0000lea   rax,
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 488d05ed700000lea   rax,
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 488d05ad720000lea   rax,
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 488d05ad520000lea   rax,
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通用):
**** Hidden Message *****

songbei6 发表于 2014-5-14 10:31:43

学习一下,楼主辛苦了。。。

5ak 发表于 2014-5-14 11:37:10

谢谢分享。我来学习一下

860000023 发表于 2014-5-14 14:11:23

谢谢TA大分享.来学习一下.

jgyolm 发表于 2014-5-16 11:49:57

thank you for share

x64asm 发表于 2014-5-17 15:11:47

我都是调用MiProtectPages来直接改保护属性的。调用ZwProtectVirtualMemory不能修改内核页面的保护属性。

x64asm 发表于 2014-5-17 15:19:35

另外,我收集了从NT4 1381 到NT6 9600 全套服务ID,包括X86,X64,安腾处理器。定义了头文件方便使用。

Bambo 发表于 2014-6-17 15:19:19

楼上的可以把东西放出来,楼主会给一些有意思的东西给你的。

a1154212237 发表于 2014-6-20 14:06:04

支持!!!!!看看由没用取内核基地址的代码

cghost 发表于 2014-6-22 16:11:01

老大发的东西都是好东西,顶起~!

whitesilt 发表于 2014-6-24 11:58:20

学习学习

大官人 发表于 2014-7-3 11:09:33

谢谢分享!!!

haidejintou 发表于 2014-7-9 10:47:50

看看先。是否有用

网游天下 发表于 2014-8-4 04:46:31

必须学习

yhcyhy2010 发表于 2014-8-6 06:09:37

学习了

mlyknown 发表于 2014-8-8 00:24:53

。。。

renminbi 发表于 2014-9-19 14:24:56

64位的是32个字节,32位的20个字节吧

hotwen 发表于 2014-9-26 14:54:16

GetSSDTFunctionAddress 64

david2013 发表于 2014-9-27 01:15:30

看看,有用

basketwill 发表于 2014-12-23 11:30:21

好东西

suixin 发表于 2014-12-25 10:28:30

谢谢分享

zhighest 发表于 2014-12-31 20:58:35

学习下……………………

dak811 发表于 2015-2-25 14:27:50

真是好方法

KOK20141001 发表于 2015-4-8 13:32:04

谢谢老大分享了 呵呵

donydh 发表于 2015-5-22 02:42:59

学习一下,楼主辛苦了。。。

lanjingling888 发表于 2015-5-22 19:03:34

来看看呢

284406022 发表于 2015-5-25 10:23:21

还不知道有这个规律,学习了

ttblacka2 发表于 2015-5-25 17:07:18

刚下楼主分享,学习了!

Alpha.Po 发表于 2015-6-18 09:43:20

看看谢谢

nixiadexue 发表于 2015-10-21 14:48:35

我也来看看

nixiadexue 发表于 2015-10-21 14:48:54

我也来看看速度速度

qq569582281 发表于 2015-10-22 09:35:45

哈哈哈好代码,先收藏了~~~~
页: [1] 2 3
查看完整版本: [原创]在WIN64系统上定位未导出的Zw函数