mirror of
https://github.com/BeneficialCode/WinArk.git
synced 2026-10-28 11:46:32 +08:00
Run the WInArk under System account.
This commit is contained in:
@@ -3,6 +3,34 @@
|
||||
#include <sddl.h>
|
||||
#include <shellapi.h>
|
||||
#include "DriverHelper.h"
|
||||
#include <WtsApi32.h>
|
||||
#include <WinBase.h>
|
||||
|
||||
#pragma comment(lib,"wtsapi32")
|
||||
|
||||
bool SecurityHelper::IsSysRun() {
|
||||
static bool runningSystem = false;
|
||||
static bool runningSystemCheck = false;
|
||||
if (runningSystemCheck)
|
||||
return runningSystem;
|
||||
|
||||
runningSystemCheck = true;
|
||||
wil::unique_handle hToken;
|
||||
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, hToken.addressof()))
|
||||
return false;
|
||||
|
||||
BYTE buffer[128];
|
||||
DWORD len;
|
||||
if (::GetTokenInformation(hToken.get(), TokenUser, &buffer, sizeof(buffer), &len)) {
|
||||
auto user = reinterpret_cast<TOKEN_USER*>(buffer);
|
||||
runningSystem = IsSystemSid(user->User.Sid);
|
||||
}
|
||||
return runningSystem;
|
||||
}
|
||||
|
||||
bool SecurityHelper::IsSystemSid(PSID sid) {
|
||||
return ::IsWellKnownSid(sid, WinLocalSystemSid);
|
||||
}
|
||||
|
||||
bool SecurityHelper::IsRunningElevated() {
|
||||
static bool runningElevated = false;
|
||||
@@ -34,6 +62,7 @@ HICON SecurityHelper::GetShieldIcon() {
|
||||
bool SecurityHelper::RunElevated(PCWSTR param, bool ui) {
|
||||
WCHAR path[MAX_PATH];
|
||||
::GetModuleFileName(nullptr, path, _countof(path));
|
||||
|
||||
SHELLEXECUTEINFO shi = { sizeof(shi) };
|
||||
shi.lpFile = path;
|
||||
shi.nShow = SW_SHOWDEFAULT;
|
||||
@@ -52,6 +81,97 @@ bool SecurityHelper::RunElevated(PCWSTR param, bool ui) {
|
||||
return rc == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
// find first SYSTEM process with a good token to use
|
||||
HANDLE SecurityHelper::OpenSystemProcessToken() {
|
||||
PWTS_PROCESS_INFO pInfo;
|
||||
DWORD count;
|
||||
if (!::WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HANDLE hToken{};
|
||||
for (DWORD i = 0; i < count && !hToken; i++) {
|
||||
if (pInfo[i].SessionId == 0 && IsSystemSid(pInfo[i].pUserSid)
|
||||
&& !_wcsicmp(pInfo[i].pProcessName,L"services.exe")) {
|
||||
auto hProcess = DriverHelper::OpenProcess(pInfo[i].ProcessId, PROCESS_QUERY_INFORMATION);
|
||||
if (hProcess) {
|
||||
::OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY | TOKEN_IMPERSONATE, &hToken);
|
||||
::CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::WTSFreeMemory(pInfo);
|
||||
return hToken;
|
||||
}
|
||||
|
||||
bool SecurityHelper::SysRun(PCWSTR param) {
|
||||
auto hToken = OpenSystemProcessToken();
|
||||
if (!hToken)
|
||||
return false;
|
||||
|
||||
HANDLE hDupToken, hPrimary;
|
||||
::DuplicateTokenEx(hToken, TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_PRIVILEGES,
|
||||
nullptr, SecurityImpersonation, TokenImpersonation, &hDupToken);
|
||||
::DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, nullptr, SecurityImpersonation, TokenPrimary, &hPrimary);
|
||||
::CloseHandle(hToken);
|
||||
|
||||
if (hDupToken == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WCHAR path[MAX_PATH];
|
||||
::GetModuleFileName(nullptr, path, _countof(path));
|
||||
|
||||
STARTUPINFO si = { sizeof(si) };
|
||||
si.lpDesktop = const_cast<wchar_t*>(L"Winsta0\\default");
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
BOOL impersonated = ::SetThreadToken(nullptr, hDupToken);
|
||||
if (!impersonated)
|
||||
return false;
|
||||
|
||||
HANDLE hCurrentToken = INVALID_HANDLE_VALUE;
|
||||
DWORD session = 0, len = sizeof(session);
|
||||
bool ok = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &hCurrentToken);
|
||||
if (!ok)
|
||||
return false;
|
||||
::GetTokenInformation(hCurrentToken, TokenSessionId, &session, len, &len);
|
||||
::CloseHandle(hCurrentToken);
|
||||
|
||||
if (!SetPrivilege(hDupToken, SE_ASSIGNPRIMARYTOKEN_NAME, true) ||
|
||||
!SetPrivilege(hDupToken, SE_INCREASE_QUOTA_NAME, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring commandLine = path;
|
||||
commandLine += L" ";
|
||||
commandLine += param;
|
||||
|
||||
ok = ::SetTokenInformation(hPrimary, TokenSessionId, &session, sizeof(session));
|
||||
if (!::CreateProcessAsUser(hPrimary, nullptr,
|
||||
const_cast<wchar_t*>(commandLine.c_str()), nullptr, nullptr,
|
||||
FALSE, 0, nullptr, nullptr,
|
||||
&si, &pi)) {
|
||||
DWORD error = ::GetLastError();
|
||||
if (error == ERROR_PRIVILEGE_NOT_HELD) {
|
||||
if (!SetPrivilege(hDupToken, SE_IMPERSONATE_NAME, true))
|
||||
return false;
|
||||
if (!::CreateProcessWithTokenW(hPrimary, 0, nullptr,
|
||||
const_cast<wchar_t*>(commandLine.c_str()), 0, nullptr, nullptr,
|
||||
&si, &pi)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
::CloseHandle(hPrimary);
|
||||
::CloseHandle(hDupToken);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SecurityHelper::EnablePrivilege(PCWSTR privName, bool enable) {
|
||||
HANDLE hToken;
|
||||
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
|
||||
@@ -69,6 +189,31 @@ bool SecurityHelper::EnablePrivilege(PCWSTR privName, bool enable) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SecurityHelper::SetPrivilege(HANDLE hToken, PCWSTR privName, bool enable) {
|
||||
TOKEN_PRIVILEGES tp;
|
||||
LUID luid;
|
||||
|
||||
if (!::LookupPrivilegeValue(nullptr, privName, &luid))
|
||||
return false;
|
||||
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
if (enable)
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
else
|
||||
tp.Privileges[0].Attributes = 0;
|
||||
|
||||
// Enable the privilege or disable all privileges.
|
||||
if (!::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::GetLastError() == ERROR_NOT_ALL_ASSIGNED)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::wstring SecurityHelper::GetSidFromUser(PCWSTR name) {
|
||||
BYTE sid[SECURITY_MAX_SID_SIZE];
|
||||
DWORD size = sizeof(sid);
|
||||
|
||||
Reference in New Issue
Block a user