注冊(cè)表在應(yīng)用中和內(nèi)核中有區(qū)別.在驅(qū)動(dòng)中全部使用路徑來(lái)表示,而不是一般應(yīng)用程序編程中需要提供的根子健句柄.
應(yīng)用中 HKEY_LOCAL_MACHINE 驅(qū)動(dòng)中 \Registry\Machine
應(yīng)用中 HKEY_USERS 驅(qū)動(dòng)中 \Registry\User
應(yīng)用中 HKEY_CLASSES_ROOT 驅(qū)動(dòng)中沒(méi)有對(duì)應(yīng)的路徑
應(yīng)用中 HKEY_CURRENT_USER 驅(qū)動(dòng)中也沒(méi)簡(jiǎn)單的有對(duì)應(yīng)路徑,但是可以求得
打開(kāi)注冊(cè)表鍵使用函數(shù) ZwOpenKey 新建或者打開(kāi) ZwCreateKey
打開(kāi)注冊(cè)表使用以下函數(shù),不直接接受一個(gè)字符串,而是 OBJECT_ATTRIBUTES 指針(需要初始化,參考創(chuàng)建文件部分):
ZwOpenKey(
//OBJECT_ATTRIBUTES結(jié)構(gòu)的指針
_Out_ PHANDLE KeyHandle,
//設(shè)置權(quán)限,可以組合 KEY_QUERY_VALUE 讀取鍵下的值 KEY_SET_VALUE 設(shè)置鍵下的值
//KEY_CREATE_SUB_KEY 生成子健 KEY_ENUMERATE_SUB_KEYS 枚舉子健
//實(shí)際可以使用 KEY_READ KEY_WRITE 和 KEY_ALL_ACCESS 這些組合宏
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
注冊(cè)表鍵值的讀取使用 ZwQueryValueKey ,注意注冊(cè)表鍵值的類型和長(zhǎng)度.
返回值:如果實(shí)際需要的長(zhǎng)度比用戶設(shè)置的要大,返回 STATUS_BUFFER_OVERFLOW 或者 STATUS_BUFFER_TOO_SMALL
如果成功讀出全部數(shù)據(jù),返回 STATUS_SUCCESS 其他情況,返回錯(cuò)誤碼
ZwQueryValueKey(
//打開(kāi)的注冊(cè)表鍵的句柄
_In_ HANDLE KeyHandle,
//要讀取的值的名字
_In_ PUNICODE_STRING ValueName,
//需要查詢的信息類型
//KeyValueBasicInformation 獲得基礎(chǔ)信息,包涵值名和類型
//KeyValueFullInformation 獲得完整信息,包含值名,類型和值
//KeyValuePartialInformation 獲得局部信息,包含類型和值 <-- 這個(gè)最常用
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
//當(dāng)上面的變量是獲取局部信息時(shí),KEY_VALUE_PARTIAL_INFORMATION 結(jié)構(gòu)的指針?lè)祷氐竭@里
//這個(gè)結(jié)構(gòu)有4個(gè)參數(shù),2=數(shù)據(jù)類型 3=數(shù)據(jù)長(zhǎng)度 4=可變長(zhǎng)度的數(shù)據(jù)
_Out_writes_bytes_opt_(Length) PVOID KeyValueInformation,
//用戶傳入的輸入空間 KeyValueInformation 的長(zhǎng)度
_In_ ULONG Length,
//返回實(shí)際需要的長(zhǎng)度
_Out_ PULONG ResultLength
);
因?yàn)椴恢婪祷氐闹涤卸嚅L(zhǎng),所以我們應(yīng)該先獲取長(zhǎng)度,然后不足時(shí)在動(dòng)態(tài)分配內(nèi)存進(jìn)行讀取.
注冊(cè)表打開(kāi)和讀取的完全實(shí)例:
#include
VOID DriverUnload(PDRIVER_OBJECT driver){
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path){
//注冊(cè)表鍵句柄
HANDLE mykey = NULL;
//函數(shù)執(zhí)行的返回結(jié)果
NTSTATUS status;
//靜態(tài)定義要獲取的注冊(cè)表路徑
UNICODE_STRING mykeypath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
//注冊(cè)表對(duì)象屬性,包涵注冊(cè)表路徑名稱
OBJECT_ATTRIBUTES myobjattr = { 0 };
//初始化 OBJECT_ATTRIBUTES
InitializeObjectAttributes(&myobjattr, &mykeypath,OBJ_CASE_INSENSITIVE,NULL,NULL);
//打開(kāi)注冊(cè)表Key
status = ZwOpenKey(&mykey, KEY_READ, &myobjattr);
if (!NT_SUCCESS(status)){
DbgPrint("misaka: open regeditkey failed\r\n");
}
//要讀取的值的名字
UNICODE_STRING mykeyname = RTL_CONSTANT_STRING(L"ProductName");
//用來(lái)測(cè)試大小的 和 實(shí)際使用的keyinfo指針
KEY_VALUE_PARTIAL_INFORMATION keyinfo;
PKEY_VALUE_PARTIAL_INFORMATION ackeyinfo;
ULONG aclength;
//讀取注冊(cè)表鍵的值
status = ZwQueryValueKey(mykey, &mykeyname, KeyValuePartialInformation, &keyinfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION),&aclength);
if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL){
DbgPrint("misaka: read regeditkeyvalue failed\r\n");
}
//分配需要的空間, ZwQueryValueKey 的第4個(gè)參數(shù)可以獲得需要的長(zhǎng)度
ackeyinfo = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, aclength, 2333);
if (ackeyinfo == NULL){
status = STATUS_INSUFFICIENT_RESOURCES;//錯(cuò)誤處理
}
status = ZwQueryValueKey(mykey, &mykeyname, KeyValuePartialInformation, ackeyinfo,aclength,&aclength);
if (status == STATUS_SUCCESS){
UNICODE_STRING str = { 0 };
RtlInitUnicodeString(&str, (PCWSTR)ackeyinfo->Data);
DbgPrint("misaka: read regeditkeyvalue successfully ,data is: %wZ\r\n", str);
}else{
DbgPrint("misaka: read regeditkeyvalue failed\r\n");
}
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
輸出:
misaka: read regeditkeyvalue successfully ,data is: Windows 7 Ultimate