遍历系统中所有的驱动对象 admin · · Windows程序设计
1 1 0

本文共计4186个字,预计阅读时长16.7分钟。

原理

首先我们要知道驱动加载后, 会向对象目录表中的\driver 与\FileSystem 写入 驱动服务名, 那么我们只需要遍历这两张表拿到名称, 通过ObReferenceObjectByName函数即可获取驱动对象。而在这里我们可以使用微软提供的ZwQueryDirectoryObject函数获取对应的对象目录表。

遍历驱动代码

auto EnumerateObject = [&](UNICODE_STRING* Directory)
    {
        NTSTATUS            ntStatus = STATUS_SUCCESS;
        OBJECT_ATTRIBUTES   ObjAttr = { 0 };
        HANDLE              FileHandle = 0;
        IO_STATUS_BLOCK     IoStatusBlock = { 0 };
        PVOID               FileInformation = 0;
        ULONG               Length = sizeof(FILE_DIRECTORY_INFORMATION); // 这个数设置的太小会导致ZwQueryDirectoryFile蓝屏。  
        UNICODE_STRING      driverName = RTL_CONSTANT_STRING(L"Driver");

        InitializeObjectAttributes(&ObjAttr, Directory, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);

        ntStatus = ZwOpenDirectoryObject(&FileHandle, GENERIC_READ | SYNCHRONIZE, &ObjAttr);

        if (!NT_SUCCESS(ntStatus)) return ntStatus;

        Length = Length + 520; // 为何加这个数字,请看ZwEnumerateFile1的说明。

        FileInformation = ExAllocatePool(NonPagedPool, Length);

        if (NULL == FileInformation)
        {
            ZwClose(FileHandle);
            return STATUS_UNSUCCESSFUL;
        }

        RtlZeroMemory(FileInformation, Length);

        BOOLEAN         RestartScan;
        ULONG           Context = 0;
        ULONG           ReturnedLength = 0;

        do
        {
            UNICODE_STRING FileName = { 0 };
            POBJECT_DIRECTORY_INFORMATION podi = 0;
            UNICODE_STRING FullName = { 0 };

            RestartScan = FALSE; // 为TRUE会导致死循环;
            ntStatus = ZwQueryDirectoryObject(FileHandle, FileInformation, Length, TRUE, RestartScan, &Context, &ReturnedLength);

            if (STATUS_NO_MORE_FILES != ntStatus && STATUS_SUCCESS != ntStatus)
                return ntStatus;

            podi = (POBJECT_DIRECTORY_INFORMATION)FileInformation;

            // 不是驱动对象就放过。
            if (RtlCompareUnicodeString(&podi->TypeName, &driverName, TRUE) != 0)
            {
                continue;
            }

            // 申请要显示的内存,另一思路是格式化。
            FullName.MaximumLength = (USHORT)Length + Directory->MaximumLength;
            FullName.Buffer = (PWCH)ExAllocatePool(NonPagedPool, FullName.MaximumLength);

            if (NULL == FullName.Buffer) {
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }

            RtlZeroMemory(FullName.Buffer, FullName.MaximumLength);

            RtlCopyUnicodeString(&FullName, Directory);

            ntStatus = RtlAppendUnicodeToString(&FullName, L"\\");

            if (!NT_SUCCESS(ntStatus)) {
                ExFreePool(FullName.Buffer);
                break;
            }

            ntStatus = RtlAppendUnicodeStringToString(&FullName, &podi->Name);

            if (!NT_SUCCESS(ntStatus)) {
                ExFreePool(FullName.Buffer);
                break;
            }

            //DBG_PRINT("Name %wZ\n", &FullName);

            PDRIVER_OBJECT DriverObject = nullptr;

            /* 对比查找 */
            ntStatus = ObReferenceObjectByName(
                &FullName,
                OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
                NULL, FILE_ANY_ACCESS, 
                *IoDriverObjectType, 
                KernelMode, 
                NULL, 
                (PVOID*)&DriverObject
            );

            if (NT_SUCCESS(ntStatus))
            {
                /* Add */
                Mylist->push(DriverObject);
            }

            ExFreePool(FullName.Buffer);

        } while (STATUS_NO_MORE_FILES != ntStatus);

        if (STATUS_NO_MORE_FILES == ntStatus)
            ntStatus = STATUS_SUCCESS;

        if (FileInformation)
        {
            ExFreePool(FileInformation);
            FileInformation = NULL;
        }

        ZwClose(FileHandle);

        return ntStatus;
    };

测试用例 分别遍历 driver 与 FileSystem 两个目录

UNICODE_STRING  directory  = RTL_CONSTANT_STRING(L"\\driver");
UNICODE_STRING  FileSystem = RTL_CONSTANT_STRING(L"\\FileSystem");
ntStatus = EnumerateObject(&directory);
ntStatus = EnumerateObject(&FileSystem);

最新回复 ( 1 )
全部楼主
  • 妮妮 @Ta
    0 2
    66666666666