Windows驱动开发之注册表操作

转载请注明来源:
enjoy5512的博客 : http://blog.csdn.net/enjoy5512
GitHub : https://github.com/whu-enjoy

1. 在驱动中操作注册表

注册表项相当于文件夹,注册表子项子文件夹(类似目录)

1.1 打开注册表键

ZwCreateKey/ZwOpenKey
代码中测试了ZwOpenKey的使用方式
先初始化OBJECT_ATTRIBUTES结构体,然后打开注册表键


NTSTATUS ZwCreateKey(
  _Out_      PHANDLE            KeyHandle,
  _In_       ACCESS_MASK        DesiredAccess,
  _In_       POBJECT_ATTRIBUTES ObjectAttributes,
  _Reserved_ ULONG              TitleIndex,
  _In_opt_   PUNICODE_STRING    Class,
  _In_       ULONG              CreateOptions,
  _Out_opt_  PULONG             Disposition
);

Parameters

KeyHandle [out]
Pointer to a HANDLE variable that receives a handle to the key.

DesiredAccess [in]
Specifies an ACCESS_MASK value that determines the requested access to the object. In addition to the access rights that are defined for all types of objects (see ACCESS_MASK), the caller can specify one or more of the following access rights, which are specific to object directories:
DesiredAccess flag Allows caller to do this
KEY_QUERY_VALUE Read key values.
KEY_SET_VALUE Write key values.
KEY_CREATE_SUB_KEY Create subkeys for the key.
KEY_ENUMERATE_SUB_KEYS Read the key’s subkeys.
KEY_CREATE_LINK Create a symbolic link to the key. This flag is not used by device and intermediate drivers.
KEY_NOTIFY Ask to receive notification when the name, value, or attributes of the key change. For more information, see ZwNotifyChangeKey.
The caller can also specify one of the following constants, which combines several ACCESS_MASK flags.
Constant Consists of these ACCESS_MASK flags
KEY_READ STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY
KEY_WRITE STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUBKEY
KEY_EXECUTE Same as KEY_READ.
KEY_ALL_ACCESS STANDARD_RIGHTS_ALL, KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, and KEY_CREATE_LINK
ObjectAttributes [in]
Pointer to an OBJECT_ATTRIBUTES structure that specifies the object name and other attributes. Use InitializeObjectAttributes to initialize this structure. If the caller is not running in a system thread context, it must set the OBJ_KERNEL_HANDLE attribute when it calls InitializeObjectAttributes.
TitleIndex
Device and intermediate drivers set this parameter to zero.

Class [in, optional]
Pointer to a Unicode string that contains the key's object class. This information is used by the configuration manager.

CreateOptions [in]
Specifies the options to apply when creating or opening a key, specified as a compatible combination of the following flags.
CreateOptions flag Description
REG_OPTION_VOLATILE Key is not preserved when the system is rebooted.
REG_OPTION_NON_VOLATILE Key is preserved when the system is rebooted.
REG_OPTION_CREATE_LINK The newly created key is a symbolic link. This flag is not used by device and intermediate drivers.
REG_OPTION_BACKUP_RESTORE Key should be created or opened with special privileges that allow backup and restore operations. This flag is not used by device and intermediate drivers.
Disposition [out, optional]
Pointer to a variable that receives a value indicating whether a new key was created or an existing one opened.
Disposition value Description
REG_CREATED_NEW_KEY A new key was created.
REG_OPENED_EXISTING_KEY An existing key was opened.
Return value
ZwCreateKey returns STATUS_SUCCESS on success, or the appropriate NTSTATUS error code on failure.
NTSTATUS ZwOpenKey(
  _Out_ PHANDLE            KeyHandle,
  _In_  ACCESS_MASK        DesiredAccess,
  _In_  POBJECT_ATTRIBUTES ObjectAttributes
);

Parameters

KeyHandle [out]
Pointer to the HANDLE variable that receives the handle to the key.

DesiredAccess [in]
Specifies an ACCESS_MASK value that determines the requested access to the object. For more information, see the DesiredAccess parameter of ZwCreateKey.

ObjectAttributes [in]
Pointer to an OBJECT_ATTRIBUTES structure that specifies the object name and other attributes. Use InitializeObjectAttributes to initialize this structure. If the caller is not running in a system thread context, it must set the OBJ_KERNEL_HANDLE attribute when it calls InitializeObjectAttributes.

Return value
ZwOpenKey returns STATUS_SUCCESS if the given key was opened. Otherwise, it can return an error status, including the following:
STATUS_INVALID_HANDLE
STATUS_ACCESS_DENIED

1.2 读注册表键值

1)用ZwQueryValueKey 获取数据结构的长度。
2)分配如此长度的内存。
3)再次调用ZwQueryValueKey 查询。
4)回收内存

NTSTATUS ZwQueryValueKey(
  _In_      HANDLE                      KeyHandle,
  _In_      PUNICODE_STRING             ValueName,
  _In_      KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  _Out_opt_ PVOID                       KeyValueInformation,
  _In_      ULONG                       Length,
  _Out_     PULONG                      ResultLength
);

Parameters

KeyHandle [in]
Handle to the key to read value entries from. This handle is created by a successful call to ZwCreateKey or ZwOpenKey.

ValueName [in]
Pointer to the name of the value entry to obtain data for.

KeyValueInformationClass [in]
A KEY_VALUE_INFORMATION_CLASS value that determines the type of information returned in the KeyValueInformation buffer.

KeyValueInformation [out, optional]
Pointer to a caller-allocated buffer that receives the requested information.

Length [in]
Specifies the size, in bytes, of the KeyValueInformation buffer.

ResultLength [out]
Pointer to a variable that receives the size, in bytes, of the key information. If the ZwQueryValueKey routine returns STATUS_SUCCESS, callers can use the value of this variable to determine the amount of data returned. If the routine returns STATUS_BUFFER_OVERFLOW or STATUS_BUFFER_TOO_SMALL, callers can use the value of this variable to determine the size of buffer required to hold the key information.

Return value
ZwQueryValueKey returns STATUS_SUCCESS on success, or the appropriate error code on failure. Possible error code values include:
Return code Description
STATUS_OBJECT_NAME_NOT_FOUND The registry value was not available.
STATUS_BUFFER_OVERFLOW The buffer supplied is too small, and only partial data has been written to the buffer. *ResultLength is set to the minimum size required to hold the requested information.
STATUS_BUFFER_TOO_SMALL The buffer supplied is too small, and no data has been written to the buffer. *ResultLength is set to the minimum size required to hold the requested information.
STATUS_INVALID_PARAMETER The KeyInformationClass parameter is not a valid KEY_VALUE_INFORMATION_CLASS value.Warning If you specify KeyValueBasicInformation for KeyValueInformationClass, Windows 98 and Windows Me return STATUS_SUCCESS even if the registry key or value name does not exist.

1.3 写注册表键值

调用ZwSetValueKey

NTSTATUS ZwSetValueKey(
  _In_     HANDLE          KeyHandle,
  _In_     PUNICODE_STRING ValueName,
  _In_opt_ ULONG           TitleIndex,
  _In_     ULONG           Type,
  _In_opt_ PVOID           Data,
  _In_     ULONG           DataSize
);

Parameters

KeyHandle [in]
Handle to the registry key to write a value entry for. This handle is created by a successful call to ZwCreateKey or ZwOpenKey.

ValueName [in]
Pointer to the name of the value entry for which the data is to be written. This parameter can be a NULL pointer if the value entry has no name. If a name string is specified and the given name is not unique relative to its containing key, the data for an existing value entry is replaced.

TitleIndex [in, optional]
This parameter is reserved. Device and intermediate drivers should set this parameter to zero.

Type [in]
One of the following system-defined types of data to write.
Type Value Meaning
REG_BINARY Binary data in any form.
REG_DWORD A 4-byte numerical value.
REG_DWORD_LITTLE_ENDIAN A 4-byte numerical value with the least significant byte at the lowest address. Identical to REG_DWORD.
REG_DWORD_BIG_ENDIAN A 4-byte numerical value with the least significant byte at the highest address.
REG_EXPAND_SZ A null-terminated Unicode string that contains unexpanded references to environment variables, such as “%PATH%”.
REG_LINK A Unicode string that names a symbolic link. This type is irrelevant to device and intermediate drivers.
REG_MULTI_SZ An array of null-terminated strings, terminated by another zero.
REG_NONE Data with no particular type.
REG_SZ A null-terminated Unicode string.
REG_RESOURCE_LIST A device driver’s list of hardware resources, used by the driver or one of the physical devices it controls, in the \ResourceMap tree
REG_RESOURCE_REQUIREMENTS_LIST A device driver’s list of possible hardware resources it or one of the physical devices it controls can use, from which the system writes a subset into the \ResourceMap tree
REG_FULL_RESOURCE_DESCRIPTOR A list of hardware resources that a physical device is using, detected and written into the \HardwareDescription tree by the system
Note   Device drivers should not attempt to call ZwSetValueKey to explicitly write value entries in a subkey of the \Registry...\ResourceMap key. Only the system can write value entries to the \Registry...\HardwareDescription tree.

Data [in, optional]
Pointer to a caller-allocated buffer that contains the data for the value entry.

DataSize [in]
Specifies the size, in bytes, of the Data buffer. If Type is REG_XXX_SZ, this value must include space for any terminating zeros.

Return value
ZwSetValueKey returns an NTSTATUS value. Possible return values include:
STATUS_SUCCESS
STATUS_ACCESS_DENIED
STATUS_INVALID_HANDLE

2. 示例代码

//程序说明开始
//==================================================================================
// 功能 : 注册表操作函数
// 参数 : 
// (入口) 
// (出口) 无
// 返回 : NTSTATUS
// 主要思路 : 
// 调用举例 : 
// 日期 : 2016年7月6日 16:26:31 - 2016年7月6日 18:13:48
//==================================================================================
//程序说明结束
NTSTATUS
RegistryOption()
{
    HANDLE KeyHandle = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    UNICODE_STRING KeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING SourceKeyName = RTL_CONSTANT_STRING(L"SystemRoot");
    UNICODE_STRING TargetKeyName = RTL_CONSTANT_STRING(L"test");
    PKEY_VALUE_PARTIAL_INFORMATION AcKeyInfo = NULL;
    KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
    ULONG Length = 0;

    //初始化OBJECT_ATTRIBUTES结构体
    InitializeObjectAttributes(
        &ObjectAttributes,
        &KeyPath,
        OBJ_CASE_INSENSITIVE,
        NULL,
        NULL);

    //打开注册表键
    Status = ZwOpenKey(&KeyHandle, KEY_READ|KEY_WRITE, &ObjectAttributes);
    if (!NT_SUCCESS(Status))
    {
        DbgPrint("Open the Key Handle Faild!! -- %#X\n", Status);
        return Status;
    }

    //第一次读取注册表键值探测数据大小
    Status = ZwQueryValueKey(
        KeyHandle,
        &SourceKeyName,
        KeyValuePartialInformation,
        &KeyInfo,
        sizeof(KEY_VALUE_PARTIAL_INFORMATION),
        &Length);   
    if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
    {
        DbgPrint("读取SystemRoot键值失败!! - %#X\n", Status);
        ZwClose(KeyHandle);
        return Status;
    }

    //根据上面探测的注册表键值大小动态分配内存
    AcKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, Length, "tag2");
    if (NULL == AcKeyInfo)
    {
        DbgPrint("在分配保存Key键值的内存空间时失败!!");
        ZwClose(KeyHandle);
        Status = STATUS_INSUFFICIENT_RESOURCES;
        return Status;
    }

    //再次读取注册表键值
    Status = ZwQueryValueKey(
    KeyHandle,
    &SourceKeyName,
    KeyValuePartialInformation,
    AcKeyInfo,
    Length,
    &Length);
    if (!NT_SUCCESS(Status))
    {
        DbgPrint("读取SystemRoot键值失败!! - %#X\n", Status);
        ZwClose(KeyHandle);
        ExFreePool(AcKeyInfo);
        return Status;
    }

    //写入注册表值
    Status = ZwSetValueKey(
    KeyHandle,
    &TargetKeyName,
    0,
    AcKeyInfo->Type,
    AcKeyInfo->Data,
    AcKeyInfo->DataLength);
    if (!NT_SUCCESS(Status))
    {
        DbgPrint("写入test键值失败!! - %#X ", Status);
        ZwClose(KeyHandle);
        ExFreePool(AcKeyInfo);
        return Status;
    }   

    //释放内存与句柄
    ZwClose(KeyHandle);
    ExFreePool(AcKeyInfo);
    return Status;
}

找到一篇很不错的博客:
http://www.cnblogs.com/mydomain/archive/2
010/10/29/1864013.html

你可能感兴趣的:(注册表,驱动开发)