213 lines
4.5 KiB
C++
213 lines
4.5 KiB
C++
#include "Common.h"
|
|
#include "ProcessUtils.h"
|
|
#include "TokenUtils.h"
|
|
#include "Logger.h"
|
|
|
|
DWORD GetPidByName(const wchar_t* exeName)
|
|
{
|
|
if (!exeName)
|
|
return 0;
|
|
|
|
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
if (snap == INVALID_HANDLE_VALUE)
|
|
return 0;
|
|
|
|
PROCESSENTRY32W pe{};
|
|
pe.dwSize = sizeof(pe);
|
|
|
|
if (!Process32First(snap, &pe))
|
|
{
|
|
CloseHandle(snap);
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (_wcsicmp(pe.szExeFile, exeName) == 0)
|
|
{
|
|
DWORD pid = pe.th32ProcessID;
|
|
CloseHandle(snap);
|
|
return pid;
|
|
}
|
|
} while (Process32Next(snap, &pe));
|
|
|
|
CloseHandle(snap);
|
|
return 0;
|
|
}
|
|
|
|
bool ProcessExistsByName(const wchar_t* exeName)
|
|
{
|
|
return GetPidByName(exeName) != 0;
|
|
}
|
|
|
|
static bool BuildCommandLine(
|
|
const wchar_t* exePath,
|
|
const wchar_t* args,
|
|
std::wstring& fullPath,
|
|
std::wstring& commandLine)
|
|
{
|
|
if (!exePath || !*exePath)
|
|
return false;
|
|
|
|
wchar_t abs[4096]{};
|
|
DWORD n = GetFullPathNameW(exePath, _countof(abs), abs, nullptr);
|
|
|
|
if (n == 0)
|
|
wcscpy_s(abs, _countof(abs), exePath);
|
|
|
|
fullPath = abs;
|
|
|
|
if (GetFileAttributesW(fullPath.c_str()) == INVALID_FILE_ATTRIBUTES)
|
|
{
|
|
Log(L"[-] Executable not found: %s", fullPath.c_str());
|
|
return false;
|
|
}
|
|
|
|
commandLine.clear();
|
|
commandLine += L'"';
|
|
commandLine += fullPath;
|
|
commandLine += L'"';
|
|
|
|
if (args && *args)
|
|
{
|
|
commandLine += L' ';
|
|
commandLine += args;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool CreateProcessAsSystemImpl(
|
|
HANDLE systemToken,
|
|
const wchar_t* exePath,
|
|
const wchar_t* args,
|
|
bool interactive,
|
|
bool suspended,
|
|
NewProcInfo* out)
|
|
{
|
|
if (out)
|
|
*out = NewProcInfo();
|
|
|
|
if (!systemToken || !exePath)
|
|
return false;
|
|
|
|
HANDLE tok = DuplicateSystemTokenFromHandle(systemToken);
|
|
if (!tok)
|
|
{
|
|
Log(L"[-] Failed to duplicate SYSTEM token for process creation");
|
|
return false;
|
|
}
|
|
|
|
EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME);
|
|
EnablePrivilege(SE_INCREASE_QUOTA_NAME);
|
|
|
|
if (interactive)
|
|
{
|
|
DWORD session = WTSGetActiveConsoleSessionId();
|
|
|
|
if (session != 0xFFFFFFFF)
|
|
{
|
|
if (!SetTokenInformation(tok, TokenSessionId, &session, sizeof(session)))
|
|
{
|
|
Log(L"[!] SetTokenInformation(TokenSessionId) failed: %lu", GetLastError());
|
|
}
|
|
}
|
|
}
|
|
|
|
LPVOID env = nullptr;
|
|
BOOL createdEnv = CreateEnvironmentBlock(&env, tok, FALSE);
|
|
|
|
STARTUPINFOW si{};
|
|
si.cb = sizeof(si);
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = interactive ? SW_SHOWDEFAULT : SW_HIDE;
|
|
|
|
if (interactive)
|
|
si.lpDesktop = const_cast<LPWSTR>(L"Winsta0\\Default");
|
|
|
|
std::wstring fullPath;
|
|
std::wstring cmd;
|
|
|
|
if (!BuildCommandLine(exePath, args, fullPath, cmd))
|
|
{
|
|
if (createdEnv)
|
|
DestroyEnvironmentBlock(env);
|
|
|
|
CloseHandle(tok);
|
|
return false;
|
|
}
|
|
|
|
PROCESS_INFORMATION pi{};
|
|
|
|
DWORD creationFlags = 0;
|
|
|
|
if (!interactive)
|
|
creationFlags |= CREATE_NO_WINDOW;
|
|
|
|
if (suspended)
|
|
creationFlags |= CREATE_SUSPENDED;
|
|
|
|
BOOL ok = CreateProcessAsUserW(
|
|
tok,
|
|
fullPath.c_str(),
|
|
cmd.data(),
|
|
nullptr,
|
|
nullptr,
|
|
FALSE,
|
|
creationFlags,
|
|
createdEnv ? env : nullptr,
|
|
nullptr,
|
|
&si,
|
|
&pi);
|
|
|
|
if (!ok)
|
|
{
|
|
Log(L"[-] CreateProcessAsUserW failed: %lu", GetLastError());
|
|
}
|
|
else
|
|
{
|
|
Log(L"[+] Created process: PID %lu", pi.dwProcessId);
|
|
|
|
if (out)
|
|
{
|
|
out->hProcess = pi.hProcess;
|
|
out->hThread = pi.hThread;
|
|
out->processId = pi.dwProcessId;
|
|
}
|
|
else
|
|
{
|
|
if (pi.hThread)
|
|
CloseHandle(pi.hThread);
|
|
|
|
if (pi.hProcess)
|
|
CloseHandle(pi.hProcess);
|
|
}
|
|
}
|
|
|
|
if (createdEnv)
|
|
DestroyEnvironmentBlock(env);
|
|
|
|
CloseHandle(tok);
|
|
|
|
return ok == TRUE;
|
|
}
|
|
|
|
bool StartProcessAsSystem(
|
|
HANDLE systemToken,
|
|
const wchar_t* exePath,
|
|
const wchar_t* args,
|
|
bool interactive)
|
|
{
|
|
return CreateProcessAsSystemImpl(systemToken, exePath, args, interactive, false, nullptr);
|
|
}
|
|
|
|
bool CreateProcessSuspendedAsSystem(
|
|
HANDLE systemToken,
|
|
const wchar_t* exePath,
|
|
const wchar_t* args,
|
|
bool interactive,
|
|
NewProcInfo* out)
|
|
{
|
|
return CreateProcessAsSystemImpl(systemToken, exePath, args, interactive, true, out);
|
|
}
|