读取指定用户注册表代码
2009-05-25 21:10
501 查看
如何读取指定用户的 HKEY_CURRENT_USER 注册表键
注册表中 HKEY_CURRENT_USER 键下的内容隶属当前用户,所以当你以不同用户登陆时该键下的内容都是不尽相同的。但有时候我们有读取指定用户该键下内容的需求。比如,我们有一个服务程序运行在 Session0, SYSTEM 权限,而我们想读取的却是当前登陆到本地控制台的用户的 IE 代理服务器设置参数。我们当然不能直接从服务中打开 HKEY_CURENT_USER 键, 用我们当前令牌打开的是 SYSTEM 的 HKEY_CURRENT_USER 键,或许我们想可以通过当前线程扮演控制台用户来读取这个键
ImpersonateLoggedOnUser(hToken);
RegOpenKeyEx(HKEY_CURRENT_USER...);
RevertToSelf();
其实这个方法也是不行的,因为虽然我们取得了控制台用户的令牌,并且模仿该用户,但因为在当前空间并没有装载该用户的环境变量,用户上下文,所以这里的 RegOpenKeyEx 调用还是失败的。
好在微软为我们准备了
LoadUserProfile();
首先我们可以用
WTSGetActiveConsoleSessionId 取得当前控制台会话的 id, 这个API xp/2003 以上才有,2000 没有怎么办?2000直接可以省却这一步了,因为 2000 不支持用户切换,所以本地控制台永远运行在 Session0.
然后你可以用 WTSQueryUserToken 获得指定 Session 已登陆用户令牌。这个API依然是 xp/2003 才支持, 2000 怎么办,自己想办法吧(是不是可以打开 explorer.exe 的令牌看看 :) )。
然后 LoadUserProfile 装载该用户的环境变量了。
这段代码贴在下面吧, 可能不完整,我使用的这几个 API 都是动态装载的, 因为我们的软件可能要支持 98, 所以只能动态装载,否则就根本不能运行了。注意一下粗体部分,关键就在这里了。不清楚就看看 MSDN 吧,微软讲得很清楚了。向 MSDN team 致敬!
HANDLE hToken = NULL;
BOOL bImpersonated = FALSE;
PROFILEINFOA cuProfileInfo;
TCHAR szUsername[MAX_PATH];
DWORD dwUsernameLen = MAX_PATH;
if(GetConsoleUserToken(&hToken))
{
if(ImpersonateLoggedOnUser(hToken))
{
bImpersonated = TRUE;
//MessageBox(NULL, "I.. L.. User OK", "", NULL);
}
GetUserName(szUsername, &dwUsernameLen);
memset(&cuProfileInfo, 0, sizeof(cuProfileInfo));
cuProfileInfo.dwSize = sizeof(PROFILEINFOA);
cuProfileInfo.lpUserName = szUsername;
cuProfileInfo.dwFlags = 1;
if(bImpersonated)
{
RevertToSelf();
bImpersonated = FALSE;
}
if(pfnLoadUserProfile)
{
if(pfnLoadUserProfile(hToken, &cuProfileInfo))
{
RegOpenKeyEx((struct HKEY__ *)cuProfileInfo.hProfile, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
//MessageBox(NULL, "Open spc key", "", NULL);
}
else
{
RegOpenKeyEx(HKEY_CURRENT_USER, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
}
}
//MessageBox(NULL, "ImpersonateLoggedOnUser Successful", "atagtctl", NULL);
}
else
{
RegOpenKeyEx(HKEY_CURRENT_USER, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
}
are you sure WTSQueryUserToken successfully, do you DuplicateTokenEx with SecurityImpersonation ,
even though you ImpersonateLoggedOnUser successfully, however you still can not access HKCU directly, because in this session special user's Profile never be loaded, you should call LoadUserProfile() first, then use the returned handle to access HKCU,
fellow is some parts of my code, hope can help you.
I just got Logged on console user token, and our code support 2000, so I didn't use WTSQueryUserToken, and dynamic load some API
if(GetConsoleUserToken(hToken)) // the function defined follow
{
if(pfnImpersonateLoggedOnUser)
{
if(pfnImpersonateLoggedOnUser(hToken))
{
bImpersonated = TRUE;
//MessageBox(NULL, "I.. L.. User OK", "", NULL);
}
}
GetUserName(szUsername, &dwUsernameLen);
memset(&cuProfileInfo, 0, sizeof(cuProfileInfo));
cuProfileInfo.dwSize = sizeof(PROFILEINFOA);
cuProfileInfo.lpUserName = szUsername;
cuProfileInfo.dwFlags = 1;
if(bImpersonated)
{
if(pfnRevertToSelf)
pfnRevertToSelf();
bImpersonated = FALSE;
}
if(pfnLoadUserProfile)
{
if(pfnLoadUserProfile(hToken, &cuProfileInfo))
{
RegOpenKeyEx((struct HKEY__ *)cuProfileInfo.hProfile, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
//MessageBox(NULL, "Open spc key", "", NULL);
}
else
{
RegOpenKeyEx(HKEY_CURRENT_USER, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
}
}
//MessageBox(NULL, "ImpersonateLoggedOnUser Successful", "atagtctl", NULL);
}
BOOL GetConsoleUserToken(HANDLE& hToken)
{
if(CheckOsVersion() < MS_WINXP) return FALSE;
BOOL bRet = FALSE;
DWORD dwConsoleSessionId = 0;
g_hKernel32 = LoadLibrary("Kernel32.dll");
//g_hUserenv = LoadLibrary("userenv.dll");
if(g_hKernel32)
{
pfnWTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionId) GetProcAddress(g_hKernel32, "WTSGetActiveConsoleSessionId");
//pfnLoadUserProfile = (LoadUserProfileA) GetProcAddress(g_hUserenv, "LoadUserProfileA");
if(pfnWTSGetActiveConsoleSessionId)
{
dwConsoleSessionId = pfnWTSGetActiveConsoleSessionId();
pfnWTSGetActiveConsoleSessionId = NULL;
FreeLibrary(g_hKernel32);
g_hKernel32 = NULL;
if(dwConsoleSessionId == 0xFFFFFFFF)
{
// There is no session attached to the console
return FALSE;
}
}
else
{
dwConsoleSessionId = 0;
FreeLibrary(g_hKernel32);
g_hKernel32 = NULL;
return FALSE;
}
}
else
{
return FALSE;
}
HMODULE hPsapi = LoadLibrary("psapi.dll");
HMODULE hAdvapi32 = LoadLibrary("advapi32.dll");
if(NULL == hPsapi || hAdvapi32 == NULL)
{
if(hPsapi)
{
FreeLibrary(hPsapi);
hPsapi = NULL;
}
if(hAdvapi32)
{
FreeLibrary(hAdvapi32);
hAdvapi32 = NULL;
}
return FALSE;
}
pfnEnumProcesses = (PEnumProcesses) GetProcAddress(hPsapi, "EnumProcesses");
pfnGetModuleFileNameEx = (PGetModuleFileNameEx) GetProcAddress(hPsapi, "GetModuleFileNameExA");
pfnOpenProcessToken = (POpenProcessToken) GetProcAddress(hAdvapi32, "OpenProcessToken");
pfnGetTokenInformation = (PGetTokenInformation) GetProcAddress(hAdvapi32, "GetTokenInformation");
if(NULL == pfnEnumProcesses
|| NULL == pfnGetModuleFileNameEx
|| NULL == pfnOpenProcessToken
|| NULL == pfnGetTokenInformation)
{
pfnEnumProcesses = NULL;
pfnGetModuleFileNameEx = NULL;
pfnOpenProcessToken = NULL;
pfnGetTokenInformation = NULL;
FreeLibrary(hPsapi);
FreeLibrary(hAdvapi32);
hPsapi = NULL;
hAdvapi32 = NULL;
return FALSE;
}
DWORD aProcesses[1024] = {0};
DWORD dwNeeded = 0;
DWORD dwProcesses = 0;
if(!pfnEnumProcesses(aProcesses, sizeof(aProcesses), &dwNeeded))
{
pfnEnumProcesses = NULL;
pfnGetModuleFileNameEx = NULL;
FreeLibrary(hPsapi);
hPsapi = NULL;
FreeLibrary(hAdvapi32);
hAdvapi32 = NULL;
return FALSE;
}
dwProcesses = dwNeeded / sizeof(DWORD);
HANDLE hProcess = NULL;
char szProcessName[MAX_PATH];
char szDrive[MAX_PATH];
char szDir[MAX_PATH];
char szName[MAX_PATH];
char szExt[MAX_PATH];
DWORD dwExplorerSessionID = 0;
DWORD dwRetLength = 0;
for(DWORD i=0; i<dwProcesses; i++)
{
ZeroMemory(szProcessName, MAX_PATH);
ZeroMemory(szDrive, MAX_PATH);
ZeroMemory(szDir, MAX_PATH);
ZeroMemory(szName, MAX_PATH);
ZeroMemory(szExt, MAX_PATH);
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcessesIdea);
if(NULL != hProcess)
{
if(0 != pfnGetModuleFileNameEx(hProcess, NULL, szProcessName, sizeof(szProcessName)))
{
_splitpath(szProcessName, szDrive, szDir, szName, szExt);
if( (stricmp("explorer", szName) == 0) && (stricmp(".exe", szExt) == 0) )
{
if(pfnOpenProcessToken(hProcess, TOKEN_DUPLICATE|TOKEN_QUERY|TOKEN_IMPERSONATE, &hToken))
{
if(pfnGetTokenInformation(hToken, TokenSessionId, &dwExplorerSessionID, sizeof(DWORD), &dwRetLength))
{
if(dwExplorerSessionID == dwConsoleSessionId)
{
CloseHandle(hProcess);
bRet = TRUE;
break;
}
}
}
}
}
if(hToken)
CloseHandle(hToken);
hToken = NULL;
CloseHandle(hProcess);
hProcess = NULL;
}
}
if(hPsapi)
{
FreeLibrary(hPsapi);
hPsapi = NULL;
}
if(hAdvapi32)
{
FreeLibrary(hAdvapi32);
hAdvapi32 = NULL;
}
pfnEnumProcesses = NULL;
pfnGetModuleFileNameEx = NULL;
pfnOpenProcessToken = NULL;
pfnGetTokenInformation = NULL;
return bRet;
}
注册表中 HKEY_CURRENT_USER 键下的内容隶属当前用户,所以当你以不同用户登陆时该键下的内容都是不尽相同的。但有时候我们有读取指定用户该键下内容的需求。比如,我们有一个服务程序运行在 Session0, SYSTEM 权限,而我们想读取的却是当前登陆到本地控制台的用户的 IE 代理服务器设置参数。我们当然不能直接从服务中打开 HKEY_CURENT_USER 键, 用我们当前令牌打开的是 SYSTEM 的 HKEY_CURRENT_USER 键,或许我们想可以通过当前线程扮演控制台用户来读取这个键
ImpersonateLoggedOnUser(hToken);
RegOpenKeyEx(HKEY_CURRENT_USER...);
RevertToSelf();
其实这个方法也是不行的,因为虽然我们取得了控制台用户的令牌,并且模仿该用户,但因为在当前空间并没有装载该用户的环境变量,用户上下文,所以这里的 RegOpenKeyEx 调用还是失败的。
好在微软为我们准备了
LoadUserProfile();
首先我们可以用
WTSGetActiveConsoleSessionId 取得当前控制台会话的 id, 这个API xp/2003 以上才有,2000 没有怎么办?2000直接可以省却这一步了,因为 2000 不支持用户切换,所以本地控制台永远运行在 Session0.
然后你可以用 WTSQueryUserToken 获得指定 Session 已登陆用户令牌。这个API依然是 xp/2003 才支持, 2000 怎么办,自己想办法吧(是不是可以打开 explorer.exe 的令牌看看 :) )。
然后 LoadUserProfile 装载该用户的环境变量了。
这段代码贴在下面吧, 可能不完整,我使用的这几个 API 都是动态装载的, 因为我们的软件可能要支持 98, 所以只能动态装载,否则就根本不能运行了。注意一下粗体部分,关键就在这里了。不清楚就看看 MSDN 吧,微软讲得很清楚了。向 MSDN team 致敬!
HANDLE hToken = NULL;
BOOL bImpersonated = FALSE;
PROFILEINFOA cuProfileInfo;
TCHAR szUsername[MAX_PATH];
DWORD dwUsernameLen = MAX_PATH;
if(GetConsoleUserToken(&hToken))
{
if(ImpersonateLoggedOnUser(hToken))
{
bImpersonated = TRUE;
//MessageBox(NULL, "I.. L.. User OK", "", NULL);
}
GetUserName(szUsername, &dwUsernameLen);
memset(&cuProfileInfo, 0, sizeof(cuProfileInfo));
cuProfileInfo.dwSize = sizeof(PROFILEINFOA);
cuProfileInfo.lpUserName = szUsername;
cuProfileInfo.dwFlags = 1;
if(bImpersonated)
{
RevertToSelf();
bImpersonated = FALSE;
}
if(pfnLoadUserProfile)
{
if(pfnLoadUserProfile(hToken, &cuProfileInfo))
{
RegOpenKeyEx((struct HKEY__ *)cuProfileInfo.hProfile, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
//MessageBox(NULL, "Open spc key", "", NULL);
}
else
{
RegOpenKeyEx(HKEY_CURRENT_USER, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
}
}
//MessageBox(NULL, "ImpersonateLoggedOnUser Successful", "atagtctl", NULL);
}
else
{
RegOpenKeyEx(HKEY_CURRENT_USER, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
}
are you sure WTSQueryUserToken successfully, do you DuplicateTokenEx with SecurityImpersonation ,
even though you ImpersonateLoggedOnUser successfully, however you still can not access HKCU directly, because in this session special user's Profile never be loaded, you should call LoadUserProfile() first, then use the returned handle to access HKCU,
fellow is some parts of my code, hope can help you.
I just got Logged on console user token, and our code support 2000, so I didn't use WTSQueryUserToken, and dynamic load some API
if(GetConsoleUserToken(hToken)) // the function defined follow
{
if(pfnImpersonateLoggedOnUser)
{
if(pfnImpersonateLoggedOnUser(hToken))
{
bImpersonated = TRUE;
//MessageBox(NULL, "I.. L.. User OK", "", NULL);
}
}
GetUserName(szUsername, &dwUsernameLen);
memset(&cuProfileInfo, 0, sizeof(cuProfileInfo));
cuProfileInfo.dwSize = sizeof(PROFILEINFOA);
cuProfileInfo.lpUserName = szUsername;
cuProfileInfo.dwFlags = 1;
if(bImpersonated)
{
if(pfnRevertToSelf)
pfnRevertToSelf();
bImpersonated = FALSE;
}
if(pfnLoadUserProfile)
{
if(pfnLoadUserProfile(hToken, &cuProfileInfo))
{
RegOpenKeyEx((struct HKEY__ *)cuProfileInfo.hProfile, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
//MessageBox(NULL, "Open spc key", "", NULL);
}
else
{
RegOpenKeyEx(HKEY_CURRENT_USER, IEPROXY_LOCALUSER_KEY, 0, KEY_QUERY_VALUE, ®KeyFrom);
}
}
//MessageBox(NULL, "ImpersonateLoggedOnUser Successful", "atagtctl", NULL);
}
BOOL GetConsoleUserToken(HANDLE& hToken)
{
if(CheckOsVersion() < MS_WINXP) return FALSE;
BOOL bRet = FALSE;
DWORD dwConsoleSessionId = 0;
g_hKernel32 = LoadLibrary("Kernel32.dll");
//g_hUserenv = LoadLibrary("userenv.dll");
if(g_hKernel32)
{
pfnWTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionId) GetProcAddress(g_hKernel32, "WTSGetActiveConsoleSessionId");
//pfnLoadUserProfile = (LoadUserProfileA) GetProcAddress(g_hUserenv, "LoadUserProfileA");
if(pfnWTSGetActiveConsoleSessionId)
{
dwConsoleSessionId = pfnWTSGetActiveConsoleSessionId();
pfnWTSGetActiveConsoleSessionId = NULL;
FreeLibrary(g_hKernel32);
g_hKernel32 = NULL;
if(dwConsoleSessionId == 0xFFFFFFFF)
{
// There is no session attached to the console
return FALSE;
}
}
else
{
dwConsoleSessionId = 0;
FreeLibrary(g_hKernel32);
g_hKernel32 = NULL;
return FALSE;
}
}
else
{
return FALSE;
}
HMODULE hPsapi = LoadLibrary("psapi.dll");
HMODULE hAdvapi32 = LoadLibrary("advapi32.dll");
if(NULL == hPsapi || hAdvapi32 == NULL)
{
if(hPsapi)
{
FreeLibrary(hPsapi);
hPsapi = NULL;
}
if(hAdvapi32)
{
FreeLibrary(hAdvapi32);
hAdvapi32 = NULL;
}
return FALSE;
}
pfnEnumProcesses = (PEnumProcesses) GetProcAddress(hPsapi, "EnumProcesses");
pfnGetModuleFileNameEx = (PGetModuleFileNameEx) GetProcAddress(hPsapi, "GetModuleFileNameExA");
pfnOpenProcessToken = (POpenProcessToken) GetProcAddress(hAdvapi32, "OpenProcessToken");
pfnGetTokenInformation = (PGetTokenInformation) GetProcAddress(hAdvapi32, "GetTokenInformation");
if(NULL == pfnEnumProcesses
|| NULL == pfnGetModuleFileNameEx
|| NULL == pfnOpenProcessToken
|| NULL == pfnGetTokenInformation)
{
pfnEnumProcesses = NULL;
pfnGetModuleFileNameEx = NULL;
pfnOpenProcessToken = NULL;
pfnGetTokenInformation = NULL;
FreeLibrary(hPsapi);
FreeLibrary(hAdvapi32);
hPsapi = NULL;
hAdvapi32 = NULL;
return FALSE;
}
DWORD aProcesses[1024] = {0};
DWORD dwNeeded = 0;
DWORD dwProcesses = 0;
if(!pfnEnumProcesses(aProcesses, sizeof(aProcesses), &dwNeeded))
{
pfnEnumProcesses = NULL;
pfnGetModuleFileNameEx = NULL;
FreeLibrary(hPsapi);
hPsapi = NULL;
FreeLibrary(hAdvapi32);
hAdvapi32 = NULL;
return FALSE;
}
dwProcesses = dwNeeded / sizeof(DWORD);
HANDLE hProcess = NULL;
char szProcessName[MAX_PATH];
char szDrive[MAX_PATH];
char szDir[MAX_PATH];
char szName[MAX_PATH];
char szExt[MAX_PATH];
DWORD dwExplorerSessionID = 0;
DWORD dwRetLength = 0;
for(DWORD i=0; i<dwProcesses; i++)
{
ZeroMemory(szProcessName, MAX_PATH);
ZeroMemory(szDrive, MAX_PATH);
ZeroMemory(szDir, MAX_PATH);
ZeroMemory(szName, MAX_PATH);
ZeroMemory(szExt, MAX_PATH);
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcessesIdea);
if(NULL != hProcess)
{
if(0 != pfnGetModuleFileNameEx(hProcess, NULL, szProcessName, sizeof(szProcessName)))
{
_splitpath(szProcessName, szDrive, szDir, szName, szExt);
if( (stricmp("explorer", szName) == 0) && (stricmp(".exe", szExt) == 0) )
{
if(pfnOpenProcessToken(hProcess, TOKEN_DUPLICATE|TOKEN_QUERY|TOKEN_IMPERSONATE, &hToken))
{
if(pfnGetTokenInformation(hToken, TokenSessionId, &dwExplorerSessionID, sizeof(DWORD), &dwRetLength))
{
if(dwExplorerSessionID == dwConsoleSessionId)
{
CloseHandle(hProcess);
bRet = TRUE;
break;
}
}
}
}
}
if(hToken)
CloseHandle(hToken);
hToken = NULL;
CloseHandle(hProcess);
hProcess = NULL;
}
}
if(hPsapi)
{
FreeLibrary(hPsapi);
hPsapi = NULL;
}
if(hAdvapi32)
{
FreeLibrary(hAdvapi32);
hAdvapi32 = NULL;
}
pfnEnumProcesses = NULL;
pfnGetModuleFileNameEx = NULL;
pfnOpenProcessToken = NULL;
pfnGetTokenInformation = NULL;
return bRet;
}
相关文章推荐
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键收藏
- c#的代码判断用户ip是否在指定的ip段内
- C#指定用户执行程序的示例代码(转载)
- 测试用指定块大小读取文件时间的代码
- 如何用java代码让android Market显示指定的程序以便用户下载?
- MYSQL实现排名及查询指定用户排名功能(并列排名功能)实例代码
- windows平台下,c++获取cpu型号,读取注册表获取系统软硬件信息代码
- 汇编语言32位控制台读取用户输入字符程序代码分析(17)
- ORACLE 创建只读用户,指定可以读取的视图及库表
- 利用Ado.net来读取用户所指定的excel数据
- 读取注册表中的指定软件的路径
- 修改注册表解决域用户本地配置读取错误
- java 代码读取指定文件
- windows下服务或SYSTEM权限读取当前用户注册表HKEY_CURRENT_USER
- [ZT]C# 代码实现设置用户"NETWORK SERVICE"具有对文件夹的读取权限。
- java读取文件并获得文件编码,转换为指定编码的工具类代码
- 通过注册表设置指定用户启动项的权限