Kmd--10注册表

 

注册表
10.1 注册表结构
       注册表( Registry )——系统配置和管理中起重要作用的一个中心数据库。他的结构与注册驱动的结构是类似的,但是注册表不是静态存储在硬盘上而是在系统中动态改变的。注册表是由键组成的,存储在硬盘目录中。最高层的键被称为根键或主键。根键是一个包含其他子键 (subkeys) 或值 (values) 的容器。类似于硬盘上的文件。值用来保存合适的数据。配置管理器用来执行和管理注册表。
注册表一共有六个根键:

HKEY_USER
存储所有帐户的信息 ;
 
HKEY_CURRENT_USER
存储当前登录用户的信息 ;
 
HKEY_LOCAL_MACHINE
存储系统配置信息:硬件描述,安全策略,用户密码,系统设置,应用程序,以及服务和驱动等信息 ;
 
HKEY_CURRENT_CONFIG
存储当前硬件配置信息 ;
 
HKEY_CLASSES_ROOT
存储文件扩展名和组件对象模型( COM )的对象注册信息 ;
 
HKEY_PERFORMANCE_DATA
存储性能相关信息

HKEY_PERFORMANCE_DATA 是一个特别的键,直接访问需要的信息。可以通过性能数据帮助器( PDH, Performance Data Helper )库, Pdh.dll 模块来访问性能计数器信息。除了性能计数之外,这个键还包括许多其他额外信息。例如,进程功能状态( psapi.dll ),进程列表,流操作,模块等等。这些信息都来自于键 HKEY_PERFORMANCE_DATA 。注册表编辑器regedit和regedit32没有显示这个键的内容,对他的编辑没有作用。
HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG HKEY_CLASSES_ROOT 这三个根键不包含任何的信息。实际上是与其他子键相关联的。
 
 

HKEY_CURRENT_USER
HKEY_USER 的一个子键与当前系统登录用户相关的一个子键
HKEY_CURRENT_USER,HKEY_CURRENT_CONFIG HKEY_CLASSES_ROOT
这三个根键不包含任何的信息。实际上是与其他子键相关联的。
 
HKEY_CURRENT_CONFIG
与这个子键相关
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Hardware Profiles/Current.
 
HKEY_CLASSES_ROOT
与这个子键相关
 HKEY_LOCAL_MACHINE/SOFTWARE/Classes
и HKEY_CURRENT_USER/SOFTWARE/Classes.

10.2 访问注册表的驱动
       下面通过内核访问注册表,访问注册表的方式跟访问其他命名对象的方式相同,或者通过命名空间控制对象(第三部分有关于这个的详细说明)。为了使命名空间注册表和控制对象配置管理器相关联,必须在注册表名下创建一个键类型对象( 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 个字符,你可以用你认为可行的方法。
    10.3 RegistryWorks 驱动源码
  现在我们知道根键的名字,获得他们是很简单的。
;@echo off
;goto make
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
; RegistryWorks - Creates, sets/reads and deletes registry key
;
; Written by Four-F ([email protected])
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
.386
.model flat, stdcall
option casemap:none
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                 I N C L U D E   F I L E S                                       
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
include /masm32/include/w2k/ntstatus.inc
include /masm32/include/w2k/ntddk.inc
include /masm32/include/w2k/ntoskrnl.inc
includelib /masm32/lib/w2k/ntoskrnl.lib
include /masm32/Macros/Strings.mac
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                 R E A D O N L Y    D A T A                                       
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.const
;CCOUNTED_UNICODE_STRING "//Registry//User", g_usKeyName, 4
;CCOUNTED_UNICODE_STRING "//Registry//Machine", g_usKeyName, 4
;CCOUNTED_UNICODE_STRING "//Registry//CurrentConfig", g_usKeyName, 4
;"//Registry//User//.Default"
CCOUNTED_UNICODE_STRING "//Registry//Machine//Software//CoolApp", g_usMachineKeyName, 4
CCOUNTED_UNICODE_STRING "SomeData", g_usValueName, 4
CTW0 "It's just a string", g_wszStringData, 4
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                         C O D E                                                  
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.code
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                 CreateKey                                                  
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CreateKey proc
local oa:OBJECT_ATTRIBUTES
local hKey:HANDLE
local dwDisposition:DWORD
 invoke DbgPrint, $CTA0("/nRegistryWorks: *** Creating registry key/n")
 ; Pay attention at OBJ_KERNEL_HANDLE flag.
 ; It's not necessary to specify it here because we call CreateKey and other routines from DriverEntry
 ; running in system process context. So the handle will belong to the kernel anyway.
 ; But if you e running in the context of a user-mode process the OBJ_KERNEL_HANDLE must be set.
 ; This restricts the use of the handle to processes running only in kernel mode.
 ; Otherwise, the handle can be accessed by the process in whose context the driver is running.
 ; A process-specific handle will go away if the process terminates.
 ; A kernel handle doesn disappear until the operating system shuts down
 ; and can be used without ambiguity in any process.
 InitializeObjectAttributes addr oa, addr g_usMachineKeyName, OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
 ; REG_OPTION_VOLATILE means that key is not to be stored across boots.
 ; We don't have to specify this flag here since we'll delete the key right after it will be created
 invoke ZwCreateKey, addr hKey, KEY_WRITE, addr oa, 0, NULL, REG_OPTION_VOLATILE, addr dwDisposition
 .if eax == STATUS_SUCCESS
 
     .if dwDisposition == REG_CREATED_NEW_KEY
       ; A new key object was created.
       invoke DbgPrint, $CTA0("RegistryWorks: Registry key //Registry//Machine//Software//CoolApp created/n")
     .elseif dwDisposition == REG_OPENED_EXISTING_KEY
       ; An existing key object was opened.
       invoke DbgPrint, $CTA0("RegistryWorks: Registry key //Registry//Machine//Software//CoolApp opened/n")
     .endif
 
     invoke ZwClose, hKey
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key handle closed/n")
 .else
     invoke DbgPrint, $CTA0("RegistryWorks: Can't create registry key. Status: %08X/n"), eax
 .endif
 
 ret
 
CreateKey endp
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                  SetValueKey                                                
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SetValueKey proc
local oa:OBJECT_ATTRIBUTES
local hKey:HANDLE
 invoke DbgPrint, $CTA0("/nRegistryWorks: *** Opening registry key to set new value/n")
 InitializeObjectAttributes addr oa, addr g_usMachineKeyName, OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
 invoke ZwOpenKey, addr hKey, KEY_SET_VALUE, ecx
 .if eax == STATUS_SUCCESS
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key openeded/n")
 
     invoke ZwSetValueKey, hKey, addr g_usValueName, 0, REG_SZ, /
                   addr g_wszStringData, sizeof g_wszStringData
     .if eax == STATUS_SUCCESS
       invoke DbgPrint, $CTA0("RegistryWorks: Registry key value added/n")
     .else
       invoke DbgPrint, /
            $CTA0("RegistryWorks: Can't set registry key value. Status: %08X/n"), eax
     .endif
 
     invoke ZwClose, hKey
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key handle closed/n")
 .else
     invoke DbgPrint, $CTA0("RegistryWorks: Can't open registry key. Status: %08X/n"), eax
 .endif
 ret
 
SetValueKey endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                 QueryValueKey                                               
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
QueryValueKey proc
local oa:OBJECT_ATTRIBUTES
local hKey:HANDLE
local cb:DWORD
local ppi:PKEY_VALUE_PARTIAL_INFORMATION
local as:ANSI_STRING
local us:UNICODE_STRING
 
 invoke DbgPrint, $CTA0("/nRegistryWorks: *** Opening registry key to read value/n")
 
 InitializeObjectAttributes addr oa, addr g_usMachineKeyName, OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
 invoke ZwOpenKey, addr hKey, KEY_QUERY_VALUE, ecx
 
 .if eax == STATUS_SUCCESS
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key openeded/n")
 
     invoke ZwQueryValueKey, hKey, addr g_usValueName, /
                   KeyValuePartialInformation, NULL, 0, addr cb
     .if cb != 0
       invoke ExAllocatePool, PagedPool, cb
       .if eax != NULL
         mov ppi, eax
 
         invoke ZwQueryValueKey, hKey, addr g_usValueName, /
                     KeyValuePartialInformation, ppi, cb, addr cb
         .if ( eax == STATUS_SUCCESS ) && ( cb != 0 )
 
            mov eax, ppi
            .if [KEY_VALUE_PARTIAL_INFORMATION PTR [eax]]._Type == REG_SZ
              lea eax, (KEY_VALUE_PARTIAL_INFORMATION PTR [eax]).Data
              invoke RtlInitUnicodeString, addr us, eax
              invoke RtlUnicodeStringToAnsiString, addr as, addr us, TRUE
              .if eax == STATUS_SUCCESS
                invoke DbgPrint, /
                   $CTA0("RegistryWorks: Registry key value is: /=%s/=/n"), as.Buffer
                invoke RtlFreeAnsiString, addr as
              .endif
            .endif
          .else
            invoke DbgPrint, /
                $CTA0("RegistryWorks: Can't query registry key value. Status: %08X/n"), eax
         .endif
         invoke ExFreePool, ppi
       .else
         invoke DbgPrint, $CTA0("RegistryWorks: Can't allocate memory. Status: %08X/n"), eax
       .endif
     .else
       invoke DbgPrint, /
       $CTA0("RegistryWorks: Can't get bytes count needed for key partial information. Status: %08X/n"), eax
     .endif
     invoke ZwClose, hKey
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key handle closed/n")
 .else
     invoke DbgPrint, $CTA0("RegistryWorks: Can't open registry key. Status: %08X/n"), eax
 .endif
 
 ret
 
QueryValueKey endp
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                        DeleteKey                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
DeleteKey proc
 
local oa:OBJECT_ATTRIBUTES
local hKey:HANDLE
 
 invoke DbgPrint, $CTA0("/nRegistryWorks: *** Deleting registry key/n")
 
 InitializeObjectAttributes addr oa, addr g_usMachineKeyName, OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
 invoke ZwOpenKey, addr hKey, KEY_ALL_ACCESS, ecx
 
 .if eax == STATUS_SUCCESS
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key opened/n")
     invoke ZwDeleteKey, hKey
     .if eax == STATUS_SUCCESS
       invoke DbgPrint, $CTA0("RegistryWorks: Registry key deleted/n")
     .else
       invoke DbgPrint, $CTA0("RegistryWorks: Can't delete registry key. Status: %08X/n"), eax
     .endif
     invoke ZwClose, hKey
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key handle closed/n")
 .else
     invoke DbgPrint, $CTA0("RegistryWorks: Can't open registry key. Status: %08X/n"), eax
 .endif
 
 ret
 
DeleteKey endp
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                      EnumerateKey                                                
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
EnumerateKey proc
 
local oa:OBJECT_ATTRIBUTES
local hKey:HANDLE
local cb:DWORD
local pbi:PKEY_BASIC_INFORMATION
local pfi:PKEY_FULL_INFORMATION
local as:ANSI_STRING
local us:UNICODE_STRING
local dwSubKeys:DWORD
local pwszKeyName:PWCHAR
 
 invoke DbgPrint, $CTA0("/nRegistryWorks: *** Opening //Registry//User key to enumerate/n")
 
 CCOUNTED_UNICODE_STRING "//Registry//User", g_usUserKeyName, 4
 
 InitializeObjectAttributes addr oa, addr g_usUserKeyName, OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL
 ; Open key to enumerate subkeys
 invoke ZwOpenKey, addr hKey, KEY_ENUMERATE_SUB_KEYS, ecx
 
 .if eax == STATUS_SUCCESS
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key openeded/n")
 
     invoke ZwQueryKey, hKey, KeyFullInformation, NULL, 0, addr cb
     .if cb != 0
 
       invoke ExAllocatePool, PagedPool, cb
       .if eax != NULL
         mov pfi, eax
 
         invoke ZwQueryKey, hKey, KeyFullInformation, pfi, cb, addr cb
         .if ( eax == STATUS_SUCCESS ) && ( cb != 0 )
 
            mov eax, pfi
            push (KEY_FULL_INFORMATION PTR [eax]).SubKeys
            pop dwSubKeys
 
            invoke DbgPrint, /
              $CTA0("RegistryWorks: ---------- Starting enumerate subkeys ----------/n")
 
            push ebx
            xor ebx, ebx
            .while ebx < dwSubKeys
              invoke ZwEnumerateKey, hKey, ebx, KeyBasicInformation, NULL, 0, addr cb
              .if cb != 0
                invoke ExAllocatePool, PagedPool, cb
                .if eax != NULL
                   mov pbi, eax
 
                   invoke ZwEnumerateKey, hKey, ebx, KeyBasicInformation, pbi, cb, addr cb
                   .if ( eax == STATUS_SUCCESS ) && ( cb != 0 )
 
                     ; Allocate memory for subkey name
                     mov eax, pbi
                     mov eax, (KEY_BASIC_INFORMATION PTR [eax]).NameLength
                     add eax, sizeof WCHAR         ; place for terminating zero
                     mov cb, eax
                     invoke ExAllocatePool, PagedPool, cb
                     .if eax != NULL
                       mov pwszKeyName, eax
 
                       ; Zero buffer
                       invoke memset, pwszKeyName, 0, cb
 
                       ; The unicode-string pointed by KEY_BASIC_INFORMATION._Name
                       ; is not null-terminated. To avoid BSOD copy it into zeroed temporary buffer.
                       mov ecx, pbi
                       mov eax, (KEY_BASIC_INFORMATION PTR [ecx]).NameLength
                       shr eax, 1           ; / sizeof WCHAR. NumOfBytes -> NumOfChars
                       lea ecx, (KEY_BASIC_INFORMATION PTR [ecx])._Name
                       invoke wcsncpy, pwszKeyName, ecx, eax
 
                       invoke RtlInitUnicodeString, addr us, pwszKeyName
                       invoke RtlUnicodeStringToAnsiString, addr as, addr us, TRUE
                       .if eax == STATUS_SUCCESS
                         invoke DbgPrint, $CTA0("RegistryWorks: /=%s/=/n"), as.Buffer
                          invoke RtlFreeAnsiString, addr as
                       .endif
 
                       invoke ExFreePool, pwszKeyName
                     .endif
                   .else
                     invoke DbgPrint, /
                       $CTA0("RegistryWorks: Can't enumerate registry keys. Status: %08X/n"), eax                 
                   .endif
                   invoke ExFreePool, pbi
                .endif
              .endif
              inc ebx            ; next subkey
            .endw
            pop ebx
 
            invoke DbgPrint, /
              $CTA0("RegistryWorks: ------------------------------------------------/n")
 
         .else
            invoke DbgPrint, /
              $CTA0("RegistryWorks: Can't query registry key information. Status: %08X/n"), eax
         .endif
         invoke ExFreePool, pfi
       .else
         invoke DbgPrint, $CTA0("RegistryWorks: Can't allocate memory. Status: %08X/n"), eax
       .endif
     .endif
 
     invoke ZwClose, hKey
     invoke DbgPrint, $CTA0("RegistryWorks: Registry key handle closed/n")
 
 .else
     invoke DbgPrint, $CTA0("RegistryWorks: Can't open registry key. Status: %08X/n"), eax
 .endif
 
 ret
 
EnumerateKey endp
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       DriverEntry                                                
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
 
 invoke DbgPrint, $CTA0("/nRegistryWorks: Entering DriverEntry/n")
    
 
 ;:::::::::::::::::::::::::::::::::::::::
 ; Create new registry key              ;
 ;:::::::::::::::::::::::::::::::::::::::
 
 invoke CreateKey
 
 ;:::::::::::::::::::::::::::::::::::::::
 ; Set registry key value               ;
 ;:::::::::::::::::::::::::::::::::::::::
 
 invoke SetValueKey
 
 ;:::::::::::::::::::::::::::::::::::::::
 ; Query registry key value             ;
 ;:::::::::::::::::::::::::::::::::::::::
 
 invoke QueryValueKey
 
 ;:::::::::::::::::::::::::::::::::::::::
 ; Delete registry key                  ;
 ;:::::::::::::::::::::::::::::::::::::::
 
 invoke DeleteKey
 
 ;:::::::::::::::::::::::::::::::::::::::
 ; Enumerating registry keys            ;
 ;:::::::::::::::::::::::::::::::::::::::
 
 invoke EnumerateKey
 
 
 invoke DbgPrint, $CTA0("/nRegistryWorks: Leaving DriverEntry/n")
 
 mov eax, STATUS_DEVICE_CONFIGURATION_ERROR
 ret
 
DriverEntry endp
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                                                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
end DriverEntry
 
:make
 
set drv=RegistryWorks
/masm32/bin/ml /nologo /c /coff %drv%.bat
/masm32/bin/link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj
 
del %drv%.obj
echo.
pause
驱动代码包含几个独立的函数: CreateKey, SetValueKey, QueryValueKey, DeleteKey and EnumerateKey, 每个都是从零开始操作注册表的,对于学习来说例子是最直观的。
10.3.1 创建和打开子键
CreateKey 这个函数跟 ZwCreateKey 函数一样用来创建一个新的子键 Registry / Machine / Software / CoolApp
       invoke ZwCreateKey, addr hKey, KEY_WRITE, addr oa, 0, NULL, REG_OPTION_VOLATILE, addr dwDisposition
REG_OPTION_VOLATILE 禁止标志,记录已经建立的子键——硬盘上的注册表文件。这些子键在重启后清除。在这个例子中,这个标志不是必须的因为我们要删除整个子键。如果你想让这个子键永久保存,就不应该用这个标志。
    .if eax == STATUS_SUCCESS
        .if dwDisposition == REG_CREATED_NEW_KEY
        .elseif dwDisposition == REG_OPENED_EXISTING_KEY
        .endif
通过对这个函数 ZwCreateKey 的成功调用,通过这个变量 dwDisposition 是否等于 REG_CREATED_NEW_KEY 表示创建一个新建 , 或等于 REG_CREATED_NEW_KEY 表示这个子键在注册表中已经存在并打开这个子键。
       invoke ZwOpenKey, addr hKey, KEY_SET_VALUE, ecx
       invoke ZwOpenKey, addr hKey, KEY_QUERY_VALUE, ecx
       invoke ZwOpenKey, addr hKey, KEY_ALL_ACCESS, ecx
       invoke ZwOpenKey, addr hKey, KEY_ENUMERATE_SUB_KEYS, ecx
打开子键函数 ZwOpenKey 打开子键必需有访问权限。
10.3.2 创建注册表键值
  现在创建我们的子键字符串值名“ SomeData ”。
. . .
CCOUNTED_UNICODE_STRING "SomeData", g_usValueName, 4
CTW0 "It's just a string", g_wszStringData, 4
. . .
        invoke ZwSetValueKey, hKey, addr g_usValueName, 0, REG_SZ, /
                                addr g_wszStringData, sizeof g_wszStringData
REG_SZ 常量定义值的类型为:以零结尾的 unicode 字符串。还有许多其他类型,在 DDK 中有关于所有的描述。
10.3.3 获得注册表键的值
获得建名 SomeData 的值
       invoke ZwQueryValueKey, hKey, addr g_usValueName, /
                KeyValuePartialInformation, NULL, 0, addr cb
第三个参数标识函数 ZwQueryValueKey 所要求的信息类型。在 DDK 中定义三个值: KeyValueBasicInformation,KeyValueFullInformation KeyValuePartialInformation ,每一个都都有一个结构相关: KEY_VALUE_BASIC_INFORMATION, KEY_VALUE_FULL_INFORMATION KEY_VALUE_PARTIAL_INFORMATION. 在这个例子中,我们想获得这个键的内容,那我们就用这个类型 KeyValuePartialInformation
由于我们预先不知道信息类型,调用这个函数 ZwQueryValueKey 第四个参数为 NULL (指向缓冲区),第五个参数为 0 (缓冲区大小)。重要的是 ZwQueryValueKey 会计算所要求的缓冲区大小,并存储在变量 cb 中( Zw 开头的函数大部分都采用这种方式,但不是所有)。
    .if cb != 0
            invoke ExAllocatePool, PagedPool, cb
            .if eax != NULL
                mov ppi, eax
 
                invoke ZwQueryValueKey, hKey, addr g_usValueName, /
                  KeyValuePartialInformation, ppi, cb, addr cb
       申请你存空间成功,再次调用 ZwQueryValueKey 现在第四个参数是一个缓冲区指针。
.if ( eax == STATUS_SUCCESS ) && ( cb != 0 )
       mov eax, ppi
 .if [KEY_VALUE_PARTIAL_INFORMATION PTR [eax]]._Type == REG_SZ
在任何情况下都检查键值的类型。
lea eax, (KEY_VALUE_PARTIAL_INFORMATION PTR [eax]).Data
如果值的类型为 REG_SZ ,数据域结构 KEY_VALUE_PARTIAL_INFORMATION 包含 unicode 零字符串行,我们用这个行来存储调试信息,因此要转换为 ansi
       invoke RtlInitUnicodeString, addr us, eax
这个函数 RtlInitUnicodeString 的第二个参数指向一个 unicode 字符串地址,并且填充第一个参数指向的 UNICODE_STRING 结构。
invoke RtlUnicodeStringToAnsiString, addr as, addr us, TRUE
这个函数 RtlUnicodeStringToAnsiString unicode 字符串行转为 ansi 。如果最后一个参数是 TRUE ,函数自己会提供一个缓冲区。函数会写这行并填充 ANSI_STRING 结构(在这个例子中作为一个变量)。 ANSI_STRING 结构缓冲区在被选折的缓冲区中列出转换后的 ansi 行。如果最后一个参数设置为 FALSE 指向当前选折的 ansi 行缓冲区并把这个地址赋值给 ANSI_STRING 结构中的缓冲区。在这个例子中我们要求这个函数分配一个缓冲区为我们。
              .if eax == STATUS_SUCCESS
          invoke DbgPrint, /
   $CTA0("RegistryWorks: Registry key value is: /=%s/=/n"), as.Buffer
      invoke RtlFreeAnsiString, addr as
                        .endif
DDK 中(至少在 2000 DDK 中) RtlUnicodeStringToAnsiString 函数的描述是非常模糊的,我甚至说是不明确的。如果 DDK 描述的更好。让我们看一个简单的例子。
wsz db 'a', 0, 'b', 0, 'c', 0, 0, 0
us UNICODE_STRING <>
as ANSI_STRING    <>
初始化我们的变量, wsz unicode 字符串行,将会被转化为 ANSI 格式。
us._Length        = ?
us.MaximumLength = ?
us.Buffer         = ?
as._Length        = ?
as.MaximumLength = ?
as.Buffer         = ?
RtlInitUnicodeString 填充 us 变量根据 wsz 行的大小。
invoke RtlInitUnicodeString, addr us, addr wsz
 
us._Length        = 6
us.MaximumLength = 8
us.Buffer         = offset wsz
 
as._Length        = ?
as.MaximumLength = ?
as.Buffer         = ?
RtlUnicodeStringToAnsiString 最后一个参数可以定义将要分配 us. MaximumLength / sizeof WCHAR 大小的缓冲区。当这个域 as.Buffer 指向这个缓冲区,函数 RtlUnicodeStringToAnsiString 开始转换这行。如果这个操作成功,这个变量将要包转换字符串的所有的描述。
invoke RtlUnicodeStringToAnsiString, addr as, addr us, TRUE
 
us._Length        = 6
us.MaximumLength = 8
us.Buffer         = offset wsz
 
       as._Length        = 3
       as.MaximumLength = 4
as.Buffer         = -> 'a', 'b', 'c', 0 
; pointer to the selected feature RtlUnicodeStringToAnsiString,,,TRUE
; buffer, which contains the converted string wsz in ANSI format.
RtlUnicodeStringToAnsiString 函数分配的缓冲区利用后必须调用 RtlFreeAnsiString 释放,作为指向 ANSI_STRING 结构的指针不能传递指针指向自己的缓冲区。 RtlFreeAnsiString 释放缓冲区 as.Buffer
invoke RtlFreeAnsiString, addr as
 
us._Length        = 6
us.MaximumLength = 8
us.Buffer         = offset wsz
 
as._Length        = 0
as.MaximumLength = 0
as.Buffer         = NULL
我希望现在都明白了。
10.3.4 删除注册表子键
我认为不用我的解释也能够理解。
10.3.5 跟新注册表内容
现在我们来看位于 / Registry / User 下的子键
invoke ZwQueryKey, hKey, KeyFullInformation, NULL, 0, addr cb
        .if cb != 0
 
            invoke ExAllocatePool, PagedPool, cb
            .if eax != NULL
                mov pfi, eax
 
                invoke ZwQueryKey, hKey, KeyFullInformation, pfi, cb, addr cb
                .if ( eax == STATUS_SUCCESS ) && ( cb != 0 )
 
                    mov eax, pfi
                    push (KEY_FULL_INFORMATION PTR [eax]).SubKeys
                    pop dwSubKeys
为了得到所要求的子键的内容首先必须知道它包含的子键 / 键名的数量。 我们用 KeyFullInformation 类型信息。得到要求的内存大小和调用转换函数 ZwQueryKey ,我们通过变量 dwSubKeys 获得键 / 值的数量。
 push ebx
                    xor ebx, ebx
                    .while ebx < dwSubKeys
                        invoke ZwEnumerateKey, hKey, ebx, KeyBasicInformation, NULL, 0, addr cb
                        .if cb != 0
 
                            invoke ExAllocatePool, PagedPool, cb
                            .if eax != NULL
                                mov pbi, eax
 
                                invoke ZwEnumerateKey, hKey, ebx, KeyBasicInformation, pbi, cb, addr cb
                                .if ( eax == STATUS_SUCCESS ) && ( cb != 0 )
ZwEnumerateKey 函数用 KeyBasicInformation 类型信息。跟以前一样调用两次:第一次获得数量,第二次获得具体的信息。
               mov eax, pbi
               mov eax, (KEY_BASIC_INFORMATION PTR [eax]).NameLength
               add eax, sizeof WCHAR
               mov cb, eax
               invoke ExAllocatePool, PagedPool, cb 
结构的名字返回在 KEY_BASIC_INFORMATION 结构中,值的类型 unicode 行,但是这个行不全为零。为了将子键转换为 ansi 行,我们需要全零行因此分配一个临时缓冲区。
 .if eax != NULL
      mov pwszKeyName, eax
 
      invoke memset, pwszKeyName, 0, cb
 
     mov ecx, pbi
     mov eax, (KEY_BASIC_INFORMATION PTR [ecx]).NameLength
     shr eax, 1
     lea ecx, (KEY_BASIC_INFORMATION PTR [ecx])._Name
     invoke wcsncpy, pwszKeyName, ecx, eax
复制子键 / 名到一个临时缓冲区。
   invoke RtlInitUnicodeString, addr us, pwszKeyName
   invoke RtlUnicodeStringToAnsiString, addr as, addr us, TRUE
     .if eax == STATUS_SUCCESS
        invoke DbgPrint, $CTA0("RegistryWorks: /=%s/=/n"), as.Buffer
       invoke RtlFreeAnsiString, addr as
     .endif
对上面的细节进行改变,显示子键名和调试信息。
 invoke ExFreePool, pwszKeyName
                                    .endif
                                .endif
                                invoke ExFreePool, pbi
                            .endif
                        .endif
                        inc ebx
                    .endw
                    pop ebx
                .endif
                invoke ExFreePool, pfi
            .endif
        .endif
释放一些必须的资源。
 
 
 
 
 

你可能感兴趣的:(Kmd--10注册表)