8、Windows驱动开发技术详解笔记(4) 基本语法回顾

简介:  4、注册表操作 和文件操作类似,在操作注册表之前需要首先打开注册表,获得一个句柄,这可以通过函数ZwCreateKey 完成。与ZwCreateFile函数类似,它通过一个OBJECT_ATTRIBUTES 获得需要创建或打开的路径信息,但在内核中这个路径与用户模式下不相同,实际上,因为用户模式下的应用程序总是由某个“当前用户”打开的,因此在用户模式下可以直接访问HKEY_CLASSES_ROOT 和HKEY_CURRENT_USER,但工作在内核模式下的驱动程序不属于任何一个用户,因此不能直接访问这两个根键。

 4、注册表操作

和文件操作类似,在操作注册表之前需要首先打开注册表,获得一个句柄,这可以通过函数ZwCreateKey 完成。与ZwCreateFile函数类似,它通过一个OBJECT_ATTRIBUTES 获得需要创建或打开的路径信息,但在内核中这个路径与用户模式下不相同,实际上,因为用户模式下的应用程序总是由某个当前用户打开的,因此在用户模式下可以直接访问HKEY_CLASSES_ROOT HKEY_CURRENT_USER,但工作在内核模式下的驱动程序不属于任何一个用户,因此不能直接访问这两个根键。

如果ZwCreateKey 指定的项不存在,则会直接创建该项,同时由函数的Disposition参数返回REG_CREATED_NEW_KEY;如果指定项已经存在了,则 Disposition返回值REG_OPENED_EXISTING_KEYDDK同样提供了一个ZwOpenKey函数用以简化打开注册表的操作。同时DDK还提供一系列以Rtl 开头的运行时函数,它们可以是对Zw系列函数的封装,可以有效地简化对注册表的操作过程。

wps_clip_image-6573

wps_clip_image-25020

Zw系统注册相关函数

http://msdn.microsoft.com/en-us/library/ff566425%28VS.85%29.aspx

wps_clip_image-10646

Rtl系统注册相关函数

http://msdn.microsoft.com/en-us/library/ff561822%28VS.85%29.aspx

1)读写注册表

注册表是以二元形式存储的,即键名键值,通过键名来设置键值,其中键值分为多种情况。

wps_clip_image-11238

表 注册键类型

通过ZwSetValueKe y 函数添加或修改注册表键值,通过ZwQueryValueKe y

数查询相关键值。

2)枚举

枚举注册表通常分两种情况:枚举一个注册表项的所有子项和枚举一个注册表项的所有子键。

枚举子项使用ZwQueryKey(注意不是ZwQueryValueKey)和ZwEnumerateKe y配合完成,枚举子键使用ZwQueryKeyZwEnumerateValueKey配合完成。

我们以枚举子项来说明思路,首先利用ZwQueryKey获得某项究竟有多少个子项,然后利用ZwEnumerateKe y来获取指定子项的详细信息,这个过程是通过一个子项索引(index)来完成的。在使用ZwQueryKey时,可以将参数KeyInformationClass指定为KeyFullInformation,它对应KEY_FULL_INFORMATION结构中的SubKeys指明了该项中有多少子项。

3)一个例子如下

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
 
   
1 /* ***********************************************************************
2
3 * 函数名称:RegEnumTest
4
5 * 功能描述:测试读取注册表
6
7 * 参数列表:
8
9 * 返回 值:返回状态
10
11 ************************************************************************ */
12
13 NTSTATUS
14
15 RegEnumTest()
16
17 {
18
19 UNICODE_STRING ustrRegString;
20
21 UNICODE_STRING ustrKeyName;
22
23 HANDLE hRegister;
24
25 ULONG ulSize, i = 0 ;
26
27 OBJECT_ATTRIBUTES obj_attrib;
28
29 NTSTATUS status;
30
31 PKEY_FULL_INFORMATION pfi;
32
33 PKEY_BASIC_INFORMATION pbi;
34
35   // 初始化
36  
37 RtlInitUnicodeString( & ustrRegString,L " \\Registry\\Machine\\SOFTWARE\\ODBC\\ODBC.INI " );
38
39 InitializeObjectAttributes( & obj_attrib,
40
41   & ustrRegString,
42
43 OBJ_CASE_INSENSITIVE,
44
45 NULL,
46
47 NULL);
48
49   // 打开注册表
50
51 status = ZwOpenKey( & hRegister, KEY_ALL_ACCESS, & obj_attrib);
52
53 if (NT_SUCCESS(status))
54
55 {
56
57 KdPrint(( " [Test] ZwOpenKey %wZ Success! " , ustrRegString));
58
59 }
60
61 // 第一次调用是为了获取需要的长度
62
63 ZwQueryKey(hRegister, KeyFullInformation, NULL, 0 , & ulSize);
64
65 pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize);
66
67 // 第二次调用是为了获取数据
68
69 ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, & ulSize);
70
71 for (i = 0 ; i < pfi -> SubKeys; i ++ )
72
73 {
74
75 // 获取第i 个子项的长度
76
77 ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0 , & ulSize);
78
79 pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize);
80
81 // 获取第i 个子项的数据
82
83 ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, & ulSize);
84
85 ustrKeyName.Length = (USHORT)pbi -> NameLength;
86
87 ustrKeyName.Buffer = pbi -> Name;
88
89 KdPrint(( " [Test] The %d SubItem Name : %wZ.\n " , i, & ustrKeyName));
90
91 // 释放内存
92
93 ExFreePool(pbi);
94
95 }
96
97 ExFreePool(pfi);
98
99 ZwClose(hRegister);
100
101 return STATUS_SUCCESS;
102
103 }

4)读与写

一般使用ZwQueryValueKey来读取注册表中键的值。要注意的是注册表中的值可能有多种数据类型。而且长度也是没有定数的。为此,在读取过程中,就可能要面对很多种可能的情况。

http://msdn.microsoft.com/en-us/library/ff567069%28VS.85%29.aspx

其参数中:

KeyValueInformationClass:本次查询所需要查询的信息类型。这有如下的三种可能。

KeyValueBasicInformation:获得基础信息,包含值名和类型。

KeyValueFullInformation:获得完整信息。包含值名、类型和值的数据。

KeyValuePartialInformation:获得局部信息。包含类型和值数据。

使用KeyValuePartialInformation最常见。

KeyValueInformation:当KeyValueInformationClass被设置为KeyValuePartialInformation时,KEY_VALUE_PARTIAL_INFORMATION结构将被返回到这个指针所指内存中。

示例代码:

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
 
    
1 // 要读取的值的名字
2
3 UNICODE_STRING my_key_name =
4
5 RTL_CONSTANT_STRING(L”SystemRoot”);
6
7 // 用来试探大小的key_infor
8
9 KEY_VALUE_PARTIAL_INFORMATION key_infor;
10
11 // 最后实际用到的key_infor指针。内存分配在堆中
12
13 PKEY_VALUE_PARTIAL_INFORMATION ac_key_infor;
14
15 ULONG ac_length;
16
17 ……
18
19 // 前面已经打开了句柄my_key,下面如此来读取值:
20
21 status = ZwQueryValueKey(
22
23 my_key,
24
25 & my_key_name,
26
27 KeyValuePartialInformation,
28
29 & key_infor,
30
31 sizeof (KEY_VALUE_PARTIAL_INFORMATION),
32
33 & ac_length);
34
35 if ( ! NT_SUCCESS(status) &&
36
37 status != STATUS_BUFFER_OVERFLOW &&
38
39 status != STATUS_BUFFER_TOO_SMALL)
40
41 {
42
43 // 错误处理
44
45
46
47 }
48
49 // 如果没失败,那么分配足够的空间,再次读取
50
51 ac_key_infor = (PKEY_VALUE_PARTIAL_INFORMATION)
52
53 ExAllocatePoolWithTag(NonpagedPool,ac_length ,MEM_TAG);
54
55 if (ac_key_infor == NULL)
56
57 {
58
59 stauts = STATUS_INSUFFICIENT_RESOURCES;
60
61 // 错误处理
62
63
64
65 }
66
67 status = ZwQueryValueKey(
68
69 my_key,
70
71 & my_key_name,
72
73 KeyValuePartialInformation,
74
75 ac_key_infor,
76
77 ac_length,
78
79 & ac_length);
80
81 // 到此为止,如果status为STATUS_SUCCESS,则要读取的数据已经
82
83 // 在ac_key_infor->Data中。请转换为UNICODE_STRING
84
85 ……

写:

一般使用函数ZwSetValueKey

http://msdn.microsoft.com/en-us/library/ff567109%28VS.85%29.aspx

其中的TileIndex参数请始终填入0

Data是要写入的数据的开始地址,而DataSize是要写入的数据的长度。由于Data是一个空指针,因此,Data可以指向任何数据。 ZwSetValueKey执行时:如果Value已经存在,则写入覆盖,否则新建一个。下面的例子写入一个名字为“Test”,而且值为“My Test Value”的字符串值。假设my_key是一个已经打开的子键的句柄。

UNICODE_STRING name = RTL_CONSTANT_STRING(LTest);

PWCHAR value = { LMy Test Value};

// 数据长度要将字符串长度加上1,把最后一个空结束符

status = ZwSetValueKey(my_key,

&name,0,REG_SZ,value,(wcslen(value)+1)*sizeof(WCHAR));

if(!NT_SUCCESS(status))

{

// 错误处理

……

}

目录
相关文章
|
14天前
|
IDE 关系型数据库 开发工具
使用Visual Basic进行Windows窗体开发
【4月更文挑战第27天】本文介绍了使用Visual Basic进行Windows窗体(WinForms)开发的步骤,从搭建开发环境到创建、设计用户界面,再到编写事件驱动的代码和数据绑定。Visual Basic结合WinForms提供了一种易学易用的桌面应用开发方案。通过调试、优化、部署和维护,开发者可以构建专业应用程序。随着技术发展,掌握最新UI设计和开发工具对于保持竞争力至关重要。本文为初学者提供了基础指导,鼓励进一步探索和学习。
|
4月前
|
缓存 网络协议 数据安全/隐私保护
[运维笔记] - (命令).Windows server常用网络相关命令总结
[运维笔记] - (命令).Windows server常用网络相关命令总结
202 0
|
11天前
|
前端开发 Linux iOS开发
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
【4月更文挑战第30天】Flutter扩展至桌面应用开发,允许开发者用同一代码库构建Windows、macOS和Linux应用,提高效率并保持平台一致性。创建桌面应用需指定目标平台,如`flutter create -t windows my_desktop_app`。开发中注意UI适配、性能优化、系统交互及测试部署。UI适配利用布局组件和`MediaQuery`,性能优化借助`PerformanceLogging`、`Isolate`和`compute`。
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
|
13天前
|
编解码 Linux Windows
FFmpeg开发笔记(十三)Windows环境给FFmpeg集成libopus和libvpx
本文档介绍了在Windows环境下如何为FFmpeg集成libopus和libvpx库。首先,详细阐述了安装libopus的步骤,包括下载源码、配置、编译和安装,并更新环境变量。接着,同样详细说明了libvpx的安装过程,注意需启用--enable-pic选项以避免编译错误。最后,介绍了重新配置并编译FFmpeg以启用这两个库,通过`ffmpeg -version`检查是否成功集成。整个过程参照了《FFmpeg开发实战:从零基础到短视频上线》一书的相关章节。
FFmpeg开发笔记(十三)Windows环境给FFmpeg集成libopus和libvpx
|
14天前
|
编解码 Linux Windows
FFmpeg开发笔记(十一)Windows环境给FFmpeg集成vorbis和amr
在Windows环境下,为FFmpeg集成音频编解码库,包括libogg、libvorbis和opencore-amr,涉及下载源码、配置、编译和安装步骤。首先,安装libogg,通过配置、make和make install命令完成,并更新PKG_CONFIG_PATH。接着,安装libvorbis,同样配置、编译和安装,并修改pkgconfig文件。之后,安装opencore-amr。最后,重新配置并编译FFmpeg,启用ogg和amr支持,通过ffmpeg -version检查是否成功。整个过程需确保环境变量设置正确,并根据路径添加相应库。
FFmpeg开发笔记(十一)Windows环境给FFmpeg集成vorbis和amr
|
1月前
|
Linux 编译器 C语言
FFmpeg开发笔记(二)搭建Windows系统的开发环境
在Windows上学习FFmpeg通常较困难,但通过安装预编译的FFmpeg开发包可以简化流程。首先需要安装MSYS2来模拟Linux环境。下载并执行MSYS2安装包,然后修改msys2_shell.cmd以继承Windows的Path变量。使用pacman安装必要的编译工具。接着,下载预编译的FFmpeg Windows包,解压并配置系统Path。最后,在MSYS2环境中运行`ffmpeg -version`确认安装成功。欲深入学习FFmpeg开发,推荐阅读《FFmpeg开发实战:从零基础到短视频上线》。
FFmpeg开发笔记(二)搭建Windows系统的开发环境
|
2月前
|
数据可视化 数据库 C++
Qt 5.14.2揭秘高效开发:如何用VS2022快速部署Qt 5.14.2,打造无与伦比的Windows应用
Qt 5.14.2揭秘高效开发:如何用VS2022快速部署Qt 5.14.2,打造无与伦比的Windows应用
105 0
|
4月前
|
存储 Ubuntu 开发工具
ffmpeg笔记(二)windows下和ubuntu-16.04下ffmpeg编译
ffmpeg笔记(二)windows下和ubuntu-16.04下ffmpeg编译
|
5月前
|
Linux API C++
音视频windows安装ffmpeg6.0并使用vs调试源码笔记
音视频windows安装ffmpeg6.0并使用vs调试源码笔记
128 0
|
5月前
|
监控 安全 API
5.9 Windows驱动开发:内核InlineHook挂钩技术
在上一章`《内核LDE64引擎计算汇编长度》`中,`LyShark`教大家如何通过`LDE64`引擎实现计算反汇编指令长度,本章将在此基础之上实现内联函数挂钩,内核中的`InlineHook`函数挂钩其实与应用层一致,都是使用`劫持执行流`并跳转到我们自己的函数上来做处理,唯一的不同的是内核`Hook`只针对`内核API`函数,但由于其身处在`最底层`所以一旦被挂钩其整个应用层都将会受到影响,这就直接决定了在内核层挂钩的效果是应用层无法比拟的,对于安全从业者来说学会使用内核挂钩也是很重要。
44 1
5.9 Windows驱动开发:内核InlineHook挂钩技术

热门文章

最新文章