mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2026-06-19 23:20:57 +00:00
- IPC Uses PID to identify the process
- Exception code now shows in hex capitals - Fixed version checking and bumped the version support - Added process blacklist for already injected game detection - Used std::all_of instead of std::string::find for digit checks
This commit is contained in:
+3
-3
@@ -79,9 +79,9 @@ private: //variables
|
|||||||
std::string TargetBuild{"default"};
|
std::string TargetBuild{"default"};
|
||||||
static inline std::atomic<bool> Shutdown{false}, Exit{false};
|
static inline std::atomic<bool> Shutdown{false}, Exit{false};
|
||||||
std::string FullVersion{Version + ".99"};
|
std::string FullVersion{Version + ".99"};
|
||||||
VersionParser SupportedVersion{"0.24.1.2"};
|
VersionParser SupportedVersion{"0.25.4.0"};
|
||||||
IPC IPCToGame{"BeamMP_OUT", "BeamMP_Sem1", "BeamMP_Sem2", 0x1900000};
|
std::unique_ptr<IPC> IPCToGame{};
|
||||||
IPC IPCFromGame{"BeamMP_IN", "BeamMP_Sem3", "BeamMP_Sem4", 0x1900000};
|
std::unique_ptr<IPC> IPCFromGame{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShutdownException : public std::runtime_error {
|
class ShutdownException : public std::runtime_error {
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ private:
|
|||||||
static inline uint64_t DllBaseAddr;
|
static inline uint64_t DllBaseAddr;
|
||||||
static int lua_open_jit_D(lua_State* State);
|
static int lua_open_jit_D(lua_State* State);
|
||||||
static void RegisterGEFunctions();
|
static void RegisterGEFunctions();
|
||||||
static int GetTickCount_D(void* GEState, void* Param2, void* Param3, void* Param4);
|
// static int GetTickCount_D(void* GEState, void* Param2, void* Param3, void* Param4);
|
||||||
static void IPCListener();
|
static void IPCListener();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
class IPC {
|
class IPC {
|
||||||
public:
|
public:
|
||||||
IPC() = delete;
|
IPC() = default;
|
||||||
IPC(const char* MemID, const char* SemID, const char* SemID2, size_t Size) noexcept;
|
IPC(uint32_t ID, size_t Size) noexcept;
|
||||||
[[nodiscard]] size_t size() const noexcept;
|
[[nodiscard]] size_t size() const noexcept;
|
||||||
[[nodiscard]] char* c_str() const noexcept;
|
[[nodiscard]] char* c_str() const noexcept;
|
||||||
void send(const std::string& msg) noexcept;
|
void send(const std::string& msg) noexcept;
|
||||||
@@ -21,6 +21,7 @@ public:
|
|||||||
void try_receive() noexcept;
|
void try_receive() noexcept;
|
||||||
void receive() noexcept;
|
void receive() noexcept;
|
||||||
~IPC() noexcept;
|
~IPC() noexcept;
|
||||||
|
static bool mem_used(uint32_t MemID) noexcept;
|
||||||
private:
|
private:
|
||||||
void* SemConfHandle_;
|
void* SemConfHandle_;
|
||||||
void* MemoryHandle_;
|
void* MemoryHandle_;
|
||||||
|
|||||||
@@ -5,15 +5,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Memory{
|
class Memory{
|
||||||
public:
|
public:
|
||||||
static uint64_t FindPattern(const char* module, const char* Pattern[]);
|
static uint64_t FindPattern(const char* module, const char* Pattern[]);
|
||||||
|
static uint32_t GetBeamNGPID(const std::vector<uint32_t>& BL);
|
||||||
static uint64_t GetModuleBase(const char* Name);
|
static uint64_t GetModuleBase(const char* Name);
|
||||||
static void Print(const std::string& msg);
|
static void Print(const std::string& msg);
|
||||||
static void Inject(uint32_t PID);
|
static void Inject(uint32_t PID);
|
||||||
static uint32_t GetTickCount();
|
static uint32_t GetTickCount();
|
||||||
static uint32_t GetBeamNGPID();
|
|
||||||
static uint32_t EntryPoint();
|
static uint32_t EntryPoint();
|
||||||
static uint32_t GetPID();
|
static uint32_t GetPID();
|
||||||
};
|
};
|
||||||
|
|||||||
+34
-25
@@ -16,7 +16,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
LONG WINAPI CrashHandler(EXCEPTION_POINTERS* p) {
|
LONG WINAPI CrashHandler(EXCEPTION_POINTERS* p) {
|
||||||
LOG(ERROR) << "CAUGHT EXCEPTION! Code " << p->ExceptionRecord->ExceptionCode;
|
LOG(ERROR) << "CAUGHT EXCEPTION! Code 0x" << std::hex << std::uppercase << p->ExceptionRecord->ExceptionCode;
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,15 +85,11 @@ void Launcher::WindowsInit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::LaunchGame() {
|
void Launcher::LaunchGame() {
|
||||||
if(Memory::GetBeamNGPID() != 0) {
|
|
||||||
LOG(FATAL) << "Game is already running, please close it and try again!";
|
|
||||||
throw ShutdownException("Fatal Error");
|
|
||||||
}
|
|
||||||
VersionParser GameVersion(BeamVersion);
|
VersionParser GameVersion(BeamVersion);
|
||||||
if(GameVersion.data[0] > SupportedVersion.data[0]) {
|
if(GameVersion.data[1] > SupportedVersion.data[1]) {
|
||||||
LOG(FATAL) << "BeamNG V" << BeamVersion << " not yet supported, please wait until we update BeamMP!";
|
LOG(FATAL) << "BeamNG V" << BeamVersion << " not yet supported, please wait until we update BeamMP!";
|
||||||
throw ShutdownException("Fatal Error");
|
throw ShutdownException("Fatal Error");
|
||||||
} else if(GameVersion.data[0] < SupportedVersion.data[0]) {
|
} else if(GameVersion.data[1] < SupportedVersion.data[1]) {
|
||||||
LOG(FATAL) << "BeamNG V" << BeamVersion << " not supported, please update and launch the new update!";
|
LOG(FATAL) << "BeamNG V" << BeamVersion << " not supported, please update and launch the new update!";
|
||||||
throw ShutdownException("Fatal Error");
|
throw ShutdownException("Fatal Error");
|
||||||
} else if(GameVersion > SupportedVersion) {
|
} else if(GameVersion > SupportedVersion) {
|
||||||
@@ -101,27 +97,40 @@ void Launcher::LaunchGame() {
|
|||||||
} else if(GameVersion < SupportedVersion) {
|
} else if(GameVersion < SupportedVersion) {
|
||||||
LOG(WARNING) << "BeamNG V" << BeamVersion << " is slightly older than recommended, this might cause issues!";
|
LOG(WARNING) << "BeamNG V" << BeamVersion << " is slightly older than recommended, this might cause issues!";
|
||||||
}
|
}
|
||||||
|
if(Memory::GetBeamNGPID({}) == 0) {
|
||||||
ShellExecuteA(nullptr, nullptr, "steam://rungameid/284160", nullptr, nullptr, SW_SHOWNORMAL);
|
ShellExecuteA(nullptr, nullptr, "steam://rungameid/284160", nullptr, nullptr, SW_SHOWNORMAL);
|
||||||
//ShowWindow(GetConsoleWindow(), HIDE_WINDOW);
|
//ShowWindow(GetConsoleWindow(), HIDE_WINDOW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::WaitForGame() {
|
void Launcher::WaitForGame() {
|
||||||
LOG(INFO) << "Waiting for the game, please start BeamNG manually in case of steam issues";
|
LOG(INFO) << "Searching for a game process, please start BeamNG manually in case of steam issues";
|
||||||
do{
|
std::vector<uint32_t> BlackList;
|
||||||
GamePID = Memory::GetBeamNGPID();
|
do {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
auto PID = Memory::GetBeamNGPID(BlackList);
|
||||||
}while(GamePID == 0 && !Shutdown.load());
|
if(PID != 0 && IPC::mem_used(PID)) {
|
||||||
|
BlackList.emplace_back(PID);
|
||||||
|
} else {
|
||||||
|
GamePID = PID;
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
} while(GamePID == 0 && !Shutdown.load());
|
||||||
if(Shutdown.load())return;
|
if(Shutdown.load())return;
|
||||||
|
|
||||||
if(GamePID == 0) {
|
if(GamePID == 0) {
|
||||||
LOG(FATAL) << "Game process not found! aborting";
|
LOG(FATAL) << "Game process not found! aborting";
|
||||||
throw ShutdownException("Fatal Error");
|
throw ShutdownException("Fatal Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(INFO) << "Game found! PID " << GamePID;
|
LOG(INFO) << "Game found! PID " << GamePID;
|
||||||
|
|
||||||
|
IPCToGame = std::make_unique<IPC>(GamePID, 0x1900000);
|
||||||
|
IPCFromGame = std::make_unique<IPC>(GamePID+1, 0x1900000);
|
||||||
|
|
||||||
IPCSystem = std::thread(&Launcher::ListenIPC, this);
|
IPCSystem = std::thread(&Launcher::ListenIPC, this);
|
||||||
Memory::Inject(GamePID);
|
Memory::Inject(GamePID);
|
||||||
setDiscordMessage("In menus");
|
setDiscordMessage("In menus");
|
||||||
while(!Shutdown.load() && Memory::GetBeamNGPID() != 0) {
|
while(!Shutdown.load() && Memory::GetBeamNGPID(BlackList) != 0) {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Game process was lost";
|
LOG(INFO) << "Game process was lost";
|
||||||
@@ -130,15 +139,15 @@ void Launcher::WaitForGame() {
|
|||||||
|
|
||||||
void Launcher::ListenIPC() {
|
void Launcher::ListenIPC() {
|
||||||
while(!Shutdown.load()) {
|
while(!Shutdown.load()) {
|
||||||
IPCFromGame.receive();
|
IPCFromGame->receive();
|
||||||
if(!IPCFromGame.receive_timed_out()) {
|
if(!IPCFromGame->receive_timed_out()) {
|
||||||
auto& MSG = IPCFromGame.msg();
|
auto& MSG = IPCFromGame->msg();
|
||||||
if(MSG[0] == 'C') {
|
if(MSG[0] == 'C') {
|
||||||
HandleIPC(IPCFromGame.msg().substr(1));
|
HandleIPC(IPCFromGame->msg().substr(1));
|
||||||
} else {
|
} else {
|
||||||
ServerHandler.ServerSend(IPCFromGame.msg().substr(1), false);
|
ServerHandler.ServerSend(IPCFromGame->msg().substr(1), false);
|
||||||
}
|
}
|
||||||
IPCFromGame.confirm_receive();
|
IPCFromGame->confirm_receive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,9 +155,9 @@ void Launcher::ListenIPC() {
|
|||||||
void Launcher::SendIPC(const std::string& Data, bool core) {
|
void Launcher::SendIPC(const std::string& Data, bool core) {
|
||||||
static std::mutex Lock;
|
static std::mutex Lock;
|
||||||
std::scoped_lock Guard(Lock);
|
std::scoped_lock Guard(Lock);
|
||||||
if(core)IPCToGame.send("C" + Data);
|
if(core)IPCToGame->send("C" + Data);
|
||||||
else IPCToGame.send("G" + Data);
|
else IPCToGame->send("G" + Data);
|
||||||
if(IPCToGame.send_timed_out()) {
|
if(IPCToGame->send_timed_out()) {
|
||||||
LOG(WARNING) << "Timed out while sending \"" << Data << "\"";
|
LOG(WARNING) << "Timed out while sending \"" << Data << "\"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,8 @@
|
|||||||
#include "Memory/BeamNG.h"
|
#include "Memory/BeamNG.h"
|
||||||
#include "Memory/Memory.h"
|
#include "Memory/Memory.h"
|
||||||
|
|
||||||
//atomic_queue::AtomicQueue2<std::string, 1000> AtomicQueue;
|
|
||||||
std::unique_ptr<atomic_queue<std::string, 1000>> Queue;
|
std::unique_ptr<atomic_queue<std::string, 1000>> Queue;
|
||||||
|
|
||||||
|
|
||||||
int BeamNG::lua_open_jit_D(lua_State* State) {
|
int BeamNG::lua_open_jit_D(lua_State* State) {
|
||||||
Memory::Print("Got lua State");
|
Memory::Print("Got lua State");
|
||||||
GELua::State = State;
|
GELua::State = State;
|
||||||
@@ -21,16 +19,17 @@ int BeamNG::lua_open_jit_D(lua_State* State) {
|
|||||||
|
|
||||||
void BeamNG::EntryPoint() {
|
void BeamNG::EntryPoint() {
|
||||||
Queue = std::make_unique<atomic_queue<std::string, 1000>>();
|
Queue = std::make_unique<atomic_queue<std::string, 1000>>();
|
||||||
|
uint32_t PID = Memory::GetPID();
|
||||||
auto status = MH_Initialize();
|
auto status = MH_Initialize();
|
||||||
if(status != MH_OK)Memory::Print(std::string("MH Error -> ") + MH_StatusToString(status));
|
if(status != MH_OK)Memory::Print(std::string("MH Error -> ") + MH_StatusToString(status));
|
||||||
Memory::Print("PID : " + std::to_string(Memory::GetPID()));
|
Memory::Print("PID : " + std::to_string(PID));
|
||||||
GELua::FindAddresses();
|
GELua::FindAddresses();
|
||||||
/*GameBaseAddr = Memory::GetModuleBase(GameModule);
|
/*GameBaseAddr = Memory::GetModuleBase(GameModule);
|
||||||
DllBaseAddr = Memory::GetModuleBase(DllModule);*/
|
DllBaseAddr = Memory::GetModuleBase(DllModule);*/
|
||||||
OpenJITDetour = std::make_unique<Hook<def::lua_open_jit>>(GELua::lua_open_jit, lua_open_jit_D);
|
OpenJITDetour = std::make_unique<Hook<def::lua_open_jit>>(GELua::lua_open_jit, lua_open_jit_D);
|
||||||
OpenJITDetour->Enable();
|
OpenJITDetour->Enable();
|
||||||
IPCToLauncher = std::make_unique<IPC>("BeamMP_IN", "BeamMP_Sem3", "BeamMP_Sem4", 0x1900000);
|
IPCFromLauncher = std::make_unique<IPC>(PID, 0x1900000);
|
||||||
IPCFromLauncher = std::make_unique<IPC>("BeamMP_OUT", "BeamMP_Sem1", "BeamMP_Sem2", 0x1900000);
|
IPCToLauncher = std::make_unique<IPC>(PID+1, 0x1900000);
|
||||||
IPCListener();
|
IPCListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-7
@@ -7,18 +7,22 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "Memory/IPC.h"
|
#include "Memory/IPC.h"
|
||||||
|
|
||||||
IPC::IPC(const char* MemID, const char* SemID, const char* SemID2, size_t Size) noexcept : Size_(Size) {
|
IPC::IPC(uint32_t ID, size_t Size) noexcept : Size_(Size) {
|
||||||
SemHandle_ = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, SemID);
|
std::string Sem{"MP_S" + std::to_string(ID)},
|
||||||
|
SemConf{"MP_SC" + std::to_string(ID)},
|
||||||
|
Mem{"MP_IO" + std::to_string(ID)};
|
||||||
|
|
||||||
|
SemHandle_ = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, Sem.c_str());
|
||||||
if(SemHandle_ == nullptr) {
|
if(SemHandle_ == nullptr) {
|
||||||
SemHandle_ = CreateSemaphoreA(nullptr, 0, 1, SemID);
|
SemHandle_ = CreateSemaphoreA(nullptr, 0, 1, Sem.c_str());
|
||||||
}
|
}
|
||||||
SemConfHandle_ = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, SemID2);
|
SemConfHandle_ = OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE, SemConf.c_str());
|
||||||
if(SemConfHandle_ == nullptr) {
|
if(SemConfHandle_ == nullptr) {
|
||||||
SemConfHandle_ = CreateSemaphoreA(nullptr, 0, 1, SemID2);
|
SemConfHandle_ = CreateSemaphoreA(nullptr, 0, 1, SemConf.c_str());
|
||||||
}
|
}
|
||||||
MemoryHandle_ = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, MemID);
|
MemoryHandle_ = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, Mem.c_str());
|
||||||
if(MemoryHandle_ == nullptr) {
|
if(MemoryHandle_ == nullptr) {
|
||||||
MemoryHandle_ = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, DWORD(Size), MemID);
|
MemoryHandle_ = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, DWORD(Size), Mem.c_str());
|
||||||
}
|
}
|
||||||
Data_ = (char*)MapViewOfFile(MemoryHandle_, FILE_MAP_ALL_ACCESS, 0, 0, Size);
|
Data_ = (char*)MapViewOfFile(MemoryHandle_, FILE_MAP_ALL_ACCESS, 0, 0, Size);
|
||||||
}
|
}
|
||||||
@@ -77,4 +81,12 @@ IPC::~IPC() noexcept {
|
|||||||
CloseHandle(MemoryHandle_);
|
CloseHandle(MemoryHandle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IPC::mem_used(uint32_t MemID) noexcept {
|
||||||
|
std::string Mem{"MP_IO" + std::to_string(MemID)};
|
||||||
|
HANDLE MEM = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, Mem.c_str());
|
||||||
|
bool used = MEM != nullptr;
|
||||||
|
UnmapViewOfFile(MEM);
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
|
|
||||||
|
uint32_t Memory::GetBeamNGPID(const std::vector<uint32_t>& BL) {
|
||||||
uint32_t Memory::GetBeamNGPID() {
|
|
||||||
SetLastError(0);
|
SetLastError(0);
|
||||||
PROCESSENTRY32 pe32;
|
PROCESSENTRY32 pe32;
|
||||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||||
@@ -20,7 +19,11 @@ uint32_t Memory::GetBeamNGPID() {
|
|||||||
|
|
||||||
if(Process32First(Snapshot, &pe32)) {
|
if(Process32First(Snapshot, &pe32)) {
|
||||||
do{
|
do{
|
||||||
if(std::string("BeamNG.drive.x64.exe") == pe32.szExeFile)break;
|
if(std::string("BeamNG.drive.x64.exe") == pe32.szExeFile &&
|
||||||
|
std::find(BL.begin(), BL.end(), pe32.th32ProcessID) == BL.end() &&
|
||||||
|
std::find(BL.begin(), BL.end(), pe32.th32ParentProcessID) == BL.end()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}while(Process32Next(Snapshot, &pe32));
|
}while(Process32Next(Snapshot, &pe32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ std::string Server::Auth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Res = Res.substr(1);
|
Res = Res.substr(1);
|
||||||
if(Res.find_first_not_of("0123456789") == std::string::npos){
|
if(std::all_of(Res.begin(), Res.end(), isdigit)){
|
||||||
ClientID = std::stoi(Res);
|
ClientID = std::stoi(Res);
|
||||||
}else{
|
}else{
|
||||||
Abort();
|
Abort();
|
||||||
@@ -253,7 +253,7 @@ void Server::SyncResources() {
|
|||||||
} else continue;
|
} else continue;
|
||||||
Pos++;
|
Pos++;
|
||||||
if (fs::exists(a)) {
|
if (fs::exists(a)) {
|
||||||
if (FS->find_first_not_of("0123456789") != std::string::npos)continue;
|
if (!std::all_of(FS->begin(), FS->end(), isdigit))continue;
|
||||||
if (fs::file_size(a) == std::stoull(*FS)){
|
if (fs::file_size(a) == std::stoull(*FS)){
|
||||||
UpdateUl(false,std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + a.substr(a.find_last_of('/')));
|
UpdateUl(false,std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + a.substr(a.find_last_of('/')));
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
|||||||
Reference in New Issue
Block a user