Win 驱动编程 - 内核里操作注册表
一 概述
? ? RING0 操作注冊表和 RING3 的區別也不大,同樣是“獲得句柄->執行操作->關閉句柄”的模式,同樣也只能使用內核 API 不能使用 WIN32API。不過內核里有一套 RTL 函數,把 Zw系列的注冊表函數進行了封裝。
接下來說說注冊表的本質。注冊表其實是文件,它存儲在 c:\windows\system32\config
這個目錄下(打開目錄,看到那幾個帶鎖圖標的文件就是。為什么帶鎖?因為被 SYSTEM 進
程獨占訪問了)。注冊表文件被稱為 HIVE 文件,此格式是微軟專用的,不公開,每個系統都不一定相同,但總體來說變化不大。當系統關機之前,或者調用 ZwFlushKey 時,把內存中的修改存入磁盤。另外,我們用 WINDOWS 自帶的注冊表編輯器看到的注冊表有 5 個根項,其實 這 是 “ 幻 象 ”, 真 正 的 根 項 只 有 兩 個 : HKEY_LOCAL_MACHINE 和 HKEY_USERS 。HKEY_CLASSES_ROOT 和 HKEY_CURRENT_CONFIG 其實都是 HKEY_LOCAL_MACHINE 的“下屬”。
HKEY_CURRENT_USER 則是 HKEY_USERS 的“下屬”,獨立列出來只為了方便操作。
關于注冊表的操作不多,無非就是:新建 KEY、重命名 KEY、刪除 KEY、新建/設置 VALUE、讀取 VALUE、刪除 VALUE、枚舉子 KEY 和 VALUE。
幾個常見的、和注冊表相關的Zw函數的功能:
二 示例代碼
1.新建 KEY
2.重命名 KEY(不建議用,如果可以的話最好是 刪除然后創建)
(這里用到的關鍵 API『ZwRenameKey』沒有導出,需要自己定位,大家可以先
用硬編碼測試。在 WINDNG 里輸入 x nt!ZwRenameKey 即可獲得函數地址)
3.刪除 KEY
void RegDeleteKey(LPWSTR KeyName) { OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING usKeyName; NTSTATUS ntStatus; HANDLE hRegister; RtlInitUnicodeString(&usKeyName, KeyName); InitializeObjectAttributes(&objectAttributes, &usKeyName, OBJ_CASE_INSENSITIVE,//對大小寫敏感 NULL, NULL); ntStatus = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes); if (NT_SUCCESS(ntStatus)) { ntStatus = ZwDeleteKey(hRegister); ZwClose(hRegister); }}4.新建/設置 VALUE
void RegSetValueKey(LPWSTR REG_KEY_NAME, LPWSTR REG_VALUE_NAME, DWORD DataType, PVOID DataBuffer, DWORD DataLength) { OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING usKeyName, usValueName; NTSTATUS ntStatus; HANDLE hRegister; ULONG Type; RtlInitUnicodeString(&usKeyName, REG_KEY_NAME); RtlInitUnicodeString(&usValueName, REG_VALUE_NAME); InitializeObjectAttributes(&objectAttributes, &usKeyName, OBJ_CASE_INSENSITIVE,//對大小寫敏感 NULL, NULL); ntStatus = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes); if (NT_SUCCESS(ntStatus)) { ntStatus = ZwSetValueKey(hRegister, &usValueName, 0, DataType, DataBuffer, DataLength); ZwFlushKey(hRegister); ZwClose(hRegister); } }
?
5.讀取 VALUE
6.刪除 VALUE
7.枚舉子 KEY
VOID EnumerateSubItemRegTest() { #define ?MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\xxxxxxxx" UNICODE_STRING RegUnicodeString; HANDLE hRegister; //初始化 UNICODE_STRING 字符串 RtlInitUnicodeString(&RegUnicodeString, MY_REG_SOFTWARE_KEY_NAME); OBJECT_ATTRIBUTES objectAttributes; //初始化 objectAttributes InitializeObjectAttributes(&objectAttributes, &RegUnicodeString, OBJ_CASE_INSENSITIVE,//對大小寫敏感 NULL, NULL); //打開注冊表 NTSTATUS ntStatus = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes); if (NT_SUCCESS(ntStatus)) { KdPrint(("Open register successfully\n")); } ULONG ulSize; //第一次調用 ZwQueryKey 為了獲取 KEY_FULL_INFORMATION 數據的長度 ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize); PKEY_FULL_INFORMATION pfi = (PKEY_FULL_INFORMATION) ExAllocatePool(PagedPool, ulSize); //第二次調用 ZwQueryKey 為了獲取 KEY_FULL_INFORMATION 數據的數據 ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize); for (ULONG i = 0; i<pfi->SubKeys; i++) { //第一次調用 ZwEnumerateKey 為了獲取 KEY_BASIC_INFORMATION 數據的長度 ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize); PKEY_BASIC_INFORMATION pbi = (PKEY_BASIC_INFORMATION) ExAllocatePool(PagedPool, ulSize); //第二次調用 ZwEnumerateKey 為了獲取 KEY_BASIC_INFORMATION 數據的數據 ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize); UNICODE_STRING uniKeyName; uniKeyName.Length = uniKeyName.MaximumLength = (USHORT)pbi->NameLength; uniKeyName.Buffer = pbi->Name; KdPrint(("The %d sub item name:%wZ\n", i, &uniKeyName)); ExFreePool(pbi); } ExFreePool(pfi); ZwClose(hRegister); }8.枚舉子 VALUE
VOID EnumerateSubValueRegTest() { #define ?MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\xxxxxxxx" UNICODE_STRING RegUnicodeString; HANDLE hRegister; //初始化 UNICODE_STRING 字符串 RtlInitUnicodeString(&RegUnicodeString, MY_REG_SOFTWARE_KEY_NAME); OBJECT_ATTRIBUTES objectAttributes; //初始化 objectAttributes InitializeObjectAttributes(&objectAttributes, &RegUnicodeString, OBJ_CASE_INSENSITIVE,//對大小寫敏感 NULL, NULL); //打開注冊表 NTSTATUS ntStatus = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes); if (NT_SUCCESS(ntStatus)) { KdPrint(("Open register successfully\n")); } ULONG ulSize; //查詢 VALUE 的大小 ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize); PKEY_FULL_INFORMATION pfi = (PKEY_FULL_INFORMATION) ExAllocatePool(PagedPool, ulSize); ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize); for (ULONG i = 0; i<pfi->Values; i++) { //查詢單個 VALUE 的大小 ZwEnumerateValueKey(hRegister, i, KeyValueBasicInformation, NULL, 0, &ulSize); PKEY_VALUE_BASIC_INFORMATION pvbi = (PKEY_VALUE_BASIC_INFORMATION) ExAllocatePool(PagedPool, ulSize); //查詢單個 VALUE 的詳情 ZwEnumerateValueKey(hRegister, i, KeyValueBasicInformation, pvbi, ulSize, &ulSize); UNICODE_STRING uniKeyName; uniKeyName.Length = uniKeyName.MaximumLength = (USHORT)pvbi->NameLength; uniKeyName.Buffer = pvbi->Name; KdPrint(("The %d sub value name:%wZ\n", i, &uniKeyName)); if (pvbi->Type == REG_SZ) { KdPrint(("The sub value type:REG_SZ\n")); } else if (pvbi->Type == REG_MULTI_SZ) { KdPrint(("The sub value type:REG_MULTI_SZ\n")); } else if (pvbi->Type == REG_DWORD) { KdPrint(("The sub value type:REG_DWORD\n")); } else if (pvbi->Type == REG_BINARY) { KdPrint(("The sub value type:REG_BINARY\n")); } ExFreePool(pvbi); } ExFreePool(pfi); ZwClose(hRegister); }?
總結
以上是生活随笔為你收集整理的Win 驱动编程 - 内核里操作注册表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows驱动开发 - 内核模式下的
- 下一篇: NC命令行作为服务端、客户端以及win3