EFTCheatPVE/operator/system/ServiceManager.h
2025-12-10 23:07:02 +08:00

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;
}
}