服务模拟当前活动用户

转载自: https://blog.csdn.net/nirendao/article/details/52077637

有效性未经验证

首先,对“活动用户”的定义是,当前拥有桌面的用户。对于Windows XP及其以后的系统,即使是可以多个用户同时登录了,拥有桌面的也仅仅只有一个。
如果系统级服务调用Windows API来获取注册表键值的时候,直接以HKEY_CURRENT_USER为参数,则取到的并不是活动用户的注册表信息,而是系统用户的注册表信息,即,位于HKEY_LOCAL_MACHINE之下的。那么如何以系统服务的身份获取活动用户(真正的HKEY_CURRENT_USER)之下的注册表信息呢?主要有以下这么几步:

系统服务程序调用 WTSGetActiveConsoleSessionId() 以获取当前活动用户的sessionId.
以此sessionId为参数,调用 WTSQueryUserToken() 以获取当前活动用户的 hUserToken.
以此hUserToken为参数,调用 DuplicateTokenEx() 以复制一个token,如hFakeToken.
以此hFakeToken为参数,调用 ImpersonateLoggedOnUser() 以模拟活动用户登录的环境.
调用 RegOpenCurrentUser() 以打开活动用户的 HKEY_CURRENT_USER.
调用 RegOpenKeyEx() 以获取指定位置的注册表键值.
以QT和Windows API来实现的代码如下:

 1 void GetUserRegistryFromSystemService()
 2 {
 3 #ifdef Q_OS_WIN
 4 
 5     DWORD sessionId = WTSGetActiveConsoleSessionId();
 6     qInfo() << "Session ID = " << sessionId;
 7 
 8     wchar_t * ppUserName[100];
 9     DWORD sizeOfUserName;
10     WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppUserName, &sizeOfUserName);
11     qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppUserName);
12 
13     std::wstring strValueOfBinDir = L"Unknown Value";
14     LONG regOpenResult = ERROR_SUCCESS;
15 
16     HANDLE hUserToken = NULL;
17     HANDLE hFakeToken = NULL;
18 
19     if (WTSQueryUserToken(sessionId, &hUserToken))
20     {
21          if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hFakeToken) == TRUE)
22          {
23             if (ImpersonateLoggedOnUser(hFakeToken))
24             {
25                 HKEY hKey;
26 
27                 regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey);
28                 if (regOpenResult != ERROR_SUCCESS)
29                 {
30                     qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult;
31                 }
32 
33                 HKEY hSubKey;
34 
35                 RegOpenKeyEx(hKey,
36                              TEXT("Software\Baidu\BaiduYunGuanjia"),
37                              0,
38                              KEY_READ,
39                              &hSubKey);
40                 GetStringRegKey(hSubKey, TEXT("installDir"), strValueOfBinDir, TEXT("Unknown"));
41 
42                 RevertToSelf();
43             }
44             else
45             {
46                 qCritical() << "Failed to ImpersonateLoggedOnUser...";
47             }
48             CloseHandle(hFakeToken);
49         }
50         else
51         {
52             qCritical() << "Failed to call DuplicateTokenEx...";
53         }
54         CloseHandle(hUserToken);
55     }
56     else
57     {
58         qCritical() << "Failed to get the user token of session " << sessionId;
59     }
60 
61     qInfo() << "The value of Registry is " << QString::fromWCharArray( strValueOfBinDir.c_str() );
62 
63 #endif
64 }
原文地址:https://www.cnblogs.com/talenth/p/12418806.html