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

遍历系统中加载的驱动可以在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 );
        }
      }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小鹏的专栏

ubuntu下C++如何调用python程序,gdb调试C++代码

Linux下gdb调试C++代码:http://jingyan.baidu.com/article/acf728fd464984f8e410a369.html ...

3069
来自专栏PPV课数据科学社区

【学习】七天搞定SAS(三):基本模块调用

搞定基本的函数之后,开始鼓捣SAS里面的模型。也就是说,要开始写PROC了。说实话,越学SAS,越觉得SAS像Stata...无论是从输出的样式,还是语法。好不...

3195
来自专栏lgp20151222

RestTemplate的异常:Not enough variables available to expand

原因:RestTemplate使用出错,我的情况是不知道这里要求用RestTemplate的使用格式,应该很多人都是这样吧?不过,看了下RestTemplate...

1084
来自专栏Hongten

My Notepad

I have spent near more two weeks to write this Notepad application. At this mome...

1072
来自专栏运维前线

Docker 学习资源整理

Awesome Docker A curated list of Docker resources and projects Inspired by...

5215
来自专栏蓝天

Orace开源的异步IO编程库,特点是接口非常简单

452
来自专栏杨建荣的学习笔记

通过java来格式化sql语句(r4笔记第61天)

经常在抓取一些sql语句的时候,得到的sql文本有格式的问题,如果尝试得到执行计划,每次都会费一番周折。 比如下面的sql语句,基本包含了常见的格式问题。第3行...

3444
来自专栏算法+

3D Lut 电影级调色算法 附完整C代码

长话短说,3d lut(全称 : 3D Lookup table )它是通过建立一个颜色映射表,对图像的色调进行重调的算法。

95410
来自专栏游戏杂谈

CURLcode的定义

http://curl.haxx.se/libcurl/c/libcurl-errors.html

2642
来自专栏王磊的博客

C# 控制台应用程序输出颜色字体[更正版]

首先感谢院子里的“yanxinchen”,之前的方法是通过c#调用系统api实现的,相比之下我的有点画蛇添足了,哈哈。 最佳解决方案的代码: static vo...

3878

扫码关注云+社区