关于Ring3层的注册表监控

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Ring3层的注册表监控相关的知识,希望对你有一定的参考价值。

  最近一直想做远程操作的注册表,将客户端的注册表发送到主控端,遇到两个问题:

 1.不能每次点击TreeControl都是一次请求的发送,太浪费资源。

 2.在客户端的注册表监控效果也不是很好。(驱动不稳定,只想用Ring3层)

 

  第一个问题比较好解决,在主控端加一个缓存结构就Ok,但是第二个问题还有一些问题。

常用的注册表监控一般都会使用钩子,Hook有关注册表操作的函数。但是这种方法是针对进程

而言,如果要监控全局,就要对每个进程Inject,这基本不现实。

  一个使用DETOUR库的RegQueryValueExW函数

技术分享
 1 DETOUR_TRAMPOLINE(LONG APIENTRY Real_RegQueryValueExW(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD), RegQueryValueExW);
 2 LONG APIENTRY Mine_RegQueryValueExW(
 3                                   HKEY hKey,
 4                                   LPCWSTR lpValueName,
 5                                   LPDWORD lpReserved,
 6                                   LPDWORD lpType,
 7                                   LPBYTE lpData,
 8                                   LPDWORD lpcbData)
 9 {
10     LONG nRet;
11     __try{
12         nRet = Real_RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
13         if(!HOOK_RegQueryValueEx)
14             return nRet;
15         if(GetCurrentProcessId() == ExplorerPID)
16             return nRet;
17         if(GetCurrentProcessId() == RegMonPID)
18             return nRet;
19         if((PID == 0) || ((GetCurrentProcessId() == PID) && (PID>0)) )
20         {
21             if(nRet != ERROR_SUCCESS)
22                 return nRet;
23             COPYDATASTRUCT data;
24             PARAMS params = {0};
25             params.PID = GetCurrentProcessId();
26             params.hKey = hKey;
27             
28             if(lpValueName == NULL || /*lpType == NULL ||*/ lpData == NULL || lpcbData == NULL)
29                 return nRet;
30             
31             memcpy(params.buffer1, lpValueName, wcslen(lpValueName)*2);
32             
33             if(lpType == NULL)
34                 params.type = 0;
35             else
36                 params.type = *lpType;
37             
38             if(*lpcbData == 0)
39             {
40                 return nRet;
41             }
42             else if(*lpcbData>1024)
43             {
44                 memcpy(params.buffer2, lpData, 1024);
45                 params.cbBuffer2 = 1024;
46             }
47             else
48             {
49                 memcpy(params.buffer2, lpData, *lpcbData);
50                 params.cbBuffer2 = *lpcbData;
51             }
52 
53             params.result = nRet;
54             
55             data.cbData = sizeof(PARAMS);
56             data.lpData = &params;
57             data.dwData = TYPE_RegQueryValueExW;
58             SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&data);
59         }
60         
61     }__finally{
62     };
63     return nRet;
64 }
View Code

  要在Ring3全局监控注册表的变化,只能使用RegNotifyChangeKeyValue微软提供的接口,但得不到具体的改变。

  MSDN提供的例子:

 1 #include <windows.h>
 2 #include <tchar.h>
 3 #include <stdio.h>
 4 
 5 //void main(int argc, char *argv[])
 6 void __cdecl _tmain(int argc, TCHAR *argv[])
 7 {
 8    DWORD  dwFilter = REG_NOTIFY_CHANGE_NAME |
 9                      REG_NOTIFY_CHANGE_ATTRIBUTES |
10                      REG_NOTIFY_CHANGE_LAST_SET |
11                      REG_NOTIFY_CHANGE_SECURITY; 
12 
13    HANDLE hEvent;
14    HKEY   hMainKey;
15    HKEY   hKey;
16    LONG   lErrorCode;
17 
18    // Display the usage error message.
19    if (argc != 3) 
20    {
21       _tprintf(TEXT("Usage: notify [HKLM|HKU|HKCU|HKCR|HCC] [<subkey>]\\n"));
22       return;
23    }
24 
25    // Convert parameters to appropriate handles.
26    if (_tcscmp(TEXT("HKLM"), argv[1]) == 0) hMainKey=HKEY_LOCAL_MACHINE;
27    else if(_tcscmp(TEXT("HKU"), argv[1]) == 0) hMainKey=HKEY_USERS;
28    else if(_tcscmp(TEXT("HKCU"), argv[1]) == 0) hMainKey=HKEY_CURRENT_USER;
29    else if(_tcscmp(TEXT("HKCR"), argv[1]) == 0) hMainKey=HKEY_CLASSES_ROOT;
30    else if(_tcscmp(TEXT("HCC"), argv[1]) == 0) hMainKey=HKEY_CURRENT_CONFIG;
31    else 
32    {
33       _tprintf(TEXT("Usage: notify [HKLM|HKU|HKCU|HKCR|HCC] [<subkey>]\\n"));
34       return;
35    }
36 
37    // Open a key.
38     lErrorCode = RegOpenKeyEx(hMainKey, argv[2], 0, KEY_NOTIFY, &hKey);
39    if (lErrorCode != ERROR_SUCCESS)
40    {
41       _tprintf(TEXT("Error in RegOpenKeyEx (%d).\\n"), lErrorCode);
42       return;
43    }
44 
45    // Create an event.
46    hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
47    if (hEvent == NULL)
48    {
49       _tprintf(TEXT("Error in CreateEvent (%d).\\n"), GetLastError());
50       return;
51    }
52 
53    // Watch the registry key for a change of value.
54    lErrorCode = RegNotifyChangeKeyValue(hKey, 
55                                         TRUE, 
56                                         dwFilter, 
57                                         hEvent, 
58                                         TRUE);
59    if (lErrorCode != ERROR_SUCCESS)
60    {
61       _tprintf(TEXT("Error in RegNotifyChangeKeyValue (%d).\\n"), lErrorCode);
62       return;
63    }
64 
65    // Wait for an event to occur.
66    _tprintf(TEXT("Waiting for a change in the specified key...\\n"));
67    if (WaitForSingleObject(hEvent, INFINITE) == WAIT_FAILED)
68    {
69       _tprintf(TEXT("Error in WaitForSingleObject (%d).\\n"), GetLastError());
70       return;
71    }
72    else _tprintf(TEXT("\\nChange has occurred.\\n"));
73 
74    // Close the key.
75    lErrorCode = RegCloseKey(hKey);
76    if (lErrorCode != ERROR_SUCCESS)
77    {
78       _tprintf(TEXT("Error in RegCloseKey (%d).\\n"), GetLastError());
79       return;
80    }
81    
82    // Close the handle.
83    if (!CloseHandle(hEvent))
84    {
85       _tprintf(TEXT("Error in CloseHandle.\\n"));
86       return;
87    }
88 }

  暂时先这样解决吧,有什么好的方法再多多积累。







以上是关于关于Ring3层的注册表监控的主要内容,如果未能解决你的问题,请参考以下文章

ring0

CPU的Ring等级

Intel X86 CPU之特权级别

Ring3 APC注入

关于片段生命周期

跟踪 Ring3 - Ring0 的运行流程