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 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
釋放一些必須的資源。
 
 
 
 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章