之二:Win7-x64 + VMWare (Win7-x64) + WinDbg 雙機除錯環境搭建
驅動開發入門 - 之二
Win7-x64 + VMWare (Win7-x64) + WinDbg
雙機除錯環境搭建
Win7-x64 + VMWare (Win7-x64) + WinDbg
雙機除錯環境搭建
完整原文下載(轉載請註明出處,僅供分享學習,嚴禁用於商業用途)
1. 概述
1.1. 前言
為方便起見,在下文中使用【HostOS】指代【物理機/宿主機/除錯機】,用【GuestOS】指代【虛擬機器/客戶機/被除錯機】。
WinDbg是一款雙機除錯工具,它安裝在HostOS上,HostOS與GuestOS通過串列埠相連線,使用時需要在HostOS用WinDbg除錯GuestOS上執行的核心程式。
由於使用兩臺物理機做雙機除錯的成本較高、可操作性較低,因此本文雙機除錯的環境是基於物理機(HostOS)與VMWare虛擬機器(GuestOS)搭建的
之所以使用虛擬機器搭建雙機除錯環境,主要出於以下幾個方面考慮:
① 驅動程式執行在系統核心,在調測時需要把作業系統設定到測試模式,極大降低安全性。
② 經驗不足的情況下編寫核心程式很容易導致系統藍屏,在HostOS除錯風險過大。
③ HostOS無法除錯自己。到VS2010為止的IDE均不支援驅動程式的除錯功能,只能在作業系統中載入驅動時除錯,而載入驅動程式的作業系統是無法除錯自身的(遇到INT3中斷的時候整個系統會進入假死狀態),因此需要藉助GuestOS。
1.2. 名詞解析
名詞 | 英文原文 | 解析 |
---|---|---|
HostOS | Host Operating System | 物理機/宿主機/除錯機 |
GuestOS | Guest Operating System | 虛擬機器/客戶機/被除錯機 |
COM | Cluster Communication Port | 序列通訊埠 |
KD | Kernel Debug | 核心除錯 |
1.3 WinDbg簡介
在安裝微軟Windows除錯工具集後,可以在安裝目錄下發現四個偵錯程式程式,分別是:cdb、ntsd、kd和WinDbg。
其中cdb和ntsd只能除錯使用者程式,kd主要用於核心除錯(有時候也用於使用者態除錯)。這三者的一個共同特點是都只有控制檯介面,以命令列形式工作。
而WinDbg在使用者態、核心態下都能夠發揮除錯功能,特別地,它採用了視覺化的使用者介面。所以絕大部分情況下,我們在談及Windows除錯工具時都直接指向WinDbg,而不談及其他三者。
WinDbg支援原始碼級的除錯(類似於VC自帶的偵錯程式),而且在使用者態和核心態下,都支援兩種除錯模式,即“實時除錯模式(Living)”和“事後除錯模式(Postmortem)”。
實時除錯模式(Living):是被除錯的目標物件(Target)當前正在運行當中,偵錯程式可以實時分析、修改被除錯目標的狀態,如暫存器、記憶體、變數,除錯exe可執行程式或雙機實時除錯都屬於這種模式。
事後除錯模式(Postmortem):是被除錯的目標物件(Target)已經結束了,現在只是事後對它保留的快照進行分析,這個快照稱為轉儲檔案(Dump檔案)。
2. 作業系統與預裝元件
① HostOS系統版本: Win7 SP1 x64 (必須升級到SP1版本)
② GuestOS系統版本: Win7 SP1 x64 (必須升級到SP1版本)
③ 在HostOS安裝VS2010驅動開發環境的相關元件(詳見《驅動開發入門 - 之一》,此處不再複述),之所以選擇VS2010環境,是因為VS2008在x64環境下的混合彙編能力較弱,不便於後續的開發除錯工作。
3. 相關工具安裝
目標機器 | 工具 | 版本 | 用途 | 備註 | 下載 |
---|---|---|---|---|---|
HostOS | VS2010驅動開發 環境的相關元件 |
||||
HostOS | VMWare | 11.1.2 | 安裝GuestOS 的虛擬機器 |
用於搭建隔離環境 除錯驅動程式 |
|
HostOS | WinDbg | 6.11 | Windows平臺下的 驅動程式除錯工具 |
用於配合GuestOS 雙機除錯驅動程式 |
官方地址 CSDN |
HostOS | windbg-雙機除錯.bat | 6.11 | 使得windbg連線到GuestOS的啟動指令碼 | 配合WinDbg使用, 已固化啟動引數 |
CSDN |
HostOS | Win7符號檔案 | Win7 SP1 x64 | WinDbg除錯程式碼用 | 相當於Win系統核心程式的原始碼檔案 | 官方地址 |
GuestOS | 開啟Windows測試環境.bat 關閉Windows測試環境.bat |
調測環境變更指令碼 | 把作業系統永久切換到測試模式並關閉驅動簽名校驗 | CSDN | |
GuestOS | DriverMonitor | 3.2.0 | 驅動程式裝載器 | XP x86用於安裝、啟動核心程式的除錯工具,Win7 x64可能不相容 | CSDN |
GuestOS | InstDrv | 1.3.0 | 驅動程式裝載器 | Win7用於安裝、啟動核心程式的除錯工具 | CSDN |
GuestOS | DebugView | 4.81 | 核心驅動訊息捕獲器 | 配合DriverMonitor或InstDrv使用,用於捕獲核心程式的DbgPrint / KdPrint語句所列印訊息 | CSDN |
HostOS GuestOS |
VirtualKD | 3.0 | 核心除錯加速器 | 配合WinDbg使用,提高HostOS與GuestOS傳輸速率 | 官方地址 |
3. 安裝VMware虛擬機器及GuestOS
由於VMWare11之後的虛擬機器和系統安裝都比較簡單,此處就不詳述了,僅說明一下步驟:
① 在HostOS安裝VMWare虛擬機器
② 在虛擬機器安裝Win7 x64 SP1作業系統(GuestOS)
③ 為了便於HostOS與GuestOS的檔案互動,安裝VMWare Tools(VMWare 已自帶:【選單】 –> 【虛擬機器】 –> 【安裝VMWare Tools】)
④ 在GuestOS中執行【開啟Windows測試環境.bat】指令碼使GuestOS關閉驅動簽名校驗,並進入測試模式
⑤ 在GuestOS中安裝 DriverMonitor / InstDrv 和 DebugView
注:
若第 ④ 步的指令碼下載地址已失效,可手動在GuestOS的DOS控制檯輸入以下命令:
【開啟Windows測試環境.bat】指令碼主要是兩個指令:
bcdedit -set loadoptions DDISABLE_INTEGRITY_CHECKS // 關閉驅動數字簽名校驗
bcdedit /set testsigning on // 開啟系統測試模式
【關閉Windows測試環境.bat】指令碼是配套的兩個還原指令:
bcdedit -set loadoptions DENABLE_INTEGRITY_CHECKS // 啟動驅動數字簽名校驗
bcdedit /set testsigning off // 關閉系統測試模式
5. 配置VMWare的虛擬管道串列埠
當雙機都是物理機時,HostOS與GuestOS是用物理串列埠連線的。
但是在GuestOS是虛擬機器的情況下,就不可能使用物理串列埠了,此時需要在GuestOS上設定一個用虛擬的管道串列埠,步驟如下:
① 在虛擬機器關機狀態下,選擇【編輯虛擬機器設定】,如圖 1。
② 在【硬體】選項卡【移除印表機】,如圖 2。
這是因為印表機預設佔用了串列埠COM_1,為了使得下文的配置無需修改,這裡建議刪除印表機(不刪除印表機也可以,但後面的配置請自行修改為COM_2作為管道串列埠命名)
③ 新增一個串列埠:【新增】 –> 【串列埠】 –> 【下一步】 –> 【輸出到命名管道】 –> 【下一步】,如圖 3和圖 4。
④ 如圖 5設定如下值,點選【完成】按鈕。
命名管道:\.\pipe\com_1 (會自動填上編號最小的可用串列埠)
【該端是伺服器。】
【另一端是應用程式。】
【勾上】啟動時連線。
⑤ 最後回到如圖 6所示的介面,選中剛才新建的【串列埠】,在I/O模式【勾選】輪詢時主動放棄 CPU(Y),點選【確定】即可。
6. 在GuestOS增設除錯模式的作業系統
首先區分GuestOS中作業系統的幾種模式:
>> 正常模式:初裝作業系統時的預設狀態
>> 測試模式:利用bcdedit命令開啟系統的TestSigning開關,使系統處於可以裝載未認證驅動程式的狀態(若已按上文所述操作,當前的GuestOS已處於此狀態)
>> 除錯模式:利用bcdedit命令開啟系統的debug和bootdebug 開關,使系統上執行的程式處於可以被另一個系統除錯的狀態
本節的最終目標就是在 [測試模式] 的基礎上再增加 [除錯模式],更具體地描述,就是在開機的作業系統列表中新增一個被標識為【啟用除錯程式】的作業系統,如圖 7所示(其中“Win-7雙擊除錯模式”是自定義的系統名稱,“啟用除錯程式”表示該系統處於除錯模式)
在XP時代,通過修改C:\boot.ini配置檔案可以實現此目的。但Win7系統已經沒有這個檔案了,需要通過bcdedit命令進行配置。
詳細的配置方式如下:
① 虛擬機器開機後,正常登陸到Win7系統桌面(若已按照上文配置,當前所登陸到的Win7系統正處於【測試模式】,可以通過桌面右下角的水印驗證,如圖 8所示。某些系統會遮蔽這個水印,此時可以通過命令【bcdedit /enum】確認testsigning的值是否為Yes以判斷系統當前是否處於測試模式)。
② 如圖 9和圖 10所示,以管理員身份執行DOS控制檯在控制檯中依次輸入以下命令:
bcdedit /copy {current} /d “Win7-雙機除錯模式” // 這是系統副本的名字,任意即可
bcdedit /timeout 10
這兩條命令的作用是把當前所登陸的作業系統,複製一份副本,命名為【Win7-雙機除錯模式】。新的系統會出現在開機時的作業系統列表中,該列表的呈現時間為10秒。
③ 重啟GuestOS,此時可以看到在作業系統列表中多出第一項【Win7-雙機除錯模式】,這就是剛才複製的系統副本。選擇這個系統登陸到桌面。
④ 以管理員身份執行DOS控制檯,在控制檯中依次輸入以下命令使得系統進入除錯模式:
bcdedit /debug ON
bcdedit /bootdebug ON
再輸入以下命令可檢視作業系統在除錯模式下使用的串列埠配置:
bcdedit /dbgsettings
如圖 12所示為除錯模式的配置引數,其中【debugtype=Serial】表示使用串列埠做除錯,【debugport=1】表示串列埠埠為COM_1,【baudrate=115200】為波特率,表示HostOS與GuestOS通過此虛擬串列埠交換資料的傳輸速率(約等效於10KB/s,暫時保持預設值即可)。
這裡需要注意的是,若上文小節【5 配置VMWare的虛擬的管道串列埠】中所配置的串列埠不是COM_1,這裡可以使用以下命令 修改串列埠號等 除錯模式的引數:
bcdedit /dbgsettings serial debugport:1 baudrate:115200
⑤ 到此就已經成功添加了一個除錯模式的作業系統了,重啟後可在系列列表中看見【Win-7雙擊除錯模式 [啟用除錯程式]】(如圖 13),這個就是之後要用來除錯驅動用的系統。
⑥ 為了便於之後開機後都處於除錯模式,可以通過右鍵【計算機】 –> 【屬性】 –> 【高階系統設定】 –> 【高階】 –> 【啟動和故障恢復】 –> 【設定】 修改預設的作業系統、以及作業系統列表的顯示時間,如圖 14所示:
7. WinDbg的安裝與配置
只有HostOS需要安裝WinDbg,步驟如下:
① 安裝dbg_x86_6.11.1.404.msi到HostOS任意位置
② 複製windbg_cn.exe到安裝目錄(此為漢化介面入口)
③ 複製 [windbg_cn-雙機除錯.bat] 和 [windbg-雙機除錯.bat] 指令碼到安裝目錄(這兩個指令碼功能相同,區別只是一個漢化版、一個英文版)
④ 根據上文設定的虛擬管道串列埠,右鍵編輯bat指令碼的啟動引數(若使用COM_1串列埠則無需修改):
start “” windbg_cn.exe -b -k com:pipe,port=\.\pipe\com_1,baud=115200,reconnect -y // 中文指令碼
start “” windbg.exe -b -k com:pipe,port=\.\pipe\com_1,baud=115200,reconnect -y // 英文指令碼
8. 驗證WinDbg配置(連線GuestOS)
① 啟動虛擬機器,進入【win7-雙機除錯模式 [啟動除錯程式]】系統(注:除錯模式的系統在啟動過程有兩個系統斷點,若不通過WinDbg跳過斷點,系統會陷入中斷狀態無法進入桌面)。
② 執行 [windbg_cn-雙機除錯.bat] 指令碼,若指令碼配置的啟動引數與GuestOS設定的虛擬管道串列埠引數一致,則可以明顯看到宿主系統和虛擬系統連線成功的提示,如圖 15。
③ 在系統啟動過程中,會出現多次【int 3】系統中斷,需要在WinDbg的【kd>】中輸入命令【g】以跳過中斷,直到登陸到桌面。
④ 成功進入桌面後,就可以開始使用WinDbg做雙機除錯。
9. 雙機除錯
9.1. 什麼是符號檔案
類似於在C/Java的IDE中除錯原始碼,WinDbg在除錯驅動程式時也需要用到原始碼,在Windows中把這種原始碼稱之為符號檔案(Symbol Files)。
符號檔案是一個數據信息檔案,以*.pdb副檔名標識。它包含了應用程式二進位制檔案(如*.sys、*.dll、*.exe)的除錯資訊(如程式中所有變數資訊),專用於除錯。符號檔案與二進位制檔案的編譯版本密切,當二進位制檔案被重新編譯時,上次編譯所產生的pdb檔案就過時了,不能再用於除錯工作。
用 Visual C++ 和 WinDbg 除錯程式時都要用到符號檔案,但最終生成的可執行檔案在執行時並不需要符號檔案。
例如每個 Windows 作業系統下有一個 GDI32.dll 檔案,編譯器在編譯該 DLL 的時候會產生一個 GDI32.pdb 檔案。一旦我們擁有了這個GDI32.pdb檔案,那麼便可以用它來除錯並跟蹤到 GDI32.dll 內部。
9.2. 符號檔案路徑設定
WinDbg是支援在除錯時自動線上下載對應符號檔案的。但是符號檔案內容也不少(某些符號檔案線上下載需要幾分鐘,不便於除錯),建議把離線安裝包下載到本地先預安裝。
這個是微軟提供的各個Windows版本的符號路徑下載的站點:
以本文所採用的作業系統版本為例,選擇【Windows 7 Service Pack 1 x64 retail symbols, all languages】下載,如圖 16:
下載成功後,將其安裝到HostOS的任意位置即可。
本文所選擇的符號檔案安裝目錄為:E:\04_work\re\Symbol
安裝成功後,配置環境變數:
① 右擊【計算機】–>【屬性】–>【高階系統設定】–>【高階選項卡】–>【環境變數】
② 在【系統變數】中新建四個變數:
變數名 | 變數值 | 備註 |
---|---|---|
_NT_SYMBOL_DIR | E:\04_work\re\Symbol | 符號檔案安裝目錄 |
_NT_SYMBOL_PATH | %_NT_SYMBOL_DIR%;symsrv*symsrv.dll*%_NT_SYMBOL_DIR% *http://msdl.microsoft.com/download/symbols |
符號檔案檢索位置 |
_NT_SOURCE_PATH | 根據實際情況按需配置(可不配) | 編譯驅動生成的符號檔案目錄 |
_NT_ALT_SYMBOL_PATH | 根據實際情況按需配置(可不配) | 其他符號檔案目錄 |
注:在環境變數 _NT_SYMBOL_PATH 指定了兩個路徑:第一個是本地符號檔案安裝目錄,第二個是線上符號檔案站點。 它表示如果在本地安裝目錄%_NT_SYMBOL_DIR%下找不到所需的Symbol File,就從微軟的Symbol Server上下載並儲存到%_NT_SYMBOL_DIR%目錄。
重新執行WinDbg連線到GuestOS,從控制檯的連線資訊可以看到WinDbg已成功找到符號檔案路徑位置。點選【檔案】 –> 【符號檔案路徑】 可以發現系統變數 _NT_SYMBOL_PATH 所指定的符號檔案路徑已被載入到WinDbg,如圖 17所示:
9.3. 除錯一個驅動程式
以之前的VS2010_WDK_Demo驅動專案為例(該專案通過EasySYSchs生成,已生成模板程式碼,編譯後可直接被系統載入執行,詳見《驅動開發入門 - 之一》,此處不再複述)。
在VS2010_WDK_Demo.cpp中找到入口函式DriverEntry,使用DbgPrint函式列印一句核心除錯訊息,如圖 18:
重新編譯並簽名VS2010_WDK_Demo驅動專案,拷貝VS2010_WDK_Demo.sys到GuestOS中,並使用DriverMonitor / InstDrv裝載並啟動該驅動,則可以在WinDbg中捕獲到剛才新增的核心訊息“Hello, Driver By VS2010”,如圖 19所示。
9.4. 加入斷點除錯
由於驅動程式中沒有斷點,驅動程式被裝載後轉瞬就執行完了。
為了便於除錯,這次在驅動程式的入口函式DriverEntry中加入INT 3系統中斷的彙編程式碼,如圖 20所示(此處只演示效果,暫不說明如何在x64系統中嵌入彙編程式碼,若有需要了解可見附錄):
重新編譯並簽名VS2010_WDK_Demo驅動專案。
把HostOS編譯目錄中生成的符號檔案VS2010_WDK_Demo.pdb設定到WinDbg中(【檔案】 –> 【原始檔路徑】),使得WinDbg可以在除錯過程中檢視驅動程式的原始碼,如圖 21所示。
然後拷貝驅動程式VS2010_WDK_Demo.sys到GuestOS中,簽名後使用DriverMonitor / InstDrv裝載並啟動該驅動,此時GuestOS因為系統中斷會陷入假死狀態,按【Ctrl+Alt】釋放滑鼠到HostOS,發現WinDbg已執行到斷點位置並暫停,如圖 22所示。
在WinDbg上方的工具欄提供了對驅動程式做除錯的按鈕,左側為原始碼區,右側則是控制檯,如圖 23所示為單步除錯的過程。
熟悉WinDbg的使用後,其他驅動程式的除錯方式也是大同小異,此處就不再一一敘述了。
10. 附錄1:利用VirtualKD提高除錯的傳輸速率
在除錯的過程中可能會發現WinDbg經常會不斷列印一堆意義不明XML stream訊息刷屏(如圖 24),在列印期間WinDbg與GuestOS均處於無法操作的假死狀態。
SXS.DLL: Read 0 bytes from XML stream; HRESULT returned = 0x00000001
SXS.DLL: Creating 8828 byte file mapping
C:\Users\Administrator\Desktop\DriverGenius\security\kxescan\kfc_dps.datSXS.DLL: Read 756 bytes from XML stream; HRESULT returned = 0x00000000
00000000: 3c-3f-78-6d-6c-20-76-65-72-73-69-6f-6e-3d-22-31 (<?xml version="1)
00000010: 2e-30-22-20-65-6e-63-6f-64-69-6e-67-3d-22-55-54 (.0" encoding="UT)
00000020: 46-2d-38-22-20-73-74-61-6e-64-61-6c-6f-6e-65-3d (F-8" standalone=)
00000030: 22-79-65-73-22-3f-3e-0d-0a-3c-21-2d-2d-20-43-6f ("yes"?>..<!-- Co)
00000040: 70-79-72-69-67-68-74-20-28-63-29-20-4d-69-63-72 (pyright (c) Micr)
00000050: 6f-73-6f-66-74-20-43-6f-72-70-6f-72-61-74-69-6f (osoft Corporatio)
00000060: 6e-20-2d-2d-3e-0d-0a-3c-61-73-73-65-6d-62-6c-79 (n -->..<assembly)
這種訊息實際上是HostOS與GuestOS在互動資料,當在GuestOS開啟某些程序時就可能會觸發。當需要互動的資料量很大的時候,就會造成WinDbg與GuestOS雙雙陷入假死狀態,直到資料互動完成。那麼要解決假死狀態的方法自然就是想辦法使得HostOS與GuestOS儘快完成資料互動。
在前面配置虛擬管道串列埠的時候,有一個波特率引數,預設值就是【baudrate=115200】,該值直接制約了HostOS與GuestOS互動資料的傳輸速率(115200 baudrate等效於115200 bit per secon,約為10KB/s)。但是串列埠波特率的取值範圍為300、600、1200、2400、4800、9600、19200、38400、43000、56000、57600、115200,可以發現預設值已經是最大值了,無法再上調波特率。
為此需要藉助MS提供的另一個工具VirtualKD:其原理是先在HostOS與GuestOS預裝後門程序,然後利用KD的擴充套件DLL功能向GuestOS附加到這個程序產生一條虛擬管道,WinDbg可以藉助該管道在HostOS與GuestOS之間進行除錯。相比於使用串列埠,VirtualKD的資料互動速率有極大的提升(微軟官方測試速率最高為6MB/S,即使在VMWare平臺也可達到150KB/s)。
VirtualKD的安裝和使用都比較簡單,具體步驟如下:
① 把從官方下載的VirtualKD.exe在HostOS與GuestOS中分別拷貝一份。
② 分別在HostOS與GuestOS中執行VirtualKD.exe解壓
③ 在GuestOS中執行解壓目錄中的 \target\vminstall.exe,由於是非Win10系統,必須取消勾選【Replace kdcom.dll】,其他引數可以不修改,點選【install】按鈕安裝(如圖 25),安裝成功後會提示重啟
④ 重啟後在作業系統列表會新增一個系統副本,副本名稱就是剛才定義的名稱,使用它進入系統(如圖 26)
⑤ 在HostOS中執行解壓目錄中的vmmon64.exe,點選【Debugger path…】按鈕選擇WinDbg安裝目錄下的【windbg.exe】(此方式不支援選擇漢化版的入口),最後點選【Run debugger】,VirtualKD會自動啟動WinDbg並連線到GuestOS(如圖 27)。
⑥ 在WinDbg除錯期間不能關閉VirtualKD程序
11. 附錄2: WinDbg常用命令/操作
可跳轉到此頁面查詢:
12. 附錄3:WDK(x64)+彙編的混合編譯
使用WinDbg除錯驅動程式的時候,已經涉及程式碼編寫了。而其中一個泛用的特例就是在C/C++程式碼中嵌套匯編的INT3系統中斷指令。
因此此節詳細說明一下如何在x64的C/C++驅動程式中嵌入彙編程式碼,並將其編譯到一起。
在x86的編譯平臺中是支援使用__asm{ … }語法進行內聯彙編的,亦即可以直接把彙編程式碼直接寫到C/C++程式碼之中,例如:
NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path)
{
DbgPrint("This is x86 C/C++");
__asm {
int 3 ; 系統中斷
}
DbgPrint("This is x86 C/C++");
return STATUS_SUCCESS;
}
但是在x64編譯平臺是不支援內聯彙編的。
x64平臺要求把彙編程式碼統一寫到 *.asm 檔案中,通過彙編編譯器(VS預設為ml64.exe)編譯成 *.obj 目標檔案,最後與 C/C++ 程式碼的目標檔案link到一起生成*.exe可執行檔案(或*.sys驅動檔案)。
在WDK驅動專案中,詳細的操作方式如下(這裡還是以在之前的VS2010_WDK_Demo驅動專案中新增INT3系統中斷為例):
① 在WDK專案中新建資料夾asm,再新建檔案fun.asm(檔名任意,字尾必須為*.asm)
② 在fun.asm中編寫INT3系統中斷彙編程式碼:
.CODE ; 宣告為程式碼段,類似的還有.DATA資料段
int_3 PROC ; 函式/過程,紅色部分是其名稱,可被C/C++聲明後直接呼叫
int 3
ret
int_3 ENDP
END
③ 如圖 28,在VS2010_WDK_Demo.h 標頭檔案的 extern “C” { … } 程式碼塊中新增彙編函式的外部宣告,使其可以被呼叫C/C++程式碼(至於為什麼要在extern “C”修飾符內做函式宣告,可見附錄4的【13.1 [error LNK 2019] 】):
extern "C" {
......
void int_3(void);
......
}
④ 之後就可以在VS2010_WDK_Demo.cpp 原始檔中直接呼叫 int_3() 函數了,如圖 29:
⑤ 但是現在WDK工程還不能編譯成功,原因是WDK不知道如何編譯fun.asm檔案。為此需要再為*.asm檔案指定一套編譯規則,方法如下:
右鍵【專案】 –> 【生成自定義】 –> 勾選【masm】,這組操作意為為WDK專案增加彙編檔案的編譯規則MASM(如圖 30)。
⑥ 右鍵【fun.asm】 –> 【屬性】 –> 【配置屬性】 –> 【常規】 –> 【項型別】 –> 【 Microsoft Macro Assembler】(此選項只有在執行第⑤步後才會出現) –> 【應用】,這組操作意為使用預設的MASM編譯器編譯*.asm檔案(如圖 31)。
⑦ 之後左側會增加一項【Microsoft Macro Assembler】,這就是MASM編譯器的配置項。
點選【Command Line】檢視編譯指令碼: x64平臺的編譯指令碼為ml64.exe, Win32平臺的編譯指令碼為ml.exe(如圖 32)。
由於當前工程是64位WDK專案,因此若編譯指令碼不是ml64.exe,需要在配置管理器新增x64平臺。
⑧ (重要)點選【Object File】檢視*.asm檔案編譯所生成的目標檔案*.obj的輸出位置。由於配置值使用了巨集變數,可【點選配置值】 –> 【下拉】 –> 【編輯】 –> 【巨集】,找到對應的變數檢視其真實值。
如圖 33所示,配置值為【$(IntDir)%(FileName).obj】。
其中$(IntDir)為巨集變數,查得其值為x64\amd64\
%(FileName)泛指所編譯的*.asm檔名稱(不含字尾),如當前所編譯的fun.asm檔案,%(FileName)的值則為fun。
因此對於fun.asm彙編檔案而言,$(IntDir)%(FileName).obj的真實值為x64\amd64\fun.obj,記下這個值。
⑨ 驅動工程是通過WDK的build命令進行編譯的(在VS2010中是驅動工程目錄下的BuildDrv.bat指令碼),但是build命令不會自動LINK到*.asm彙編檔案的目標檔案,直接影響就是在編譯*.cpp原始檔時,找不到*.asm彙編檔案所宣告的函式。
為此需要告訴build指令碼,在編譯*.cpp的時候要和哪些*.asm的目標檔案進行LINK。
事實上,*.asm是先於*.cpp被編譯成目標檔案的,亦即在編譯*.cpp的時候,可以把*.asm的目標檔案作為*.cpp的庫檔案,而*.asm的目標檔案位置,在第⑧步的時候已經查到了。
爾後只需要修改WDK的sources檔案,新增屬性項【TARGETLIBS】,指定值為*.asm的目標檔案(在本例中就是x64\amd64\fun.obj),如圖 34所示。
⑩ 最後編譯專案:【生成】–>【(重新)生成解決方案】,如無意外則編譯成功,如圖 35:
注:
在64位驅動工程中混合彙編編譯的方式,暫時只適用於VS2010。
在VS2008的驅動工程中,即使使用相同步驟配置,其DDK的build.bat指令碼卻無法呼叫MASM編譯器ml64.exe對*.asm彙編檔案進行編譯,亦即在編譯*.cpp時無法自動得到*.asm的目標檔案並進行LINK。
13. 附錄4:常見異常解決方案
13.1. [error LNK 2019] - unresolved external symbol [email protected] referenced in function [email protected]
#include<ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
DbgPrint("load Driver\r\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path)
{
DbgPrint("Hello, WDK Demo!");
driver->DriverUnload=DriverUnload;
return STATUS_SUCCESS;
}
以上述驅動程式原始碼為例,在使用VS2008 / VS2010 編譯時報錯如下:
1>DDKBLD: ================ Build warnings =======================
1>1>BufferOverflowK.lib(gs_support.obj) : error LNK2019: unresolved external symbol [email protected] referenced in function [email protected]
1>1>d:\01_wor~1\c\vs2008\re\helloddk\helloddk\bufferoverflowk.lib(gs_support.obj) : error LNK2019: unresolved external symbol [email protected] referenced in function [email protected]
1>1>d:\01_wor~1\c\vs2008\re\helloddk\helloddk\objchk_win7_x86\i386\HelloDDK.sys : fatal error LNK1120: 1 unresolved externals
1>1>d:\01_wor~1\c\vs2008\re\helloddk\helloddk\objchk_win7_x86\i386\helloddk.sys : error LNK1120: 1 unresolved externals
1>DDKBLD: =======================================================
異常原因:
這是一個連結錯誤,表示系統在連結時找不到入口函式[email protected]。
在VS2008 / VS2010中預設的編譯方式是採用C++方式的,而這個錯誤意思是C編譯器對DriverEntry進行編譯後的結果,字首“_”是C編譯器特有的,字尾“@8”是所有引數的長度。所以C++編譯器一定是把DriverEntry編譯成了系統無法認識的另一副模樣了(實際上,C++編譯器會把它編譯成以“[email protected]@”開頭的一串很長的符號)。
解決方案:
在報錯的函式DriverEntry前面加上extern “C”修飾符即可。
extern “C”提醒編譯器要使用C編譯格式編譯DriverEntry函式,這樣編譯生成的函式名稱為“[email protected]”,連結器即可正確地識別出符號了。
需要注意的是,若報錯的不是函式DriverEntry ,而是其他函式XXXXX,則也需要在前面新增extern “C”修飾符。
修改後的程式碼如下:
#include<ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
DbgPrint("load Driver\r\n");
}
extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path)
{
DbgPrint("Hello, WDK Demo!");
driver->DriverUnload=DriverUnload;
return STATUS_SUCCESS;
}
13.2. GuestOS安裝VirtualKD後若退出TestSigning模式則無法啟動Windows
GuestOS安裝VirtualKD後,若再使用以下命令關閉系統的測試模式,則會出現如圖 36所示的情況,無法登入系統,錯誤程式碼為0xc0000428。
bcdedit /set testsigning off // 關閉系統測試模式
異常原因:
GuestOS安裝VirtualKD後,C:\Windows\System32\kdcom.dll會被替換成供VirtualKD使用的另一個同名檔案kdcom.dll,原kdcom.dll會被備份為kdcom_old.dll。
需知kdcom.dll是Windows中極其重要的檔案,負責除錯驅動程式以及核心模組,它在windows開機時就會被載入到記憶體中,如果損壞會導致藍屏。
而由於VirtualKD的kdcom.dll簽名可能是過期失效(或未被認可)的,此後若關閉系統的測試模式,系統在啟動時會重新發起對kdcom.dll檔案的簽名校驗,最終因校驗不通過導致系統啟動失敗。
解決方案:
在系統關閉測試模式之前,恢復原有的kdcom.dll檔案即可 (若很不幸地你的GuestOS在恢復kdcom.dll前已經關閉了測試模式,可以嘗試還原VM快照或者用PE登陸系統替換kdcom.dll檔案)。
開啟C:\Windows\System32目錄,可以發現有兩個檔案:kdcom.dll與kdcom_old.dll
右鍵檢視kdcom.dll屬性,在詳細資訊一欄可知這是VirtualKD使用的檔案,而另一個kdcom_old.dll原檔案。只需備份kdcom.dll,然後把kdcom_old.dll重新命名為kdcom.dll即可。
需要注意的是,恢復kdcom.dll檔案後VirtualKD就會失效了,若下次需要使用VirtualKD則還得把這兩個檔案再次交換。
相關推薦
之二:Win7-x64 + VMWare (Win7-x64) + WinDbg 雙機除錯環境搭建
驅動開發入門 - 之二Win7-x64 + VMWare (Win7-x64) + WinDbg雙機除錯環境搭建 —— By EXP 2017-10-08 完整原文下載(轉載請註明出處,僅供分享學習,嚴禁用於商業用途) 1. 概述
Win7雙機除錯環境搭建之配置VMware的管道虛擬串列埠
轉:http://www.16boke.com/article/detail/171 WinDbg除錯核心時,被設計為雙機除錯,需要另一臺計算機(除錯機)來除錯被除錯的計算機(被除錯機),WinDbg必須安裝在除錯機上,除錯機與被除錯機通過串列埠相連線。 環境: 主機:
Win7雙機除錯環境搭建之常見問題
轉:http://www.16boke.com/article/detail/175 環境: 主機:Win7 虛擬機器:VMware 11.1.0 build-2496824 虛擬機器內作業系統(又稱GuestOS):Win7 WinDbg:適合除錯機的相應位數
Win7雙機除錯環境搭建之除錯
轉:http://www.16boke.com/article/detail/174 環境: 主機:Win7 虛擬機器:VMware 11.1.0 build-2496824 虛擬機器內作業系統(又稱GuestOS):Win7 WinDbg:適
Win7雙機除錯環境搭建之配置WinDbg
轉:http://www.16boke.com/article/detail/173 環境: 主機:Win7 虛擬機器:VMware 11.1.0 build-2496824 虛擬機器內作業系統(又稱GuestOS):Win7 WinDbg:適
Win7雙機除錯環境搭建之配置GuestOS的啟動項
轉:http://www.16boke.com/article/detail/172 環境: 主機:Win7 虛擬機器:VMware 11.1.0 build-2496824 虛擬機器內作業系統(又稱GuestOS):Win7 WinDbg:適合除錯機的相應位數
WinDbg+VMWare雙機除錯環境搭建
因為要學習一下驅動開發,需要搭建一個除錯環境,我按照《寒江獨釣——windows核心安全程式設計》一書搭建了一個WinDbg+VMWare的雙機除錯環境,這其中遇到了一些小問題,雖然只是一些細節問題,但是如果初次遇到的話還是讓人有點抓狂的,我記錄下來,希望幫到和我遇到一樣問
搭建VS2017+WDK10+WinDBG雙機除錯Win7環境過程遇到的坑與解決(WinDBG找不到串列埠、security_cookie導致的藍屏、看不到除錯訊息等)
一直使用Visual Studio + WDK的方式開發Windows驅動,最近想在VS2017下安裝WDK10開發驅動,結果遇到問題了,首先是沒法實現雙機除錯,然後是編譯出來的驅動在Win7平臺下一載入就藍屏,定位到是security_cookie的問題,緊接
winDbg + VMware + window 雙機聯調環境搭建
真機調試 net 服務 x64 。。 .exe 鏈接 成了 內核開發 這裏簡單的介紹一下內核開發雙機聯調的搭建環境,盡管網上有很多類似的文章,但看了很多總是不太舒服,覺得不太明白,所以自己實踐一下總結一篇。下面就拿我的環境簡單介紹,希望別人可以看懂。準備工具:裝虛擬機VMw
libevent學習之二:Windows7(Win7)下編譯libevent
Linux下編譯參考原始碼中的README檔案即可,這裡主要記錄Windows下的編譯。一.準備工作去官網下載最新的穩定釋出版本libevent-2.0.22-stable二.使用VS2012編譯1.解
4.AngularJS四大特征之二: 雙向數據綁定
sco font int out grep 模型 多行文本 pan oot AngularJS四大特征之二: 雙向數據綁定 (1)方向一:把Model數據綁定到View上——此後不論何時只要Model發生了改變,則View中的呈現會立即隨之改變!實現方法: {{ }}、
linux學習之二:日常的基礎命令收集
幫助文檔 gedit 查看 日期 取整 style 位置 某月 linux 1、 ls 2、pwd 顯示當前目錄所在位置 3、date 日期時間 4、cal 日歷 默認顯示當前該月 cal 2012 :查看2012年的日歷 cal 月 年 : 查看某年某月
【只怕沒有幾個人能說清楚】系列之二:Unity中的特殊文件夾
物體 avi ebp time 編輯模式 tro hive 預覽 打包 參考:http://www.manew.com/thread-99292-1-1.html 1. 隱藏文件夾 以.開頭的文件夾會被忽略。在這種文件夾中的資源不會被導入,腳本不會被編譯。也不會出現
雙態運維分享之二: 服務型CMDB的消費場景
新增 iso20000 那種 .cn 關聯 通知 變更 不同 維護 近年來,CMDB在IT運維管理中的價值逐步得到認可,使用CMDB的期望值也日益增長。然而,CMDB實施和維護的高成本卻一直是建設者們的痛點。那麽今天,我們來探討一下如何通過消費來持續驅動CMDB的逐步完善。
UVM序列篇之二:sequence和item(上)
技術 一點 目標 idt 需要 開始 掛載 ron 前行 無論是自駕item,穿過sequencer交通站,通往終點driver,還是坐上sequence的大巴,一路沿途觀光,最終跟隨導遊停靠到風景點driver,在介紹如何駕駛item和sequence,遵守什麽交規,最終
Horizon7.1部署之二:Horizon Composer服務器安裝
vmware horizon composerHorizon Composer是個可選服務,如果計劃部署鏈接克隆桌面池(可以節省90%磁盤利用率),則需要安裝。我在windows2016上部署的Sql Server2016,ip是X.X.X.2,並在建立一個名為Horizon Composer的數據庫,防火墻
【2017-07-01】Linux應用開發工程師面試問題記錄之二:關於結構體的大小及內存對齊問題
偶數 而且 strong span net 但是 開發 f11 flag Tencent後臺服務器開發有一道題是計算一個結構體的sizeof的大小: struct strData { int m_Int; char m_Char; short m_Short; char
Linux時間子系統之二:Alarm Timer
數據 類型 oid mtime orm 分別是 type mon 超時 一、前言 嚴格來講Alarm Timer也算POSIX Timer一部分,包含兩種類型CLOCK_REALTIME_ALARM和CLOCK_BOOTTIME_ALARM。分別是在CLOCK_REALTI
Modbus庫開發筆記之二:Modbus消息幀的生成
不同的 command dwr 分別是 slave 識別碼 align 數據格式 .com 前面我們已經對Modbus的基本事務作了說明,也據此設計了我們將要實現的主從站的操作流程。這其中與Modbus直接相關的就是Modbus消息幀的生成。Modbus消息幀也是實現Mod
玩玩微信公眾號Java版之二:接收、處理及返回微信消息
log med iou set arch weixin b- rom data- 前面已經配置了微信服務器,那麽先開始最簡單的接收微信消息吧~ 可以用我們的微信號來直接進行測試,下面先看測試效果圖: 這是最基本的文本消息的接收、處理及返回,來看看是怎麽實現的