Windows驱动开发(5) - 内核模式下的注册表操作

时间:2021-01-20 04:52:20

Windows驱动开发(5) - 内核模式下的注册表操作

1、创建关闭注册表

1.1 创建注册表

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
);

参数
- KeyHandle:[out] :获得的注册表句柄。
- DesiredAccess:[in] :访问权限,一般设置为KEY_ALL_ACCESS
- KEY_QUERY_VALUE:读键值
- KEY_SET_VALUE:写键值
- KEY_CREATE_SUB_KEY:创建键的子健
- KEY_ENUMERATE_SUB_KEYS:读键的子健
- KEY_CREATE_LINK:创建符号链接
- KEY_NOTIFY:
还可以指定下面的几个常量,它包含了一个或多个ACCESS_MASK标志。
- KEY_READ
- KEY_WRITE
- KEY_EXECUTE
- KEY_ALL_ACCESS
- ObjectAttributes:[in] :OBJECT_ATTRIBUTES 数据结构,指示打开的状态。
- TitleIndex:[in] :很少用到,一般设置为0。
- Class:[in] :很少用到,一般设置为NULL。
- CreateOptions:[in] :创建时的选项,一般设置为REG_OPTION_NON_VOLATILE。
- Disposition:[out] :返回是创建成功,还是打开成功。返回值是REG_CREATED_NEW_KEY,REG_OPENEND_EXISTING_KEY。

返回值
返回是否创建成功。

1.2 关闭注册表

NTSTATUS ZwClose(
_In_ HANDLE Handle
);
  • Handle:注册表句柄

2、打开注册表

NTSTATUS ZwOpenKey(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
)
;
  • KeyHandle:返回被打开的句柄
  • DesiredAccess:访问权限,一般设置为KEY_ALL_ACCESS
  • ObjectAttributes:OBJECT_ATTRIBUTES 数据结构,指示打开的状态
  • 返回值:返回是否创建成功。

3、添加、修改注册表键值

NTSTATUS ZwSetValueKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_opt_ ULONG TitleIndex,
_In_ ULONG Type,
_In_opt_ PVOID Data,
_In_ ULONG DataSize
);
  • KeyHandle:注册表句柄
  • ValueName:要新建或修改的键名
  • TitleIndex:很少用,一般设为0
  • Type:键值类型
    • REG_BINARY:二进制
    • REG_SZ:宽字符串
    • REG_EXPAND_SZ:扩展宽字符串
    • REG_MULTI_SZ:多个字符串
    • REG_DWORD:4字节整型
    • REG_QWORD:8字节存储
  • Data:对应Type类型的键值数据指针
  • DataSize:记录键值数据的大小
  • 返回值:返回新建或修改的结果

4、查询注册表

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
);
  • KeyHandle:注册表句柄
  • ValueName:要查询的键名
  • KeyValueInformationClass:根据KeyValueInformation的不同选择不同的查询类别
    • KeyValueBasicInformation
    • KeyValueFullInformation
    • KeyValuePartialInformation
  • KeyValueInformation:查询数据指针
  • Length:要查数据的长度
  • ResultLength:实际查询数据的长度
  • 返回值:表示查询数据是否成功

5、枚举子项

  用ZwQueryKey与ZwEnumerateKey 来枚举子项。
  ZwQueryKey获取某注册表项究竟有多少个子项,而ZwEnumerateKey 针对第几个子项获取该子项的具体信息。
  我们发现,凡是调用有长度的函数,一般都是两次调用,第一次调用来获得具体查询(使用该函数)需要的内存需要多大长度,第二次调用时来查询具体信息。

NTSTATUS ZwQueryKey(
_In_ HANDLE KeyHandle,
_In_ KEY_INFORMATION_CLASS KeyInformationClass,
_Out_opt_ PVOID KeyInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);
  • KeyHandle:注册表项的句柄
  • KeyInformationClass:查询的类别,一般选择KeyFullInformation
  • KeyInformation:查询的数据指针。
  • Length:数据长度
  • ResultLength:返回的数据长度
  • 返回值:指示查询是否成功
NTSTATUS ZwEnumerateKey(
_In_ HANDLE KeyHandle,
_In_ ULONG Index,
_In_ KEY_INFORMATION_CLASS KeyInformationClass,
_Out_opt_ PVOID KeyInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);
  • KeyHandle:注册表项的句柄
  • Index:很少用到,一般为0
  • KeyInformationClass:查询的类别,一般选择KeyFullInformation
  • KeyInformation:查询的数据指针。
  • Length:子项信息的长度
  • ResultLength:返回的子项信息的长度
  • 返回值:指示枚举是否成功

6、枚举子健

通过ZwQueryKey与ZwEnumerateValueKey来枚举子键。

NTSTATUS ZwEnumerateValueKey(
_In_ HANDLE KeyHandle,
_In_ ULONG Index,
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
_Out_opt_ PVOID KeyValueInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);

7、删除子健

只能删除没有子项的项目。

NTSTATUS ZwDeleteKey(
_In_ HANDLE KeyHandle
)
;

8、其他

DDK中定义了一些运行时函数来简化上面的操作。
- RtlCreateRegistryKey:创建注册表
- RtlCheckRegistryKey:检查注册表中的一个给定的名称键是否存在
- RtlWriteRegistryValue:写注册表
- RtlDeleteRegistryValue“删除注册表