Skip to content

Instantly share code, notes, and snippets.

@somma
Last active August 27, 2022 15:32
Show Gist options
  • Save somma/94aa6c97f9d532676a62ec1099b94c71 to your computer and use it in GitHub Desktop.
Save somma/94aa6c97f9d532676a62ec1099b94c71 to your computer and use it in GitHub Desktop.
create_process_as_login_user
bool
create_process_as_login_user(
_In_ const wchar_t* cmdline
)
{
_ASSERTE(NULL != cmdline);
if (NULL == cmdline) return false;
DWORD session_id = WTSGetActiveConsoleSessionId();
DWORD explorer_pid = 0xFFFFFFFF;
//
// 타겟 세션의 explorer.exe 프로세스를 찾고,
// 해당 프로세스의 토큰으로 프로세스를 생성한다.
//
PROCESSENTRY32 proc_entry = { 0 };
DWORD creation_flag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
LPVOID env_block = NULL;
size_t cmd_len = 0;
wchar_t* cmd = NULL;
PROCESS_INFORMATION pi = { 0 };
TOKEN_PRIVILEGES tp = { 0 };
LUID luid = { 0 };
STARTUPINFO si = { 0 };
HANDLE snap = INVALID_HANDLE_VALUE;
HANDLE user_token = NULL;
HANDLE primary_token = NULL;
HANDLE duplicated_token = NULL;
HANDLE process_handle = NULL;
bool ret = false;
do
{
snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap == INVALID_HANDLE_VALUE)
{
log_err "CreateToolhelp32Snapshot(), gle=%u", GetLastError() log_end;
break;
}
do
{
proc_entry.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(snap, &proc_entry))
{
log_err "Process32First(), gle=%u", GetLastError() log_end;
break;
}
do
{
if (_wcsicmp(proc_entry.szExeFile, L"explorer.exe") == 0)
{
DWORD explorer_sessio_id = 0;
if (ProcessIdToSessionId(proc_entry.th32ProcessID, &explorer_sessio_id) &&
explorer_sessio_id == session_id)
{
explorer_pid = proc_entry.th32ProcessID;
break;
}
}
} while (Process32Next(snap, &proc_entry));
} while (false);
CloseHandle(snap);
if (0xFFFFFFFF == explorer_pid)
{
log_err "can not find 'explorer.exe'" log_end;
break;
}
if (TRUE != WTSQueryUserToken(session_id,
&user_token))
{
log_err "WTSQueryUserToken(), gle=%u", GetLastError() log_end;
break;
}
si.cb = sizeof(si);
si.lpDesktop = L"winsta0\\default";
process_handle = OpenProcess(MAXIMUM_ALLOWED,
FALSE,
explorer_pid);
if (NULL == process_handle)
{
log_err "OpenProcess(), gle=%u", GetLastError() log_end;
break;
}
if (TRUE != OpenProcessToken(process_handle,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
&primary_token))
{
log_err "OpenProcessToken(), gle=%u", GetLastError() log_end;
break;
}
if (TRUE != LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
log_err "LookupPrivilegeValue(), gle=%u", GetLastError() log_end;
break;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (TRUE != DuplicateTokenEx(primary_token,
MAXIMUM_ALLOWED,
NULL,
SecurityIdentification,
TokenPrimary,
&duplicated_token))
{
log_err "DuplicateTokenEx(), gle=%u", GetLastError() log_end;
break;
}
//> adjust token privilege
if (TRUE != SetTokenInformation(duplicated_token,
TokenSessionId,
(void*)session_id,
sizeof(DWORD)))
{
//log_err L"SetTokenInformation(), gle=0x%08x", GetLastError() log_end
// note - 이 에러는 무시해도 된다.
}
if (TRUE != AdjustTokenPrivileges(duplicated_token,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
NULL))
{
DWORD err = GetLastError();
if (ERROR_NOT_ALL_ASSIGNED != err)
{
log_err "AdjustTokenPrivileges(), gle=%u", err log_end;
break;
}
// ERROR_NOT_ALL_ASSIGNED is OK!
}
if (TRUE == CreateEnvironmentBlock(&env_block,
duplicated_token,
TRUE))
{
creation_flag |= CREATE_UNICODE_ENVIRONMENT;
}
//> create process in the consol session
cmd_len = (wcslen(cmdline) + 1) * sizeof(wchar_t);
cmd = (wchar_t*)malloc(cmd_len);
if (NULL == cmd)
{
log_err "insufficient memory for cmdline" log_end;
break;
}
StringCbPrintfW(cmd, cmd_len, L"%s", cmdline);
si.wShowWindow = SW_HIDE;
if (TRUE != CreateProcessAsUser(duplicated_token,
NULL,
cmd,
NULL,
NULL,
FALSE,
creation_flag,
env_block,
NULL,
&si,
&pi))
{
log_err "CreateProcessAsUserW(), gle=%u", GetLastError() log_end;
break;
}
if (NULL == pi.hProcess)
{
log_err "CreateProcessAsUserW() failed. gle=%u", GetLastError() log_end;
break;
}
if (WAIT_OBJECT_0 != ::WaitForSingleObject(pi.hProcess, 180000))
{
log_err "WaitForSingleObject Timeout. gle=%u", GetLastError() log_end;
break;
}
//
// OK!!!
//
ret = true;
} while (FALSE);
if (NULL != cmd)
{
free(cmd);
}
if (NULL != pi.hProcess)
{
CloseHandle(pi.hProcess);
}
if (NULL != pi.hThread)
{
CloseHandle(pi.hThread);
}
if (NULL != process_handle)
{
CloseHandle(process_handle);
}
if (NULL != primary_token)
{
CloseHandle(primary_token);
}
if (NULL != duplicated_token)
{
CloseHandle(duplicated_token);
}
if (NULL != user_token)
{
CloseHandle(user_token);
}
if (NULL != env_block)
{
DestroyEnvironmentBlock(env_block);
}
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment