天天看點

DDK樣例toaster分析(1)

    msddk樣例中toaster是一個比較完整和值得學習的pnp驅動,包括了一個完整的裝置棧(含總線驅動/功能驅動,以及裝置棧中各層過濾驅動)和驅動安裝程式(含驅動安裝包/類安裝程式/協安裝程式)。本篇記錄在xp下調試busenum驅動入口(關于環境的搭建網上一搜一大把,這裡就省了,當然也可以參考這篇:​​win7 x64部署和序列槽調試虛拟驅動toaster​​)。

    通過新增硬體的方式安裝busenum.sys後,會依次進入busenum.c!DriverEntry和pnp.c!Bus_AddDevice。AddDevice是本篇的重點,是以進入DriverEntry後在這個函數上下一個斷點:

kd> lmvm busenum //檢視驅動和調試符号加載是否正确
start    end        module name
b20e9000 b20f2b80   busenum    (private pdb symbols)  d:\winddk\7600.16385.1\src\general\toaster\wdm\bus\objchk_wxp_x86\i386\BusEnum.pdb
    Loaded symbol image file: busenum.sys 

kd> !itoldyouso busenum
busenum.sys
    Timestamp: 57639546
  SizeOfImage: 9B80
          pdb: d:\winddk\7600.16385.1\src\general\toaster\wdm\bus\objchk_wxp_x86\i386\BusEnum.pdb
      pdb sig: A0EB3691-6995-416E-9BF4-C25A160C9318
          age: 1
Loaded pdb is d:\winddk\7600.16385.1\src\general\toaster\wdm\bus\objchk_wxp_x86\i386\BusEnum.pdb
BusEnum.pdb
      pdb sig: A0EB3691-6995-416E-9BF4-C25A160C9318
          age: 1

MATCH: BusEnum.pdb and busenum.sys      

确定sys檔案加載正确後,查找函數并下斷點,然後繼續運作:

kd> x busenum!Bus_AddDevice
b20eca60 busenum!Bus_AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)
kd> bp busenum!Bus_AddDevice
kd> bl
 1 e b20eca60     0001 (0001) busenum!Bus_AddDevice      

當windbg進入Bus_AddDevice遇到斷點時,函數有兩個參數:PDRIVER_OBJECT DriverObject和PDEVICE_OBJECT PhysicalDeviceObject。DriverObject很好了解,就是busenum.sys,有windbg為證:

kd> dd DriverObject l1
f8ae99e8  8227a3b8

kd> !drvobj 8227a3b8
Driver object (8227a3b8) is for:
 \Driver\busenum      

PhysicalDeviceObject是什麼 呢?如果是pnp裝置驅動,那很簡單,這就是底層總線驅動對應的裝置。但busenum本身是總線驅動,誰提供底層裝置?答案是pnp管理器

kd> dd PhysicalDeviceObject l1
f8ae99ec  81f41030
kd> !devobj 81f41030 ---> 這個裝置是pnp建立的裝置
Device object (81f41030) is for:
 00000082 \Driver\PnpManager DriverObject 823eb2b0 ---> windbg指出,建立裝置對象的驅動對象

kd> !drvobj 823eb2b0
Driver object (823eb2b0) is for:
 \Driver\PnpManager  --->驅動對象
Driver Extension List: (id , addr)
該驅動對象的裝置對象
Device Object list:
81f41030  823e73d0  823e7610  823e7850      

原來,pnp管理器為了維護一顆裝置樹,在加載總線驅動前會為總線裝置建立一個pnpmanage裝置對象,作為裝置棧的棧底對象,讓總線裝置attach上去。在busenum.sys代碼中也有這種裝置棧的上下展現:

NTSTATUS
Bus_AddDevice(
    __in PDRIVER_OBJECT DriverObject,
    __in PDEVICE_OBJECT PhysicalDeviceObject
    )
{
    status = IoCreateDevice (
                    DriverObject,...,&deviceObject);
    deviceData->UnderlyingPDO = PhysicalDeviceObject;
    deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (
                                    deviceObject,
                                    PhysicalDeviceObject);
}      

首先代碼建立busenum.sys的裝置對象,然後attach到pnpmanager裝置對象上。難怪toaster的幫助文檔中注釋這個對象為Fdo,而把Bus_AddDevice的第二個參數認為是Pdo。

來看下建立裝置後裝置棧情況:

kd> !drvobj 8227a3b8
Driver object (8227a3b8) is for:
 \Driver\busenum
Driver Extension List: (id , addr)
;相比剛進入DriverEntry時,現在busenum驅動對象下已經有一個裝置對象了,這個就是調用IoCreateDevice時建立的
Device Object list:
81f2a930      
kd> dd deviceObject l1
f8ae99dc  81f2a930 ;裝置對象的位址
kd> !devobj 81f2a930 ;驗證一下裝置對象的屬主
Device object (81f2a930) is for:
  \Driver\busenum DriverObject 8227a3b8 
Current Irp 00000000 RefCount 0 Type 0000002a Flags 00000088
DevExt 81f2a9e8 DevObjExt 81f2aa90 
ExtensionFlags (0000000000)  
Device queue is not busy.      
kd> !devstack 81f2a930 ;81f2a930就是前面IoCreateDevice建立的裝置對象

  !DevObj   !DrvObj            !DevExt   ObjectName
 > 81f2a930  \Driver\busenum    81f2a9e8  
  81f41030  \Driver\PnpManager 00000000  00000082
  !DevNode 81f2a008 :
  DeviceInst is "ROOT\UNKNOWN\0000" ;裝置執行個體
  ServiceName is "busenum"          ;裝置對應的服務名      

至此busenum的裝置棧已經成形了,可以建立Fdo了。

在結束本文前,還有一些瑣碎的東西需要記錄。就是busenum.inf中DDinstall section

    安裝busenum驅動後,打開裝置管理器,在system devices下可以看到裝置對象。

DDK樣例toaster分析(1)

如圖所示,裝置出現在system devices下,裝置執行個體是ROOT\Unknow\0000。問題來了,為什麼會這樣?

首先,裝置管理器是以類裝置為視圖,不同的裝置類歸入不同的類下(物以類聚)。是以出現在system devices下一定是刻意設定,那麼這由誰來設定?當然是inf檔案了,在version節中指定:下面的内容摘自bus.inf

[Version]
Signature="$WINDOWS NT$"
Class=System ;指明busenum屬于system類
ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} ;類的guid
Provider=%MSFT%
DriverVer=09/21/2006,6.0.5736.1
CatalogFile=toaster.cat      

其次,硬體ID,由inf檔案DDinstall節指定,msdn文檔上一般将DDinstall節認為是從Manufacturer開始:

[Manufacturer]
%StdMfg%=Standard

[Standard]
; These are the toaster bus pnp ids

%ToasterBus.DeviceDesc%=ToasterBus_Device, root\busenum ;root\busenum指定了裝置的HardwareID      

有了這兩項,在結合驅動在系統資料庫下的路徑可以找到相應的資訊:

先确定裝置的總線關系,inf檔案中已經指出了busenum屬于root總線,它在系統資料庫中的路徑為:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root

裝置執行個體ROOT\Unknow\0000表明,busenum在root總線的Unknow\0000下,在這個項中可以找到驅動的service和class資訊:

DDK樣例toaster分析(1)

1)通過ROOT\Unknow\0000索引驅動的service為busenum

在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{SerivceName}下可以找到各種驅動注冊的服務相關的系統資料庫值:

對于busenum驅動ServiceName是busenum

DDK樣例toaster分析(1)

ImagePath是驅動程式被安裝的路徑,這些資訊在Inf檔案中都有對應内容,

[ToasterBus_Device.NT.Services] ;這個節是服務安裝節
AddService = busenum,%SPSVCINST_ASSOCSERVICE%, busenum_Service_Inst      
;AddService對應驅動在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\下建立的服務名
{4D36E97D-E325-11CE-BFC1-08002BE10318}
; -------------- busenum driver install sections
[busenum_Service_Inst]
DisplayName    = %busenum.SVCDESC% ;<span style="font-family: Arial, Helvetica, sans-serif;">busenum.SVCDESC</span><span style="font-family: Arial, Helvetica, sans-serif;">=busenum.SVCDESC = "Toaster Bus Enumerator"對應系統資料庫項DisplayName和在裝置管理器上顯示的名字</span>
ServiceType    = 1               ; SERVICE_KERNEL_DRIVER 
StartType      = 3               ; SERVICE_DEMAND_START <span style="font-family: Arial, Helvetica, sans-serif;">;對應系統資料庫的Start</span>
ErrorControl   = 1               ; SERVICE_ERROR_NORMAL
ServiceBinary  = %12%\busenum.sys                       ;對應系統資料庫中ImagePath
LoadOrderGroup = Extended Base      

2)通過ROOT\Unknow\0000索引驅動的class資訊

在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{ClassGuid}

對于busenum驅動ClassGuid是{4D36E97D-E325-11CE-BFC1-08002BE10318},挨個找過去可以找到busenum系統資料庫項:

繼續閱讀