遍历系统中加载的驱动可以在R3层完成,通过几个未导出的函数:ZwOpenDirectoryObject、ZwQueryDirectoryObject,下面是具体的代码。

//在这定义些基本的数据结构,这些本身是在R0层用的比较多的
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef ULONG NTSTATUS;
// 对象属性定义
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
UNICODE_STRING *ObjectName;
ULONG Attributes;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

// 基本信息定义
typedef struct _DIRECTORY_BASIC_INFORMATION {
UNICODE_STRING ObjectName;
UNICODE_STRING ObjectTypeName;
} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;

// 返回值或状态类型定义
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define DIRECTORY_QUERY (0x0001)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
// 初始化对象属性宏定义
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
// 字符串初始化

//用来存储设备驱动对象名称的链表
extern vector<CString> g_DriverNameList;
vector<DRIVER_INFO> g_DriverNameList;
typedef VOID(CALLBACK* RTLINITUNICODESTRING)(PUNICODE_STRING, PCWSTR);

RTLINITUNICODESTRING RtlInitUnicodeString;
// 打开对象
typedef NTSTATUS(WINAPI *ZWOPENDIRECTORYOBJECT)(
OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
ZWOPENDIRECTORYOBJECT ZwOpenDirectoryObject;
// 查询对象
typedef
NTSTATUS
(WINAPI *ZWQUERYDIRECTORYOBJECT)(
IN HANDLE DirectoryHandle,
OUT PVOID Buffer,
IN ULONG BufferLength,
IN BOOLEAN ReturnSingleEntry,
IN BOOLEAN RestartScan,
IN OUT PULONG Context,
OUT PULONG ReturnLength OPTIONAL
);
ZWQUERYDIRECTORYOBJECT ZwQueryDirectoryObject;
// 关闭已经打开的对象
typedef NTSTATUS (WINAPI *ZWCLOSE)(IN HANDLE Handle);
ZWCLOSE ZwClose;

BOOL EnumDriver()
{
HMODULE hNtdll = NULL;
UNICODE_STRING strDirName;
OBJECT_ATTRIBUTES oba;
NTSTATUS ntStatus;
HANDLE hDirectory;
hNtdll = LoadLibrary(_T("ntdll.dll"));
if (NULL == hNtdll)
{
return FALSE;
}

RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress(hNtdll, "RtlInitUnicodeString");
ZwOpenDirectoryObject = (ZWOPENDIRECTORYOBJECT)GetProcAddress(hNtdll, "ZwOpenDirectoryObject");
ZwQueryDirectoryObject = (ZWQUERYDIRECTORYOBJECT)GetProcAddress(hNtdll, "ZwQueryDirectoryObject");
ZwClose = (ZWCLOSE)GetProcAddress(hNtdll, "ZwClose");

RtlInitUnicodeString(&strDirName, _T("\\Driver"));
InitializeObjectAttributes(&oba, &strDirName, OBJ_CASE_INSENSITIVE, NULL, NULL);
ntStatus = ZwOpenDirectoryObject(&hDirectory, DIRECTORY_QUERY, &oba);
if (ntStatus != STATUS_SUCCESS)
{
return FALSE;
}

PDIRECTORY_BASIC_INFORMATION pBuffer = NULL;
PDIRECTORY_BASIC_INFORMATION pBuffer2 = NULL;
ULONG ulLength = 0x800; // 2048
ULONG ulContext = 0;
ULONG ulRet = 0;
// 查询目录对象
do
{
if (pBuffer != NULL)
{
free(pBuffer);
}
ulLength = ulLength * 2;
pBuffer = (PDIRECTORY_BASIC_INFORMATION)malloc(ulLength);
if (NULL == pBuffer)
{
if (pBuffer != NULL)
{
free(pBuffer);
}
if (hDirectory != NULL)
{
ZwClose(hDirectory);
}

return FALSE;
}
ntStatus = ZwQueryDirectoryObject(hDirectory, pBuffer, ulLength, FALSE, TRUE, &ulContext, &ulRet);
} while (ntStatus == STATUS_MORE_ENTRIES || ntStatus == STATUS_BUFFER_TOO_SMALL);

if (STATUS_SUCCESS == ntStatus)
{
pBuffer2 = pBuffer;
while ((pBuffer2->ObjectName.Length != 0) && (pBuffer2->ObjectTypeName.Length != 0))
{
CString strDriverName;
strDriverName = pBuffer2->ObjectName.Buffer;
g_DriverNameList.push_back(strDriverName);
pBuffer2++;
}
}

if (pBuffer != NULL)
{
free(pBuffer);
}
if (hDirectory != NULL)
{
ZwClose(hDirectory);
}

return TRUE;
}

通过设备对象的地址来获取设备对象的名称一般是在R0层完成,下面是具体的代码

//定义相关的结构体和宏
typedef struct _OBJECT_CREATE_INFORMATION
{
ULONG Attributes;
HANDLE RootDirectory;
PVOID ParseContext;
KPROCESSOR_MODE ProbeMode;
ULONG PagedPoolCharge;
ULONG NonPagedPoolCharge;
ULONG SecurityDescriptorCharge;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_QUALITY_OF_SERVICE SecurityQos;
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} OBJECT_CREATE_INFORMATION, * POBJECT_CREATE_INFORMATION;

typedef struct _OBJECT_HEADER
{
LONG PointerCount;
union
{
LONG HandleCount;
PSINGLE_LIST_ENTRY SEntry;
};
POBJECT_TYPE Type;
UCHAR NameInfoOffset;
UCHAR HandleInfoOffset;
UCHAR QuotaInfoOffset;
UCHAR Flags;
union
{
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
PVOID QuotaBlockCharged;
};

PSECURITY_DESCRIPTOR SecurityDescriptor;
QUAD Body;
} OBJECT_HEADER, * POBJECT_HEADER;

#define NUMBER_HASH_BUCKETS 37
typedef struct _OBJECT_DIRECTORY
{
struct _OBJECT_DIRECTORY_ENTRY* HashBuckets[NUMBER_HASH_BUCKETS];
struct _OBJECT_DIRECTORY_ENTRY** LookupBucket;
BOOLEAN LookupFound;
USHORT SymbolicLinkUsageCount;
struct _DEVICE_MAP* DeviceMap;
} OBJECT_DIRECTORY, * POBJECT_DIRECTORY;

typedef struct _OBJECT_HEADER_NAME_INFO
{
POBJECT_DIRECTORY Directory;
UNICODE_STRING Name;
ULONG Reserved;
#if DBG
ULONG Reserved2 ;
LONG DbgDereferenceCount ;
#endif
} OBJECT_HEADER_NAME_INFO, * POBJECT_HEADER_NAME_INFO;

#define OBJECT_TO_OBJECT_HEADER( o ) \
CONTAINING_RECORD( (o), OBJECT_HEADER, Body )

#define OBJECT_HEADER_TO_NAME_INFO( oh ) ((POBJECT_HEADER_NAME_INFO) \
((oh)->NameInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->NameInfoOffset)))

void GetDeviceName(PDEVICE_OBJECT pDeviceObj)
{
POBJECT_HEADER ObjectHeader;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;

if ( pDeviceObj == NULL )
{
DbgPrint( "pDeviceObj is NULL!\n" );
return;
}
// 得到对象头
ObjectHeader = OBJECT_TO_OBJECT_HEADER( pDeviceObj );

if ( ObjectHeader )
{
// 查询设备名称并打印
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );

if ( ObjectNameInfo && ObjectNameInfo->Name.Buffer )
{
DbgPrint( "Driver Name:%wZ - Device Name:%wZ - Driver Address:0x%x - Device Address:0x%x\n",
&pDeviceObj->DriverObject->DriverName,
&ObjectNameInfo->Name,
pDeviceObj->DriverObject,
pDeviceObj );
}

// 对于没有名称的设备,则打印 NULL
else if ( pDeviceObj->DriverObject )
{
DbgPrint( "Driver Name:%wZ - Device Name:%S - Driver Address:0x%x - Device Address:0x%x\n",
&pDeviceObj->DriverObject->DriverName,
L"NULL",
pDeviceObj->DriverObject,
pDeviceObj );
}
}
}