您的位置:首页 > 其它

Windows驱动开发之注册表操作

2016-07-06 22:44 495 查看
转载请注明来源:

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 flagAllows caller to do this
KEY_QUERY_VALUERead key values.
KEY_SET_VALUEWrite key values.
KEY_CREATE_SUB_KEYCreate subkeys for the key.
KEY_ENUMERATE_SUB_KEYSRead the key’s subkeys.
KEY_CREATE_LINKCreate a symbolic link to the key. This flag is not used by device and intermediate drivers.
KEY_NOTIFYAsk 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 theseACCESS_MASK flags
KEY_READSTANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY
KEY_WRITESTANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUBKEY
KEY_EXECUTESame as KEY_READ.
KEY_ALL_ACCESSSTANDARD_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 flagDescription
REG_OPTION_VOLATILEKey is not preserved when the system is rebooted.
REG_OPTION_NON_VOLATILEKey is preserved when the system is rebooted.
REG_OPTION_CREATE_LINKThe newly created key is a symbolic link. This flag is not used by device and intermediate drivers.
REG_OPTION_BACKUP_RESTOREKey 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 valueDescription
REG_CREATED_NEW_KEYA new key was created.
REG_OPENED_EXISTING_KEYAn 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 codeDescription
STATUS_OBJECT_NAME_NOT_FOUNDThe registry value was not available.
STATUS_BUFFER_OVERFLOWThe 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_SMALLThe 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_PARAMETERThe 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 ValueMeaning
REG_BINARYBinary data in any form.
REG_DWORDA 4-byte numerical value.
REG_DWORD_LITTLE_ENDIANA 4-byte numerical value with the least significant byte at the lowest address. Identical to REG_DWORD.
REG_DWORD_BIG_ENDIANA 4-byte numerical value with the least significant byte at the highest address.
REG_EXPAND_SZA null-terminated Unicode string that contains unexpanded references to environment variables, such as “%PATH%”.
REG_LINKA Unicode string that names a symbolic link. This type is irrelevant to device and intermediate drivers.
REG_MULTI_SZAn array of null-terminated strings, terminated by another zero.
REG_NONEData with no particular type.
REG_SZA null-terminated Unicode string.
REG_RESOURCE_LISTA 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_LISTA 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_DESCRIPTORA 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  驱动开发 注册表