《C++黑客编程解密》04 - 内核驱动开发

在windows下,驱动不仅用于控制硬件设备,也可以创建虚拟设备,也可以和具体设备无关。可以通过windows提供的接口很方便地对内核扩展。驱动模块加载到内核后就可以工作在和操作系统平级地平台上运行。

在安装vs之后还要再安装wdk https://docs.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk
注意:win11使用vs2022与相应wdk,win10使用vs2019和相应wdk。

win10 下运行程序可能会报错,提示要修复漏洞,到vs installer 中再下载几个组件:

 

编译程序前需要做:

  1. 移除项目自动生成的.inf文件
  2. 配置属性 - C/C++ -常规
    警告等级 设置为 等级3
    将警告视为错误 设置为 否
  3. 配置属性 - 链接器 -常规
    将链接器警告视为错误 设置为 否
  4. 配置属性 - Driver Signing - General
    Sign Mode 设置为 Off。

驱动版 Hello World

开发驱动时不再使用 main WinMain,而是使用 DriveEntry 作为入口函数

// DriverEntry[WDK kernel] 定义,除此以外还有很多 DriverEntry 函数的定义
NTSTATUS
DriverEntry(
    __in struct _DRIVER_OBJECT *DriverObject,  // 一个指向驱动对象结构体地指针
    __in PUNICODE_STRING RegistryPath          // 一个UNICODE字符串,指向此驱动负责的注册表
)
{ ... }

helloworld的例子:

#include <ntddk.h>

VOID DriverUnload(PDRIVER_OBJECT pDriverOjbect)
{
    KdPrint(("DriverUnload Routine!\r\n"));
}

NTSTATUS DriverEntry(
            PDRIVER_OBJECT pDriverObject,
            PUNICODE_STRING pRegistryPath)
{
    KdPrint(("%S\r\n", pDriverObject->DriverName.Buffer));
    pDriverObject->DriverUnload = DriverUnload;
    
    return STATUS_SUCCESS;
}

DriverObject 结构体:

typedef struct _DRIVER_OBJECT {
    CSHORT Type;
    CSHORT Size;

    //
    // The following links all of the devices created by a single driver
    // together on a list, and the Flags word provides an extensible flag
    // location for driver objects.
    //

    PDEVICE_OBJECT DeviceObject;   // 指向驱动程序创建的设备对象的指针
    ULONG Flags;

    //
    // The following section describes where the driver is loaded.  The count
    // field is used to count the number of times the driver has had its
    // registered reinitialization routine invoked.
    //

    PVOID DriverStart;
    ULONG DriverSize;
    PVOID DriverSection;
    PDRIVER_EXTENSION DriverExtension;   // 指向驱动程序扩展的指针

    //
    // The driver name field is used by the error log thread
    // determine the name of the driver that an I/O request is/was bound.
    //

    UNICODE_STRING DriverName;

    //
    // The following section is for registry support.  This is a pointer
    // to the path to the hardware information in the registry
    //

    PUNICODE_STRING HardwareDatabase; // 指向 注册表中硬件配置信息的 \Registry\Machine\Hardware 路径的指针

    //
    // The following section contains the optional pointer to an array of
    // alternate entry points to a driver for "fast I/O" support.  Fast I/O
    // is performed by invoking the driver routine directly with separate
    // parameters, rather than using the standard IRP call mechanism.  Note
    // that these functions may only be used for synchronous I/O, and when
    // the file is cached.
    //

    PFAST_IO_DISPATCH FastIoDispatch; // 指向定义驱动程序快速 I/O 入口点的结构的指针。 此成员仅由 FSD 和网络传输驱动程序使用。

    //
    // The following section describes the entry points to this particular
    // driver.  Note that the major function dispatch table must be the last
    // field in the object so that it remains extensible.
    //

    PDRIVER_INITIALIZE DriverInit;  // DriverEntry 例程的入口点,由 I/O 管理器设置
    PDRIVER_STARTIO DriverStartIo;  // 驱动程序的 StartIo 例程的入口点(如果有)(由驱动程序初始化时 DriverEntry 例程设置)。 如果驱动程序没有 StartIo 例程 ,则此成员为 NULL。
    PDRIVER_UNLOAD DriverUnload;    // 卸载驱动时的回调函数 typedef VOID DRIVER_UNLOAD ( _In_ struct _DRIVER_OBJECT *DriverObject );
    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; // 一个调度表,由驱动程序的 DispatchXxx 例程的入口点数组组成。 数组的索引值是表示IRP_MJ_ IRP 主要函数代码的索引值。 每个驱动程序必须在此数组中为驱动程序处理的 IRP_MJ_XXX 请求设置入口点
} DRIVER_OBJECT;

驱动程序装载

将驱动程序加载为一个服务,卸载时直接删除服务。常见的Windows驱动程序分为两类,一类时不支持即插即用的NT式驱动,另一类是支持即插即用的WDM式驱动。NT式驱动程序安装是基于服务的,WDM式驱动安装是基于INF文件的。

void Load(char* szDriverPath)
{
    char szFileName[256];
    _splitpath(szDriverPath, NULL, NULL, szFileName, NULL);

    // 打开服务控制管理器
    SC_HANDLE hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    // 创建驱动对应的服务
    SC_HANDLE hService = CreateService(hScm, szFileName, szFileName,
        SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
        SERVICE_ERROR_IGNORE, szDriverPath, NULL, NULL, NULL, NULL, NULL);

    // 启动服务
    StartService(hService, NULL, NULL);

    CloseServiceHandle(hService);
    CloseServiceHandle(hScm);
}

void Unload(char* szDriverPath)
{
    char szFileName[256];
    _splitpath(szDriverPath, NULL, NULL, szFileName, NULL);

    // 打开服务控制管理器
    SC_HANDLE hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    // 获得服务句柄
    SC_HANDLE hService = OpenService(hScm, szFileName, SERVICE_ALL_ACCESS);

    // 关闭服务
    SERVICE_STATUS status;
    ControlService(hService, SERVICE_CONTROL_STOP, &status);
    // 删除服务
    DeleteService(hService);

    // 关闭句柄
    CloseServiceHandle(hService);
}

 

内核下文件操作

内核中不能使用用户层的win32api函数,需要使用内存层对应函数。

文件创建或打开:

再应用层文件完整路径为"c:\\a.txt",内核层描述方式为"\\?\\c:\\a.txt";
符号链接在用户模式下以"\\\\.\\"开头,内核模式下以"\\??\\"或"\\DosDevices\\"开头。

// 可以创建和打开
NTSYSAPI
NTSTATUS
NTAPI
ZwCreateFile(
    _Out_ PHANDLE FileHandle,                  // 返回文件打开的句柄
    _In_ ACCESS_MASK DesiredAccess,            // 打开文件的操作 GENERIC_READ GENERIC_WRITE
    _In_ POBJECT_ATTRIBUTES ObjectAttributes,  // 指向包含文件名的结构体的指针
    _Out_ PIO_STATUS_BLOCK IoStatusBlock,      // 指向接收操作结果的指针
    _In_opt_ PLARGE_INTEGER AllocationSize,    // 指定文件初始化大小的64位整数
    _In_ ULONG FileAttributes,                 // 通常 FILE_ATTRIBUTE_NORMAL
    _In_ ULONG ShareAccess,                    // 文件共享方式 FILE_SHARE_READ FILE_SHARE_WRITE FILE_SHARE_DELETE
    _In_ ULONG CreateDisposition,              // FILE_CREATE FILE_OPEN FILE_OPEN_IF
    _In_ ULONG CreateOptions,                  // 通常使用 FILE_SYNCHRONOUS_IO_NONALERT 表示文件是同步操作
    _In_reads_bytes_opt_(EaLength) PVOID EaBuffer,  // 一般为NULL
    _In_ ULONG EaLength                        // NULL
    );



// 第三个参数指向的结构体
typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
    PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;

// 一般使用  InitializeObjectAttributes 宏进行初始化
//++
//
// VOID
// InitializeObjectAttributes(
//     _Out_ POBJECT_ATTRIBUTES p, 指向结构体的指针
//     _In_ PUNICODE_STRING n,     对象名称,用UNICODE_STRING 描述,对于 ZwCreateFile 该处指定文件名
//     _In_ ULONG a,               一般设置为 OBJ_CASE_INSENSITIVE 意味名字字符串不区分大小写
//     _In_ HANDLE r,              一般NULL
//     _In_ PSECURITY_DESCRIPTOR s 一般NULL
//     )
//
//--

#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;               \
    }

// 内核对宽字符串的封装,使用KdPrint 输出: KdPrint(("%wZ", &uniString));
// 初始化方法:RtlInitUnicodeString(&FooU, L"Foo");
typedef struct _UNICODE_STRING {
    USHORT Length;         // 字符串长度
    USHORT MaximumLength;  // 缓存区长度
    PWSTR Buffer;          // 缓冲区指针
#endif // MIDL_PASS
} UNICODE_STRING;

用于打开的简化函数

NTSYSAPI
NTSTATUS
NTAPI
ZwOpenFile(
    _Out_ PHANDLE FileHandle,
    _In_ ACCESS_MASK DesiredAccess,
    _In_ POBJECT_ATTRIBUTES ObjectAttributes,
    _Out_ PIO_STATUS_BLOCK IoStatusBlock,
    _In_ ULONG ShareAccess,
    _In_ ULONG OpenOptions
    );

关闭句柄:

NTSYSAPI
NTSTATUS
NTAPI
ZwClose(
    _In_ HANDLE Handle
    );

相关操作

  1. ZwReadFile
  2. ZwWriteFile
  3. ZwQueryInformationFile
  4. ZwSetInformationFile
NTSYSAPI
NTSTATUS
NTAPI
ZwQueryInformationFile(
    _In_ HANDLE FileHandle,                     // 被打开文件句柄
    _Out_ PIO_STATUS_BLOCK IoStatusBlock,       // 返回设置的状态
    _Out_writes_bytes_(Length) PVOID FileInformation,  // 依据FileInformationClass 的不同而不同
    _In_ ULONG Length,                          // 数据长度,第3个参数大小
    _In_ FILE_INFORMATION_CLASS FileInformationClass   // 描述需获取的属性类型
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwSetInformationFile(
    _In_ HANDLE FileHandle,
    _Out_ PIO_STATUS_BLOCK IoStatusBlock,
    _In_reads_bytes_(Length) PVOID FileInformation, // 设置参数
    _In_ ULONG Length,
    _In_ FILE_INFORMATION_CLASS FileInformationClass
    );

// FILE_INFORMATION_CLASS 的常用值有三种类型 FileStandardInformation FileBasicInformation FilePositionInformation,每种类型对应不同结构体

 

NTSYSAPI
NTSTATUS
NTAPI
ZwReadFile(
    _In_ HANDLE FileHandle,
    _In_opt_ HANDLE Event,                // 用于异步完成读取,一般为NULL
    _In_opt_ PIO_APC_ROUTINE ApcRoutine,  // 回调例程,异步完成时读取,一般UNULL
    _In_opt_ PVOID ApcContext,            // NULL
    _Out_ PIO_STATUS_BLOCK IoStatusBlock, // 记录读取操作的状态
    _Out_writes_bytes_(Length) PVOID Buffer,  // 保存内容的缓冲区
    _In_ ULONG Length,                    // 准备读取内容的字节数
    _In_opt_ PLARGE_INTEGER ByteOffset,   // 指定读取内容的偏移地址
    _In_opt_ PULONG Key                   // 附加信息 一般NULL
    );

NTSYSAPI
NTSTATUS
NTAPI
ZwWriteFile(
    _In_ HANDLE FileHandle,
    _In_opt_ HANDLE Event,
    _In_opt_ PIO_APC_ROUTINE ApcRoutine,
    _In_opt_ PVOID ApcContext,
    _Out_ PIO_STATUS_BLOCK IoStatusBlock,
    _In_reads_bytes_(Length) PVOID Buffer,
    _In_ ULONG Length,
    _In_opt_ PLARGE_INTEGER ByteOffset,
    _In_opt_ PULONG Key
    );

 

内存管理函数

NTKERNELAPI
PVOID
ExAllocatePool (
    // 枚举值 NonPagedPool非分页内存:不会被交换到文件中的虚拟内存  PagedPool分页内存:可以被交换到文件中的虚拟内存
    __drv_strictTypeMatch(__drv_typeExpr) _In_ POOL_TYPE PoolType,
    _In_ SIZE_T NumberOfBytes  // 要分配的内存大小
    );

#define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length))

NTKERNELAPI
VOID
NTAPI
ExFreePool (
    _Pre_notnull_ __drv_freesMem(Mem) PVOID P
    );

 

例子:

查看代码
 #include <ntddk.h>
#define FILENAME L"\\??\\c:\\a.txt"
#define BUFFERLEN 10

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
}

VOID CreateFileTest()
{
    NTSTATUS status = STATUS_SUCCESS;
    
    OBJECT_ATTRIBUTES ObjAttribute;
    IO_STATUS_BLOCK ioStatusBlock;
    
    UNICODE_STRING uniFile;
    
    HANDLE hFile = NULL;
    
    RtlInitUnicodeString(&uniFile, FILENAME);
    
    // 初始化一个对象属性
    InitializeObjectAttributes(&ObjAttribute,
                &uniFile,
                OBJ_CASE_INSENSITIVE, 
                NULL,
                NULL);
                
    // 创建文件
    status = ZwCreateFile(&hFile,
                GENERIC_READ | GENERIC_WRITE,
                &ObjAttribute,
                &ioStatusBlock,
                0,
                FILE_ATTRIBUTE_NORMAL,
                FILE_SHARE_READ,
                FILE_OPEN_IF,
                FILE_SYNCHRONOUS_IO_NONALERT,
                NULL,
                0);
    
    if ( NT_SUCCESS(status) )
    {
        KdPrint(("File Create ok ! \r\n"));
    }
    else
    {
        KdPrint(("File Create faild ! \r\n"));
    }
    

    ZwClose(hFile);
}

VOID OpenFileTest()
{
    IO_STATUS_BLOCK ioStatusBlock;
    OBJECT_ATTRIBUTES ObjAttribute;
    HANDLE hFile;
    UNICODE_STRING uniFileName;
    NTSTATUS status;
    
    FILE_STANDARD_INFORMATION fsi;
    FILE_POSITION_INFORMATION fpi;
    PVOID Buffer = NULL;
    
    RtlInitUnicodeString(&uniFileName, FILENAME);
    
    // 初始化一个对象属性
    InitializeObjectAttributes(&ObjAttribute, 
                        &uniFileName,
                        OBJ_CASE_INSENSITIVE,
                        NULL,
                        NULL);
    
    // 打开文件
    status = ZwOpenFile(&hFile,
                    GENERIC_READ | GENERIC_WRITE,
                    &ObjAttribute,
                    &ioStatusBlock,
                    FILE_SHARE_READ,
                    FILE_SYNCHRONOUS_IO_NONALERT);
    
    if ( NT_SUCCESS(status) )
    {
        KdPrint(("OpenFile Successfully ! \r\n"));
    }
    else
    {
        KdPrint(("OpenFile UnSuccessfully ! \r\n"));
        return ;
    }
    
    // 获取文件属性
    status = ZwQueryInformationFile(hFile,
                        &ioStatusBlock,
                        &fsi,
                        sizeof(FILE_STANDARD_INFORMATION),
                        FileStandardInformation);
    
    // 输出新创建的文件是否是目录
    KdPrint(("Is Directory %d \r\n", fsi.Directory));
    
    // 分配空间
    Buffer = ExAllocatePool(PagedPool, BUFFERLEN);
    
    if ( Buffer == NULL )
    {
        ZwClose(hFile);
        return ;
    }
    
    // 填充值为
    RtlFillMemory(Buffer, BUFFERLEN, 0x61);
    
    // 写文件
    status = ZwWriteFile(hFile,
                    NULL,
                    NULL,
                    NULL,
                    &ioStatusBlock,
                    Buffer,
                    BUFFERLEN,
                    0,
                    NULL);

    if ( NT_SUCCESS(status) )
    {
        KdPrint(("ZwWriteFile Successfully ! \r\n"));
    }
    
    // 释放申请的空间
    ExFreePool(Buffer);
    
    // 获取文件属性
    status = ZwQueryInformationFile(hFile,
                        &ioStatusBlock,
                        &fsi,
                        sizeof(FILE_STANDARD_INFORMATION),
                        FileStandardInformation);
                        
    // 输出新创建的文件是否是目录
    KdPrint(("FileSize =  %d \r\n", (LONG)fsi.EndOfFile.QuadPart));

    Buffer = ExAllocatePool(PagedPool, (fsi.EndOfFile.QuadPart * 2));
    if ( Buffer == NULL )
    {
        KdPrint(("ExAllocatePool UnSuccessfully ! \r\n"));
        ZwClose(hFile);
        return ;
    }    
    
    
    fpi.CurrentByteOffset.QuadPart = 0;
    // 设置文件指针
    status = ZwSetInformationFile(hFile, 
                            &ioStatusBlock, &fpi,
                            sizeof(FILE_POSITION_INFORMATION),
                            FilePositionInformation);
    
    // 读取文件内容
    status = ZwReadFile(hFile, NULL, NULL, NULL,
                        &ioStatusBlock, Buffer,
                        (LONG)fsi.EndOfFile.QuadPart,
                        NULL, NULL);
                        
    if ( NT_SUCCESS(status) )
    {
        KdPrint(("ZwReadFile Successfully ! \r\n"));
    }
    KdPrint(("%s", Buffer));
    
    ExFreePool(Buffer);
    ZwClose(hFile);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, 
                     PUNICODE_STRING pRegistryPath)
{
    pDriverObject->DriverUnload = DriverUnload;
    
    CreateFileTest();
    
    OpenFileTest();
    
    return STATUS_SUCCESS;
}

 

注册表操作

  1. ZwCreateKey
  2. ZwOpenKey
  3. ZwSetValueKey
  4. ZwQueryValueKey
// 用于创建和打开
NTSYSAPI
NTSTATUS
NTAPI
ZwCreateKey(
    _Out_ PHANDLE KeyHandle,
    _In_ ACCESS_MASK DesiredAccess,     // 访问权限 KEY_ALL_ACCESS
    _In_ POBJECT_ATTRIBUTES ObjectAttributes,  // 用于保存要创建的子键
    _Reserved_ ULONG TitleIndex,        // 0
    _In_opt_ PUNICODE_STRING Class,     // NULL
    _In_ ULONG CreateOptions,           // 一般 REG_OPTION_NON_VOLATILE
    _Out_opt_ PULONG Disposition        // 返回创建成功还是打开成功
    );


NTSYSAPI
NTSTATUS
NTAPI
ZwOpenKey(
    _Out_ PHANDLE KeyHandle,
    _In_ ACCESS_MASK DesiredAccess,
    _In_ POBJECT_ATTRIBUTES ObjectAttributes
    );


NTSYSAPI
NTSTATUS
NTAPI
ZwSetValueKey(
    _In_ HANDLE KeyHandle,
    _In_ PUNICODE_STRING ValueName, // 新建或修改的键名
    _In_opt_ ULONG TitleIndex,      // 一般为0
    _In_ ULONG Type,                // 键值类型,REG_SZ REG_DWORD REG_MULTI_SZ
    _In_reads_bytes_opt_(DataSize) PVOID Data,  // 写入键值的值
    _In_ ULONG DataSize             // 记录数据的大小
    );


NTSYSAPI
NTSTATUS
NTAPI
ZwQueryValueKey(
    _In_ HANDLE KeyHandle,
    _In_ PUNICODE_STRING ValueName, // 键名
    _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, // 查询方式
    _Out_writes_bytes_to_opt_(Length, *ResultLength) PVOID KeyValueInformation, // 根据前者选择不同类别
    _In_ ULONG Length,              // 要查数据长度
    _Out_ PULONG ResultLength       // 实际查询数据长度
    );

 

 

查看代码
 #include <ntddk.h>

#define REG_PATH L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\run\\"

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
}

VOID CreateKey()
{
    UNICODE_STRING uniRegPath;
    OBJECT_ATTRIBUTES objAttributes;
    NTSTATUS nStatus;
    HANDLE hRegistry;
    ULONG ulResult;
    
    RtlInitUnicodeString(&uniRegPath, REG_PATH);
    InitializeObjectAttributes(&objAttributes,
                        &uniRegPath,
                        OBJ_CASE_INSENSITIVE,
                        NULL,
                        NULL);
    
    // 创建注册表项
    nStatus = ZwCreateKey(&hRegistry,
                    KEY_ALL_ACCESS,
                    &objAttributes,
                    0,
                    NULL,
                    REG_OPTION_NON_VOLATILE,
                    &ulResult);
                    
    if ( NT_SUCCESS(nStatus) )
    {
        KdPrint(("ZwCreateKey Successfully ! \r\n"));
    }
    else
    {
        KdPrint(("ZwCreateKey Unsuccessfully ! \r\n"));
    }

    // 关闭注册表句柄
    ZwClose(hRegistry);
}

VOID QueryAndSetKey(HANDLE hRegistry)
{
    UNICODE_STRING uniValueName;
    NTSTATUS nStatus;
    PWCHAR pValue = L"test";
    PKEY_VALUE_PARTIAL_INFORMATION  pKeyValuePartialClass;
    ULONG ulResult;
    
    RtlInitUnicodeString(&uniValueName, L"test");
    
    // 添加注册表键值
    nStatus = ZwSetValueKey(hRegistry,
                        &uniValueName,
                        0,
                        REG_SZ,
                        pValue,
                        wcslen(pValue) * 2 + sizeof(WCHAR));
    
    if ( NT_SUCCESS(nStatus) )
    {
        KdPrint(("ZwSetValueKey Successfully ! \r\n"));
    }
    else
    {
        KdPrint(("ZwSetValueKey Unsuccessfully ! \r\n"));
    }
    
    // 查询注册表项
    nStatus = ZwQueryValueKey(hRegistry,
                            &uniValueName,
                            KeyValuePartialInformation,
                            NULL,
                            NULL,
                            &ulResult);
    
    // STATUS_BUFFER_TOO_SMALL表示缓冲区太小
    if ( nStatus == STATUS_BUFFER_TOO_SMALL || ulResult != 0 )
    {
        pKeyValuePartialClass = ExAllocatePool(PagedPool, ulResult);
        nStatus = ZwQueryValueKey(hRegistry,
                            &uniValueName,
                            KeyValuePartialInformation,
                            pKeyValuePartialClass,
                            ulResult,
                            &ulResult);
        
        KdPrint(("%S \r\n", pKeyValuePartialClass->Data));
        
        ExFreePool(pKeyValuePartialClass);
    }
    else
    {
        KdPrint(("ZwQueryValueKey Unsuccessfully ! \r\n"));
    }
}

VOID OpenKey()
{
    UNICODE_STRING uniRegPath;
    OBJECT_ATTRIBUTES objAttributes;
    HANDLE hRegistry;
    NTSTATUS nStatus;
    
    RtlInitUnicodeString(&uniRegPath, REG_PATH);
    InitializeObjectAttributes(&objAttributes,
                        &uniRegPath,
                        OBJ_CASE_INSENSITIVE,
                        NULL,
                        NULL);
     
    // 打开注册表
    nStatus = ZwOpenKey(&hRegistry, KEY_ALL_ACCESS, &objAttributes);
    
    if ( NT_SUCCESS(nStatus) )
    {
        KdPrint(("ZwOpenKey Successfully ! \r\n"));
    }
    else
    {
        KdPrint(("ZwOpenKey Unsuccessfully ! \r\n"));
        return ;
    }
    
    // 查询并设置
    QueryAndSetKey(hRegistry);
    
    // 关闭注册表句柄
    ZwClose(hRegistry);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
    pDriverObject->DriverUnload = DriverUnload;
    
    CreateKey();
    OpenKey();

    return STATUS_SUCCESS;
}

 

posted @ 2022-08-09 12:18  某某人8265  阅读(501)  评论(0编辑  收藏  举报