vs+vm双机调试
基礎:
VS2017安裝成功
wdk10
注意事項:
關閉 、主機 客戶機 防火墻 、 互相ping都能ping通。
一、具體操作步驟
工具安裝就不說了,不會的百度一下。只說一下一些關鍵的地方。
1、安裝好虛擬機后,給虛擬機增加一個串口設備。具體操作見圖:
完成配置后虛擬機設備配置就多了一個串行端口的設備。因為打印機用了端口1。所以設備里面顯示的是串行端口2(如果想設置成端口1,把打印機設備刪了在添加串口設備)。
2、配置虛擬機系統為調試模式
?以管理員身份,在虛擬機命令行模式下運行如下2個命令開啟。
?bcdedit /debug on
? bcdedit /dbgsettings serial debugport:n baudrate:115200
? where n is the number of a COM port on the virtual machine.(n時虛擬機的一個COM端口號。就是設備顯示的串行端口2,n就是端口2)。
1
2
3
4
5
6
3、把WDK10的虛擬機調試驅動拷貝到虛擬機中安裝。
因為VS2017可以調試x86 x64兩種驅動所以兩個都拷貝到虛擬機安裝。也可以根據需要情況安裝(32位里安裝x86版)
4、VS2017開發工具配置
在VS2017的菜單欄點擊DRIVER–TEST–CONFIGURE 如圖
配置界面,下面兩個選項第一項由VS2017幫我們創建一個WDKuser測試賬戶,自動打開測試模式等。第二個是使用我們自己配置的參數。由于上面我們已經配置了串口參數 、設置了調試模式所以我們選擇第二個就行了。
DESKTOP-1R835HV是虛擬機里安裝的操作系統的計算機名
如下配置在內核模式中,選擇串口、配置好波特率、勾上2個選項、管道名稱、端口號。
出現上述紅色框字樣則說明配置已經成功了。(不要開啟全局代理軟件,否則會出現連接不上的問題)。
5、使用工具安裝調試64位驅動
使用DebugView打印內核調試信息是開發驅動的非常重要的手段,但DebugView默認在WINDOWS 7和WINDOWS 10下卻無法獲取內核的調試日志,驅動調用KdPint/DbgPrint等的打印結果是無法被DebugView給捕捉到的。設置方法如下(復制下面的代碼到txt文件。改后綴為.reg后執行,然后重啟電腦):
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter]
“DEFAULT”=dword:0000000f
還有自己編譯出來的驅動要使用編譯的Debug版本來測試,Release版本是不會執行KdPrint/DbgPint函數的。
6、在VS2017中下斷點進行調試
如果你第五部已經完成了,并且在DebugView中已經能夠輸出調試的打印信息了,辣么騷年你已經離成功只有一部之遙了
創建一個驅動工程,WDK10提供的模板中根本沒有提供NT驅動模板,我們如何創建NT驅動呢?
解決:其實雖然沒有提供NT模板,但是我們可以建立WDM空模板工程,然后再自己添加文件,編譯,得到的也就是NT驅動了。
驅動工程中會幫你建立一個inf文件,NT是使用不到的,可以直接刪除。我們直接添加一個first.c
在文件中添加測試代碼。
#include <ntddk.h>?
VOID DriverUnload(PDRIVER_OBJECT objDriver)
{
?? ?// 什么也不做,只打印一行字符串
? ? DbgPrint("My Dirver is Ending...\r\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT objDriver, PUNICODE_STRING strRegPath)
{
?? ?// 打印一行字符串,并注冊驅動卸載函數,以便于驅動卸載
?? ?DbgPrint("My Dirver Is Starting!\r\n");
?? ?objDriver->DriverUnload = DriverUnload;
?? ?return STATUS_SUCCESS;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
編譯,報錯,沒有關系,這些都是因為安全警告等級太高了,我們可以降低編譯器警告等級的方式解決:
如果編譯的時候還是出現錯誤 可以參照 我的另外一篇博文
https://blog.csdn.net/qq_21763381/article/details/83210572
辣么現在我們開始附加虛擬機的內核進行調試了。
首先把虛擬機的系統內核附加到VS2017,具體步驟見下圖
選中內核調試模式、選自己配置的那個電腦、選中下面列表中內核。見下圖
點擊附加,然后出現下圖界面,點擊一下全部中斷。
然后我們在下面的Debugger Immediate Winddow窗口的 Kd> 一行輸入命令 g 讓系統運行起來。這樣虛擬機中的系統又可以點擊了。
最后一步了。使用我們剛剛建立的驅動工程編譯出來的.sys驅動文件拷貝到虛擬機中。用第五步的工具進行安裝、啟動。啟動的時候自動觸發VS2017中的下的斷點。至此可以像平時我們調試程序一樣進行單步調試了。
注意事項:1、一定要拷貝Debug版本的進行調試。
2、拷貝到虛擬機中的.sys文件一定要是你源碼編譯出來的。如果改動了源碼后一定要重新拷貝一份新的驅動文件到虛擬機中調試。否則無法觸發斷點的。
安裝驅動程序
啟動驅動程序
當驅動程序啟動時,發現斷點已經被激活了
原文鏈接:https://blog.csdn.net/qq_21763381/article/details/83242916
?
?
?
-----------------------------
?
?
?
驅動開發入門 - 之二
Win7-x64 + VMWare (Win7-x64) + WinDbg
雙機調試環境搭建
—— By EXP 2017-10-08
完整原文下載(轉載請注明出處,僅供分享學習,嚴禁用于商業用途)
1. 概述
1.1. 前言
適讀人群:具備良好的C/C++開發經驗,一定的逆向工程基礎。?
前置閱讀:《驅動開發入門 - 之一 :Win7 SP1 x64 驅動開發環境搭建》
為方便起見,在下文中使用【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簡介
——部分內容摘于博文:http://blog.csdn.net/keidoekd2345/article/details/50125747
在安裝微軟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. 相關工具安裝
?
表 1 工具清單
目標機器?? ?工具?? ?版本?? ?用途?? ?備注?? ?下載
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。
圖 1 編輯虛擬機設置
② 在【硬件】選項卡【移除打印機】,如圖 2。?
這是因為打印機默認占用了串口COM_1,為了使得下文的配置無需修改,這里建議刪除打印機(不刪除打印機也可以,但后面的配置請自行修改為COM_2作為管道串口命名)
圖 2 移除打印機
③ 添加一個串行端口:【添加】 –> 【串行端口】 –> 【下一步】 –> 【輸出到命名管道】 –> 【下一步】,如圖 3和圖 4。
圖 3 添加串行端口
圖 4 設置為管道串口
④ 如圖 5設置如下值,點擊【完成】按鈕。?
命名管道:\.\pipe\com_1 (會自動填上編號最小的可用串口)?
【該端是服務器。】?
【另一端是應用程序。】?
【勾上】啟動時連接。
圖 5 設置虛擬管道串口參數
⑤ 最后回到如圖 6所示的界面,選中剛才新建的【串行端口】,在I/O模式【勾選】輪詢時主動放棄 CPU(Y),點擊【確定】即可。
圖 6 設置串口IO模式
6. 在GuestOS增設調試模式的操作系統
首先區分GuestOS中操作系統的幾種模式:?
>> 正常模式:初裝操作系統時的默認狀態?
>> 測試模式:利用bcdedit命令打開系統的TestSigning開關,使系統處于可以裝載未認證驅動程序的狀態(若已按上文所述操作,當前的GuestOS已處于此狀態)?
>> 調試模式:利用bcdedit命令打開系統的debug和bootdebug 開關,使系統上運行的程序處于可以被另一個系統調試的狀態
本節的最終目標就是在 [測試模式] 的基礎上再增加 [調試模式],更具體地描述,就是在開機的操作系統列表中新增一個被標識為【啟用調試程序】的操作系統,如圖 7所示(其中“Win-7雙擊調試模式”是自定義的系統名稱,“啟用調試程序”表示該系統處于調試模式)?
在XP時代,通過修改C:\boot.ini配置文件可以實現此目的。但Win7系統已經沒有這個文件了,需要通過bcdedit命令進行配置。
圖 7 系統列表
詳細的配置方式如下:?
① 虛擬機開機后,正常登陸到Win7系統桌面(若已按照上文配置,當前所登陸到的Win7系統正處于【測試模式】,可以通過桌面右下角的水印驗證,如圖 8所示。某些系統會屏蔽這個水印,此時可以通過命令【bcdedit /enum】確認testsigning的值是否為Yes以判斷系統當前是否處于測試模式)。
圖 8 測試模式水印
② 如圖 9和圖 10所示,以管理員身份運行DOS控制臺在控制臺中依次輸入以下命令:
bcdedit /copy {current} /d “Win7-雙機調試模式” // 這是系統副本的名字,任意即可?
bcdedit /timeout 10
這兩條命令的作用是把當前所登陸的操作系統,復制一份副本,命名為【Win7-雙機調試模式】。新的系統會出現在開機時的操作系統列表中,該列表的呈現時間為10秒。
圖 9 使用管理員運行DOS
圖 10 復制當前操作系統
③ 重啟GuestOS,此時可以看到在操作系統列表中多出第一項【Win7-雙機調試模式】,這就是剛才復制的系統副本。選擇這個系統登陸到桌面。
圖 11 操作系統列表
④ 以管理員身份運行DOS控制臺,在控制臺中依次輸入以下命令使得系統進入調試模式:
bcdedit /debug ON?
bcdedit /bootdebug ON
再輸入以下命令可查看操作系統在調試模式下使用的串口配置:
bcdedit /dbgsettings
如圖 12所示為調試模式的配置參數,其中【debugtype=Serial】表示使用串口做調試,【debugport=1】表示串口端口為COM_1,【baudrate=115200】為波特率,表示HostOS與GuestOS通過此虛擬串口交換數據的傳輸速率(約等效于10KB/s,暫時保持默認值即可)。
圖 12 設置當前系統為調試模式
這里需要注意的是,若上文小節【5 配置VMWare的虛擬的管道串口】中所配置的串口不是COM_1,這里可以使用以下命令 修改串口號等 調試模式的參數:
bcdedit /dbgsettings serial debugport:1 baudrate:115200
⑤ 到此就已經成功添加了一個調試模式的操作系統了,重啟后可在系列列表中看見【Win-7雙擊調試模式 [啟用調試程序]】(如圖 13),這個就是之后要用來調試驅動用的系統。
圖 13 操作系統列表
⑥ 為了便于之后開機后都處于調試模式,可以通過右鍵【計算機】 –> 【屬性】 –> 【高級系統設置】 –> 【高級】 –> 【啟動和故障恢復】 –> 【設置】 修改默認的操作系統、以及操作系統列表的顯示時間,如圖 14所示:
圖 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做雙機調試。
圖 15 WinDbg連接GuestOS
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版本的符號路徑下載的站點:
https://developer.microsoft.com/en-us/windows/hardware/download-symbols
以本文所采用的操作系統版本為例,選擇【Windows 7 Service Pack 1 x64 retail symbols, all languages】下載,如圖 16:
圖 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所示:
圖 17 符號文件路徑設置
9.3. 調試一個驅動程序
以之前的VS2010_WDK_Demo驅動項目為例(該項目通過EasySYSchs生成,已生成模板代碼,編譯后可直接被系統加載運行,詳見《驅動開發入門 - 之一》,此處不再復述)。?
在VS2010_WDK_Demo.cpp中找到入口函數DriverEntry,使用DbgPrint函數打印一句內核調試消息,如圖 18:
圖 18 添加內核調試消息語句
重新編譯并簽名VS2010_WDK_Demo驅動項目,拷貝VS2010_WDK_Demo.sys到GuestOS中,并使用DriverMonitor / InstDrv裝載并啟動該驅動,則可以在WinDbg中捕獲到剛才添加的內核消息“Hello, Driver By VS2010”,如圖 19所示。
圖 19 調試一個簡單的驅動程序
9.4. 加入斷點調試
由于驅動程序中沒有斷點,驅動程序被裝載后轉瞬就運行完了。?
為了便于調試,這次在驅動程序的入口函數DriverEntry中加入INT 3系統中斷的匯編代碼,如圖 20所示(此處只演示效果,暫不說明如何在x64系統中嵌入匯編代碼,若有需要了解可見附錄):
圖 20 添加系統中斷
重新編譯并簽名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的使用后,其他驅動程序的調試方式也是大同小異,此處就不再一一敘述了。
圖 21 設置源文件路徑
圖 22 驅動程序陷入中斷
圖 23 驅動程序調試
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)
1
2
3
4
5
6
7
8
9
10
圖 24 HostOS與GuestOS交互數據刷屏
這種消息實際上是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進程
圖 25 在GuestOS安裝VirtualKD
圖 26 操作系統列表新增VirtualKD調試系統
圖 27 在HostOS配置VirtualKD運行WinDbg
11. 附錄2: WinDbg常用命令/操作
可跳轉到此頁面查詢:
WinDbg 命令手冊
12. 附錄3:WDK(x64)+匯編的混合編譯
——部分內容參考于博文:http://blog.csdn.net/cosmoslife/article/details/9071949
使用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;?
}
1
2
3
4
5
6
7
8
9
10
11
但是在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
1
2
3
4
5
6
7
8
③ 如圖 28,在VS2010_WDK_Demo.h 頭文件的 extern “C” { … } 代碼塊中添加匯編函數的外部聲明,使其可以被調用C/C++代碼(至于為什么要在extern “C”修飾符內做函數聲明,可見附錄4的【13.1 [error LNK 2019] 】):
extern "C" {?
? ? ......
? ? void int_3(void);
? ? ......
}?
1
2
3
4
5
圖 28 在*.h頭文件聲明*.asm的外部函數
④ 之后就可以在VS2010_WDK_Demo.cpp 源文件中直接調用 int_3() 函數了,如圖 29:
圖 29 在*.cpp源文件調用*.asm的外部函數
⑤ 但是現在WDK工程還不能編譯成功,原因是WDK不知道如何編譯fun.asm文件。為此需要再為*.asm文件指定一套編譯規則,方法如下:?
右鍵【項目】 –> 【生成自定義】 –> 勾選【masm】,這組操作意為為WDK項目增加匯編文件的編譯規則MASM(如圖 30)。
圖 30 為WDK工程添加新的編譯規則(MASM)
⑥ 右鍵【fun.asm】 –> 【屬性】 –> 【配置屬性】 –> 【常規】 –> 【項類型】 –> 【 Microsoft Macro Assembler】(此選項只有在執行第⑤步后才會出現) –> 【應用】,這組操作意為使用默認的MASM編譯器編譯*.asm文件(如圖 31)。
圖 31 為*.asm匯編文件指定MASM編譯器
⑦ 之后左側會增加一項【Microsoft Macro Assembler】,這就是MASM編譯器的配置項。?
點擊【Command Line】查看編譯腳本: x64平臺的編譯腳本為ml64.exe, Win32平臺的編譯腳本為ml.exe(如圖 32)。?
由于當前工程是64位WDK項目,因此若編譯腳本不是ml64.exe,需要在配置管理器新增x64平臺。
圖 32 確認MASM編譯器的匯編編譯腳本是否正確
⑧ (重要)點擊【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,記下這個值。
圖 33 確認*.asm匯編文件編譯所生成的目標文件位置
⑨ 驅動工程是通過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所示。
圖 34 為驅動工程指定*.asm的目標文件作為鏈接庫文件
⑩ 最后編譯項目:【生成】–>【(重新)生成解決方案】,如無意外則編譯成功,如圖 35:
圖 35 成功編譯含*.asm匯編文件的驅動工程
注:?
在64位驅動工程中混合匯編編譯的方式,暫時只適用于VS2010。?
在VS2008的驅動工程中,即使使用相同步驟配置,其DDK的build.bat腳本卻無法調用MASM編譯器ml64.exe對*.asm匯編文件進行編譯,亦即在編譯*.cpp時無法自動得到*.asm的目標文件并進行LINK。
13. 附錄4:常見異常解決方案
13.1. [error LNK 2019] - unresolved external symbol _DriverEntry@8 referenced in function _GsDriverEntry@8
#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;?
}
1
2
3
4
5
6
7
8
9
10
11
12
13
以上述驅動程序源碼為例,在使用VS2008 / VS2010 編譯時報錯如下:
1>DDKBLD: ================ Build warnings =======================?
1>1>BufferOverflowK.lib(gs_support.obj) : error LNK2019: unresolved external symbol _DriverEntry@8 referenced in function _GsDriverEntry@8?
1>1>d:\01_wor~1\c\vs2008\re\helloddk\helloddk\bufferoverflowk.lib(gs_support.obj) : error LNK2019: unresolved external symbol _DriverEntry@8 referenced in function _GsDriverEntry@8?
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: =======================================================
異常原因:?
這是一個鏈接錯誤,表示系統在鏈接時找不到入口函數_DriverEntry@8。?
在VS2008 / VS2010中默認的編譯方式是采用C++方式的,而這個錯誤意思是C編譯器對DriverEntry進行編譯后的結果,前綴“_”是C編譯器特有的,后綴“@8”是所有參數的長度。所以C++編譯器一定是把DriverEntry編譯成了系統無法認識的另一副模樣了(實際上,C++編譯器會把它編譯成以“?DriverEntry@@”開頭的一串很長的符號)。?
?
解決方案:?
在報錯的函數DriverEntry前面加上extern “C”修飾符即可。?
extern “C”提醒編譯器要使用C編譯格式編譯DriverEntry函數,這樣編譯生成的函數名稱為“_DriverEntry@8”,鏈接器即可正確地識別出符號了。?
需要注意的是,若報錯的不是函數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;?
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
13.2. GuestOS安裝VirtualKD后若退出TestSigning模式則無法啟動Windows
GuestOS安裝VirtualKD后,若再使用以下命令關閉系統的測試模式,則會出現如圖 36所示的情況,無法登入系統,錯誤代碼為0xc0000428。
bcdedit /set testsigning off // 關閉系統測試模式
圖 36 無法啟動Windows
異常原因:?
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則還得把這兩個文件再次交換。
圖 37 C:\Windows\System32\kdcom.dll
圖 38 VirtualKD的kdcom.dll
原文鏈接:https://blog.csdn.net/lyy289065406/article/details/78231172
總結
- 上一篇: mysql下载哪一代版本好_潮一代更好的
- 下一篇: 预约清单ui设计_持续交付质量设计所需的