遍历系统中加载的驱动可以在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!
" );
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
",
&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
",
&pDeviceObj->DriverObject->DriverName,
L"NULL",
pDeviceObj->DriverObject,
pDeviceObj );
}
}
}