这里需要用到一个未公开的(undocumented)API
ObReferenceObjectByName
函数可以通过对象名字得到包括设备对象在内的各种内核对象的指针,比如内核事件,互斥体对象等.他会增加内核对象的引用计数,使用完内核对象后要用ObDereferenceObject内核函数将引用计数减1.
定义参考:
NTKERNELAPI NTSTATUS ObReferenceObjectByName ( __in PUNICODE_STRING ObjectName, __in ULONG Attributes, __in_opt PACCESS_STATE AccessState, __in_opt ACCESS_MASK DesiredAccess, __in POBJECT_TYPE ObjectType, __in KPROCESSOR_MODE AccessMode, __inout_opt PVOID ParseContext, __out PVOID * Object )支持从driver name获取DRIVER_OBJECT,从device name获取DEVICE_OBJECT
从Driver name获取DRIVER_OBJECT:
// API define #ifdef __cplusplus extern "C" { #endif #include <NTDDK.h> NTKERNELAPI NTSTATUS ObReferenceObjectByName( IN PUNICODE_STRING ObjectName, IN ULONG Attributes, IN PACCESS_STATE PassedAccessState OPTIONAL, IN ACCESS_MASK DesiredAccess OPTIONAL, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, OUT PVOID *Object ); extern POBJECT_TYPE *IoDriverObjectType; #ifdef __cplusplus } #endif // use such API NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING DriverName; PDRIVER_OBJECT pDriverObj = NULL; RtlInitUnicodeString(&DriverName, L"\\Driver\\usbhub"); // usbhub as an example status = ObReferenceObjectByName( &DriverName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode, NULL, (PVOID*)&pDriverObj);
我们可以通过DRIVER_OBJECT->DeviceObject来获取此Driver产生的DEVICE_OBJECT,并通过DEVICE_OBJECT->NextDevice来遍历所有的DEVICE_OBJECT。
typedef struct _DRIVER_OBJECT { CSHORT Type; CSHORT Size; // // The following links all of the devices created by a single driver // together on a list, and the Flags word provides an extensible flag // location for driver objects. // PDEVICE_OBJECT DeviceObject; ULONG Flags; // // The following section describes where the driver is loaded. The count // field is used to count the number of times the driver has had its // registered reinitialization routine invoked. // PVOID DriverStart; ULONG DriverSize; PVOID DriverSection; PDRIVER_EXTENSION DriverExtension; // // The driver name field is used by the error log thread // determine the name of the driver that an I/O request is/was bound. // UNICODE_STRING DriverName; // // The following section is for registry support. Thise is a pointer // to the path to the hardware information in the registry // PUNICODE_STRING HardwareDatabase; // // The following section contains the optional pointer to an array of // alternate entry points to a driver for "fast I/O" support. Fast I/O // is performed by invoking the driver routine directly with separate // parameters, rather than using the standard IRP call mechanism. Note // that these functions may only be used for synchronous I/O, and when // the file is cached. // PFAST_IO_DISPATCH FastIoDispatch; // // The following section describes the entry points to this particular // driver. Note that the major function dispatch table must be the last // field in the object so that it remains extensible. // PDRIVER_INITIALIZE DriverInit; PDRIVER_STARTIO DriverStartIo; PDRIVER_UNLOAD DriverUnload; PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; } DRIVER_OBJECT;
if (STATUS_SUCCESS == status && NULL != pDriverObj) { PDEVICE_OBJECT pDevObj = pDriverObj->DeviceObject; ULONG resultLength = 0; PWCHAR pResultBuffer = NULL; while(NULL != pDevObj) { if (pDevObj->Flags & DO_BUS_ENUMERATED_DEVICE ) // PDO { resultLength = 0; status = IoGetDeviceProperty( // get PDO device name pDevObj, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &resultLength); if (STATUS_BUFFER_TOO_SMALL == status && resultLength>0) { pResultBuffer = ExAllocatePoolWithTag( NonPagedPool, resultLength+1, 'NCSP'); if (pResultBuffer) { RtlZeroMemory(pResultBuffer, resultLength+1); status = IoGetDeviceProperty( pDevObj, DevicePropertyPhysicalDeviceObjectName, resultLength, pResultBuffer, &resultLength); } } if (pResultBuffer) { ExFreePool(pResultBuffer); } } pDevObj = pDevObj->NextDevice; } ObDereferenceObject(pPciDriverObj); }