How can I get the active user name in a SYSTEM process using C++?

时间:2022-09-06 08:07:43

I have used GetUserName() METHOD , but the username it returned is 'SYSTEM' in a SYSTEM process.How can I get the active username in a SYSTEM process? THIS IS MY CODE:

我使用了GetUserName()METHOD,但它返回的用户名是SYSTEM进程中的'SYSTEM'。如何在SYSTEM进程中获取活动用户名?这是我的代码:

void getComputerUsername(char * username,char * domainname)
{
 HANDLE hp , htoken;
 char buff[1024];
 unsigned long size = 1024;

 TOKEN_USER *tuser;
 PSID sid;
 TCHAR * user = new TCHAR[256];
 TCHAR * domain=new TCHAR[256];
 SID_NAME_USE snu;

 hp = htoken = INVALID_HANDLE_VALUE;
 hp = GetCurrentProcess();
 if(OpenProcessToken(hp, TOKEN_QUERY, &htoken))
 {
     if(GetTokenInformation(htoken, TokenUser, (void*)buff, size, &size))
 {
     tuser = (TOKEN_USER*)buff;
     sid = tuser->User.Sid;
     size = 256;
     if(LookupAccountSid(NULL, sid, user, &size, domain, &size, &snu))
     {
    int iLength = WideCharToMultiByte(CP_ACP, 0, user, -1, NULL, 0, NULL, NULL);  
    WideCharToMultiByte(CP_ACP, 0, user, -1, username, iLength, NULL, NULL);   

    iLength = WideCharToMultiByte(CP_ACP, 0, domain, -1, NULL, 0, NULL, NULL);  
    WideCharToMultiByte(CP_ACP, 0, domain, -1, domainname, iLength, NULL, NULL);  
           //strcpy( user,username);
     }
 }
 }

}

}

4 个解决方案

#1


1  

You need to enumerate through all the running processes using EnumProcesses

您需要使用EnumProcesses枚举所有正在运行的进程

Then see this answer to get the username from the process:

然后看到这个答案,从过程中获取用户名:

https://*.com/a/2686150/203244

https://*.com/a/2686150/203244

#2


3  

If you want to know who is logged onto the physical console, you can call WTSGetActiveConsoleSessionId to get the terminal services (aka "fast user switching" aka "remote desktop") session ID that is currently active.

如果您想知道谁登录到物理控制台,您可以调用WTSGetActiveConsoleSessionId来获取当前活动的终端服务(也称为“快速用户交换”又名“远程桌面”)会话ID。

You can then call WTSQuerySessionInformation with WTSUserName to get the username.

然后,您可以使用WTSUserName调用WTSQuerySessionInformation来获取用户名。

(If the user you're interested in might be logged on via Remote Desktop, this approach will not work.)

(如果您感兴趣的用户可能通过远程桌面登录,则此方法无效。)

#3


1  

Enumerating all processes is a way to do it but it has certain issues:

枚举所有进程是一种方法,但它有一些问题:

1) You can't enumerate both x86 and x64 processes in the same service process using documented Windows APIs. An x86 service can only enumerate x86 processes and an x64 service can only enumerate x64 processes. A way to circumvent that is to have an x86 service launch an x64 helper process (and vice versa) to do the rest of the enumeration task.

1)您无法使用文档化的Windows API在同一服务进程中枚举x86和x64进程。 x86服务只能枚举x86进程,而x64服务只能枚举x64进程。避免这种情况的一种方法是让x86服务启动x64辅助进程(反之亦然)来执行枚举任务的其余部分。

2) The only process that is always present for a logged on user across different Windows versions (e.g. Vista to Windows 10) is explorer.exe however that process is x64 on x64 OS platforms and x32 on x32 OS platforms and its presence does not mean that the user is actively logged in.

2)对于不同Windows版本(例如Vista到Windows 10)的登录用户始终存在的唯一进程是explorer.exe,但该进程在x64 OS平台上是x64,在x32 OS平台上是x32,并且它的存在并不意味着用户已主动登录。

A better way is to enumerate sessions, find the active interactive session or sessions that is also connected and then get the user name of that session.

更好的方法是枚举会话,查找活动的交互式会话或已连接的会话,然后获取该会话的用户名。

The code below does much more than that, including impersonation of that user and running a process as that user all from a windows service, but if you are just interested in the user name please look for the second instance the WTSQuerySessionInformation() function is called.

下面的代码远不止于此,包括模拟该用户并从Windows服务中以该用户身份运行进程,但如果您只是对用户名感兴趣,请查找第二个实例,调用WTSQuerySessionInformation()函数。

//Function to run a process as active user from windows service
void ImpersonateActiveUserAndRun(WCHAR* path, WCHAR* args)
{
    DWORD session_id = -1;
    DWORD session_count = 0;

    WTS_SESSION_INFOA *pSession = NULL;


    if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
    {
        //log success
    }
    else
    {
        //log error
        return;
    }

    for (int i = 0; i < session_count; i++)
    {
        session_id = pSession[i].SessionId;

        WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
        WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;

        DWORD bytes_returned = 0;
        if (::WTSQuerySessionInformation(
            WTS_CURRENT_SERVER_HANDLE,
            session_id,
            WTSConnectState,
            reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
            &bytes_returned))
        {
            wts_connect_state = *ptr_wts_connect_state;
            ::WTSFreeMemory(ptr_wts_connect_state);
            if (wts_connect_state != WTSActive) continue;
        }
        else
        {
            //log error
            continue;
        }

        HANDLE hImpersonationToken;

        if (!WTSQueryUserToken(session_id, &hImpersonationToken))
        {
            //log error
            continue;
        }


        //Get real token from impersonation token
        DWORD neededSize1 = 0;
        HANDLE *realToken = new HANDLE;
        if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
        {
            CloseHandle(hImpersonationToken);
            hImpersonationToken = *realToken;
        }
        else
        {
            //log error
            continue;
        }


        HANDLE hUserToken;

        if (!DuplicateTokenEx(hImpersonationToken,
            //0,
            //MAXIMUM_ALLOWED,
            TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
            NULL,
            SecurityImpersonation,
            TokenPrimary,
            &hUserToken))
        {
            //log error
            continue;
        }

        // Get user name of this process
        //LPTSTR pUserName = NULL;
        WCHAR* pUserName;
        DWORD user_name_len = 0;

        if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
        {
            //log username contained in pUserName WCHAR string
        }

        //Free memory                         
        if (pUserName) WTSFreeMemory(pUserName);

        ImpersonateLoggedOnUser(hUserToken);

        STARTUPINFOW StartupInfo;
        GetStartupInfoW(&StartupInfo);
        StartupInfo.cb = sizeof(STARTUPINFOW);
        //StartupInfo.lpDesktop = "winsta0\\default";

        PROCESS_INFORMATION processInfo;

        SECURITY_ATTRIBUTES Security1;
        Security1.nLength = sizeof SECURITY_ATTRIBUTES;

        SECURITY_ATTRIBUTES Security2;
        Security2.nLength = sizeof SECURITY_ATTRIBUTES;

        void* lpEnvironment = NULL;

        // Get all necessary environment variables of logged in user
        // to pass them to the new process
        BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);
        if (!resultEnv)
        {
            //log error
            continue;
        }

        WCHAR PP[1024]; //path and parameters
        ZeroMemory(PP, 1024 * sizeof WCHAR);
        wcscpy(PP, path);
        wcscat(PP, L" ");
        wcscat(PP, args);

        // Start the process on behalf of the current user 
        BOOL result = CreateProcessAsUserW(hUserToken, 
            NULL,
            PP,
            //&Security1,
            //&Security2,
            NULL,
            NULL,
            FALSE, 
            NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
            //lpEnvironment,
            NULL,
            //"C:\\ProgramData\\some_dir",
            NULL,
            &StartupInfo,
            &processInfo);

        if (!result)
        {
            //log error
        }
        else
        {
            //log success
        }

        DestroyEnvironmentBlock(lpEnvironment);

        CloseHandle(hImpersonationToken);
        CloseHandle(hUserToken);
        CloseHandle(realToken);

        RevertToSelf();
    }

    WTSFreeMemory(pSession);
}

#4


0  

Enumerate the desktops and find the "Default" desktop. Get the user SID from that desktop. Maybe you have to try to find the correct access rights; I tried the code from an interactive process only.

枚举桌面并找到“默认”桌面。从该桌面获取用户SID。也许您必须尝试找到正确的访问权限;我只尝试了交互过程中的代码。

BOOL CALLBACK EnumDesktopProc(_In_  LPTSTR lpszDesktop, _In_  LPARAM lParam)
{
    // todo: check if desktop is "Default"
    char info[1000];
    auto hd = OpenDesktop(lpszDesktop, NULL, FALSE, DESKTOP_READOBJECTS);
    GetUserObjectInformation(hd, UOI_USER_SID, info, 1000, NULL);
    return TRUE;
}

BOOL CALLBACK EnumWindowStationProc(_In_  LPTSTR lpszWindowStation, _In_  LPARAM lParam)
{
    auto hs = OpenWindowStation(lpszWindowStation, FALSE, WINSTA_ENUMDESKTOPS);
    EnumDesktops(hs, &EnumDesktopProc, NULL);
    return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
    EnumWindowStations(&EnumWindowStationProc, NULL);
    return 0;
}

#1


1  

You need to enumerate through all the running processes using EnumProcesses

您需要使用EnumProcesses枚举所有正在运行的进程

Then see this answer to get the username from the process:

然后看到这个答案,从过程中获取用户名:

https://*.com/a/2686150/203244

https://*.com/a/2686150/203244

#2


3  

If you want to know who is logged onto the physical console, you can call WTSGetActiveConsoleSessionId to get the terminal services (aka "fast user switching" aka "remote desktop") session ID that is currently active.

如果您想知道谁登录到物理控制台,您可以调用WTSGetActiveConsoleSessionId来获取当前活动的终端服务(也称为“快速用户交换”又名“远程桌面”)会话ID。

You can then call WTSQuerySessionInformation with WTSUserName to get the username.

然后,您可以使用WTSUserName调用WTSQuerySessionInformation来获取用户名。

(If the user you're interested in might be logged on via Remote Desktop, this approach will not work.)

(如果您感兴趣的用户可能通过远程桌面登录,则此方法无效。)

#3


1  

Enumerating all processes is a way to do it but it has certain issues:

枚举所有进程是一种方法,但它有一些问题:

1) You can't enumerate both x86 and x64 processes in the same service process using documented Windows APIs. An x86 service can only enumerate x86 processes and an x64 service can only enumerate x64 processes. A way to circumvent that is to have an x86 service launch an x64 helper process (and vice versa) to do the rest of the enumeration task.

1)您无法使用文档化的Windows API在同一服务进程中枚举x86和x64进程。 x86服务只能枚举x86进程,而x64服务只能枚举x64进程。避免这种情况的一种方法是让x86服务启动x64辅助进程(反之亦然)来执行枚举任务的其余部分。

2) The only process that is always present for a logged on user across different Windows versions (e.g. Vista to Windows 10) is explorer.exe however that process is x64 on x64 OS platforms and x32 on x32 OS platforms and its presence does not mean that the user is actively logged in.

2)对于不同Windows版本(例如Vista到Windows 10)的登录用户始终存在的唯一进程是explorer.exe,但该进程在x64 OS平台上是x64,在x32 OS平台上是x32,并且它的存在并不意味着用户已主动登录。

A better way is to enumerate sessions, find the active interactive session or sessions that is also connected and then get the user name of that session.

更好的方法是枚举会话,查找活动的交互式会话或已连接的会话,然后获取该会话的用户名。

The code below does much more than that, including impersonation of that user and running a process as that user all from a windows service, but if you are just interested in the user name please look for the second instance the WTSQuerySessionInformation() function is called.

下面的代码远不止于此,包括模拟该用户并从Windows服务中以该用户身份运行进程,但如果您只是对用户名感兴趣,请查找第二个实例,调用WTSQuerySessionInformation()函数。

//Function to run a process as active user from windows service
void ImpersonateActiveUserAndRun(WCHAR* path, WCHAR* args)
{
    DWORD session_id = -1;
    DWORD session_count = 0;

    WTS_SESSION_INFOA *pSession = NULL;


    if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
    {
        //log success
    }
    else
    {
        //log error
        return;
    }

    for (int i = 0; i < session_count; i++)
    {
        session_id = pSession[i].SessionId;

        WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
        WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;

        DWORD bytes_returned = 0;
        if (::WTSQuerySessionInformation(
            WTS_CURRENT_SERVER_HANDLE,
            session_id,
            WTSConnectState,
            reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
            &bytes_returned))
        {
            wts_connect_state = *ptr_wts_connect_state;
            ::WTSFreeMemory(ptr_wts_connect_state);
            if (wts_connect_state != WTSActive) continue;
        }
        else
        {
            //log error
            continue;
        }

        HANDLE hImpersonationToken;

        if (!WTSQueryUserToken(session_id, &hImpersonationToken))
        {
            //log error
            continue;
        }


        //Get real token from impersonation token
        DWORD neededSize1 = 0;
        HANDLE *realToken = new HANDLE;
        if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
        {
            CloseHandle(hImpersonationToken);
            hImpersonationToken = *realToken;
        }
        else
        {
            //log error
            continue;
        }


        HANDLE hUserToken;

        if (!DuplicateTokenEx(hImpersonationToken,
            //0,
            //MAXIMUM_ALLOWED,
            TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
            NULL,
            SecurityImpersonation,
            TokenPrimary,
            &hUserToken))
        {
            //log error
            continue;
        }

        // Get user name of this process
        //LPTSTR pUserName = NULL;
        WCHAR* pUserName;
        DWORD user_name_len = 0;

        if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
        {
            //log username contained in pUserName WCHAR string
        }

        //Free memory                         
        if (pUserName) WTSFreeMemory(pUserName);

        ImpersonateLoggedOnUser(hUserToken);

        STARTUPINFOW StartupInfo;
        GetStartupInfoW(&StartupInfo);
        StartupInfo.cb = sizeof(STARTUPINFOW);
        //StartupInfo.lpDesktop = "winsta0\\default";

        PROCESS_INFORMATION processInfo;

        SECURITY_ATTRIBUTES Security1;
        Security1.nLength = sizeof SECURITY_ATTRIBUTES;

        SECURITY_ATTRIBUTES Security2;
        Security2.nLength = sizeof SECURITY_ATTRIBUTES;

        void* lpEnvironment = NULL;

        // Get all necessary environment variables of logged in user
        // to pass them to the new process
        BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);
        if (!resultEnv)
        {
            //log error
            continue;
        }

        WCHAR PP[1024]; //path and parameters
        ZeroMemory(PP, 1024 * sizeof WCHAR);
        wcscpy(PP, path);
        wcscat(PP, L" ");
        wcscat(PP, args);

        // Start the process on behalf of the current user 
        BOOL result = CreateProcessAsUserW(hUserToken, 
            NULL,
            PP,
            //&Security1,
            //&Security2,
            NULL,
            NULL,
            FALSE, 
            NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
            //lpEnvironment,
            NULL,
            //"C:\\ProgramData\\some_dir",
            NULL,
            &StartupInfo,
            &processInfo);

        if (!result)
        {
            //log error
        }
        else
        {
            //log success
        }

        DestroyEnvironmentBlock(lpEnvironment);

        CloseHandle(hImpersonationToken);
        CloseHandle(hUserToken);
        CloseHandle(realToken);

        RevertToSelf();
    }

    WTSFreeMemory(pSession);
}

#4


0  

Enumerate the desktops and find the "Default" desktop. Get the user SID from that desktop. Maybe you have to try to find the correct access rights; I tried the code from an interactive process only.

枚举桌面并找到“默认”桌面。从该桌面获取用户SID。也许您必须尝试找到正确的访问权限;我只尝试了交互过程中的代码。

BOOL CALLBACK EnumDesktopProc(_In_  LPTSTR lpszDesktop, _In_  LPARAM lParam)
{
    // todo: check if desktop is "Default"
    char info[1000];
    auto hd = OpenDesktop(lpszDesktop, NULL, FALSE, DESKTOP_READOBJECTS);
    GetUserObjectInformation(hd, UOI_USER_SID, info, 1000, NULL);
    return TRUE;
}

BOOL CALLBACK EnumWindowStationProc(_In_  LPTSTR lpszWindowStation, _In_  LPARAM lParam)
{
    auto hs = OpenWindowStation(lpszWindowStation, FALSE, WINSTA_ENUMDESKTOPS);
    EnumDesktops(hs, &EnumDesktopProc, NULL);
    return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
    EnumWindowStations(&EnumWindowStationProc, NULL);
    return 0;
}