I am working on a project where I have to create a windows token for a given SID. The intention is to generate an elevated token for a standard user. I am aware of an undocumented function "NtCreateToken()" which could do that but I dont get through much workable examples to achieve it.
The following is the code written for that :
typedef NTSTATUS(__stdcall* NtCreateToken)(
PHANDLE TokenHandle,
ACCESS_MASK DesiredAccess,
TokenGeneratorTypes::POBJECT_ATTRIBUTES ObjectAttributes,
TOKEN_TYPE TokenType,
PLUID AuthenticationId,
PLARGE_INTEGER ExpirationTime,
PTOKEN_USER User,
PTOKEN_GROUPS Groups,
TokenGeneratorTypes::PTOKEN_PRIVILEGES Privileges,
PTOKEN_OWNER Owner,
PTOKEN_PRIMARY_GROUP PrimaryGroup,
PTOKEN_DEFAULT_DACL DefaultDacl,
PTOKEN_SOURCE TokenSource
);
LUID GetLuidOfPrivilege(LPCWSTR privilegeName)
{
PLUID pluid = nullptr;
LUID luid;
LookupPrivilegeValue(nullptr, privilegeName, pluid);
luid.LowPart = pluid->LowPart;
luid.HighPart = pluid->HighPart;
return luid;
}
PHANDLE GenerateElevatedToken(LPCWSTR sid)
{
HMODULE hModule = GetModuleHandle(TEXT("ntdll.dll"));
NtCreateToken CreateToken = nullptr;
PSID* psid = nullptr;
TOKEN_PRIMARY_GROUP pgroup;
TOKEN_USER user;
static TOKEN_SOURCE source = { {"User32 "} };
static TOKEN_DEFAULT_DACL tdd;
static TokenGeneratorTypes::_SID Administrators = { SID_REVISION,2,SECURITY_NT_AUTHORITY,{SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS} };
static TOKEN_GROUPS groups = { 1,{{&Administrators,SE_GROUP_ENABLED | SE_GROUP_MANDATORY}} };
static SECURITY_QUALITY_OF_SERVICE sqos = {
sizeof(sqos), SecurityImpersonation, SECURITY_DYNAMIC_TRACKING
};
PHANDLE tokenHandle = nullptr;
static TokenGeneratorTypes::OBJECT_ATTRIBUTES oa = {
sizeof oa, 0, 0, 0, 0, &sqos
};
HANDLE currentToken;
TOKEN_STATISTICS tstats;
DWORD returnLength;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, ¤tToken);
GetTokenInformation(currentToken, TOKEN_INFORMATION_CLASS::TokenStatistics, &tstats, sizeof(tstats), &returnLength);
TokenGeneratorTypes::TOKEN_PRIVILEGES Privileges = {
25, {
{ {GetLuidOfPrivilege(SE_INCREASE_QUOTA_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_SECURITY_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_TAKE_OWNERSHIP_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_LOAD_DRIVER_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_SYSTEM_PROFILE_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_SYSTEMTIME_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_PROF_SINGLE_PROCESS_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_INC_BASE_PRIORITY_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_CREATE_PAGEFILE_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_BACKUP_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_RESTORE_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_SHUTDOWN_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_DEBUG_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_SYSTEM_ENVIRONMENT_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_CHANGE_NOTIFY_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_REMOTE_SHUTDOWN_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_UNDOCK_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_MANAGE_VOLUME_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_IMPERSONATE_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_CREATE_GLOBAL_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_INC_WORKING_SET_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_TIME_ZONE_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_CREATE_SYMBOLIC_LINK_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
{ { GetLuidOfPrivilege(SE_TCB_NAME) }, SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }
} };
if (hModule != 0)
{
CreateToken = (NtCreateToken)GetProcAddress(hModule, "NtCreateToken");
if (CreateToken == 0)
{
return nullptr;
}
}
else
{
return nullptr;
}
ConvertStringSidToSidW(sid,psid);
pgroup = { psid };
user = { psid };
LUID sessionId = {1,0 };
PLUID psessionId = &sessionId;
CreateToken(tokenHandle, TOKEN_ALL_ACCESS, &oa, TokenPrimary,psessionId, &tstats.ExpirationTime, &user,
&groups, (TokenGeneratorTypes::PTOKEN_PRIVILEGES) & Privileges, 0, &pgroup, &tdd, &source);
return tokenHandle;
}
The token generated from the above function is used to create a process in session id 1. The following is the code for the same :
wstring processName = _T("notepad.exe");
TCHAR* name = (wchar_t*)processName.c_str();
PROCESS_INFORMATION processInformation; STARTUPINFO startupInfo = GetStartupInfo();
ZeroMemory(&processInformation, sizeof(processInformation));
std::wstring sid = "....."
PHANDLE tkn = GenerateElevatedToken(sid.c_str());
CreateProcessAsUser(tkn, nullptr, name, nullptr,
nullptr, false, 0, nullptr, nullptr, &startupInfo, &processInformation);
The isssue I am facing is that, the process simply starts and exits after a few seconds. I can provide more context (including for TokenGeneratorTypes and GetStartupInfo()) if required. Please point out the error with the above code.
What I have tried:
I have tried executing this program with the SeCreateTokenPrivilege enabled. However, still process simply exits.