WDK7600自帶的toaster驅動是個很好的學習驅動的案例,從總線驅動到App層,Class-install/Co-install都有涉及。本文主要涉及驅動部署和調試。
1.先說說調試的準備工作。一般調試驅動都是在虛拟機中進行的,這裡也不例外,用windbg+vmware輕按兩下聯調。通常開發階段,Wdm驅動以inf形式安裝并加載,加載後依次執行DriverEntry,AddDevice并響應IRP_MJ_PNP&IRP_MN_START事件。安裝的同時,pnp管理器會複制檔案及改寫系統資料庫,待下次重新開機,驅動在系統重新開機階段會加載運作驅動。是以,在DriverEntry時加入斷點尤為重要,要不然将錯過這些函數的調試時機。在x86時代,加入口斷點無非是代碼中插入 asm int 3.但是,這麼美好的時代已經過去了,x64驅動不支援嵌入彙編。取而代之,必須通過編寫一個asm檔案,在源碼中以調用外部函數的形式,共5步來實作。
1.1第一步實作int 3的彙編代碼形如:
.code
asm_int3 proc
int 3
ret
asm_int3 endp
end
1.2将這段代碼儲存為softbp.asm。然後用wdk自帶的ml64編譯,注意僅編譯生成obj檔案:
ml64 /c softbp.asm
1.3接着是在C檔案中調用這個函數,如在wdm/bus/busenum.c的DriverEntry處加入斷點
extern void asm_int3(); //<-------------外部函數聲明
NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Initialize the driver dispatch table.
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path,
to driver-specific key in the registry.
Return Value:
NT Status Code
--*/
{
asm_int3(); //<--------------外部函數調用
Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Driver Entry \n"));
//
// Save the RegistryPath for WMI.
1.4修改sources檔案,添加對softbp.obj的連結:
原本sources檔案中TARGETLIBS的值為
TARGETLIBS= $(DDK_LIB_PATH)\wdmsec.lib \
$(DDK_LIB_PATH)\ntstrsafe.lib
修改為:
TARGETLIBS= $(DDK_LIB_PATH)\wdmsec.lib \
$(DDK_LIB_PATH)\ntstrsafe.lib \
softbp.obj
1.5運作build -ceZ編譯連結整個toaster工程。
2.得到驅動檔案後就是部署階段。win7 x64的部署也是夠磨人的:bcdedit增加啟動項(再次懷念xp的好,修改boot.ini就夠了),禁用驅動簽名,最後安裝驅動。以下的步驟都在虛拟機中進行
2.1增加啟動項:
2.1.1 以administrator權限下進入cmd,運作bcdedit指令設定端口COM1為調試端口, baudrate為115200(我已将虛拟機的列印機移除,列印機可恥的占用着COM1,并将序列槽的名字改為COM1)
bcdedit /dbgsettings serial baudrate:115200 debugport:1
2.1.2 複制一個開機選項, 以進入OS的debug模式
bcdedit /copy {current} /d DebugEnty
2.1.3 接着增加一個新的選項到引導菜單
bcdedit /displayorder {current} {6426f429-17fc-11e6-bf64-ad656b9740aa}
{6426f429-17fc-11e6-bf64-ad656b9740aa}是2.1.2運作結束後生成的id值
2.1.4 激活前面生成的debug項
bcdedit /debug {6426f429-17fc-11e6-bf64-ad656b9740aa} on
最後上一張效果圖,然後重新開機機器準備調試:
3.windbg連結。
開始序列槽連接配接前,要設定調試符号和windbg啟動參數,我直接寫了個腳本setenv.bat完成這兩步,以後輕按兩下運作即可:
;set _NT_SYMBOL_PATH=SRV*C:\sym;用于設定調試符号的路徑
set _NT_SYMBOL_PATH=SRV*C:\sym;
;我的winbdg裝在下列位置,後面的參數是序列槽調試參數
"D:\WinDDK\7600.16385.1\Debuggers\windbg.exe" -b -k com:pipe,port=\\.\pipe\com_1,baud=115200,pipe
系統重新開機後輕按兩下setenv.bat,在虛拟機中選擇DebugEntry 按F8進入進階啟動項,然後選擇Disable Driver Signature Enforcement
(注,在等待虛拟機啟動期間,經常出現windbg閃退,這時再輕按兩下setenv.bat即可。)
4.部署toaster
進入win7後,在控制台中沒有硬體向導的一席之地!需要通過在開始菜單-運作中輸入hdwwiz.exe來打開。真是何其不易。ms出于安全目的,希望我們通過driver store安裝受信得驅動,倒給開發驅動的找了一堆破事。安裝toaster的步驟不再叙述,參照wdk中xp下安裝方式在hdwwiz.exe中設定即可。
安裝的末尾,也就是進入DriverEntry,由于我們在代碼中設定了int3斷點,是以windbg會獲得執行權。這時可以追加并驗證toaster的調試符号,因為此時驅動已經加載到記憶體中,是以設定斷點不會報類似code not set之類的錯誤,而且符号也能正确加載。
追加toaster調試符号
kd> .sympath+ C:\toaster\wdm\bus\objchk_win7_amd64\amd64
Symbol search path is: SRV*C:\sym;C:\toaster\wdm\bus\objchk_win7_amd64\amd64
檢驗符号是否加載
kd> lm m busenum*
start end module name
fffff880`0392e000 fffff880`0393e000 busenum (private pdb symbols) c:\toaster\wdm\bus\objchk_win7_amd64\amd64\BusEnum.pdb
驗證符号是否和sys版本一緻
kd> !itoldyouso busenum c:\toaster\wdm\bus\objchk_win7_amd64\amd64\busenum.sys
busenum.sys
Timestamp: 57333596
SizeOfImage: 10000
pdb: c:\toaster\wdm\bus\objchk_win7_amd64\amd64\BusEnum.pdb
pdb sig: A8748D1B-8C93-4855-BBC7-4D773CADC3B0
age: 1
Loaded pdb is c:\toaster\wdm\bus\objchk_win7_amd64\amd64\BusEnum.pdb
BusEnum.pdb
pdb sig: A8748D1B-8C93-4855-BBC7-4D773CADC3B0
age: 1
MATCH: BusEnum.pdb and busenum.sys
驗證目前執行的位置是不是在busenum中
kd> ln $ip
(fffff880`039301a0) busenum!asm_int3 | (fffff880`039301c0) busenum!__security_check_cookie
Exact matches:
待一切驗證完畢,就可以在AddDevice 等函數入口下斷點。等下次系統在啟動階段時,會在這些斷點處停下。
如果想多次進入DriverEntry/AddDevice函數,可以在裝置管理器中找到toaster裝置,然後右鍵disable/enable裝置,就能多次進入這些函數