【WINAPI】获取系统当前用户名

概述:windows 操作系统获取系统当前登录的用户

0x01 API查询结果总结

以域名为domain,系统当前登录用户名为 test 为例举例说明,设备名为 WIN-FEKV0FJ89UQ

API 用户态进程 服务进程
GetUserName test SYSTEM
GetEnvironmentVariable(获取环境变量 %USERNAME%) test WIN-FEKV0FJ89UQ$
WTSQuerySessionInformation(不指定sessionid) test 服务进程中会返回空
WTSQuerySessionInformation(指定sessionid为WTSGetActiveConsoleSessionId()) test test
GetUserNameExA test(返回形式依据传入的参数1) domain\WIN-FEKV0FJ89UQ

总结下来,如果要获取系统当前登录的用户名,那么不管是在用户进程还是服务进程,使用 WTSQuerySessionInformation 指定 Sessionid 的方法比较靠谱。

0x02 获取用户的API

GetUserName

GetUserName以其运行的exe为主,用户态进程下获取的系统当前登录的用户名,服务进程中获取的为 system 用户。

1
2
3
4
5
6
7
std::string GetLoginUsernameByApi()
{
char username[1024];
DWORD usernameLength = sizeof username;
GetUserName(username, &usernameLength);
return username;
}

通过环境变量获取

%USERNAME% 和 GetUserName 本质上一致,不同的是,服务进程中,%USERNAME% 字段保存的是主机名+&,只有用户态进程下才是当前系统登录用户名

1
2
3
4
5
6
std::string getLoginUsernameByEnv()
{
char username[1024];
GetEnvironmentVariable("USERNAME", username, sizeof username);
return username;
}

WTSQuerySessionInformation 通过会话查询用户名

1
2
3
4
5
6
7
8
9
10
std::string getLoginUsernameBySession()
{
LPWSTR usernameBuffer = NULL;
DWORD infoSize = 0;

WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS::WTSUserName, &usernameBuffer, &infoSize);
string username(usernameBuffer);

return username;
}

GetUserNameExA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
	BOOL GetNameEx()
{
// 获取当前登录用户的域信息
PCHAR cpuName = new CHAR[256];
PCHAR domainName = new CHAR[256];
DWORD domainNameSize = 0;

ZeroMemory(domainName, 256);

GetComputerObjectNameA(NameSamCompatible, NULL, &domainNameSize);
if (GetComputerObjectNameA(NameSamCompatible, cpuName, &domainNameSize))
{
std::wcout << "当前登录的域机器: " << cpuName << std::endl;
}
else
{
std::cerr << "无法获取域信息" << std::endl;
}

domainNameSize = 0;
GetUserNameExA(NameDisplay, NULL, &domainNameSize);
if (GetUserNameExA(NameDisplay, domainName, &domainNameSize))
{
std::wcout << "当前登录的域用户: " << domainName << std::endl;
}
else {
std::cerr << "无法获取域信息" << std::endl;
}
}

0x03 如何在服务进程中获取系统当前登录的用户

获取当前控制台会话ID,然后再调用 WTSQuerySessionInformationW 查询用户名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BOOL GetLocalCurUserName(std::wstring& strUserName)
{
BOOL bRet = FALSE;
DWORD sessionId = WTSGetActiveConsoleSessionId();
LPWSTR ppBuffer[100];
DWORD bufferSize;
bRet = WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppBuffer, &bufferSize);

printf(" GetLocal1CurUserName --> %s", *ppBuffer);

if (bRet == TRUE)
{
strUserName = *ppBuffer;
WTSFreeMemory(ppBuffer);
}

return bRet;
}

0x04 其他方式

上述指定 Sessionid 的方法也可以通过 ProcessIdToSessionId 来获取 Sessionid。思路就是获取进程 Explorer.exe 的进程id,然后通过 PID 获取 Sessionid,最后通过 WTSQuerySessionInformationW 获取到对应的用户名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
DWORD GetPorceeIdByName(const std::string& procName)
{
const char* FindExe = procName.c_str();
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
if (strcmp(pe.szExeFile, FindExe) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
//printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile);
}
CloseHandle(hSnapshot);
}

bool GetUserNameByPid(DWORD pid, std::wstring& username)
{
DWORD SessionId;
ProcessIdToSessionId(pid, &SessionId);

LPWSTR usernameBuffer = NULL;
DWORD infoSize = 0;
if (FALSE == WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, SessionId, WTS_INFO_CLASS::WTSUserName, &usernameBuffer, &infoSize))
{
return false;
}

username = usernameBuffer;

return true;
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
void test()
{
DWORD dwPid;
wstring wsUserName;
if (dwPid = GetPorceeIdByName("explorer.exe"))
{
if (GetUserNameByPid(dwPid, wsUserName))
{
std::wcout << "explorer.exe:" << wsUserName << endl;
}
}
}

【WINAPI】获取系统当前用户名
https://hodlyounger.github.io/A_OS/Windows/API/【winapi】获取系统当前用户名/
作者
mingming
发布于
2024年1月23日
许可协议