文章目录
Windows 通过login_id获取uname,usid,udomain
#include <windows.h>
#include <stdint.h>
#include <sddl.h>
#include <string>
#include <Ntsecapi.h>
#pragma comment(lib,"Secur32.lib")
int GetProcessUserNameAndSidAndDomainByLoginId(const uint64_t login_id,
std::wstring& proc_uname,
std::wstring& proc_usid,
std::wstring& proc_udomain) {
int ret = 1;
do {
if (login_id < 0) {
break;
}
PSECURITY_LOGON_SESSION_DATA sessionData = nullptr;
NTSTATUS retval =
LsaGetLogonSessionData((PLUID)&login_id, &sessionData);
if (retval == 0) {
if (login_id == 999) {
proc_uname = L"SYSTEM";
}
else {
std::wstring wstr_uname(
sessionData->UserName.Buffer,
sessionData->UserName.Length / sizeof(WCHAR));
proc_uname = wstr_uname;
}
std::wstring wstr_domain(
sessionData->LogonDomain.Buffer,
sessionData->LogonDomain.Length / sizeof(WCHAR));
proc_usid = wstr_domain;
LPWSTR wstr_usid = nullptr;
BOOL b_con =
ConvertSidToStringSidW(sessionData->Sid, &wstr_usid);
if (b_con) {
proc_usid = wstr_usid;
LocalFree(wstr_usid);
}
if (sessionData) {
LsaFreeReturnBuffer(sessionData);
}
ret = 0;
}
} while (false);
if (ret == 1) {
ret = 0;
if (login_id == 999) {
proc_uname = L"SYSTEM";
proc_usid = L"S-1-5-18";
}
else if (login_id == 997) {
proc_uname = L"LOCAL SERVICE";
proc_usid = L"S-1-5-19";
}
else if (login_id == 996) {
proc_uname = L"NETWORK SERVICE";
proc_usid = L"S-1-5-20";
}
else {
ret = 1;
}
}
return ret;
}
int main() {
uint64_t login_id = 999;
std::wstring proc_uname;
std::wstring proc_usid;
std::wstring proc_udomain;
int ret = GetProcessUserNameAndSidAndDomainByLoginId(login_id, proc_uname, proc_usid, proc_udomain);
if (ret != 0) {
printf("failed");
}
else {
printf("uname:%S ,uid:%S,udomain:%S", proc_uname.c_str(), proc_usid.c_str(), proc_udomain.c_str());
}
system("pause");
return 0;
}
获取本地所有账户信息
#include <windows.h>
#include <iostream>
#include <string>
#include <sddl.h>
#include <map>
#include <winternl.h>
#define _NTDEF_
#include <ntsecapi.h>
typedef struct USER_INFO
{
std::wstring UserName;
std::wstring Sid;
std::wstring LogonDomain;
} USER_INFO, *PUSER_INFO;
#pragma comment(lib, "Secur32.lib")
std::map<ULONGLONG, USER_INFO> g_UserInfoList;
LSA_HANDLE OpenLsaPolicy()
{
LSA_HANDLE LsaHandle;
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
// 初始化LSA对象属性
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
ObjectAttributes.Length = sizeof(ObjectAttributes);
// 打开本地安全性授权(LSA)策略
if (LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION, &LsaHandle) != 0)
{
return NULL;
}
return LsaHandle;
}
VOID CloseLsaPolicy(LSA_HANDLE LsaHandle)
{
LsaClose(LsaHandle);
}
BOOLEAN InitUserInfoList()
{
BOOLEAN bSuccessed = FALSE;
PLUID pLuids = NULL;
ULONG LuidCount = NULL;
// 枚举
if (LsaEnumerateLogonSessions(&LuidCount, &pLuids) != 0)
{
goto CleanUp;
}
for (ULONG i = 0; i < LuidCount; i++)
{
PSECURITY_LOGON_SESSION_DATA pSessionData;
auto status = LsaGetLogonSessionData(&pLuids[i], &pSessionData);
if (status != 0)
{
printf("status[%08X]\r\n", status);
continue;
}
ULONGLONG LogonId = *(reinterpret_cast<PULONGLONG>(&pSessionData->LogonId));
LPWSTR StrSidW = NULL;
printf("LogonId[%llx] status[%08X]\r\n", LogonId, status);
if (ConvertSidToStringSid(pSessionData->Sid, &StrSidW))
{
g_UserInfoList[LogonId].Sid = StrSidW;
if (pSessionData->UserName.Buffer) {
g_UserInfoList[LogonId].UserName.assign(pSessionData->UserName.Buffer, pSessionData->UserName.Length / sizeof(WCHAR));
}
if (pSessionData->LogonDomain.Buffer) {
g_UserInfoList[LogonId].LogonDomain.assign(pSessionData->LogonDomain.Buffer, pSessionData->LogonDomain.Length / sizeof(WCHAR));
}
LocalFree(StrSidW);
}
LsaFreeReturnBuffer(pSessionData);
}
bSuccessed = TRUE;
CleanUp:
if (pLuids)
{
LsaFreeReturnBuffer(pLuids);
}
return bSuccessed;
}
int wmain(int arc, const wchar_t* argv[]) {
if (InitUserInfoList())
{
printf("Init succssed\r\n");
}
else
{
printf("Init failed\r\n");
}
}
记录坑
windows server 2012R1机器会调用LsaGetLogonSessionData返回0xC0000017L
STATUS_NO_MEMORY
以及 0xC000005FL
STATUS_NO_SUCH_LOGON_SESSION
前者,迄今不知道原因,离谱,用demo在机器跑没有问题,放到项目的代码里面跑就有问题。
后者,可能session退出了,导致对应的login_id过期,后面代码加了缓存,用于查找旧用户信息。