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

摘要:
=状态_成功){returnFALSE;}PDIRECTORY_BASIC_INFORMATIONpBuffer=NULL;PDIRECTORY_BASIC_INFORMATIONpBuffer2=NULL;ULONGulLength=0x800;//2048ULONGulContext=0;ULONGulRet=0;//查询目录对象do{if(pBuffer!

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

免责声明:文章转载自《遍历系统中加载的驱动程序以及通过设备对象指针获取设备对象名称》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Windows下使用MINGW编译ffplaySpringboot分布式,excel导出,运用POI导出,前端用的jsp下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CSS 属性选择器的深入挖掘

CSS 属性选择器,可以通过已经存在的属性名或属性值匹配元素。 属性选择器是在 CSS2 中引入的并且在 CSS3 中得到了很好拓展。本文将会比较全面的介绍属性选择器,尽可能的去挖掘这个选择器在不同场景下的不同用法。 简单的语法介绍 [attr]:该选择器选择包含 attr 属性的所有元素,不论 attr 的值为何。 [attr=val]:该选择器仅选...

深度解析C语言中的sizeof

1)解析C语言中的sizeof 一、sizeof的概念  sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。 二、sizeof的使用方法  1、用于数据类型   sizeof使用形式:...

最全C++11/14/17/20/23 的新特性代码案例

最全C++11/14/17/20/23 的新特性代码案例 来源https://zhuanlan.zhihu.com/p/389895793 C++11新特性 关键字 新增关键字 thread_local static_assert nullptr noexcept decltype constexpr char16_t char32_t alignof...

nginx 414 Request-URI Too Large

症状 nginx 414 Request-URI Too Large #客户端请求头缓冲区大小,如果请求头总长度大于小于128k,则使用此缓冲区, #请求头总长度大于128k时使用large_client_header_buffers设置的缓存区client_header_buffer_size 128k; #large_client_header_buf...

C语言判断文件指针是否结尾的问题

c语言的文件指针结尾问题:有两个方法可以判断文件指针是否到结尾pay attention:读取文件的函数会影响文件指针移动1.使用feof(文件指针)函数判断,如果到了结尾返回0,否则返回非02.使用EOF(就是-1)判断指针是否到结尾 仅用于普通文件,不适用于二进制文件适用条件--------重点方法1:*1.有一个弊端就是,feof函数判断文件指...

kafka时间轮的原理(一)

概述早就想写关于kafka时间轮的随笔了,奈何时间不够,技术感觉理解不到位,现在把我之前学习到的进行整理一下,以便于以后并不会忘却。kafka时间轮是一个时间延时调度的工具,学习它可以掌握更加灵活先进的定时器技术,补益多多。本文由浅到深进行讲解,先讲解定时器基础以及常用定时器,接着就是主要的kafka时间轮实现。大部分都是原理。后期作者写第二部分的时候专门...