一、什么是写拷贝
写拷贝是VAD树里的属性。当访问一个线性地址,页表项 PTE = 0 时,就会触发缺页异常,跳转到异常处理函数,处理函数会检查VAD树,看看这个线性地址到底是没挂物理页,还是写拷贝,或者是别的什么情况。
举个例子,在Windows XP系统里,MessageBoxA 这个函数位于 ntdll.dll,假如我想HOOK它,比如把它头两个字节的 MOV EDI,EDI 改成JMP,此时由于 PTE = 0,就会触发缺页异常。然后异常处理函数遍历 VAD 树,就会发现 MessageBoxA 的属性是 WriteCopy.
此时,如果你对数据进行修改,系统会帮你拷贝一份 MessageBoxA 的代码,然后你的HOOK就只对本进程有效。
二、如何在windbg中打印 VAD 树
首先,!process 0 0 查看进程信息
PROCESS 81ecbd50 SessionId: 0 Cid: 0118 Peb: 7ffde000 ParentCid: 05c4
DirBase: 11edc000 ObjectTable: e15ae880 HandleCount: 18.
Image: MessageBoxA_PDE_PTE.exe
然后查看 EPROCESS 结构:
kd> dt _EPROCESS 81ecbd50
ntdll!_EPROCESS
...
+0x11c VadRoot : 0x81e8e8d8 Void
+0x120 VadHint : 0x81e8e8d8 Void
+0x124 CloneRoot : (null)
+0x128 NumberOfPrivatePages : 0x4a
+0x12c NumberOfLockedPages : 0
+0x130 Win32Process : 0xe1ad8608 Void
+0x134 Job : (null)
...
然后 !vad 打印:
kd> !vad 0x81e8e8d8
VAD level start end commit
81d440b0 ( 1) 10 10 1 Private READWRITE
81e2cb70 ( 2) 20 20 1 Private READWRITE
81e8e8d8 ( 0) 30 12f 6 Private READWRITE
81d12318 ( 3) 130 132 0 Mapped READONLY Pagefile-backed section
81e552c8 ( 2) 140 140 0 Mapped READONLY Pagefile-backed section
81e25c60 ( 4) 150 24f 9 Private READWRITE
81d71d60 ( 3) 250 25f 6 Private READWRITE
81dead50 ( 5) 260 26f 0 Mapped READWRITE Pagefile-backed section
81f12898 ( 4) 270 285 0 Mapped READONLY \WINDOWS\system32\unicode.nls
81e3f2d8 ( 6) 290 2d0 0 Mapped READONLY \WINDOWS\system32\locale.nls
81d5e648 ( 5) 2e0 320 0 Mapped READONLY \WINDOWS\system32\sortkey.nls
81ec9320 ( 7) 330 335 0 Mapped READONLY \WINDOWS\system32\sorttbls.nls
81d707f0 ( 6) 340 380 0 Mapped READONLY Pagefile-backed section
81e929c0 ( 7) 3d0 3df 8 Private READWRITE
81e90970 ( 8) 3e0 3e0 1 Private READWRITE
81b47688 ( 9) 3f0 3f0 1 Private READWRITE
81b29358 ( 1) 400 41a 18 Mapped Exe EXECUTE_WRITECOPY \;F:\VBoxSvr\Projects\MessageBoxA_PDE_PTE\Debug\MessageBoxA_PDE_PTE.exe
81d400a8 ( 6) 420 4e7 0 Mapped EXECUTE_READ Pagefile-backed section
81b0f3a0 ( 7) 4f0 5f2 0 Mapped READONLY Pagefile-backed section
81d5ed80 ( 8) 600 8ff 0 Mapped EXECUTE_READ Pagefile-backed section
81e918b0 ( 9) 900 90f 8 Private READWRITE
81d40110 (10) 910 912 0 Mapped READONLY \WINDOWS\system32\ctype.nls
81d18980 (11) 920 92d 0 Mapped READWRITE Pagefile-backed section
81fc0768 (12) 930 930 1 Private READWRITE
81d4b238 ( 5) 10200 10371 7 Mapped Exe EXECUTE_WRITECOPY \;F:\VBoxSvr\Projects\MessageBoxA_PDE_PTE\Debug\MSVCR100D.dll
81aee750 ( 7) 62c20 62c28 1 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\lpk.dll
81e55128 ( 8) 73fa0 7400a 16 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\usp10.dll
81d8fd30 ( 6) 76300 7631c 1 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\imm32.dll
81d55d00 ( 7) 76d70 76d91 1 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\apphelp.dll
81d57998 ( 8) 77bd0 77bd7 1 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\version.dll
81d19630 ( 4) 77d10 77d9f 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\user32.dll
81d90128 ( 6) 77da0 77e48 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\advapi32.dll
81ea8c48 ( 7) 77e50 77ee1 1 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\rpcrt4.dll
81d5e618 ( 5) 77ef0 77f38 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\gdi32.dll
81d40178 ( 6) 77fc0 77fd0 1 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\secur32.dll
81da9d10 ( 3) 7c800 7c91d 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\kernel32.dll
81d5bca0 ( 2) 7c920 7c9b2 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ntdll.dll
81dc4f70 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
81b2f1d8 ( 3) 7ffa0 7ffd2 0 Mapped READONLY Pagefile-backed section
81d13f88 ( 5) 7ffdd 7ffdd 1 Private READWRITE
81f5c498 ( 4) 7ffde 7ffde 1 Private READWRITE
Total VADs: 41 average level: 6 maximum depth: 12
三、如何绕过写拷贝
提供两种思路:
1、另外申请一个线性地址,映射到MessageBoxA的物理页,设置PTE的R/W属性,使其可读写。
2、修改 VAD 树,将写拷贝改为可读可写。
---------------------
作者:hambaga
来源:优快云
原文:https://blog.youkuaiyun.com/Kwansy/article/details/109232856
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:优快云,CNBLOG博客文章一键转载插件