我本來想在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映射的頁了,這些頁也沒了寫時複製特性,再改也沒用。如果其它節也有這種情況,也肯定被改過了!
未完待續~~~~