简体   繁体   English

使用SYSTEM级别进程(Windows Service)中已登录的用户上下文模拟并运行任何方法:

[英]Impersonate and run any method using a logged in user context from SYSTEM level process (Windows Service):

I have created a template class which will create a thread with logged-in user token and run any method. 我已经创建了一个模板类,它将使用登录的用户令牌创建一个线程并运行任何方法。 I passed it to the template class with the help of std::function and run it in the user level context. 我借助std :: function将其传递给模板类,并在用户级别的上下文中运行它。

My Current Usage: 我目前的用法:

1.The class is used in a windows service process ( which is running as SYSTEM level). 1.该类在Windows服务进程(以SYSTEM级别运行)中使用。

2.The thread is created in a suspended state and SetThreadToken() is used to apply the Impersonated token created from "explorer.exe". 2.线程在挂起状态下创建,并且SetThreadToken()用于应用从“ explorer.exe”创建的模拟令牌。 ( I know it is not a feasible way in multiple logged-in users case but for time being I need this thing to get work out). (我知道在多个已登录用户的情况下这不是可行的方法,但暂时我需要使用此工具解决问题)。

3.After these I will resume the thread to execute the passed util method in user level context. 3.之后,我将继续线程以在用户级别上下文中执行传递的util方法。

Referred thread impersonation from : Create thread with specific privilege c++ 引用的线程模拟来自: 创建具有特定特权的线程c ++

Problem Facing: 面对问题:

Successfully impersonated the logged-in user and the created thread also is running in user-level context (verified using GetUserName() API ) but the execution of any API from the method I have passed to the template class is not as expected. 成功模拟了已登录的用户,并且创建的线程也在用户级上下文中运行(已使用GetUserName() API进行了验证),但是从我传递给模板类的方法中执行的任何API均与预期不符。 (Example: I have tried to read HKCU entry of the impersonated user but it is always failed with error: ERROR_FILE_NOT_FOUND. 2 (0x2) ). (示例:我试图读取模拟用户的HKCU条目,但它总是失败,并显示错误: ERROR_FILE_NOT_FOUND。2(0x2) )。 PS: Cross Checked the registry tree and the respective key is present there. PS:交叉检查了注册表树,并且那里有相应的注册表项。

NOTE: The above example( REG read ) is one of the util methods I have tried to pass to the Userimpersonator class and tried to run in user context from the service but in run time I will use this with any util method. 注意:上面的示例( REG read )是我尝试传递给Userimpersonator类并尝试从服务在用户上下文中运行的util方法之一,但是在运行时,我将将此方法与任何util方法一起使用。

UserImpersonator.h 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 );

};

Method definitions: 方法定义:

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();
}

Example for Usage: 用法示例:

    UserImpersonator< bool,std::function<bool()> > ImpersonatedObj(ImpersonationType::IMPERSONATION_USING_EXPLORER,true);

    auto f = std::bind(&IsRegKeyExists);

    BOOL res = ImpersonatedObj.ImpersonateAndRunAsThread(f);

Util Method: 使用方法:

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 this is Predefined Key - this handles is cached: HKEY_CURRENT_USER这是预定义的密钥 -此句柄已缓存:

The HKEY_CURRENT_USER key maps to the root of the current user's branch in the HKEY_USERS key. HKEY_CURRENT_USER键映射到HKEY_USERS键中当前用户分支的根。 It is cached for all threads in a process. 它为进程中的所有线程缓存 Therefore, this value does not change when another user's profile is loaded. 因此,加载另一个用户的配置文件时,此值不会更改。 RegOpenCurrentUser uses the thread's token to access the appropriate key, or the default if the profile is not loaded. RegOpenCurrentUser使用线程的令牌访问相应的密钥,如果未加载配置文件,则使用默认值。

so you need first open user root key via RegOpenCurrentUser and use this handle instead HKEY_CURRENT_USER . 因此,您首先需要通过RegOpenCurrentUser打开用户根密钥,然后使用此句柄HKEY_CURRENT_USER also possible use RegDisablePredefinedCache and RegDisablePredefinedCacheEx in case you indirect access user registry hive 如果您间接访问用户注册表配置单元,也可以使用RegDisablePredefinedCacheRegDisablePredefinedCacheEx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何正确地模拟用户的服务? - How to impersonate a user from a service correctly? 即使从系统服务使用RegOpenCurrentUser也无法获取用户级别的注册表值 - Cannot get user level registry value even using RegOpenCurrentUser from system service Windows 7或Windows 2008如何在本地系统帐户或系统上下文中启动进程(通过桌面应用程序) - Windows 7 or Windows 2008 how to launch a process in Local System Account or System Context (from desktop aplication) 如何从Windows服务在系统帐户下启动单独的进程? - how to start separate process under system account from a windows service? C ++检查是否有任何用户登录Windows 7 - C++ check if any user is logged in to windows 7 从 C++ Windows 服务中获取当前登录的用户名 - get current Logged in user name from within a C++ windows service 从管理员帐户模拟SYSTEM(或等效) - Impersonate SYSTEM (or equivalent) from Administrator Account 用于启动和重新启动用户进程的Windows服务(使用GUI) - Windows Service for launching and restarting a user process (with GUI) 如何从C ++的Windows XP上的管理员进程获取有关已登录用户的语言环境信息? - How do I get locale information about logged-in user from an administrator process on Windows XP in c++? 在系统上下文中运行进程 - Running Process in system context
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM