首页
社区
课程
招聘
[原创]Delphi研究之驱动开发篇(八)-- 注册表
发表于: 2008-8-25 10:21 10690

[原创]Delphi研究之驱动开发篇(八)-- 注册表

2008-8-25 10:21
10690

8.1 注册表的结构
注册表(Registry)是基本数据的中心,在系统的设置和管理方面扮演着重要的角色。注册表的结构类似于磁盘的逻辑结构,但是注册表的内容不是磁盘数据的静态组合,而是随系统的工作进程而动态改变。注册表由keys构成,键就像磁盘的目录。最上层的keys叫做root keys。keys本身就是一个容器,装着其它的keys,装在里面的这些keys叫做subkeys或是values,就像磁盘上的文件。values保存着实际数据。对注册表的操作与管理是由Configuration Manager负责的。
root keys有六个:

HKEY_USER
包含所有注册信息;

HKEY_CURRENT_USER
保存着当前用户的注册信息;

HKEY_LOCAL_MACHINE
保存着系统配置信息:硬件设备支持记录,安全策略,用户口令,应用程序设置和服务及驱动程序配置。

HKEY_CURRENT_CONFIG
包含当前硬件配置信息;

HKEY_CLASSES_ROOT
保存着文件关联和COM类的注册数据;

HKEY_PERFORMANCE_DATA
包含着性能信息。

HKEY_PERFORMANCE_DATA 是一个特殊的键,未必会直接用到。在用户模式下,关于性能统计的信息是通过Performance Data Helper库来访问的,这个库实现在模块pdh.dll里。标准程序Performance Monitor正是利用了这个库。除性能统计之外这个键还包含着许多补充信息。例如,用于枚举进程、线程和模块等等的Process Status函数(在psapi.dll里实现)正是从HKEY_PERFORMANCE_DATA键中获得的信息。注册表编辑器Regedit和Regedt32并不能显示出这个键的内容,因此无法编辑。
根键HKEY_CURRENT_USER、HKEY_CURRENT_CONFIG和HKEY_CLASSES_ROOT并不包含什么信息。它们只是链接到注册表其它的子键。

HKEY_CURRENT_USER
链接到子键HKEY_USER\ 系统用户中对应于当前用户的注册信息。

HKEY_CURRENT_CONFIG
链接到子键HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current.
HKEY_CLASSES_ROOT
链接到子键HKEY_LOCAL_MACHINE\SOFTWARE\Classes和HKEY_CURRENT_USER\SOFTWARE\Classes.

8.2 在驱动程序中访问注册表
如何在内核模式下访问注册表?对注册表的访问和访问其它命名对象完全相同,即通过对象管理器的名字空间(详细方法见第三章)来访问。为了将注册表名字空间与对象管理器名字空间集成起来,配置管理器(Configuration Manager)在建立了一个名为“Registry”注册键类型的对象(key object)并将其放在对象管理器名字空间的根目录下。对于内核模式组件,有进入注册表的入口点。
所有的内核函数,对命名对象的访问要获得其名称,这个名称位于结构体OBJECT_ATRIBUTES的一个成员中,这个我们以前就知道了。如果对象类型为注册表键,则对象名字应该起始于“\Registry”。我要说的是,我不知道打开HKEY_PERFORMANCE_DATA根键要用什么名字,以及更一般的说,对某个键要用哪个名字。我在这方面作出过努力,但都是白费。如果您了解这方面的东西,还请您教我一下。有两个根键还算简单。

键 名称
HKEY_USER "\Registry\User"
HKEY_LOCAL_MACHINE "\Registry\Machine"

对于三个链接到其它地方的键还需要额外的操作。比如说,操作HKEY_CURRENT_CONFIG键需要知道它链接到了子键HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current上并用这个根键名字代替。这样就得到了\Registry\Machine\SYSTEM\CurrentControlSet\Hardware Profiles\Current这个名字。很可惜,我们不能使用CTW0和$CTW0宏来定义这个长长的unicode字符串,这个字符串超出了47个符号的限制。对此您可以用自己的方案来解决。

8.3 RegistryWorks驱动程序源代码
现在,当我们熟知根键名字的时候,理解它们就不会太困难。

unit RegistryWorks;

interface

uses
  nt_status, ntoskrnl, native, winioctl, fcall, macros;

function _DriverEntry(pDriverObject:PDRIVER_OBJECT;
                      pusRegistryPath:PUNICODE_STRING): NTSTATUS; stdcall;

implementation

var
  g_usMachineKeyName: UNICODE_STRING;
  g_usValueName: UNICODE_STRING;
  g_wszStringData: UNICODE_STRING;

procedure CreateKey;
var
  oa: OBJECT_ATTRIBUTES;
  hKey: THANDLE;
  dwDisposition: DWORD;
  RtnCode: NTSTATUS;
begin
  DbgPrint(#13#10'RegistryWorks: *** Creating registry key'#13#10);

  InitializeObjectAttributes(oa, @g_usMachineKeyName,
                             OBJ_CASE_INSENSITIVE, 0, nil);
  RtnCode := ZwCreateKey(hKey, KEY_WRITE, @oa, 0, nil,
                         REG_OPTION_VOLATILE, dwDisposition);
  if  RtnCode = STATUS_SUCCESS then
  begin
    if dwDisposition = REG_CREATED_NEW_KEY then
    begin
      DbgPrint('RegistryWorks: Registry key \Registry\Machine\Software\CoolApp created'#13#10);
    end else if dwDisposition = REG_OPENED_EXISTING_KEY then
    begin
      DbgPrint('RegistryWorks: Registry key \Registry\Machine\Software\CoolApp opened'#13#10);
    end;          
    ZwClose(hKey);
    DbgPrint('RegistryWorks: Registry key handle closed'#13#10);
  end else
  begin
    DbgPrint('RegistryWorks: Can''t create registry key. Status: %08X'#13#10,
             RtnCode);
  end;
end;

procedure SetValueKey;
var
  oa: OBJECT_ATTRIBUTES;
  hKey: THANDLE;
  RtnCode: NTSTATUS;
begin
  DbgPrint(#13#10'RegistryWorks: *** Opening registry key to set new value'#13#10);
  InitializeObjectAttributes(oa, @g_usMachineKeyName,
                             OBJ_CASE_INSENSITIVE, 0, nil);
  RtnCode := ZwOpenKey(hKey, KEY_SET_VALUE, @oa);
  if RtnCode = STATUS_SUCCESS then
  begin
    DbgPrint('RegistryWorks: Registry key openeded'#13#10);
    RtnCode := ZwSetValueKey(hKey, @g_usValueName, 0, REG_SZ,
                             @g_wszStringData,
                             sizeof(g_wszStringData));
    if RtnCode = STATUS_SUCCESS then
    begin
      DbgPrint('RegistryWorks: Registry key value added'#13#10);
    end else
    begin
      DbgPrint('RegistryWorks: Can''t set registry key value. Status: %08X'#13#10,
               RtnCode);
    end;
    ZwClose(hKey);
    DbgPrint('RegistryWorks: Registry key handle closed'#13#10);
  end else
  begin
    DbgPrint('RegistryWorks: Can''t open registry key. Status: %08X'#13#10,
             RtnCode);
  end;
end;

procedure QueryValueKey;
var
  oa: OBJECT_ATTRIBUTES;
  hKey: THANDLE;
  cb: DWORD;
  ppi: PKEY_VALUE_PARTIAL_INFORMATION;
  _as: ANSI_STRING;
  us: UNICODE_STRING;
  RtnCode: NTSTATUS;
begin
  DbgPrint(#13#10'RegistryWorks: *** Opening registry key to read value'#13#10);
  InitializeObjectAttributes(oa, @g_usMachineKeyName,
                             OBJ_CASE_INSENSITIVE, 0, nil);
  RtnCode := ZwOpenKey(hKey, KEY_QUERY_VALUE, @oa);
  if RtnCode = STATUS_SUCCESS then
  begin
    DbgPrint('RegistryWorks: Registry key openeded'#13#10);
    RtnCode := ZwQueryValueKey(hKey, @g_usValueName,
                               KeyValuePartialInformation,
                               nil, 0, cb);
    if cb <> 0 then
    begin
      ppi := ExAllocatePool(PagedPool, cb);
      if ppi <> nil then
      begin
        RtnCode := ZwQueryValueKey(hKey, @g_usValueName,
                                   KeyValuePartialInformation,
                                   ppi, cb, cb);
        if (RtnCode = STATUS_SUCCESS ) and ( cb <> 0) then
        begin
          if ppi^._Type = REG_SZ then
          begin
            //RtlInitUnicodeString(us, @ppi^.Data);
            if RtlUnicodeStringToAnsiString(@_as, @ppi^.Data, true) = STATUS_SUCCESS then
            begin
              DbgPrint('RegistryWorks: Registry key value is: %s'#13#10,
                       _as.Buffer);
              RtlFreeAnsiString(@_as);
            end;
          end;
        end else
        begin
          DbgPrint('RegistryWorks: Can''t query registry key value. Status: %08X'#13#10,
                   RtnCode);
        end;
        ExFreePool(ppi);
      end else
      begin
        DbgPrint('RegistryWorks: Can''t allocate memory. Status: %08X'#13#10,
                 ppi);
      end;
    end else
    begin
      DbgPrint('RegistryWorks: Can''t get bytes count needed for key partial information. Status: %08X'#13#10,
               RtnCode);
    end;
    ZwClose(hKey);
    DbgPrint('RegistryWorks: Registry key handle closed'#13#10);
  end else
  begin
    DbgPrint('RegistryWorks: Can''t open registry key. Status: %08X'#13#10,
             RtnCode);
  end;
end;

procedure DeleteKey;
var
  oa: OBJECT_ATTRIBUTES;
  hKey: THANDLE;
  RtnCode: NTSTATUS;
begin
  DbgPrint(#13#10'RegistryWorks: *** Deleting registry key'#13#10);
  InitializeObjectAttributes(oa, @g_usMachineKeyName,
                             OBJ_CASE_INSENSITIVE, 0, nil);
  RtnCode := ZwOpenKey(hKey, KEY_ALL_ACCESS, @oa);
  if RtnCode = STATUS_SUCCESS then
  begin
    DbgPrint('RegistryWorks: Registry key opened'#13#10);
    RtnCode := ZwDeleteKey(hKey);
    if RtnCode = STATUS_SUCCESS then
    begin
      DbgPrint('RegistryWorks: Registry key deleted'#13#10);
    end else
    begin
      DbgPrint('RegistryWorks: Can''t delete registry key. Status: %08X'#13#10,
               RtnCode);
    end;
    ZwClose(hKey);
    DbgPrint('RegistryWorks: Registry key handle closed'#13#10);
  end else
  begin
    DbgPrint('RegistryWorks: Can''t open registry key. Status: %08X'#13#10,
             RtnCode);
  end;
end;

procedure EnumerateKey;
var
  oa: OBJECT_ATTRIBUTES;
  hKey: THANDLE;
  cb: DWORD;
  pbi: PKEY_BASIC_INFORMATION;
  pfi: PKEY_FULL_INFORMATION;
  _as: ANSI_STRING;
  us: UNICODE_STRING;
  dwSubKeys, iCnt: DWORD;
  pwszKeyName: PWideChar;
  g_usUserKeyName: UNICODE_STRING;
  RtnCode: NTSTATUS;
  lpTemp: PVOID;
begin
  lpTemp := nil;
  DbgPrint(#13#10'RegistryWorks: *** Opening \Registry\User key to enumerate'#13#10);
  RtlInitUnicodeString(g_usUserKeyName, '\Registry\User');

  InitializeObjectAttributes(oa, @g_usUserKeyName,
                             OBJ_CASE_INSENSITIVE, 0, nil);
  RtnCode := ZwOpenKey(hKey, KEY_ENUMERATE_SUB_KEYS, @oa);
  if RtnCode = STATUS_SUCCESS then
  begin
    DbgPrint('RegistryWorks: Registry key openeded'#13#10);
    ZwQueryKey(hKey, KeyFullInformation, lpTemp, 0, cb);
    if cb <> 0 then
    begin
      pfi := ExAllocatePool(PagedPool, cb);
      if pfi <> nil then
      begin
        RtnCode := ZwQueryKey(hKey, KeyFullInformation, PVOID(pfi),
                              cb, cb);
        if (RtnCode = STATUS_SUCCESS ) and ( cb <> 0) then
        begin
          dwSubKeys := pfi^.SubKeys;
          DbgPrint('RegistryWorks: ---------- Starting enumerate subkeys ----------'#13#10);
          iCnt := 0;
          while iCnt < dwSubKeys do
          begin
            ZwEnumerateKey(hKey, iCnt, KeyBasicInformation,
                           lpTemp, 0, cb);
            if cb <> 0 then
            begin
              pbi := ExAllocatePool(PagedPool, cb);
              if pbi <> nil then
              begin
                RtnCode := ZwEnumerateKey(hKey, iCnt,
                                          KeyBasicInformation,
                                          PVOID(pbi), cb, cb);
                if (RtnCode = STATUS_SUCCESS ) and ( cb <> 0) then
                begin
                  cb := pbi^.NameLength + sizeof(WCHAR);
                  pwszKeyName := ExAllocatePool(PagedPool, cb);
                  if pwszKeyName <> nil then
                  begin
                    memset(pwszKeyName, 0, cb);
                    wcsncpy(pwszKeyName, PWideChar(@pbi^._Name), pbi^.NameLength div 2);

                    RtlInitUnicodeString(us, pwszKeyName);
                    if RtlUnicodeStringToAnsiString(@_as, @us, TRUE) = STATUS_SUCCESS then
                    begin
                      DbgPrint('RegistryWorks: %s'#13#10,
                               _as.Buffer);
                      RtlFreeAnsiString(@_as);
                    end;
                    ExFreePool(pwszKeyName);
                  end;
                end else
                begin
                  DbgPrint('RegistryWorks: Can''t enumerate registry keys. Status: %08X'#13#10,
                           RtnCode);
                end;
                ExFreePool(pbi);
              end;
            end;
            inc(iCnt);
          end;
          DbgPrint('RegistryWorks: ------------------------------------------------'#13#10);
        end else
        begin
          DbgPrint('RegistryWorks: Can''t query registry key information. Status: %08X'#13#10,
                   RtnCode);
        end;
        ExFreePool(pfi);
      end else
      begin
        DbgPrint('RegistryWorks: Can''t allocate memory. Status: %08X'#13#10,
                 pfi);
      end;
    end;
    ZwClose(hKey);
    DbgPrint('RegistryWorks: Registry key handle closed'#13#10);
  end else
  begin
    DbgPrint('RegistryWorks: Can''t open registry key. Status: %08X'#13#10,
             RtnCode);
  end;
end;

{驱动程序进入点}
function _DriverEntry(pDriverObject:PDRIVER_OBJECT; pusRegistryPath:PUNICODE_STRING): NTSTATUS;
begin
  DbgPrint(#13#10'RegistryWorks: Entering DriverEntry'#13#10);
  {初始化相关unicode字符串}
  RtlInitUnicodeString(g_usMachineKeyName, '\Registry\Machine\Software\CoolApp');
  RtlInitUnicodeString(g_usValueName, 'SomeData');
  RtlInitUnicodeString(g_wszStringData, 'It''s just a string');
  CreateKey;
  SetValueKey;
  QueryValueKey;
  DeleteKey;
  EnumerateKey;

  DbgPrint(#13#10'RegistryWorks: Leaving DriverEntry'#13#10);
  result := STATUS_DEVICE_CONFIGURATION_ERROR;
end;

end.
RtnCode := ZwCreateKey(hKey, KEY_WRITE, @oa, 0, nil,
                                         REG_OPTION_VOLATILE, dwDisposition);
if  RtnCode = STATUS_SUCCESS then
begin
  if dwDisposition = REG_CREATED_NEW_KEY then
  begin
    DbgPrint('RegistryWorks: Registry key \Registry\Machine\Software\CoolApp created'#13#10);
  end else if dwDisposition = REG_OPENED_EXISTING_KEY then
  begin
    DbgPrint('RegistryWorks: Registry key \Registry\Machine\Software\CoolApp opened'#13#10);
  end;
ZwOpenKey(hKey, KEY_SET_VALUE, @oa);
ZwOpenKey(hKey, KEY_QUERY_VALUE, @oa);
ZwOpenKey(hKey, KEY_ALL_ACCESS, @oa);
ZwOpenKey(hKey, KEY_ENUMERATE_SUB_KEYS, @oa);
RtnCode := ZwSetValueKey(hKey, @g_usValueName, 0, REG_SZ,
                             @g_wszStringData,
                             sizeof(g_wszStringData));
RtnCode := ZwQueryValueKey(hKey, @g_usValueName,
                          KeyValuePartialInformation,
                          nil, 0, cb);
if cb <> 0 then
begin
  ppi := ExAllocatePool(PagedPool, cb);
  if ppi <> nil then
  begin
    RtnCode := ZwQueryValueKey(hKey, @g_usValueName,
                              KeyValuePartialInformation,
                              ppi, cb, cb);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (12)
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
2
占个沙发,慢慢看
2008-8-25 10:47
0
雪    币: 217
活跃值: (91)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
N久没看到新的文章,还以为不继续了,支持一下
2008-8-25 12:04
0
雪    币: 1004
活跃值: (75)
能力值: ( LV9,RANK:570 )
在线值:
发帖
回帖
粉丝
4
有这么多兄弟支持,怎么会不继续呢,只是目前在做一个较大的项目,更新速度可能会稍微慢些。
2008-8-25 12:10
0
雪    币: 65
活跃值: (811)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
5
来支持一下~
2008-8-25 12:11
0
雪    币: 347
活跃值: (30)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
6
我也来支持一下子
2008-8-25 12:21
0
雪    币: 196
活跃值: (35)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
我是常常盯着这个专题,嘿嘿。
2008-8-27 10:01
0
雪    币: 277
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
占个沙发,慢慢看
2008-8-27 10:19
0
雪    币: 215
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
貌似不能访问跨单元的变量,一访问就BSOD,严重不方便,请问LZ可以解决下么
2009-1-13 12:46
0
雪    币: 563
活跃值: (101)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不错收藏了
2009-1-13 13:08
0
雪    币: 255
活跃值: (49)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
11
顶一下lz 期待精彩继续 ^_^
2009-1-13 16:38
0
雪    币: 104
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
Mark~
2009-10-10 13:59
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
Make 时出现 command arguments too long
如何解决啊
2009-12-2 15:12
0
游客
登录 | 注册 方可回帖
返回
//