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“删除注册表