天天看點

Windbg核心調試之三: 調試驅動

這次我們通過一個實際調試驅動的例子,來逐漸體會Windbg在核心調試中的作用.

由于條件所限,大多數情況下,很多人都是用VMware+Windbg調試核心(VMware的确是個好東西

Windbg核心調試之三: 調試驅動

).但這樣的調試需要占用大量的系統資源,對于和我一樣急性子的朋友來說這是不可接受的:).利用雙機調試就可以讓你一邊喝咖啡一邊輕松的看結果,而不至于郁悶的等待每次長達數分鐘的系統響應.有關雙機調試的基本設定,請參考:http://www.cnblogs.com/Sonic2007/archive/2008/03/20/1114807.html

本次調試驅動所建構的環境如下:

host computer: WinXP+Windbg

Target computer:  Vista SP1

driver object: sys

connect setting: 1394資料線

說明: 1.1394卡在很多機器上都已經沒有了,Vista也取消了1394的資料連接配接協定

Windbg核心調試之三: 調試驅動

(調試還是可以的),但不可否認的是利用1394資料線連接配接調試要比COM口和USB速率快很多(為什麼好用的東西卻得不到支援!

Windbg核心調試之三: 調試驅動

).2.本次調試的driver是公司開發的某個軟體的驅動程式,拿來嘗試在Vista SP1下track.由于涉及到商業機密,本驅動源代碼不便公開.3.Vista SP1就沒什麼好說的了,前些天才釋出,MS又一個失敗的典型.

OK,Let's go!

該驅動是一個類型sr.sys(MS的System Restore驅動)的Filter Driver,屬于檔案系統過濾驅動,加載在檔案系統驅動上層,由Filter Manager負責與使用者層和底層通信.連接配接到目标機後,按下Ctrl+break中斷目前狀态.(注:你也可以進入到explorer之後再中斷,為了了解驅動加載時的進入點,以及系統啟動時核心的裝态,我們中斷到這裡)

Microsoft (R) Windows Debugger  Version 6.6.0007.5

Copyright (c) Microsoft Corporation. All rights reserved.

Using 1394 for debugging

Opened \\.\DBG1394_INSTANCE01

Waiting to reconnect...

Connected to Windows Vista 6000 x86 compatible target, ptr64 FALSE

Kernel Debugger connection established.

Symbol search path is: D:\symbolslocal; D:\IR\SystemOK\Restore\Driver\objchk_wlh_x86\i386

Executable search path is: 

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntkrnlmp.exe - 

Windows Vista Kernel Version 6000 MP (1 procs) Free x86 compatible

Built by: 6000.16584.x86fre.vista_gdr.071023-1545

Kernel base = 0x81800000 PsLoadedModuleList = 0x81908ad0

System Uptime: not available

WARNING: Whitespace at start of path element

Break instruction exception - code 80000003 (first chance)

*******************************************************************************

*                                                                                                                                           

*   You are seeing this message because you pressed either                                                         

*       CTRL+C (if you run kd.exe) or,                                        

*       CTRL+BREAK (if you run WinDBG),                                      

*   on your debugger machine's keyboard.                                      

*                                                                             

*                   THIS IS NOT A BUG OR A SYSTEM CRASH                       

* If you did not intend to break into the debugger, press the "g" key, then   

* press the "Enter" key now.  This message might immediately reappear.  If it 

* does, press "g" and "Enter" again.                                          

nt!RtlpBreakWithStatusInstruction:

818355e8 cc              int     3

然後,在Command line裡鍵入lm,檢視目前系統加載的子產品和驅動(會發現我們的driver列在其中):

kd> lm

start    end        module name

80404000 80412000   PCIIDEX    (deferred)             

80412000 80419000   intelide   (deferred)             

80419000 80429000   mountmgr   (deferred)             

80429000 80438000   volmgr     (deferred)             

80438000 8045d000   pci        (deferred)             

8045d000 80465000   msisadrv   (deferred)             

80465000 8046e000   WMILIB     (deferred)             

8046e000 804b1000   acpi       (deferred)             

804b1000 804be000   WDFLDR     (deferred)             

804be000 80539000   Wdf01000   (deferred)             

80539000 8061a000   CI         (deferred)             

8061a000 80655000   CLFS       (deferred)             

80655000 8065d000   BOOTVID    (pdb symbols)          

8065d000 80666000   PSHED      (deferred)             

80666000 806c6000   mcupdate_GenuineIntel   (deferred)             

806c6000 806ce000   kdcom      (deferred)             

81800000 81b95000   nt         (pdb symbols)          

81b95000 81bc9000   hal        (pdb symbols)         

81c06000 81c0e000   spldr      (deferred)             

81c0e000 81c44000   volsnap    (deferred)             

81c44000 81cae000   ksecdd     (deferred)             

81cae000 81db6000   Ntfs       (deferred)             

81db6000 81def000   NETIO      (deferred)             

81def000 81e1a000   msrpc      (deferred)             

81e1a000 81f1e000   ndis       (deferred)             

81f1e000 81f270c0   PxHelp20   (deferred)             

81f28000 81f4f000   sys32v   (private pdb symbols)  

81f4f000 81f5f000   fileinfo   (deferred)             

81f5f000 81f90000   fltmgr     (deferred)             

81f90000 81fae000   ataport    (deferred)             

81fae000 81fb6000   atapi      (deferred)             

81fb6000 82000000   volmgrx    (deferred)             

8234f000 82358000   crcdisk    (deferred)             

82358000 82368000   agp440     (deferred)             

82368000 82389000   CLASSPNP   (deferred)             

82389000 8239a000   disk       (deferred)             

8239a000 823bd000   fvevol     (deferred)             

823bd000 823e2000   ecache     (deferred)             

823e2000 823f1000   mup        (deferred)             

823f1000 82400000   partmgr    (deferred)   

注: 若符号檔案沒有加載成功,Windbg會提示響應的符号找不到,不過一般Windbg會自己尋找符号檔案路徑.實在找不到時,就包含

srv*c:\symbols*http://msdl.microsoft.com/download/symbols, 然後reload一下(!reload).

另外,鍵入lm t n, 我們可以檢視更為詳細的子產品及驅動資訊.

然後,鍵入!thread和Kp,檢視目前的線程詳細資訊和堆棧(或者Alt+6也可以看stack).注意目前thread的ID:

kd> !thread

THREAD 84254ae8  Cid 0004.0008  Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0

Not impersonating

Owning Process            84254d90       Image:         System

Wait Start TickCount      0              Ticks: 1 (0:00:00:00.015)

Context Switch Count      1             

UserTime                  00:00:00.0000

KernelTime                00:00:00.0015

Win32 Start Address nt!Phase1Initialization (0x819433ae)

Stack Init 81c06000 Current 81c05db8 Base 81c06000 Limit 81c03000 Call 0

Priority 31 BasePriority 8 PriorityDecrement 0

ChildEBP RetAddr  Args to Child              

81c05af0 818aa92c 00000001 81867999 0002625a nt!RtlpBreakWithStatusInstruction (FPO: [1,0,0])

81c05af8 81867999 0002625a 00000000 00000001 nt!KdCheckForDebugBreak+0x22 (FPO: [0,0,0])

81c05b18 81836cfd 81928100 000000d1 81c05b9c nt!KeUpdateRunTime+0x270

81c05b18 81ba4130 81928100 000000d1 81c05b9c nt!KeUpdateSystemTime+0xed (FPO: [0,2] TrapFrame @ 81c05b28)

81c05b9c 81ba3fd0 81bb28a0 8181dced 81c05bc8 hal!XmGetCodeByte+0x30 (FPO: [Non-Fpo])

81c05bac 81ba40c5 81bb28a0 0000c000 00001da4 hal!XmEmulateStream+0x88 (FPO: [Non-Fpo])

81c05bc8 81ba374d 00000010 81c05c0c 8181dced hal!XmEmulateInterrupt+0x80 (FPO: [Non-Fpo])

81c05bdc 81ba0a1c 00000010 81c05c0c 00000000 hal!x86BiosExecuteInterruptShadowed+0x43 (FPO: [Non-Fpo])

81c05bf8 81ba0a5b 00000010 81c05c0c 00000000 hal!x86BiosCall+0x22 (FPO: [Non-Fpo])

81c05c2c 80656697 80806ae0 8080f438 00000000 hal!HalpBiosDisplayReset+0x25 (FPO: [Non-Fpo])

81c05c58 81b2cd6d 00000001 81b0ab01 80806ae0 BOOTVID!VidInitialize+0x135 (FPO: [Non-Fpo])

81c05c7c 81b3f098 00000001 80806ae0 00000007 nt!InbvDriverInitialize+0x81

81c05d74 819433bb 81c05dc0 819afbad 80806ae0 nt!Phase1InitializationDiscard+0xd0

81c05d7c 819afbad 80806ae0 81c0e680 00000000 nt!Phase1Initialization+0xd

81c05dc0 8189a346 819433ae 80806ae0 00000000 nt!PspSystemThreadStartup+0x9d

00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16

kd> kp

ChildEBP RetAddr  

81c05af0 818aa92c nt!RtlpBreakWithStatusInstruction

81c05af8 81867999 nt!KdCheckForDebugBreak+0x22

81c05b18 81836cfd nt!KeUpdateRunTime+0x270

81c05b18 81ba4130 nt!KeUpdateSystemTime+0xed

81c05b9c 81ba3fd0 hal!XmGetCodeByte+0x30

81c05bac 81ba40c5 hal!XmEmulateStream+0x88

81c05bc8 81ba374d hal!XmEmulateInterrupt+0x80

81c05bdc 81ba0a1c hal!x86BiosExecuteInterruptShadowed+0x43

81c05bf8 81ba0a5b hal!x86BiosCall+0x22

81c05c2c 80656697 hal!HalpBiosDisplayReset+0x25

81c05c58 81b2cd6d BOOTVID!VidInitialize+0x135

81c05c7c 81b3f098 nt!InbvDriverInitialize+0x81

81c05d74 819433bb nt!Phase1InitializationDiscard+0xd0

81c05d7c 819afbad nt!Phase1Initialization+0xd

81c05dc0 8189a346 nt!PspSystemThreadStartup+0x9d

00000000 00000000 nt!KiThreadStartup+0x16

鍵入!process [PID] 0, 查到目前程序:

kd> !process 0004.0008 0

PROCESS 84254d90  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000

    DirBase: 00122000  ObjectTable: 830001d0  HandleCount:   1.

    Image: System

    VadRoot 00000000 Vads 0 Clone 0 Private 0. Modified 0. Locked 0.

    DeviceMap 00000000

    Token                             83003830

    ElapsedTime                       00:00:00.015

    UserTime                          00:00:00.000

    KernelTime                        00:00:00.000

    QuotaPoolUsage[PagedPool]         0

    QuotaPoolUsage[NonPagedPool]      0

    Working Set Sizes (now,min,max)  (4, 0, 0) (16KB, 0KB, 0KB)

    PeakWorkingSetSize                0

    VirtualSize                       0 Mb

    PeakVirtualSize                   0 Mb

    PageFaultCount                    0

    MemoryPriority                    BACKGROUND

    BasePriority                      8

    CommitCharge                      0

        THREAD 84254ae8  Cid 0004.0008  Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0

在lm指令列出的資訊中,start是子產品的起始位址,通過鍵入"u 驅動起始位址",我們可以反彙編出它的代碼:

kd> u 81f28000

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0x0):

81f28000 4d              dec     ebp

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0x1):

81f28001 5a              pop     edx

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0x2):

81f28002 90              nop

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0x3):

81f28003 0003            add     byte ptr [ebx],al

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0x5):

81f28005 0000            add     byte ptr [eax],al

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0x7):

81f28007 000400          add     byte ptr [eax+eax],al

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0xa):

81f2800a 0000            add     byte ptr [eax],al

sys32v!SysAllocatePostCopyWorkItem <PERF> (sys32v+0xc):

81f2800c ff              ???

逐漸查找(enter),最終我們可以發現driver的入口點.這個過程其實是非常慢的,因為系統核心在加載驅動實際代碼的過程中進行了N多次調用.如果我們本身有驅動的代碼,也可以直接包含源代碼路徑,通過在實際代碼中設定斷點,讓Windbg自己中斷到相應的代碼位置(在實際調試核心的過程中,這幾乎是不可能的,因為你不會得到Windows核心或某個驅動程式的源代碼.Linux系列的某些driver們又另當别論).這裡為了友善,我包含了sys的源代碼,增加斷點直接走到DriverEntry例程:

kd> u 81f42780

sys32v!DriverEntry [隐藏了address]:

81f42780 8bff            mov     edi,edi

81f42782 55              push    ebp

81f42783 8bec            mov     ebp,esp

81f42785 51              push    ecx

81f42786 c745fc010000c0  mov     dword ptr [ebp-4],0C0000001h

81f4278d a1749cf481      mov     eax,dword ptr [sys32v!SysDbgFlags (81f49c74)]

81f42792 83e004          and     eax,4

81f42795 7424            je      sys32v!DriverEntry+0x3b (81f427bb)

其中顯示的彙編代碼,是核心調用驅動是進行的操作,其實也和實際代碼相對應.

在driver代碼中,如果要檢視目前參數值,用dv指令:

kd> dv

   DriverObject = 0x84663730

   RegistryPath = 0x8084b560

         status = 8

       dontload = 0

另外,用"dt 參數名"可以看某個參數的目前值.

kd> dt DriverObject

Local var @ 0x81c05af8 Type _DRIVER_OBJECT*

0x84663730 

   +0x000 Type             : 4

   +0x002 Size             : 168

   +0x004 DeviceObject     : (null) 

   +0x008 Flags            : 2

   +0x00c DriverStart      : 0x81f28000 

   +0x010 DriverSize       : 0x27000

   +0x014 DriverSection    : 0x84230a68 

   +0x018 DriverExtension  : 0x846637d8 _DRIVER_EXTENSION

   +0x01c DriverName       : _UNICODE_STRING "\FileSystem\Sys"

   +0x024 HardwareDatabase : 0x81af6ed8 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"

   +0x028 FastIoDispatch   : (null) 

   +0x02c DriverInit       : 0x81f4a005     sys32v!GsDriverEntry+0

   +0x030 DriverStartIo    : (null) 

   +0x034 DriverUnload     : (null) 

   +0x038 MajorFunction    : [28] 0x8189a5c1     nt!IopInvalidDeviceRequest+0

這樣,我們就可以通過上述的這些指令,逐漸分析一個驅動程式在加載和執行過程中的情況。另外,Windbg還有衆多核心調試指令,如!irp可以檢視一個對象的資料結構,!devobj可以檢視裝置對象等,在今後的作業系統核心學習過程中會不斷用到這些指令。

從上面的操作過程我們可以看出,利用Windbg調試驅動程式,或者說進行核心調試,是非常友善的。如果我們對Windows核心有一定的了解,同時擁有一定彙編語言的功底,就可以有Windbg進行簡單的系統排障(比如系統加載是出現藍屏,或是某個系統子產品出現問題)、驅動學習等。同時,這個過程也可以讓我們更深入的了解作業系統原理。另外,Windbg也可以進行系統服務(service)的調試,這就是User mode的調試過程了。

繼續閱讀