[英]Impersonate and run any method using a logged in user context from SYSTEM level process (Windows Service):
我已经创建了一个模板类,它将使用登录的用户令牌创建一个线程并运行任何方法。 我借助std :: function将其传递给模板类,并在用户级别的上下文中运行它。
我目前的用法:
1.该类在Windows服务进程(以SYSTEM级别运行)中使用。
2.线程在挂起状态下创建,并且SetThreadToken()用于应用从“ explorer.exe”创建的模拟令牌。 (我知道在多个已登录用户的情况下这不是可行的方法,但暂时我需要使用此工具解决问题)。
3.之后,我将继续线程以在用户级别上下文中执行传递的util方法。
引用的线程模拟来自: 创建具有特定特权的线程c ++
面对问题:
成功模拟了已登录的用户,并且创建的线程也在用户级上下文中运行(已使用GetUserName() API进行了验证),但是从我传递给模板类的方法中执行的任何API均与预期不符。 (示例:我试图读取模拟用户的HKCU条目,但它总是失败,并显示错误: ERROR_FILE_NOT_FOUND。2(0x2) )。 PS:交叉检查了注册表树,并且那里有相应的注册表项。
注意:上面的示例( REG read )是我尝试传递给Userimpersonator类并尝试从服务在用户上下文中运行的util方法之一,但是在运行时,我将将此方法与任何util方法一起使用。
UserImpersonator.h
class UserImpersonator
{
public:
UserImpersonator();
UserImpersonator(ImpersonationType typeVal,bool b_ImpersonateAndRunAsThreadNeeded = false);
~UserImpersonator();
T1 ImpersonateAndRun(T2 callback_function);
T1 ImpersonateAndRunAsThread(T2 callback_function);
private:
ImpersonationType ImpersonationTypeVal;
CString m_processname;
HANDLE hToken;
HANDLE impToken;
bool m_ImpersonateAndRunAsThreadNeeded;
T1 return_value;
T2 callable_function_object;
HANDLE hThread;
BOOL InitializeImpersonation();
BOOL RevertImpersonation();
static DWORD WINAPI SpawnImpersonatedThread ( LPVOID lpParam );
};
方法定义:
template<typename T1,typename T2>
UserImpersonator<T1,T2>::UserImpersonator()
{
ImpersonationTypeVal = ImpersonationType::IMPERSONATION_USING_WINLOGON;
m_processname = _T("winlogon.exe");
hToken = NULL;
m_ImpersonateAndRunAsThreadNeeded = false;
hThread = NULL;
impToken = NULL;
InitializeImpersonation();
}
template<typename T1,typename T2>
UserImpersonator<T1,T2>::UserImpersonator(ImpersonationType typeVal,bool b_ImpersonateAndRunAsThreadNeeded)
{
ImpersonationTypeVal = typeVal;
m_processname = (typeVal == ImpersonationType::IMPERSONATION_USING_WINLOGON) ? _T("winlogon.exe") : _T("explorer.exe");
hToken = NULL;
m_ImpersonateAndRunAsThreadNeeded = b_ImpersonateAndRunAsThreadNeeded;
hThread = NULL;
impToken = NULL;
InitializeImpersonation();
}
template<typename T1,typename T2>
DWORD WINAPI UserImpersonator<T1,T2> :: SpawnImpersonatedThread ( LPVOID lpParam )
{
TRY
{
UserImpersonator* ImpersonatorObject = (UserImpersonator*) lpParam;
TCHAR UserName[200] = _T("");
DWORD size = 200 ; //sizeof ( UserName ) ;
GetUserName ( UserName , &size ) ;
CString name = CString(UserName);
ImpersonatorObject->return_value = ImpersonatorObject->ImpersonateAndRun(ImpersonatorObject->callable_function_object);
}
CATCH_ALL( e )
{
LogDebug ( _T("Exception occurs:%s"),__FUNCTIONW__ ) ;
return FALSE ;
}
END_CATCH_ALL
return 0;
}
template<typename T1,typename T2>
BOOL UserImpersonator<T1,T2>::InitializeImpersonation()
{
BOOL res = TRUE;
try
{
TCHAR UserName[200] = _T("");
DWORD size = 200 ; //sizeof ( UserName ) ;
GetUserName ( UserName , &size ) ;
CString name = CString(UserName);
HANDLE process_handle = GetProcessHandleByName(m_processname);
if ( OpenProcessToken(process_handle, TOKEN_ALL_ACCESS, &hToken) == 0 )
{
res = FALSE;
CloseHandle(process_handle);
LogCritical(_T("%s : OpenProcessToken Failed with error-%d"), __FUNCTIONW__, GetLastError());
}
}
catch(...)
{
LogDebug(_T("%s::Exception occurred"),__FUNCTIONW__);
}
return res;
}
template<typename T1,typename T2>
T1 UserImpersonator<T1,T2>::ImpersonateAndRunAsThread(T2 callback_function)
{
try
{
callable_function_object = callback_function;
hThread = ::CreateThread(0,0,SpawnImpersonatedThread,this,CREATE_SUSPENDED,0); //without using sb
BOOL b = DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityImpersonation,TokenImpersonation,&impToken);
if( hThread )
{
if(SetThreadToken(&hThread,impToken))
{
DWORD thread_suspended_count = ResumeThread(hThread);
if( thread_suspended_count == (DWORD) 0 || thread_suspended_count == (DWORD) 1 )
{
DWORD thread_return_status = WaitForSingleObject(hThread,INFINITE);
if( thread_return_status == WAIT_OBJECT_0 )
{
LogDebug(_T("%s::SpawnImpersonatedThread successfully executed the callback function"),__FUNCTIONW__);
}
else
LogDebug(_T("%s::WaitForSingleObject failed with error=%d"),__FUNCTIONW__,GetLastError());
}
}
else
LogDebug(_T("%s::SetThreadToken failed with error=%d"),__FUNCTIONW__,GetLastError());
}
else
LogDebug(_T("%s::CreateThread failed with error=%d"),__FUNCTIONW__,GetLastError());
}
catch(...)
{
LogDebug(_T("%s::Exception occurred"),__FUNCTIONW__);
}
return return_value;
}
template<typename T1,typename T2>
T1 UserImpersonator<T1,T2>:: ImpersonateAndRun(T2 callback_function)
{
try
{
return_value = callback_function();
}
catch(...)
{
LogDebug(_T("%s::Exception occurred"),__FUNCTIONW__);
}
return return_value;
}
template<typename T1,typename T2>
BOOL UserImpersonator<T1,T2>::RevertImpersonation()
{
if(hToken)
CloseHandle(hToken) ;
if(impToken)
CloseHandle(impToken) ;
return RevertToSelf();
}
template<typename T1,typename T2>
UserImpersonator<T1,T2>::~UserImpersonator()
{
RevertImpersonation();
}
用法示例:
UserImpersonator< bool,std::function<bool()> > ImpersonatedObj(ImpersonationType::IMPERSONATION_USING_EXPLORER,true);
auto f = std::bind(&IsRegKeyExists);
BOOL res = ImpersonatedObj.ImpersonateAndRunAsThread(f);
使用方法:
bool IsRegKeyExists()
{
HKEY phKey = NULL;
bool res = false;
is64bit = Is64BitConfiguration();
CString subkey = _T("Volatile Environment\\USERPROFILE");
if(is64bit)
{
lRes = RegOpenKeyEx( HKEY_CURRENT_USER, subkey.GetBuffer(), 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &phKey );
}
else
{
lRes = RegOpenKeyEx( HKEY_CURRENT_USER, subkey.GetBuffer(), 0, KEY_ALL_ACCESS, &phKey );
}
if(lRes == ERROR_SUCCESS)
{
res = true;
}
else
{
LogDebug ( _T("Key open failure! %d"), GetLastError() );
}
return res;
}
HKEY_CURRENT_USER
这是预定义的密钥 -此句柄已缓存:
HKEY_CURRENT_USER
键映射到HKEY_USERS
键中当前用户分支的根。 它为进程中的所有线程缓存 。 因此,加载另一个用户的配置文件时,此值不会更改。RegOpenCurrentUser
使用线程的令牌访问相应的密钥,如果未加载配置文件,则使用默认值。
因此,您首先需要通过RegOpenCurrentUser
打开用户根密钥,然后使用此句柄HKEY_CURRENT_USER
。 如果您间接访问用户注册表配置单元,也可以使用RegDisablePredefinedCache
和RegDisablePredefinedCacheEx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.