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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章