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 (four-f@mail.ru)
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
.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
释放一些必须的资源。
 
 
 
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值