您的位置:首页 > 运维架构

Copy-On-Write机制,全局hook(一)

2010-09-28 18:29 405 查看
我本来想在ring3下全局hook,大约有这么几种方法:

1: 用SetWindowsHookEx,安装的钩子类型,如WH_GETMESSAGE,WH_KEYBOARD等,但这种方法只能挂接系统中的所有GUI线程。

2: 还有一种通过插入注册表来实现 HKEY_LOCAL_MACHINE/Software/Microsoft/Windows NT/CurrentVersion/Windows/AppInit_DLLs,这种方法简单,但是还是只能挂钩GUI 程序,并且这个键值已经被广大HIPS所关注,吃力不讨好。

3: 用CreateRemoteThread注入到系统所有进程,但这种方法效率太低,特别是实时性太差,因为它要不停循环扫描所有进程,如果突然新建一个进程可能要过好久才能注进去,可能会漏掉很多API。

4: 通过挂钩NtResumeThread实现全局Hook,这种方法比较好,可以看http://www.xfocus.net/articles/200805/981.html

5: 禁用Copy-On-Write机制实现全局hook,但是难度很大,最终还是要去ring0禁用,http://www.xfocus.net/articles/200510/830.html
(它是非PAE的)

说起Copy-On-Write,先看一个结构

struct _hardware_pte_x86 (sizeof=4)

+0 bits0-0 valid

+0
bits1-1 write

+0 bits2-2 owner

+0 bits3-3
writethrough

+0 bits4-4 cachedisable

+0 bits5-5
accessed

+0 bits6-6 dirty

+0 bits7-7 largepage

+0
bits8-8 global

+0 bits9-9 copyonwrite

+0 bits10-10
prototype

+0 bits11-11 reserved

+0 bits12-31
pageframenumber

从上面可以看出,bits 9 被用于Copy-On-Write机制!

系统中很多dll的页面都是Copy-On-Write,但是我用调试器观察却发现Copy-On-Write(bit 9)都没有置1,调试了N久终于明白了:

只怪我被调试器忽悠了,那是因为默认所有DLL代码页、文件头等都是只读(PAGE_READONLY)的,根本不能修改。只要把
它们改成可写的,相应PTE的CopyOnWrite(bit 9)就会显现出来,但write(bit 1)仍然为0,因为copy-on-write
一定会引发异常 KiTrap0E->MmAccessFault->MiCopyOnWrite,所有这两位一定是配合使用的。我们以ntdll举例:

用OD任意加载/附加一个exe/进程,Alt+M 打开内存映射表

.txt代码节 (7c921000)

然后打开windbg->Kernel Debug

lkd> !process 0 0 Test.exe

PROCESS 87b99c88 SessionId: 0 Cid: 0f78 Peb: 7ffd5000 ParentCid: 058c

DirBase: 0a7c0600
ObjectTable: e3b9f270 HandleCount: 12.

Image: Test.exe

lkd> !vtop 0a7c0600
7c921000

X86VtoP: Virt 7c921000, pagedir a7c0600

X86VtoP: PAE PDPE a7c0608 - 000000000bdc5801

X86VtoP: PAE PDE bdc5f20 - 000000002d5e6867

X86VtoP: PAE PTE 2d5e6908 - 000000000e227025

X86VtoP: PAE Mapped phys e227000

Virtual address 7c921000 translates to physical address e227000.

!vtop可以把虚拟地址转换成物理地址,蓝色部分就是PTE!

再用OD把内存映射表中的7c921000一行改成read/write(右键单击,od的访问属性一栏不准的),再用windbg查看:

lkd> !vtop 0a7c0600
7c921000

X86VtoP: Virt 7c921000, pagedir a7c0600

X86VtoP: PAE PDPE a7c0608 - 000000000bdc5801

X86VtoP: PAE PDE bdc5f20 - 000000002d5e6867

X86VtoP: PAE PTE 2d5e6908 - 800000000e227225

X86VtoP: PAE Mapped phys e227000

Virtual address 7c921000 translates to physical address e227000.

哈哈,确实只有第九位发生变化吧(最高位置1,可能是不可执行的意思,XD Flag)。

这时,如果改动.text节的内容的话

lkd> !vtop 0a7c0600
7c921000

X86VtoP: Virt 7c921000, pagedir a7c0600

X86VtoP: PAE PDPE a7c0608 - 000000000bdc5801

X86VtoP: PAE PDE bdc5f20 - 000000002d5e6867

X86VtoP: PAE PTE 2d5e6908 - 0000000064e2e025

X86VtoP: PAE Mapped phys 64e2e000

Virtual address 7c921000 translates to physical address 64e2e000
.

可以看到PTE发生了巨大变化,从新映射了一个新的物理页64e2e000


也可以试一下其它节,但是千万不要去试.data数据节,因为软件在运行过程中早就修改了data数据,也就是说早就引发了CopyOnWrite,所
以.date已经不是原生dll映射的页了,这些页也没了写时复制特性,再改也没用。如果其它节也有这种情况,也肯定被改过了!

未完待续~~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: