Kmd--10注册表

来源:互联网 发布:淘宝旧书店 编辑:程序博客网 时间:2024/05/29 13:35

 

注册表
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 youe 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,KeyValueFullInformationKeyValuePartialInformation,每一个都都有一个结构相关: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
这个函数RtlUnicodeStringToAnsiStringunicode字符串行转为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中(至少在2000DDK中)RtlUnicodeStringToAnsiString函数的描述是非常模糊的,我甚至说是不明确的。如果DDK描述的更好。让我们看一个简单的例子。
wsz db 'a', 0, 'b', 0, 'c', 0, 0, 0
us UNICODE_STRING <>
as ANSI_STRING    <>
初始化我们的变量,wszunicode字符串行,将会被转化为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
释放一些必须的资源。
 
 
 
 
 

原创粉丝点击