174 lines
No EOL
5.3 KiB
C++
174 lines
No EOL
5.3 KiB
C++
// system/ServiceManager.h
|
|
#pragma once
|
|
|
|
#ifdef CURRENT_MODULE
|
|
#undef CURRENT_MODULE
|
|
#endif
|
|
#define CURRENT_MODULE "ServiceManager"
|
|
|
|
#include "core/Logger.h"
|
|
#include <windows.h>
|
|
#include <string>
|
|
|
|
namespace ServiceManager
|
|
{
|
|
struct ServiceHandleCloser { void operator()(SC_HANDLE h) const noexcept { if (h) CloseServiceHandle(h); } };
|
|
using UniqueServiceHandle = std::unique_ptr<std::remove_pointer<SC_HANDLE>::type, ServiceHandleCloser>;
|
|
|
|
inline bool WaitUntilGone(SC_HANDLE scm, const std::wstring& name, DWORD timeoutMs = 30000)
|
|
{
|
|
const DWORD step = 2000;
|
|
DWORD elapsed = 0;
|
|
|
|
LOG_I("Waiting for service deletion: " + std::string(name.begin(), name.end()));
|
|
|
|
while (elapsed < timeoutMs)
|
|
{
|
|
elapsed += step;
|
|
Sleep(step);
|
|
|
|
system("sc query BEService >nul 2>&1");
|
|
|
|
UniqueServiceHandle hSvc{ OpenServiceW(scm, name.c_str(), SERVICE_QUERY_STATUS) };
|
|
if (hSvc)
|
|
{
|
|
CloseServiceHandle(hSvc.get());
|
|
continue;
|
|
}
|
|
|
|
if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
|
|
{
|
|
CloseServiceHandle(hSvc.get());
|
|
LOG_I("Service fully deleted from SCM");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
LOG_W("Timeout waiting for service deletion (ERROR 1072 may occur)");
|
|
return false;
|
|
}
|
|
|
|
inline bool StopService(SC_HANDLE hSvc)
|
|
{
|
|
SERVICE_STATUS status{};
|
|
if (!ControlService(hSvc, SERVICE_CONTROL_STOP, &status))
|
|
return false;
|
|
|
|
LOG_I("Sent stop command to service");
|
|
|
|
for (int i = 0; i < 40; ++i)
|
|
{
|
|
Sleep(300);
|
|
if (!QueryServiceStatus(hSvc, &status))
|
|
return false;
|
|
if (status.dwCurrentState == SERVICE_STOPPED)
|
|
return true;
|
|
}
|
|
|
|
LOG_W("Service did not stop in time");
|
|
return false;
|
|
}
|
|
|
|
inline bool Remove(const std::wstring& serviceName)
|
|
{
|
|
UniqueServiceHandle scm{ OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT) };
|
|
if (!scm)
|
|
{
|
|
LOG_E("OpenSCManager failed: " + std::to_string(GetLastError()));
|
|
return false;
|
|
}
|
|
|
|
UniqueServiceHandle hSvc{ OpenServiceW(scm.get(), serviceName.c_str(),
|
|
SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE) };
|
|
|
|
if (!hSvc)
|
|
{
|
|
if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
|
|
{
|
|
LOG_I("Service does not exist, nothing to delete");
|
|
return true;
|
|
}
|
|
|
|
LOG_E("OpenService failed: " + std::to_string(GetLastError()));
|
|
return false;
|
|
}
|
|
|
|
system("taskkill /f /im service.exe >nul 2>&1");
|
|
|
|
StopService(hSvc.get());
|
|
|
|
if (DeleteService(hSvc.get()))
|
|
{
|
|
LOG_I("DeleteService command sent");
|
|
CloseServiceHandle(hSvc.get());
|
|
return WaitUntilGone(scm.get(), serviceName);
|
|
}
|
|
|
|
DWORD err = GetLastError();
|
|
if (err != ERROR_SERVICE_MARKED_FOR_DELETE)
|
|
{
|
|
LOG_E("DeleteService failed: " + std::to_string(err));
|
|
return false;
|
|
}
|
|
LOG_I("Service already marked for delete");
|
|
}
|
|
|
|
inline bool DeployFakeBEService(const std::wstring& fakeExePath)
|
|
{
|
|
UniqueServiceHandle scm{ OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE) };
|
|
if (!scm)
|
|
{
|
|
LOG_E("OpenSCManager(create) failed: " + std::to_string(GetLastError()));
|
|
return false;
|
|
}
|
|
|
|
// Just create and start the service
|
|
UniqueServiceHandle hSvc{ CreateServiceW(
|
|
scm.get(), L"BEService", L"BattlEye Service",
|
|
SERVICE_START | SERVICE_QUERY_STATUS,
|
|
SERVICE_WIN32_OWN_PROCESS,
|
|
SERVICE_AUTO_START,
|
|
SERVICE_ERROR_NORMAL,
|
|
fakeExePath.c_str(),
|
|
nullptr, nullptr, nullptr, nullptr, nullptr) };
|
|
|
|
if (hSvc)
|
|
return StartServiceW(hSvc.get(), 0, nullptr) ||
|
|
GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
|
|
|
|
// if failed to create the service, delete the service by force and then create
|
|
DWORD err = GetLastError();
|
|
if (err != ERROR_SERVICE_EXISTS && err != ERROR_SERVICE_MARKED_FOR_DELETE)
|
|
{
|
|
LOG_E("CreateService failed: " + std::to_string(err));
|
|
return false;
|
|
}
|
|
|
|
LOG_W("Service conflict detected, forcing cleanup...");
|
|
if (!Remove(L"BEService"))
|
|
return false;
|
|
|
|
// retry
|
|
hSvc.reset(CreateServiceW(scm.get(), L"BEService", L"BattlEye Service",
|
|
SERVICE_START | SERVICE_QUERY_STATUS,
|
|
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
|
|
SERVICE_ERROR_NORMAL, fakeExePath.c_str(),
|
|
nullptr, nullptr, nullptr, nullptr, nullptr));
|
|
|
|
if (!hSvc)
|
|
{
|
|
LOG_E("Retry CreateService failed: " + std::to_string(GetLastError()));
|
|
return false;
|
|
}
|
|
|
|
bool started = StartServiceW(hSvc.get(), 0, nullptr);
|
|
if (!started && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
|
|
{
|
|
LOG_W("StartService failed: " + std::to_string(GetLastError()));
|
|
return false;
|
|
}
|
|
|
|
LOG_I("Fake BEService is running");
|
|
return true;
|
|
}
|
|
} |