注冊表在應用中和內核中有區別.在驅動中全部使用路徑來表示,而不是一般應用程序編程中需要提供的根子健句柄.
應用中 HKEY_LOCAL_MACHINE 驅動中 \Registry\Machine
應用中 HKEY_USERS 驅動中 \Registry\User
應用中 HKEY_CLASSES_ROOT 驅動中沒有對應的路徑
應用中 HKEY_CURRENT_USER 驅動中也沒簡單的有對應路徑,但是可以求得
打開注冊表鍵使用函數 ZwOpenKey 新建或者打開 ZwCreateKey
打開注冊表使用以下函數,不直接接受一個字符串,而是 OBJECT_ATTRIBUTES 指針(需要初始化,參考創建文件部分):
ZwOpenKey(
//OBJECT_ATTRIBUTES結構的指針
_Out_ PHANDLE KeyHandle,
//設置權限,可以組合 KEY_QUERY_VALUE 讀取鍵下的值 KEY_SET_VALUE 設置鍵下的值
//KEY_CREATE_SUB_KEY 生成子健 KEY_ENUMERATE_SUB_KEYS 枚舉子健
//實際可以使用 KEY_READ KEY_WRITE 和 KEY_ALL_ACCESS 這些組合宏
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
注冊表鍵值的讀取使用 ZwQueryValueKey ,注意注冊表鍵值的類型和長度.
返回值:如果實際需要的長度比用戶設置的要大,返回 STATUS_BUFFER_OVERFLOW 或者 STATUS_BUFFER_TOO_SMALL
如果成功讀出全部數據,返回 STATUS_SUCCESS 其他情況,返回錯誤碼
ZwQueryValueKey(
//打開的注冊表鍵的句柄
_In_ HANDLE KeyHandle,
//要讀取的值的名字
_In_ PUNICODE_STRING ValueName,
//需要查詢的信息類型
//KeyValueBasicInformation 獲得基礎信息,包涵值名和類型
//KeyValueFullInformation 獲得完整信息,包含值名,類型和值
//KeyValuePartialInformation 獲得局部信息,包含類型和值 <-- 這個最常用
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
//當上面的變量是獲取局部信息時,KEY_VALUE_PARTIAL_INFORMATION 結構的指針返回到這里
//這個結構有4個參數,2=數據類型 3=數據長度 4=可變長度的數據
_Out_writes_bytes_opt_(Length) PVOID KeyValueInformation,
//用戶傳入的輸入空間 KeyValueInformation 的長度
_In_ ULONG Length,
//返回實際需要的長度
_Out_ PULONG ResultLength
);
因為不知道返回的值有多長,所以我們應該先獲取長度,然后不足時在動態分配內存進行讀取.
注冊表打開和讀取的完全實例:
#include
VOID DriverUnload(PDRIVER_OBJECT driver){
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path){
//注冊表鍵句柄
HANDLE mykey = NULL;
//函數執行的返回結果
NTSTATUS status;
//靜態定義要獲取的注冊表路徑
UNICODE_STRING mykeypath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
//注冊表對象屬性,包涵注冊表路徑名稱
OBJECT_ATTRIBUTES myobjattr = { 0 };
//初始化 OBJECT_ATTRIBUTES
InitializeObjectAttributes(&myobjattr, &mykeypath,OBJ_CASE_INSENSITIVE,NULL,NULL);
//打開注冊表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");
//用來測試大小的 和 實際使用的keyinfo指針
KEY_VALUE_PARTIAL_INFORMATION keyinfo;
PKEY_VALUE_PARTIAL_INFORMATION ackeyinfo;
ULONG aclength;
//讀取注冊表鍵的值
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個參數可以獲得需要的長度
ackeyinfo = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, aclength, 2333);
if (ackeyinfo == NULL){
status = STATUS_INSUFFICIENT_RESOURCES;//錯誤處理
}
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