转载请注明来源:
enjoy5512的博客 : http://blog.csdn.net/enjoy5512
GitHub : https://github.com/whu-enjoy
注册表项相当于文件夹,注册表子项子文件夹(类似目录)
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)用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. |
调用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
//程序说明开始
//==================================================================================
// 功能 : 注册表操作函数
// 参数 :
// (入口)
// (出口) 无
// 返回 : 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