diff --git a/WinArk/MainFrame.cpp b/WinArk/MainFrame.cpp index 5bd790d..f0ae5b4 100644 --- a/WinArk/MainFrame.cpp +++ b/WinArk/MainFrame.cpp @@ -239,7 +239,11 @@ void CMainFrame::InitDriverInterface() { if (!DriverHelper::IsDriverLoaded()) { if (!SecurityHelper::IsRunningElevated()) { if (AtlMessageBox(nullptr, L"Kernel Driver not loaded. Some functionality will not be available. Install?", IDS_TITLE, MB_YESNO | MB_ICONQUESTION) == IDYES) { - if (!SecurityHelper::RunElevated(L"install", false)) { + if (SecurityHelper::IsSysRun()) { + if(!SecurityHelper::SysRun(L"install")) + AtlMessageBox(*this, L"Error running driver installer", IDS_TITLE, MB_ICONERROR); + } + else if (!SecurityHelper::RunElevated(L"install", false)) { AtlMessageBox(*this, L"Error running driver installer", IDS_TITLE, MB_ICONERROR); } } @@ -261,7 +265,12 @@ void CMainFrame::InitDriverInterface() { } else { DriverHelper::CloseDevice(); - SecurityHelper::RunElevated(L"update", false); + if (SecurityHelper::IsSysRun()) { + if (!SecurityHelper::SysRun(L"update")) + AtlMessageBox(*this, L"Error update driver service", IDS_TITLE, MB_ICONERROR); + } + else + SecurityHelper::RunElevated(L"update", false); } } } @@ -310,6 +319,12 @@ void CMainFrame::InitConfigView() { } LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { + if (SecurityHelper::EnablePrivilege(SE_DEBUG_NAME, true)) { + if (!SecurityHelper::IsSysRun()) { + if (SecurityHelper::SysRun(L"runas")) + SendMessage(WM_CLOSE); + } + } LoadSettings(); CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE); @@ -319,7 +334,11 @@ LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ hMenu.GetSubMenu(0).DeleteMenu(ID_FILE_RUNASADMIN, MF_BYCOMMAND); CString text; GetWindowText(text); - SetWindowText(text + L" (Administrator)"); + CString append = L" (Administrator)"; + if (SecurityHelper::IsSysRun()) { + append = L" (System)"; + } + SetWindowText(text + append); } UIAddMenu(hMenu); @@ -410,6 +429,7 @@ LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ pLoop->AddIdleHandler(this); InitDriverInterface(); + InitProcessTable(); InitNetworkTable(); InitKernelModuleTable(); diff --git a/WinArk/WinArk.cpp b/WinArk/WinArk.cpp index e99fc8e..6cf274f 100644 --- a/WinArk/WinArk.cpp +++ b/WinArk/WinArk.cpp @@ -15,6 +15,7 @@ #include #include "SymbolHelper.h" + CAppModule _Module; HWND _hMainWnd; AppSettings _Settings; @@ -215,10 +216,12 @@ LONG WINAPI SelfUnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { g_hSingleInstMutex = ::CreateMutex(nullptr, FALSE, L"WinArkSingleInstanceMutex"); - if (g_hSingleInstMutex) { - if (::GetLastError() == ERROR_ALREADY_EXISTS) { - MessageBox(nullptr, L"ÇëÎðÖØ¸´Æô¶¯!!!", L"Error", MB_ICONERROR); - return -1; + if (!::wcsstr(lpstrCmdLine, L"runas")) { + if (g_hSingleInstMutex) { + if (::GetLastError() == ERROR_ALREADY_EXISTS) { + MessageBox(nullptr, L"ÇëÎðÖØ¸´Æô¶¯!!!", L"Error", MB_ICONERROR); + return -1; + } } } HRESULT hRes = ::CoInitializeEx(nullptr,COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE); diff --git a/WinSysCore/SecurityHelper.cpp b/WinSysCore/SecurityHelper.cpp index 5dfe8fb..61f8fb6 100644 --- a/WinSysCore/SecurityHelper.cpp +++ b/WinSysCore/SecurityHelper.cpp @@ -3,6 +3,34 @@ #include #include #include "DriverHelper.h" +#include +#include + +#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(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(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(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(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); diff --git a/WinSysCore/SecurityHelper.h b/WinSysCore/SecurityHelper.h index c83bc84..374a6a4 100644 --- a/WinSysCore/SecurityHelper.h +++ b/WinSysCore/SecurityHelper.h @@ -1,10 +1,15 @@ #pragma once struct SecurityHelper final { + static bool IsSysRun(); static bool IsRunningElevated(); static HICON GetShieldIcon(); - static bool RunElevated(PCWSTR privName, bool enable); + static bool IsSystemSid(PSID sid); + static bool RunElevated(PCWSTR param, bool ui); + static bool SysRun(PCWSTR param); + static HANDLE OpenSystemProcessToken(); static bool EnablePrivilege(PCWSTR privName, bool enable); static std::wstring GetSidFromUser(PCWSTR name); static HANDLE DupHandle(HANDLE hSoruce, DWORD sourcePid, DWORD access = 0); + static bool SetPrivilege(HANDLE hToken, PCWSTR privName, bool enable); }; \ No newline at end of file