新聞中心

EEPW首頁 > Windows內(nèi)核調(diào)試器原理淺析(四)

Windows內(nèi)核調(diào)試器原理淺析(四)

——
作者: 時間:2007-04-18 來源: 收藏
SoftICE的原理和WinDBG完全不一樣。它通過替換正常系統(tǒng)中的中斷處理程序來獲得系統(tǒng)的控制權(quán),也正因為這樣它才能夠?qū)崿F(xiàn)單機調(diào)試。它的功能實現(xiàn)方法很底層,很少依賴與windows給的接口函數(shù),大部分功能的實現(xiàn)都是靠IO端口讀寫等來完成的。

    SoftICE替換了IDT表中以下的中斷(陷阱)處理程序:

    0x1:    單步陷阱處理程序
    0x2:    NMI不可屏蔽中斷
    0x3:    調(diào)試陷阱處理程序
    0x6:    無效操作碼陷阱處理程序
    0xb:    段不存在陷阱處理程序
    0xc:    堆棧錯誤陷阱處理程序
    0xd:    一般保護性錯誤陷阱處理程序
    0xe:    頁面錯誤陷阱處理程序
    0x2d:    調(diào)試服務(wù)陷阱處理程序
    0x2e:    系統(tǒng)服務(wù)陷阱處理程序
    0x31:    8042鍵盤控制器中斷處理程序
    0x33:    串口2(Com2)中斷處理程序
    0x34:    串口1(Com1)中斷處理程序
    0x37:    并口中斷處理程序
    0x3c:    PS/2鼠標(biāo)中斷處理程序
    0x41:    未使用

    (這是在PIC系統(tǒng)上更換的中斷。如果是APIC系統(tǒng)的話更換的中斷號有不同,但同樣是更換這些中斷處理程序)

    其中關(guān)鍵是替換了0x3 調(diào)試陷阱處理程序和0x31 i8042鍵盤中斷處理驅(qū)動程序(鍵盤是由i8042芯片控制的),SoftICE從這兩個地方獲取系統(tǒng)的控制權(quán)。
    
    啟動softICE服務(wù)后SoftICE除了更換了IDT里的處理程序,還有幾點重要的,一是HOOK了i8042prt.sys里的READ_PORT_UCHAR函數(shù),因為在對0x60端口讀后,會改變0x64端口對應(yīng)控制寄存器的狀態(tài)。所以在SoftICE的鍵盤中斷控制程序讀了0x60端口后并返回控制權(quán)給正常的鍵盤中斷控制程序后,不要讓它再讀一次。還有就是把物理內(nèi)存前1MB的地址空間通過調(diào)用MmMapIoSpace映射到虛擬的地址空間里,里面包括顯存物理地址,以后重畫屏幕就通過修改映射到虛擬地址空間的這段顯存內(nèi)容就行了。

    如果顯示模式是彩色模式,那么顯存起始地址是0xb8000,CRT索引寄存器端口0x3d4,CRT數(shù)據(jù)寄存器端口0x3d5。如果顯示模式是單色模式,那么顯存起始地址是0xb0000,CRT索引寄存器端口0x3b4,CRT數(shù)據(jù)寄存器端口0x3b5。首先寫索引寄存器選擇要進行設(shè)置的顯示控制內(nèi)部寄存器之一(r0-r17),然后將參數(shù)寫到其數(shù)據(jù)寄存器端口。

    i8042鍵盤控制器中斷控制驅(qū)動程序在每按下一個鍵和彈起一個鍵都會被觸發(fā)。SoftICE在HOOK了正常的鍵盤中斷控制程序獲得系統(tǒng)控制權(quán)后,首先從0x60端口讀出按下鍵的掃描碼然后向0x20端口發(fā)送通用EOI(0x20)表示中斷已結(jié)束,如果沒有按下激活熱鍵(ctrl+d),則返回正常鍵盤中斷處理程序。如果是按下熱鍵則會判斷控制臺(就是那個等待輸入命令的顯示代碼的黑色屏幕)是否被激活,未被激活的話則先激活。然后設(shè)置IRQ1鍵盤中斷的優(yōu)先級為最高,同時設(shè)置兩個8259A中斷控制器里的中斷屏蔽寄存器(向0x21和0xa1發(fā)中斷掩碼,要屏蔽哪個中斷就把哪一位設(shè)為1),只允許IRQ1(鍵盤中斷)、IRQ2(中斷控制器2級聯(lián)中斷,因為PS/2鼠標(biāo)中斷是歸8259A-2中斷控制器管的,只有開放IRQ2才能響應(yīng)來自8259A-2管理的中斷)、IRQ12(PS/2鼠標(biāo)中斷,如果有的話),使系統(tǒng)這時只響應(yīng)這3個中斷。新的鍵盤和鼠標(biāo)中斷處理程序會建立一個緩沖區(qū),保存一定數(shù)量的輸入掃描信息。當(dāng)前面的工作都完成后會進入一段循環(huán)代碼,負責(zé)處理鍵盤和鼠標(biāo)輸入的掃描碼緩沖區(qū),同時不斷地更新顯存的映射地址緩沖區(qū)重畫屏幕(這段循環(huán)代碼和WinDBG里循環(huán)等待從串口發(fā)來的包的原理是一樣的,都是在后臺循環(huán)等待用戶的命令)。這段循環(huán)代碼是在激活控制臺的例程里調(diào)用的,也就是說當(dāng)控制臺已被激活的話正常流程不會再次進入這段循環(huán)代碼的(廢話,再進入系統(tǒng)不就死循環(huán)了)。當(dāng)有一個新的鍵按下時,都會重新調(diào)用一遍鍵盤中斷處理程序,因為控制臺已激活,所以它只是簡單地更新鍵盤輸入緩沖區(qū)內(nèi)容然后iret返回。它并不會返回正常的鍵盤中斷處理程序,因為那樣會交出控制權(quán)(想證明這點也很簡單,在SoftICE里斷正常的鍵盤中斷處理程序,然后g,1秒后在這里斷下,這是我們可以F10,如果SoftICE會把控制權(quán)交給正常的鍵盤中斷處理程序的話,在這里早就發(fā)生死循環(huán)了)。鼠標(biāo)中斷驅(qū)動也是一樣。這個時候?qū)嶋Hiret返回到的還是那段循環(huán)代碼里面,所以被調(diào)試的代碼并不會被執(zhí)行,除非按下了F10之類的鍵,它會指示退出循環(huán)返回最開始時的中斷處理程序,然后再iret返回最開始中斷的地方。當(dāng)然,因為設(shè)置了EFLAG里的TF位,執(zhí)行了一個指令又會通過單步的處理程序進入那段循環(huán)的代碼。

    而處理int 0x3也差不多,若沒有激活控制臺則先激活并屏蔽除了鍵盤、鼠標(biāo)及8259A-2中斷控制器外的所有中斷,然后進入那段循環(huán)代碼。

    作為對比同樣來看一下在SoftICE里處理int 0x3和單步的過程。當(dāng)執(zhí)行到int 0x3時,激活控制臺并屏蔽中斷,然后將int 0x3指令前后范圍的指令反匯編并寫入顯存映射地址空間,并把最新的寄存器值也寫進去,最后在后臺循環(huán)等待鍵盤輸入命令。當(dāng)命令是F10時,設(shè)置好EFLAG的TF位,清除8259A中斷控制器里的中斷屏蔽寄存器,開放所有中斷,將控制臺清除,從循環(huán)代碼中返回新鍵盤(或int 0x3)中斷處理程序,然后再返回到正常鍵盤(或int 0x3)中斷處理程序,由這里iret到被中斷代碼處執(zhí)行。執(zhí)行了一個指令后因為發(fā)生單步異常又進入后臺循環(huán)代碼。

    SoftICE里的單步比WinDBG要快得多的原因很簡單,SoftICE只需要把反匯編出來的代碼和數(shù)據(jù)經(jīng)過簡單處理再寫入顯存映射地址緩沖區(qū)里刷新屏幕就可以繼續(xù)執(zhí)行了,省略了串行的發(fā)包收包,怎么會不快。而中斷系統(tǒng)更快,按下鍵中斷就會發(fā)生,根本不用象WinDBG等時鐘中斷才能把系統(tǒng)斷下來。


評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉