注册表在应用中和内核中有区别.在驱动中全部使用路径来表示,而不是一般应用程序编程中需要提供的根子健句柄.
应用中 HKEY_LOCAL_MACHINE 驱动中 \Registry\Machine
应用中 HKEY_USERS 驱动中 \Registry\User
应用中 HKEY_CLASSES_ROOT 驱动中没有对应的路径
应用中 HKEY_CURRENT_USER 驱动中也没简单的有对应路径,但是可以求得
打开注册表键使用函数 ZwOpenKey 新建或者打开 ZwCreateKey
打开注册表使用以下函数,不直接接受一个字符串,而是 OBJECT_ATTRIBUTES 指针(需要初始化,参考创建文件部分):
ZwOpenKey(
//OBJECT_ATTRIBUTES结构的指针
_Out_ PHANDLE KeyHandle,
//设置权限,可以组合 KEY_QUERY_VALUE 读取键下的值 KEY_SET_VALUE 设置键下的值
//KEY_CREATE_SUB_KEY 生成子健 KEY_ENUMERATE_SUB_KEYS 枚举子健
//实际可以使用 KEY_READ KEY_WRITE 和 KEY_ALL_ACCESS 这些组合宏
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
注册表键值的读取使用 ZwQueryValueKey ,注意注册表键值的类型和长度.
返回值:如果实际需要的长度比用户设置的要大,返回 STATUS_BUFFER_OVERFLOW 或者 STATUS_BUFFER_TOO_SMALL
如果成功读出全部数据,返回 STATUS_SUCCESS 其他情况,返回错误码
ZwQueryValueKey(
//打开的注册表键的句柄
_In_ HANDLE KeyHandle,
//要读取的值的名字
_In_ PUNICODE_STRING ValueName,
//需要查询的信息类型
//KeyValueBasicInformation 获得基础信息,包涵值名和类型
//KeyValueFullInformation 获得完整信息,包含值名,类型和值
//KeyValuePartialInformation 获得局部信息,包含类型和值 <-- 这个最常用
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
//当上面的变量是获取局部信息时,KEY_VALUE_PARTIAL_INFORMATION 结构的指针返回到这里
//这个结构有4个参数,2=数据类型 3=数据长度 4=可变长度的数据
_Out_writes_bytes_opt_(Length) PVOID KeyValueInformation,
//用户传入的输入空间 KeyValueInformation 的长度
_In_ ULONG Length,
//返回实际需要的长度
_Out_ PULONG ResultLength
);
因为不知道返回的值有多长,所以我们应该先获取长度,然后不足时在动态分配内存进行读取.
注册表打开和读取的完全实例:
#include
VOID DriverUnload(PDRIVER_OBJECT driver){
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path){
//注册表键句柄
HANDLE mykey = NULL;
//函数执行的返回结果
NTSTATUS status;
//静态定义要获取的注册表路径
UNICODE_STRING mykeypath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
//注册表对象属性,包涵注册表路径名称
OBJECT_ATTRIBUTES myobjattr = { 0 };
//初始化 OBJECT_ATTRIBUTES
InitializeObjectAttributes(&myobjattr, &mykeypath,OBJ_CASE_INSENSITIVE,NULL,NULL);
//打开注册表Key
status = ZwOpenKey(&mykey, KEY_READ, &myobjattr);
if (!NT_SUCCESS(status)){
DbgPrint("misaka: open regeditkey failed\r\n");
}
//要读取的值的名字
UNICODE_STRING mykeyname = RTL_CONSTANT_STRING(L"ProductName");
//用来测试大小的 和 实际使用的keyinfo指针
KEY_VALUE_PARTIAL_INFORMATION keyinfo;
PKEY_VALUE_PARTIAL_INFORMATION ackeyinfo;
ULONG aclength;
//读取注册表键的值
status = ZwQueryValueKey(mykey, &mykeyname, KeyValuePartialInformation, &keyinfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION),&aclength);
if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL){
DbgPrint("misaka: read regeditkeyvalue failed\r\n");
}
//分配需要的空间, ZwQueryValueKey 的第4个参数可以获得需要的长度
ackeyinfo = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, aclength, 2333);
if (ackeyinfo == NULL){
status = STATUS_INSUFFICIENT_RESOURCES;//错误处理
}
status = ZwQueryValueKey(mykey, &mykeyname, KeyValuePartialInformation, ackeyinfo,aclength,&aclength);
if (status == STATUS_SUCCESS){
UNICODE_STRING str = { 0 };
RtlInitUnicodeString(&str, (PCWSTR)ackeyinfo->Data);
DbgPrint("misaka: read regeditkeyvalue successfully ,data is: %wZ\r\n", str);
}else{
DbgPrint("misaka: read regeditkeyvalue failed\r\n");
}
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
输出:
misaka: read regeditkeyvalue successfully ,data is: Windows 7 Ultimate