[普通]驱动层注册表操作

作者(passion) 阅读(889次) 评论(0) 分类( 内核开发)

在用户态下面,有大把的API可供我们操作注册表,例如RegOpenKey,RegCloseKey等,这些API都是由windows提供给用户态使用的API。

     那么对于驱动层了,因为驱动编程,并没有哪个能够提供额外的库可供我们调用,肯定是不能调用如RegOpenKey等这些API函数,那难道内核态就不能操作注册表嘛?答案显示是不成立的。那我们回头想想API的调用方式,任何注册表的操作,实际都是调用上层API,然后触发内核态API执行真正的操作,既然我们进入了内核态,那不是就可以直接调用上层API的真正实现函数么?于是乎,打开ntdll文件一看,大把的类似于ZwOpenKey,ZwEnumerateKey等函数,都是用来操作注册表的。如此,我们就一一的讨论关于注册表的一些常见操作。

一 注册表中常见数据结构

typedef struct _KEY_BASIC_INFORMATION {

  LARGE_INTEGER LastWriteTime;

  ULONG  TitleIndex;

  ULONG  NameLength;

  WCHAR  Name[1];  //  Variable-length string

} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;

typedef struct _KEY_NODE_INFORMATION {

  LARGE_INTEGER LastWriteTime;

  ULONG  TitleIndex;

  ULONG  ClassOffset;

  ULONG  ClassLength;

  ULONG  NameLength;

  WCHAR  Name[1];  //  Variable-length string

} KEY_NODE_INFORMATION, *PKEY_NODE_INFORMATION;

typedef _KEY_FULL_INFORMATION {

  LARGE_INTEGER  LastWriteTime;

  ULONG  TitleIndex;

  ULONG  ClassOffset;

  ULONG  ClassLength;

  ULONG  SubKeys;

  ULONG  MaxNameLen;

  ULONG  MaxClassLen;

  ULONG  Values;

  ULONG  MaxValueNameLen;

  ULONG  MaxValueDataLen;

  WCHAR  Class[1]; } KEY_FULL_INFORMATION; PKEY_FULL_INFORMATION

其中,KEY_BASIC_INFORMATION表示一个键下面所有的子键的信息;

KEY_NODE_INFORMATION表示该键的所有信息;

KEY_FULL_INFORMATION表示该键的所有信息,包括自身和子键的信息;

二 API函数概述

1.ZwCreateKey:打开或者创建一个新的注册表键;

2.ZwOpenKey:打开一个已在的注册表键;

3.ZwFlushKey:

4.ZwQueryKey:查询某注册表项所属的类,以及子键的数量和长度;

5.ZwQueryValueKey:查询某注册表项的所有键值信息;

6.ZwEnumerateKey:查询某子项的所有信息;

7.ZwEnumerateValueKey:获取某注册表子键的所有信息;

8.ZwClose:关闭注册表句柄;

三 注册表操作。

1.路径的表示方式

  HEKY_LOCAL_MACHINE对应在内核编程里的写法是\Registery\Machine

  HEKY_USERS对应在内核编程里的写法是\Registry\User

  另外两个主目录暂时没讨论;

2.注册表基本操作

(1)枚举注册表键下面的所有子项:利用ZwQueryKey和ZwEnumerateKey完成。

 如下例:

 RtlInitUnicodeString(&ustrRegString,strKey);

 InitializeObjectAttributes(&obj_attrib,&ustrRegString,OBJ_CASE_INSENSITIVE,NULL,NULL);

  // 打开注册表

 status = ZwOpenKey(&hRegister, KEY_READ, &obj_attrib);

  

 ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize);

 pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize);

 ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize);

 for (i = 0; i < pfi->SubKeys; i++)

 {

     ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize);

     pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize);

  

     ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize);

     ustrKeyName.Length = (USHORT)pbi->NameLength;

     ustrKeyName.Buffer = pbi->Name;

     ExFreePool(pbi);

 }

 ExFreePool(pfi);

 大致流程如下:

 A.先将文件路径信息转换为OBJECT_ATTRIBUTES类型;(同文件操作一致)

 B.打开路径对应的注册表项;

 C.调用ZwQueryKey获取该键对应的子项内容;

 D.调用ZwEnumrateKey获取子项的所有信息;

 细心发现上面没个API函数都调用两次,第一次的目的是获取子项的大小,以此动态分配内存,节约存储空

间。

(2)枚举子项下面的某对应名字的子键的内容值

如下例:

RtlInitUnicodeString( &RegUnicodeKeyName,L"DisplayName");

InitializeObjectAttributes(&objectAttributes,pStrKey, OBJ_CASE_INSENSITIVE,NULL,NULL );

ntStatus = ZwOpenKey( &hRegister,GENERIC_READ,&objectAttributes);

ntStatus = ZwQueryValueKey(hRegister,&RegUnicodeKeyName,KeyValueFullInformation,NULL,0,&ulSize);

pvfi =(PKEY_VALUE_FULL_INFORMATION)ExAllocatePool(PagedPool,ulSize);

ZwQueryValueKey(hRegister,&RegUnicodeKeyName,KeyValueFullInformation,pvfi,ulSize,&ulSize);

调用流程不在敖述,大致同上面类似,只是最后取子键值的时候,调用ZwQueryValueKey获取,对于KeyValueFullInformation值,该值记载了子键对应的名字和内容,内容在名字之后,偏移是根据DataOffset获取的。

(3)枚举子项下面的所有子键信息

InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL,    NULL );

ntStatus = ZwOpenKey( &hRegister,KEY_ALL_ACCESS, &objectAttributes);

ZwQueryKey(hRegister,KeyFullInformation,NULL,0,&ulSize);

pfi=(PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool,ulSize);

ZwQueryKey(hRegister,KeyFullInformation,pfi,ulSize,&ulSize);

for ( i=0;i<pfi->Values;i++)

{

   ZwEnumeratueKey(hRegister,i,KeyValueBasicInformation,NULL,0,&ulSize);

   pvbi =(PKEY_VALUE_BASIC_INFORMATION)ExAllocatePool(PagedPool,ulSize);

   ZwEnumeratueKey(hRegister,i,KeyValueBasicInformation,pvbi,ulSize,&ulSize);

 }

上面的流程首先打开某注册表子项,调用ZwQueryKey获取该子项对应的子键信息(数目和长度),然后调用ZwEnumeratueKey遍历该子项下面的所有子键信息。


« 上一篇:wifi共享上网(至尊版wifi)
« 下一篇:drcom至尊版使用openwrt路由器拨号
在这里写下您精彩的评论
  • 微信

  • QQ

  • 支付宝

返回首页
返回首页 img
返回顶部~
返回顶部 img