xp+WinDBG+VMware調試內核
嗬嗬,搞點突兀的標題而已。其實說的還是如何使用WinDBG和VMware來搭建調試內核的環境而已,這些網上已經有數不清的教程了,不過我喜歡自己親手寫一下。第一,把這個過程寫一遍能加深印象,就算以後忘記了也可以有筆記查找,快速想起來。第二、網上的教程很多都是互相抄來抄去,連錯誤也抄過去了。很典型一個錯誤就是Baud Rate,前麵還寫115200,後麵就寫成了11520了,狂汗!
按照我這篇筆記寫的步驟去做,絕對能夠成功,並且還能大略地了解到為什麼要這樣做的原因。第1部分是步驟,如果不想看原因的,直接按部照搬就可以成功。如果還想深入點了解為什麼要做這些步驟,這些步驟的含義是什麼?那就請繼續看第二部分。
第一部分(步驟):
先統一名稱,真實的操作係統叫HostOS,在VMware裏虛擬的操作係統叫GuestOS。
1.在VMware裏安裝好GuestOS;下載WinDBG並安裝好。
2.添加一個串口
在關閉GuestOS的情況下才能添加硬件。添加串口的過程如下:
選擇“串行端口”
選擇“輸出命名管道”
其他如下設置:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional Debug" /fastdetect /debugport=com1 /baudrate=115200
如圖:
4.創建一個WinDBG的快捷方式,在“目標”一欄後麵加上:
-b -k com:pipe,port=\\.\pipe\com_1,resets=0
如圖:
5.重啟GuestOS,選擇Debug模式。
6.雙擊第4步創建的那個快捷方式啟動WinDBG,它會自動去連接調試GuestOS。
可以看到,已經成功了,現在可以盡情地調試內核了。
第二部分(解說):
原理就是VMware在GuestOS虛擬一個COM口,並在HostOS創建了一個管道,這個管道的一端連接GuestOS的COM口,另一端則是WinDBG,所以HostOS(WinDBG)和GuestOS的所有數據交換都是通過這個管道來流通轉發的。
1.我的電腦沒有COM口,所以不能搭建調試環境?
不是的,你的電腦有沒有COM口與這個調試環境沒有任何關係,整個過程根本沒有使用到你電腦的物理COM口。VMware隻是在GuestOS虛擬了一個COM口而已。
2.在創建串口(COM口屬於串口的一種)的過程中,看到指定的管道為“\\.\pipe\com_1”,我可以指定為其他嗎?
可以的。這隻是指定一個管道名字而已,VMware用這個名字來創建一個命名管道。我完全可以改成“\\.\pipe\liangyu”、“\\.\pipe\aaa”等等,但記得要把WinDBG的快捷方式處的管道名字更改為一樣。
3.我可以在GuestOS的boot.ini文件更改那個COM口嗎?比如把COM1改為COM2?
不可以的,VMware會把虛擬出的這個COM口總是定義為com1。GuestOS的其他COM口都得讓位。
4.看到很多教程都說到要勾選“I/O模式”,如圖:
一定要勾選嗎?
這個勾選不勾選都可以,我沒發現有什麼大的區別。
5.在更改GuestOS的boot.ini文件的時候,增加有“/debugport=com1 /baudrate=115200”這些內容,含義是?
使用的調試端口是com1,波特率是115200。這是在告訴GuestOS現在要調試內核(操作係統),把調試信息往COM1口輸出,使用的波特率是115200。
我在試驗的時候發現,這個波特率其實也不一定要設為115200,完全可以修改為112233、445566等等其他數據。可能是因為WinDBG自動調節波特率來適配管道或COM口,所以波特率在這裏沒有實際意義。
6.WinDBG的快捷方式那裏添加了“-b -k com:pipe,port=\\.\pipe\com_1,resets=0”這些內容,含義是?
大概意思就是使用管道“\\.\pipe\com_1”來進行內核調試。各個參數的說明在WinDBG的參考文檔裏麵有,這裏粘貼一下:
(Kernel mode only) This option has two effects:
1. The debugger will break into the target computer immediately upon connection.
2. After a reboot, the debugger will break into the target computer once the kernel is initialized. SeeCrashing and Rebooting the Target Computer for details and for other methods of changing this status.
(Kernel mode only) Starts a kernel debugging session. For details, seeChoosing Kernel Debugging Settings. If -k is used without anyConnectType options following it, it must be the final entry on the command line.
Specifies that an unlimited number of reset packets can be sent to the target when the host and target are synchronizing. Use theresets=0 parameter for Microsoft Virtual PC and other virtual machines whose pipes drop excess bytes. Do not use this parameter for VMware or other virtual machines whose pipes do not drop all excess bytes.
7.一定要這樣創建一個WinDBG的快捷方式才能進行調試嗎?
不是的,我們完全可以先正常運行WinDBG,然後選擇菜單“File”--->“Kernel Debug...”,然後會彈出以下對話框:
然後設置如上,點確定。這樣也是可以進行調試的。
8.上麵第5、第6步有先後順序嗎?看到很多資料都很強調這個先後順序。
這個是沒有先後順序的。你可以先執行第5,再到第6步,或者先執行第6,再到第5步都是沒有關係的。
選擇Debug模式後,即使進入係統操作了很久,運行了很多東西,但隻要你運行WinDBG,照樣能夠連上去調試。所以說這裏是沒有先後順序的。
第三部分 使用WinDBG和VMware調試驅動程序
還是先統一一下名稱,真實的操作係統叫HostOS,在VMware裏虛擬的操作係統叫GuestOS。
我們編寫完驅動後,當然要進行調試,這不可能在HostOS(本機)裏調試,否則BOSD就麻煩了,而且支持本機調試的調試器比較流行的隻有 softice,這個東西早就停止更新了,而且對目前的操作係統的支持更是非常不好。所以使用WinDBG和VMware調試驅動程序絕對是我們最佳的選擇。
驅動的加載和卸載是必須的步驟,你總不會希望每次修改驅動後需要重啟係統才能進行調試吧?加載和卸載的代碼其實很簡單:
// ***************************************************************
// function : LoadDriver
// purpose : 加載驅動
//
// parameter : [IN] lpPath 驅動的完整路徑
// [OUT]
//
//
// author : liangyu
// created : 2008-7-10 17:19
// ***************************************************************
BOOL CSSDTToolGuiDlg::LoadDriver(LPTSTR lpPath)
{
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if ( NULL == hSCManager )
{
return FALSE;
}
SC_HANDLE hService = CreateService( hSCManager, _T("SSDTTool"),
_T("SSDTTool Driver"), SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE, lpPath, NULL, NULL, NULL, NULL, NULL );
if ( NULL == hService )
{
if (ERROR_SERVICE_EXISTS == GetLastError())//如果是"已經存在該驅動"導致的錯誤則繼續
{
hService = OpenService( hSCManager, _T("SSDTTool"), SERVICE_ALL_ACCESS);
}
else
{
return FALSE;
}
}
StartService( hService, 0, NULL );
CloseServiceHandle( hService );
CloseServiceHandle( hSCManager );
return TRUE;
}
// ***************************************************************
// function : UnLoadDriver
// purpose : 卸載驅動
//
// parameter : [IN] lpName 服務(驅動在SCM注冊的)名字
// [OUT]
//
//
// author : liangyu
// created : 2008-7-10 17:41
// ***************************************************************
BOOL CSSDTToolGuiDlg::UnLoadDriver(LPTSTR lpName)
{
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if ( NULL == hSCManager )
{
return FALSE;
}
SC_HANDLE hService = OpenService( hSCManager, lpName, SERVICE_ALL_ACCESS);
if ( NULL == hService )
{
return FALSE;
}
SERVICE_STATUS ss;
ControlService( hService, SERVICE_CONTROL_STOP, &ss );
DeleteService( hService );
CloseServiceHandle( hService );
CloseServiceHandle( hSCManager );
return TRUE;
}
其實有人已經寫好這個用途的工具了,《Rootkits: Subverting the Windows Kernel》提到的InstDrv(www.rootkit.com/vault/hoglund/InstDvr.zip),也有國內的網友寫好了一個中文版的(https://hi.baidu.com/coderui/blog/item/670a25fb4912b161024f566e.html),功能更齊全。我們就用它來加載和卸載要調試的驅動。
好了,開始。按照之前的說明搭好調試環境後,先用WinDBG連上VMware,如果GuestOS阻塞了,則在WinDBG輸入命令“g”,然後回車,直到讓GuestOS跑起來。我們把編譯好的驅動文件(*.sys)放到GuestOS裏,回到WinDBG,按 “Ctrl+Break”,WinDBG會讓GuestOS暫停下來,我們也可以在WinDBG的命令欄輸入命令了,如下:
在這裏輸入“bu drivername!driverentry”(大小寫不限)可以在驅動的DriverEntry函數的入口點下一個延遲斷點,其實BU的意思就是Set Unresolved Breakpoint,WinDBG會記住這個斷點,當這個驅動被加載了並且執行到這個地方,WinDBG會暫停GuestOS讓你進行調試操作。drivername是你的驅動名字,比如我在這裏的驅動名字是SSDTTool,那我在這裏輸入的命令如下:
回車後即下好斷點了。現在打開源文件,源文件在HostOS呢。“Ctrl+O”找到驅動的源文件打開,如圖:
還要設置符號路徑。“Ctrl+S”打開設置窗體,符號路徑一般有兩個(可以有多個),一個是你設置保存係統DLL的PDB文件的路徑,另一個是你驅動的PDB的路徑,以分號隔開。如下:
記得勾選“Reload”,OK後稍等片刻,等WinDBG把這些東西加載完畢後再操作。加載完後我們輸入“g”,回車,讓GuestOS跑起來。在GuestOS裏運行驅動加載/卸載工具把我們的驅動加載起來。可以看到,已經斷下來了,我們可以源碼調試驅動了:
注:打開源文件和設置符號路徑可以在一開始的時候就做,這是沒有嚴格先後順序的。
最後更新:2017-04-03 15:21:55