Last active
August 27, 2022 15:32
-
-
Save somma/94aa6c97f9d532676a62ec1099b94c71 to your computer and use it in GitHub Desktop.
create_process_as_login_user
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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