遍历系统中加载的驱动程序以及通过设备对象指针获取设备对象名称

遍历系统中加载的驱动可以在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 );
        }
      }
}
posted @ 2017-10-24 20:55  masimaro  阅读(1837)  评论(0编辑  收藏  举报