1. 程式人生 > >Xp+WinDBG+VMware除錯核心

Xp+WinDBG+VMware除錯核心

轉:https://www.cnblogs.com/lzjsky/archive/2010/12/14/1905275.html

呵呵,搞點突兀的標題而已。其實說的還是如何使用WinDBG和VMware來搭建除錯核心的環境而已,這些網上已經有數不清的教程了,不過我喜歡自己親手寫一下。第一,把這個過程寫一遍能加深印象,就算以後忘記了也可以有筆記查詢,快速想起來。第二、網上的教程很多都是互相抄來抄去,連錯誤也抄過去了。很典型一個錯誤就是Baud Rate,前面還寫115200,後面就寫成了11520了,狂汗!

按照我這篇筆記寫的步驟去做,絕對能夠成功,並且還能大略地瞭解到為什麼要這樣做的原因。第1部分是步驟,如果不想看原因的,直接按部照搬就可以成功。如果還想深入點了解為什麼要做這些步驟,這些步驟的含義是什麼?那就請繼續看第二部分。

第一部分(步驟):

先統一名稱,真實的作業系統叫HostOS,在VMware裡虛擬的作業系統叫GuestOS。

1.在VMware裡安裝好GuestOS;下載WinDBG並安裝好。

2.新增一個串列埠

在關閉GuestOS的情況下才能新增硬體。新增串列埠的過程如下:

選擇“串列埠”

選擇“輸出命名管道”

其他如下設定:

3.在GuestOS的boot.ini檔案裡填入如下內容:

 

  1. 開啟“我的電腦”,點選系統所在磁碟(如C盤),點選選單欄中的“工具”,在彈出的下拉選單中選擇“資料夾選項”。

    如何手動修改XP系統的boot.ini檔案

  2.  

    在“資料夾選項”介面,點選“檢視”選項卡。

    如何手動修改XP系統的boot.ini檔案

  3.  

    滑動滾動條找到如圖所示位置,點去“隱藏受保護的作業系統檔案”的“√”( 彈出的提示框點“是”),點選“顯示所有檔案和資料夾”,最後點選“確定”按鈕。

    如何手動修改XP系統的boot.ini檔案

  4.  

    這時“boot”檔案就顯示出來了,右擊選擇“屬性”。

    如何手動修改XP系統的boot.ini檔案

  5.  

    點去“只讀”的“√”,點選“確定”。

    如何手動修改XP系統的boot.ini檔案

  6.  

    雙擊“boot”檔案(系統預設用“記事本”開啟)。

    如何手動修改XP系統的boot.ini檔案

  7.  

    加入如圖所示語句“ C:\GHLDR=一鍵GHOST v****.**.** ”(具體版本號請根據實際情況填寫)。

    如何手動修改XP系統的boot.ini檔案

    如何手動修改XP系統的boot.ini檔案

boot.ini檔案裡填入如下內容:

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的參考文件裡面有,這裡貼上一下:

-b

(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. See Crashing and Rebooting the Target Computerfor details and for other methods of changing this status.

 

-k [ConnectType]

(Kernel mode only) Starts a kernel debugging session. For details, see Choosing Kernel Debugging Settings. If -k is used without anyConnectType options following it, it must be the final entry on the command line.

 

resets=0

Specifies that an unlimited number of reset packets can be sent to the target when the host and target are synchronizing. Use the resets=0parameter 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),也有國內的網友寫好了一箇中文版的(http://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裡執行驅動載入/解除安裝工具把我們的驅動載入起來。可以看到,已經斷下來了,我們可以原始碼除錯驅動了:

注:開啟原始檔和設定符號路徑可以在一開始的時候就做,這是沒有嚴格先後順序的。