!chkimg

!chkimg 延伸模組會藉由將可執行檔的映射與符號存放區或其他檔案存放庫上的複本進行比較,來偵測可執行檔映像中的損毀。

!chkimg [Options] [-mmw LogFile LogOptions] [Module]

參數

選項 下列選項的任何組合:

-p **** SearchPath
在存取符號伺服器之前,遞歸地搜尋 SearchPath 中的檔案。

-f
修正映像中的錯誤。 每當掃描偵測到符號存放區上的檔案與記憶體中的影像之間的差異時,符號存放區上的檔案內容就會複製到映射上。 如果您正在執行即時偵錯,您可以在執行 !chkimg -f 擴充功能之前先建立傾印檔案。

-nar
防止行動符號伺服器上檔案的對應影像。 根據預設,當檔案的複本位於符號伺服器上並對應至記憶體時, !chkimg 會將檔案的影像移至符號伺服器上。 不過,如果您使用 -nar 選項,則不會移動伺服器中的檔案影像。

已位於記憶體中的可執行映像(也就是正在掃描的映像)會移動,因為調試程式一律會重新放置載入的映像。

只有當操作系統已經移動原始映射時,這個參數才有用。 如果影像尚未移動, !chkimg 和調試程式將會移動映射。 使用此參數是罕見的。

-ss **** SectionName
將掃描限制為名稱包含 String SectionName 的區段。 掃描會包含名稱包含此字串的任何不可捨棄區段。 SectionName 區分大小寫,不能超過 8 個字元。

-如
導致掃描包含影像的所有區段,但可捨棄的區段除外。 根據預設,掃描會略過可寫入的區段、不是可執行檔的區段、名稱中有 「PAGE」 的區段,以及可捨棄的區段。

-r **** StartAddress **** EndAddress
將掃描限制為以 StartAddress 開頭的記憶體範圍,並以 EndAddress 結尾。 在此範圍內,通常會掃描任何通常會掃描的區段。 如果區段部分與這個範圍重疊,則會掃描與這個範圍重疊的區段部分。 即使您也使用 -as-ss 參數,掃描也受限於此範圍。

-nospec
導致掃描包含Hal.dll和Ntoskrnl.exe的保留區段。 根據預設, !chkimg 不會檢查這些檔案的某些部分。

-noplock
顯示具有位元組值0x90( nop 指令)和位元組值0xF0 ( 鎖定 指令) 不相符的區域。 根據預設,不會顯示這些不相符專案。

-np
導致辨識已修補的指示。

-d
顯示掃描發生時所有不相符區域的摘要。 如需此摘要文字的詳細資訊,請參閱一節。

-分貝
以類似 db 調試程式命令的格式顯示不相符的區域。 因此,每個顯示行都會顯示該行中第一個字節的位址,後面接著最多 16 個十六進位元組值。 位元組值緊接在對應的 ASCII 值後面。 所有不可列印的字元,例如歸位字元和換行字元,都會顯示為句點(.)。 不相符的位元組會以星號 \.

-lo ****
將 -d-db 顯示的輸出行數目限制為行數。

-v
顯示詳細資訊資訊。

-mmw
建立記錄檔,並記錄此檔案中 !chkimg 的活動。 記錄檔的每一行都代表單一不符。

LogFile
指定記錄檔的完整路徑。 如果您指定相對路徑,路徑會相對於目前的路徑。

LogOptions
指定記錄檔的內容。 LogOptions 是包含各種字母串連的字串。 記錄檔中的每個行都包含數個以逗號分隔的數據行。 這些數據行包含下列選項字母所指定的項目,順序是字母出現在LogOptions字串中。 您可以多次包含下列選項。 您必須至少包含一個選項。

記錄選項 記錄檔中包含的資訊

v

不相符的虛擬位址

r

模組內不相符的位移(相對位址)

s

對應至不相符位址的符號

S

包含不相符之區段的名稱

e

預期在不相符位置的正確值

w

位於不相符位置的不正確值

LogOptions 也可以包含下列部分或無其他選項。

記錄選項 效果

o

如果名稱為 LogFile檔案已經存在,則會覆寫現有的檔案。 根據預設,調試程式會將新資訊附加至任何現有檔案的結尾。

t字串

將額外的數據行加入至記錄檔。 此數據行中的每個專案都包含 String如果您將新資訊附加至現有的記錄檔,而且您必須區分新記錄與舊記錄,則 tString 選項很有用。 您無法在 tString 之間新增空白。 如果您使用 t I String 選項,它必須是 LogOptions 中的最後一個選項,因為 String 會採用來包含下一個空格之前存在的所有字元。

例如,如果 LogOptionsrSewo,則記錄檔的每一行都包含不相符位置的相對地址和區段名稱,以及該位置的預期和實際值。 此選項也會覆寫任何先前的檔案。 如果您想要建立數個具有不同選項的記錄檔,可以使用 -mmw 參數多次。 您最多可以同時建立10個記錄檔。

模組
指定要檢查的模組。 模組 可以是模組的名稱、模組的起始位址,或模組中包含的任何位址。 如果您省略 Module,調試程式會使用包含目前指令指標的模組。

DLL

Windows XP 和更新版本

Ext.dll

備註

當您使用 !chkimg 時,它會比較記憶體中可執行檔的影像與位於符號存放區上的檔案複本。

除了可捨棄的區段、不可寫入的區段、不是可執行檔、名稱中有 “PAGE” 或來自 INITKDBG 的區段之外,都會比較檔案的所有區段。 您可以使用 -ss、-as 或 -r 參數來變更此行為。

!chkimg 會將影像與檔案之間的任何不相符顯示為影像錯誤,但有下列例外狀況:

  • 不會檢查匯入位址表 (IAT) 所佔用的位址。

  • 不會檢查Hal.dll和Ntoskrnl.exe中的特定位址,因為載入這些區段時會發生某些變更。 若要檢查這些位址,請包含 -nospec 選項。

  • 如果0x90的位元組值存在於檔案中,而且0xF0的值存在於影像的對應位元組中(反之亦然),則這種情況會被視為相符。 一般而言,符號伺服器會保存單處理器和多處理器版本中有一個二進位檔版本。 在 x86 型處理器上 ,鎖定 指令會0xF0,而此指令會對應至 單處理器版本中的 nop (0x90) 指令。 如果您想要 !chkimg 將此配對顯示為不相符,請設定 -noplock 選項。

注意 如果您使用 -f 選項來修正映射不符, !chkimg 只會修正它視為錯誤的不相符專案。 例如, !chkimg 不會將0x90位元組變更為0xF0位元組,除非您包含 -noplock

當您包含 -d 選項時, !chkimg 會在掃描發生時顯示所有不相符區域的摘要。 每一個不相符都會顯示在兩行上。 第一行包含範圍的開頭、範圍的結尾、範圍的大小、對應至範圍開頭的符號名稱和位移,以及自最後一個錯誤之後的位元元組數目(以括弧括起)。 第二行以括弧括住,並包含預期的十六進位元組值、冒號,然後包含影像中實際遇到的十六進位位元組值。 如果範圍超過8個字節,則冒號和冒號之後只會顯示前8個字節。 下列範例顯示這種情況。

be000015-be000016  2 bytes - win32k!VeryUsefulFunction+15 (0x8)
     [ 85 dd:95 23 ]

有時候,驅動程式會使用攔截、重新導向或其他方法來改變Microsoft Windows 核心的一部分。 即使是不再位於堆疊上的驅動程式也可能會改變核心的一部分。 您可以使用 !chkimg 延伸模組做為檔案比較工具,以判斷驅動程式正在改變 Windows 核心的哪些部分,以及變更元件的方式。 此比較在完整傾印檔案上最為有效。

檢查每個載入的模組

您也可以搭配 !for_each_module 擴充功能使用 !chkimg 來檢查每個已載入模組的映射。 下列範例顯示這種情況。

!for_each_module !chkimg @#ModuleName 

!analyze 範例

假設您遇到錯誤檢查,例如,從 ! analyze 開始。

kd> !analyze 
....
BugCheck 1000008E, {c0000005, bf920e48, baf75b38, 0}
Probably caused by : memory_corruption
CHKIMG_EXTENSION: !chkimg !win32k
....

在此範例中 ,!analyze 輸出會建議發生記憶體損毀,並包含CHKIMG_EXTENSION行,指出Win32k.sys可能是損毀的模組。 (即使此行不存在,您也可以考慮在堆疊頂端的模組中可能損毀。從不使用 任何參數的 !chkimg 開始,如下列範例所示。

kd> !chkimg win32k
Number of different bytes for win32k: 31

下列範例顯示確實有記憶體損毀。 使用 !chkimg -d 來顯示 Win32k 模組的所有錯誤。

kd> !chkimg win32k -d
    bf920e40-bf920e46  7 bytes - win32k!HFDBASIS32::vSteadyState+1f
        [ 78 08 d3 78 0c c2 04:00 00 00 00 00 01 00 ]
    bf920e48-bf920e5f  24 bytes - win32k!HFDBASIS32::vHalveStepSize (+0x08)
        [ 8b 51 0c 8b 41 08 56 8b:00 00 00 00 00 00 00 00 ]
Number of different bytes for win32k: 31

當您嘗試反組譯所列第二個區段的損毀映射時,可能會發生下列輸出。

kd> u  win32k!HFDBASIS32::vHalveStepSize
win32k!HFDBASIS32::vHalveStepSize:
bf920e48 0000             add     [eax],al
bf920e4a 0000             add     [eax],al
bf920e4c 0000             add     [eax],al
bf920e4e 0000             add     [eax],al
bf920e50 7808            js win32k!HFDBASIS32::vHalveStepSize+0x12 (bf920e5a)
bf920e52 d3780c           sar     dword ptr [eax+0xc],cl
bf920e55 c20400           ret     0x4
bf920e58 8b510c           mov     edx,[ecx+0xc]

然後,使用 !chkimg -f 來修正記憶體損毀。

kd> !chkimg win32k -f
Warning: Any detected errors will be fixed to what we expect!
Number of different bytes for win32k: 31 (fixed)

現在您可以反組譯已更正的檢視,並查看您所做的變更。

kd> u  win32k!HFDBASIS32::vHalveStepSize
win32k!HFDBASIS32::vHalveStepSize:
bf920e48 8b510c           mov     edx,[ecx+0xc]
bf920e4b 8b4108           mov     eax,[ecx+0x8]
bf920e4e 56               push    esi
bf920e4f 8b7104           mov     esi,[ecx+0x4]
bf920e52 03c2             add     eax,edx
bf920e54 c1f803           sar     eax,0x3
bf920e57 2bf0             sub     esi,eax
bf920e59 d1fe             sar     esi,1

調查記憶體和記憶體損毀

隨機檔案和記憶體損毀可能難以調查。 在某些情況下要考慮的一個工具是啟用額外的記憶體檢查,例如使用驅動程式驗證器。 如需驅動程式驗證器的相關信息,請參閱 驅動程序驗證器

若要測試物理記憶體,請使用 Windows 記憶體診斷工具。 其使用方式和其他一般技術會在藍色屏幕數據說明。

使用掃描磁碟公用程式來識別檔案系統錯誤。 在您要掃描的磁碟驅動器上選取並按住 (或以滑鼠右鍵按兩下),然後選取 [ 屬性]。 選取 [工具]。 選取 [立即核取] 按鈕。