如何在使用C++的SYSTEM进程中获取活动用户名?

问题描述:

我已经使用了GetUserName()方法,但是它返回的用户名是SYSTEM中的'SYSTEM'。如何在SYSTEM进程中获得活动的用户名?这是我的代码:如何在使用C++的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); 
    } 
} 
} 

}

+0

哪个操作系统?我猜Windows?在Windows上,据我所知,有一个SYSTEM用户,你的应用程序确实是以该用户的身份运行的 - 所以你想得到谁的用户名? – codeling

+3

如果您的进程在SYSTEM帐户下运行,那就是您所得到的:GetUserName返回拥有当前令牌的帐户的名称。您可能想知道其他内容,例如“当前登录的用户”(可能有多个!)或“启动此过程的用户”。 –

+0

该应用程序正在WINDOWS上工作。此外,我只想知道'当前登录的用户'。使用该应用的每个人都在域中,并且拥有我想要获得的唯一登录帐户。 –

你需要使用EnumProcesses

然后看看这个答案得到来自过程的用户名通过所有正在运行的进程枚举:

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

枚举桌面并找到“默认”桌面。从该桌面获取用户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; 
} 
+0

可能在XP上工作,但之后不会,因为您要搜索服务会话。 –

+0

它的工作原理。刚刚在Window 7上测试过。打开的命令提示符以服务运行为本地系统,并得到以下输出: Station:WinSta0;桌面:默认;桌面:断开;桌面:Winlogon; 和更多的各种服务。 – cdoubleplusgood

+1

是的,您可以看到所有的服务桌面,但不能看到交互式用户的桌面,这是您在这种情况下需要的桌面。 (搜索服务桌面有时很有用,但在这种情况下不适用。) –

如果你想知道谁是登录到物理控制台,你可以调用WTSGetActiveConsoleSessionId获得终端服务(又名“快速用户切换”又名“远程桌面”)当前处于活动状态的会话ID。

然后,您可以拨WTSQuerySessionInformationWTSUserName获取用户名。

(如果你有兴趣通过远程桌面可能会被登录的用户,这种做法是行不通的)

枚举所有进程是一个办法做到这一点,但它有一定的问题:

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

2)跨越不同Windows版本(例如Vista到Windows 10)的登录用户始终存在的唯一过程是explorer.exe,但该过程在x64操作系统平台上是x64,在x32操作系统平台上是x32,存在并不意味着用户正在主动登录。

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

下面的代码远不止于此,包括模拟该用户并运行一个进程作为该用户所有来自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); 
}