我也不知道取個什么名字合適,主要是給那些準(zhǔn)備調(diào)試內(nèi)核人的參考資料
============= 編程環(huán)境 =====================
VS2008+DDK+VA+DDKWIZARD
1、安裝 VS2008,MSDN
2、安裝 DDK
3、安裝 ddkwizard_setup
4、安裝 Visual Assist X
5、-> 錯誤 1 => 找到 ddkbuild.bat、ddkbuild.cmd(下載)放入 /windows/system32 目錄下
6、-> 錯誤 2 => 計算機/.../環(huán)境變量 ,添加兩個系統(tǒng)變量
1、 W7BASE = D:\WinDDK\7600.16385.1
2、WXPBASE = D:\WinDDK\7600.16385.1
7、-> 錯誤 3 => VS2008/Tools/Options/Projects and Solutions/VC++ Directories
Win32/Include files =>
添加 D:\WinDDK\7600.16385.1\inc\api 到末尾,否則編譯普通win32應(yīng)用程序會提示錯誤
添加 D:\WinDDK\7600.16385.1\inc\ddk 到末尾
Other:如果安裝順序有錯,導(dǎo)致VA無法支持DDK,則將 api、ddk 添加到 VA 的 /Options/Projects/C/C++ Directories
=> custom/Stable include files ,一樣,添加到末尾
= done =
1 : error PRJ0019: A tool returned an error code from "erforming Makefile project actions"
=>'ddkbuild.cmd' 不是內(nèi)部或外部命令,也不是可運行的程序
2 :1>DDKBLD: ERROR #3: To build using type W7 you need to set the %W7BASE% environment variable to point to the Windows 7/Windows 2008 Server R2 DDK base directory!
3 :VS2008 中 UNICODE_STRING 按 F12 無法追蹤
============= 雙機調(diào)試 =======================
Windbg+VMware
1、安裝VMware
2、安裝Windbg(DDK里面有這個東西)
3、安裝IDA
4、VMware 設(shè)置(裝有 xp 和 win7 兩個系統(tǒng))
xp版:
在 c:\boot.ini 文件中添加 debug 的啟動項
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional - debug" /fastdetect /debug /debugport=com1 /baudrate=115200
win7版:
在 msconfig 中添加debug 啟動項
msconfig -> 高級選項 -> 調(diào)試,調(diào)試端口 COM1,波特率 115200
在VMware 上修改兩個系統(tǒng)的串口設(shè)置:
打開電源時連接
此終端是服務(wù)器
另一終端是一個應(yīng)用程序
i/o 模式 輪詢時主動放棄CPU占用
xp:使用命名管道 \\.\pipe\com_1
win7:使用命名管道 \\.\pipe\com_2
5、Windbg 設(shè)置
符號路徑,xp 與 win7 的符號都可以放在同一個目錄下,沒有的話,windbg 會自動將文件下載到 E:\sysbols
建立兩個windbg 快捷方式的設(shè)置,修改其中參數(shù),分別連接兩個虛擬機
xp:
D:\tools\windbg\windbg.exe -b -k com:port=\\.\pipe\com_1,baud=115200,pipe
win7版:
D:\tools\windbg\windbg.exe -b -k com:port=\\.\pipe\com_2,baud=115200,pipe
6、在 windbg 下 dump 兩個系統(tǒng)
將整個win7系統(tǒng)內(nèi)存dump下來( Full kernel dump),耗費了我40多個小時...其中一次機器休眠了...
(Creating a full kernel dump over the COM port is a VERY VERY slow operation.)有除COM外其他的連接方式,但我不會。。
.dump /f e:\win7_dump.dmp
============= 驅(qū)動加載工具 ====================
后面附一個源碼,喜歡的可以下
============= 準(zhǔn)備工作完成 ====================
至此,我們有了一個能隨時能增加功能的驅(qū)動加載工具,一份 win7 dump 文件,雙機調(diào)試,編程環(huán)境。
============= 從零開始分析驅(qū)動層的反調(diào)試 =========
在這以前,只有應(yīng)用層的逆向經(jīng)驗。沒接觸過驅(qū)動,也不知道反調(diào)試。
下面是我過某個游戲驅(qū)動保護的過程,這個過程從11月14號左右開始,到12月1號結(jié)束。
游戲一開始給人的表象有:[blockquote]1、游戲進程、守護進程、驅(qū)動
2、OllyICE 附加列表中無法看到目標(biāo)進程,任務(wù)管理欄則可正常顯示目標(biāo)進程名稱。
3、Windows7:去除兩個內(nèi)核鉤子Hook后,OD可看到目標(biāo)進程,但是附加時提示附加失??!(用xuetr 看的到內(nèi)核鉤子)
4、Windows XP:去掉兩個內(nèi)核鉤子,游戲直接退出。
5、采用虛擬機VMware+Windbg 調(diào)試,游戲進程 啟動時報錯!
6、VMware+Windows 7 [Debug]:游戲啟動后Windows 7系統(tǒng)無響應(yīng),只能重新啟動系統(tǒng)。
7、VMware+Windows 7:游戲可正常啟動。
8、OD加載游戲主程,OD崩潰,模塊時發(fā)生錯誤,錯誤代碼:0xc0000005(最后發(fā)現(xiàn)是PE結(jié)構(gòu)中一個模塊名字超長導(dǎo)致,我的OD很老了)
9、OD正常加載游戲主程之后,有被檢測到的信息,多次嘗試找信息出處,無果
[/blockquote]
以上是11月17日之前的各種嘗試,也是最痛苦的時候——完全找不到任何方向。之后調(diào)整了思考方向,把重心放到第5、6、7條線索上。以下是當(dāng)時調(diào)試日志的主要部分,有點小修改。
2010/11/17 對**的調(diào)試終于有點突破^_^
之前一直不清楚**是如何區(qū)分系統(tǒng)處于Debug還是正常狀態(tài)。經(jīng)過對Windows的異常分發(fā)機制,了解了Debug與正常狀態(tài)的流程不同,主要是KdpTrap與KdpStub兩個函數(shù)對應(yīng)于不同的系統(tǒng)。
至此,與雙機調(diào)試有關(guān)的地方有4處:KdpDebugRoutine(函數(shù)指針)、KdpBootedNodbug(bool)、KdPitchDebugger(bool)、DebuggerEnabled(bool)。
通過修改KdpDebugRoutine 指向 KdpStub ,以及另外3個標(biāo)志位,可將系統(tǒng)從Debug修改為正常狀態(tài),Windbg將處于等待狀態(tài)。**可正常執(zhí)行,待**加載完畢后,將上述4個值修改回來,Windbg可重新獲取話語權(quán)!
******
因此,我將要做另外一個任務(wù),一個驅(qū)動程序,可以讓系統(tǒng)在Debug與正常狀態(tài)相互切換!這樣,我就可以在游戲運行期間,隨時進行調(diào)試。如果有可能,最好讓驅(qū)動隨時與OD進行通訊。
2010/11/18 完成驅(qū)動加載工具
完成一個通用的驅(qū)動加載工具,測試,可將Debug系統(tǒng)在 Debug 與 正常狀態(tài)間隨意切換。但是對于正常系統(tǒng),卻無法切換成Debug。下一步要做的,就是將正常系統(tǒng)也能隨意切換!
(這個到現(xiàn)在也沒開始做...)
2010/11/19[blockquote]1、經(jīng)過測試,被轉(zhuǎn)換后的系統(tǒng)可以進行雙機調(diào)試,下斷 ws2_32!send 失敗。
2、使用XueTr恢復(fù)兩個內(nèi)核鉤子后,OD能夠看到 ** 進程,附加失敗
3、針對附加失敗,使用雙機調(diào)試查看原因!關(guān)鍵函數(shù) kernel32!DebugActiveProcess。
[/blockquote] 流程 kernel32!DebugActiveProcess -> ntdll!ZwDebugActiveProcess -> 功能號0x60 -> KeServiceDescriptorTable[0][0x60*4] -> nt!NtDebugActiveProcess
上述步驟能夠成功運行
失敗存在于 ntdll!NtCreateThreadEx -> nt!NtCreateThreadEx:
經(jīng)過跟蹤發(fā)現(xiàn),最終問題在上述線路中的 nt_RtlImageNtHeaderEx+0x45處,由于對象 ** 進程的PE頭被抹去,導(dǎo)致此函數(shù)判斷時,返回了一個失敗值!
進一步的,在不恢復(fù)內(nèi)核鉤子的情況下,** 的 Pe頭不被改寫,一旦恢復(fù)之后,**的某個線程會將此PE頭抹去,導(dǎo)致OD無法附加
(有 win7 dump ,結(jié)合 ida 感覺真是好)
2010/11/??
** 在對比黑白名單后,判斷是否放行目標(biāo)進程。
通過修改黑白名單的內(nèi)容,OD 可以順利附加,但是無法讀出 ** 的模塊信息!
(不知道具體日期了,主要是從 xuetr 上看到的2個內(nèi)核鉤子入手 nt!NtReadVirtualMemory,nt!NtWriteVirtualMemory,這期間,通過這條線索搞定了它的白名單)
2010/11/22
制作完相關(guān)工具后,經(jīng)測試,OD 能夠看見目標(biāo)進程,附加,但附加之后便發(fā)生錯誤,無法看到對象的模塊信息。應(yīng)該是目標(biāo)進程在不斷的對 debugport 進行清零操作,目前發(fā)現(xiàn)有
多個線程有此動作,其中有一個是在不斷新建線程,新的線程就是不斷對 debugport 做檢查。如果繞過 debugport 檢查?
(這里可能會有些不準(zhǔn)確,但確定是的某個線程在對 debugport 清零,查看了不少帖子,最后線索來自看雪)
2010/11/23 ** 對 debugport 清零的動作
Windbg 對debugport 下寫斷點[blockquote]kd> u **+0x41764
**+0x41764:
9b2fb764 8702 xchg eax,dword ptr [edx] //清零操作
9b2fb766 6685e9 test cx,bp
9b2fb769 660fbae501 bt bp,1
9b2fb76e 8b36 mov esi,dword ptr [esi]
9b2fb770 83ecdc sub esp,0FFFFFFDCh
9b2fb773 0f886545ffff js **+0x35cde (9b2efcde)
9b2fb779 f5 cmc
9b2fb77a 3bf1 cmp esi,ecx
[/blockquote]
手動修改 edx 值,發(fā)現(xiàn) od 附加后可正常存活。但是如果暫停該線程,則會導(dǎo)致od 附加后,很快游戲自動退出!
使用工具對**驅(qū)動代碼部分做修改(debugport清零),在多次測試中,很少的情況可以一直附加,但實體機狀態(tài)下,OD很快就被檢測到。在程序自退出時,有彈出守護進程被異常終止的對話框。程序自退出時,會有一個單獨線程,凍結(jié)此線程,OD 會存活的比較久。
(到現(xiàn)在為止,還不能對游戲下斷點)
2010/11/25
OD 對游戲下斷,游戲會異常退出,0x80000003
2010/11/29
了解線程的HidePort后,制作工具可以下斷點,但是OD 還會被檢測到。主要的問題在于線程0x00cc0654中調(diào)用了RtlExitUserProcess 函數(shù)(該函數(shù)又調(diào)用了ZwTerminateProcess)。
該線程會不停的創(chuàng)建,但未經(jīng)過CreateThread API(功能號為 0x58)。
現(xiàn)在的問題是,創(chuàng)建該線程是否傳遞了參數(shù)進來?如果未有參數(shù)傳遞,是否該線程檢測到OD運行?!
補充:由于游戲主線程的HidePort被設(shè)置為1,導(dǎo)致內(nèi)核將該線程上的異常屏蔽,不分發(fā)給用戶層。因此OD修改的代碼 int3 會引發(fā)一個異常,導(dǎo)致主線程退出。
2010/11/30
在 nt!NtCreatethreadEx 下斷,沒有相關(guān)創(chuàng)建 0x00cc0654 線程的調(diào)用!因此,還是無法知道程序中哪里創(chuàng)建了線程 0x00cc0654 。比較奇怪的是,該線程應(yīng)該是不斷的被創(chuàng)建的、且線程 ID 總是相同,但是 retn 之后,該線程便不再被創(chuàng)建。。(之所以這么說,是因為在該線程的入口點,總是能斷下)
2010/12/01
基本實現(xiàn) OD 的附加調(diào)試,但是 0x00cc0654 線程是從哪里來的,如何被創(chuàng)建,如何檢查OD? (一直未解決,太多的代碼變異)
總結(jié):
大部分的反調(diào)試還是在驅(qū)動層面,并且是已知的幾個技術(shù)點
1、 反Debug系統(tǒng) debug 系統(tǒng)與 正常版本切換
2、 DebugPort 清零 nop 掉相關(guān)代碼段
3、 主線程 HidePort 置 1 重置 HidePort
4、 內(nèi)核函數(shù)鉤子,采用白名單方式放行。 找到白名單,手動添加
5、 0x00cc0654 線程檢測 直接將線程入口修改為 retn
我想很多在內(nèi)核之外的人,跟我一樣在門外徘徊,其實,只要做,并沒有那么難。 |