windows下服务或SYSTEM权限读取当前用户注册表HKEY_CURRENT_USER
2014-06-04 10:36
639 查看
最近一直在给一个程序增加一个功能,需要修改注册表 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2 下的值,刚开始自认为很简单,就调用修改注册表的API函数,但是各种尝试之后一直返回错误码2,自己纠结了很久。研究了两天才找到原因,我的程序是个服务权限是 SYSTEM,读取不到 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
下的值。原因如下(自己这么想的,对不对也不确定):
1. 服务运行在系统权限之下,而不是任何一个用户
2. HKEY_CURRENT_USER存储的是当前用户的信息
3. HKEY_CURRENT_USER的部分注册表写操作被重定向到HKEY_USERS下面去了;
经过各种大神的指导,终于解决了该问题。
有两种方法:
(一)模拟一个普通用户登陆,可以操作 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
(二) 获取 SID,操作HKEY_CURRENT_USER被重定向到 HKEY_USERS
的值。
方法一:
(1)
获取sessionId
DWORD cursessionid;
cursessionid = WTSGetActiveConsoleSessionId();
(2)根据
seesionid 获取用户令牌
HANDLE hToken
WTSQueryUserToken(cursessionid, &hToken)
(3)
模拟用户登陆
ImpersonateLoggedOnUser(hToken)
(4)获取用户名
TCHAR szUsername[MAX_PATH];
DWORD dwUsernameLen = MAX_PATH;
GetUserNameGetUserName(szUsername, &dwUsernameLen);
(5)保存当前模拟用户的信息并终止当前用户标识的模拟
PROFILEINFO cuProfileInfo;
cuProfileInfo.dwSize = sizeof(cuProfileInfo);
cuProfileInfo.lpUserName = szUsername;
cuProfileInfo.dwFlags = 1;
RevertToSelf();
(6)
根据保存的普通用户信息加载环境变量,加载完之后我们就可以用作普通用户操作注册了,要特别注意红字部分,否则还是操作失败
LoadUserProfile(hToken, &cuProfileInfo)
regedit = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2\\";
RegOpenKeyExA((struct HKEY__ *)cuProfileInfo.hProfile,
regedit.c_str(), NULL, KEY_ALL_ACCESS , &hkey);
操作完成之后记得卸载环境变量
UnLoadUserProfile(hToken);
方法二:
既然我们知道注册表被重定向到 HKEY_USER 下了,那我们就可以找到具体重定向那里了。
同 方法一的前 五步骤一样的,只是我们不加载普通用户的环境变量而是获取 用户的 SID。获取到 SID 我们就可以查找到重定向的位置
PSID pSID = NULL;
DWORD cbSid = 0;
LPTSTR DomainName = NULL;
DWORD cbDomainName = 0;
SID_NAME_USE SIDNameUse;
BOOL bDone = FALSE;
if(!LookupAccountName(NULL,
szUsername,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
pSID = (PSID)malloc(cbSid);
DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR));
if(!pSID || !DomainName)
{
log_error("malloc memery is failed\s");
}
if(!LookupAccountName(NULL,
szUsername,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
log_error("%s LookupAccountName is failed\s", __FUNCTION__);
}
}
LPTSTR strsid;
ConvertSidToStringSid(pSID, &strsid);
FreeSid(pSID);
log_printf("%s\n", strsid);
if(strsid)
{
std::string regedit = strsid(这里不对的话可能是编码原因,注意编码的转换);
(在我们需要打开的子键前面再加上获取到的 SID, 就是 HKEY_CURRENT_USER 下注册表被重定向到 HKEY_USER 下的位置)
regedit += "\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2\\
RegOpenKeyExA(HKEY_USER, regedit.c_str(), NULL, KEY_ALL_ACCESS , &hkey);
我们打开 HEKY_USER 下的子键。
}
以上的步骤只是我自己操作的简单说明,可能有不对的地方,大家可以根据 MSDN 说明具体尝试
下的值。原因如下(自己这么想的,对不对也不确定):
1. 服务运行在系统权限之下,而不是任何一个用户
2. HKEY_CURRENT_USER存储的是当前用户的信息
3. HKEY_CURRENT_USER的部分注册表写操作被重定向到HKEY_USERS下面去了;
经过各种大神的指导,终于解决了该问题。
有两种方法:
(一)模拟一个普通用户登陆,可以操作 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
(二) 获取 SID,操作HKEY_CURRENT_USER被重定向到 HKEY_USERS
的值。
方法一:
(1)
获取sessionId
DWORD cursessionid;
cursessionid = WTSGetActiveConsoleSessionId();
(2)根据
seesionid 获取用户令牌
HANDLE hToken
WTSQueryUserToken(cursessionid, &hToken)
(3)
模拟用户登陆
ImpersonateLoggedOnUser(hToken)
(4)获取用户名
TCHAR szUsername[MAX_PATH];
DWORD dwUsernameLen = MAX_PATH;
GetUserNameGetUserName(szUsername, &dwUsernameLen);
(5)保存当前模拟用户的信息并终止当前用户标识的模拟
PROFILEINFO cuProfileInfo;
cuProfileInfo.dwSize = sizeof(cuProfileInfo);
cuProfileInfo.lpUserName = szUsername;
cuProfileInfo.dwFlags = 1;
RevertToSelf();
(6)
根据保存的普通用户信息加载环境变量,加载完之后我们就可以用作普通用户操作注册了,要特别注意红字部分,否则还是操作失败
LoadUserProfile(hToken, &cuProfileInfo)
regedit = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2\\";
RegOpenKeyExA((struct HKEY__ *)cuProfileInfo.hProfile,
regedit.c_str(), NULL, KEY_ALL_ACCESS , &hkey);
操作完成之后记得卸载环境变量
UnLoadUserProfile(hToken);
方法二:
既然我们知道注册表被重定向到 HKEY_USER 下了,那我们就可以找到具体重定向那里了。
同 方法一的前 五步骤一样的,只是我们不加载普通用户的环境变量而是获取 用户的 SID。获取到 SID 我们就可以查找到重定向的位置
PSID pSID = NULL;
DWORD cbSid = 0;
LPTSTR DomainName = NULL;
DWORD cbDomainName = 0;
SID_NAME_USE SIDNameUse;
BOOL bDone = FALSE;
if(!LookupAccountName(NULL,
szUsername,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
pSID = (PSID)malloc(cbSid);
DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR));
if(!pSID || !DomainName)
{
log_error("malloc memery is failed\s");
}
if(!LookupAccountName(NULL,
szUsername,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
log_error("%s LookupAccountName is failed\s", __FUNCTION__);
}
}
LPTSTR strsid;
ConvertSidToStringSid(pSID, &strsid);
FreeSid(pSID);
log_printf("%s\n", strsid);
if(strsid)
{
std::string regedit = strsid(这里不对的话可能是编码原因,注意编码的转换);
(在我们需要打开的子键前面再加上获取到的 SID, 就是 HKEY_CURRENT_USER 下注册表被重定向到 HKEY_USER 下的位置)
regedit += "\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2\\
RegOpenKeyExA(HKEY_USER, regedit.c_str(), NULL, KEY_ALL_ACCESS , &hkey);
我们打开 HEKY_USER 下的子键。
}
以上的步骤只是我自己操作的简单说明,可能有不对的地方,大家可以根据 MSDN 说明具体尝试
相关文章推荐
- 服务中读取当前用户注册表HKEY_CURRENT_USER
- 服务中读取当前用户注册表HKEY_CURRENT_USER
- 在服务中模拟当前登录用户读取HKEY_CURRENT_USER
- system 权限读取注册表HKEY_CURRENT_USER
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键
- NT服务程序中对注册表中HKey_Current_User读取的问题
- 从Windows系统服务获取活动用户的注册表信息(当前活动用户的sessionId. 当前活动用户的 hUserToken)
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键
- 如何在Windows服务程序中读写HKEY_CURRENT_USER注册表
- 如何读取指定用户的 HKEY_CURRENT_USER 注册表键收藏
- Sharepoint 2010:基于当前用户判断访问列表项目的权限 --Determine access to SPListItem based on a Current User
- mysql 查看当前登陆用户匹配原则及权限user()与current_user()
- [置顶] Windows服务(Windows Service,system权限)程序显示界面与用户交互(xp,win7通用)
- VC 用服务进程开启有UI的进程和写注册表HKEY_CURRENT_USER子键的问题
- System 权限如何访问当前用户注册表
- ASP.NET中启用Windows集成验证,怎样在调用System.DirectoryServices下的组件时传递安全上下文,也就是说当前用户凭据,来实现权限管理
- mysql 查看当前登陆用户匹配原则及权限user()与current_user()
- Windows服务(system权限)程序显示界面与用户交互,Session0通知Session1里弹出对话框(真的很牛) good
- MSCRM2011 Current User has Role 【判定当前用户角色方法】