diff --git a/src/client/main.cpp b/src/client/main.cpp index 41365a72..0575b4f2 100644 --- a/src/client/main.cpp +++ b/src/client/main.cpp @@ -39,6 +39,47 @@ launcher::mode detect_mode_from_arguments() return launcher::mode::none; } +void apply_aslr_patch(std::string* data) +{ + // sp binary + if (data->size() != 0xE1E0C8) + { + throw std::runtime_error("File size mismatch, bad game files"); + } + + auto* dos_header = reinterpret_cast(&data->at(0)); + auto* nt_headers = reinterpret_cast(&data->at(dos_header->e_lfanew)); + auto* optional_header = &nt_headers->OptionalHeader; + + if (optional_header->DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) + { + optional_header->DllCharacteristics &= ~(IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE); + } +} + +void get_aslr_patched_binary(std::string* binary, std::string* data) +{ + const auto patched_binary = "h2_sp_patched.exe"s; + + try + { + apply_aslr_patch(data); + if (!utils::io::file_exists(patched_binary) && !utils::io::write_file(patched_binary, *data, false)) + { + throw std::runtime_error("Could not write file"); + } + } + catch (const std::exception& e) + { + throw std::runtime_error( + utils::string::va("Could not create aslr patched binary for %s! %s", + binary->data(), e.what()) + ); + } + + *binary = patched_binary; +} + FARPROC load_binary(const launcher::mode mode) { loader loader; @@ -62,21 +103,10 @@ FARPROC load_binary(const launcher::mode mode) return component_loader::load_import(library, function); }); - std::string binary; - switch (mode) + std::string binary = "MW2CR.exe"; + if (!utils::io::file_exists(binary)) { - case launcher::mode::singleplayer: - binary = "MW2CR.exe"; - - if (!utils::io::file_exists(binary)) - { - binary = "h2_sp64_bnet_ship.exe"; - } - - break; - case launcher::mode::none: - default: - throw std::runtime_error("Invalid game mode!"); + binary = "h2_sp64_bnet_ship.exe"; } std::string data; @@ -87,9 +117,13 @@ FARPROC load_binary(const launcher::mode mode) binary.data())); } +#ifdef INJECT_HOST_AS_LIB + get_aslr_patched_binary(&binary, &data); + return loader.load_library(binary); +#else return loader.load(self, data); +#endif } - void remove_crash_file() { utils::io::remove_file("__h2Exe"); diff --git a/src/client/std_include.cpp b/src/client/std_include.cpp index 773e1c19..069ec5d3 100644 --- a/src/client/std_include.cpp +++ b/src/client/std_include.cpp @@ -1,13 +1,30 @@ #include +#pragma comment(linker, "/stack:0x1000000") + +#ifdef INJECT_HOST_AS_LIB +#pragma comment(linker, "/base:0x160000000") +#else +#pragma comment(linker, "/base:0x140000000") #pragma comment(linker, "/merge:.data=.cld") #pragma comment(linker, "/merge:.rdata=.clr") #pragma comment(linker, "/merge:.cl=.main") #pragma comment(linker, "/merge:.text=.main") -#pragma comment(linker, "/stack:0x1000000") -#pragma comment(linker, "/base:0x140000000") +#endif + +#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language=''\"") + +#ifndef INJECT_HOST_AS_LIB #pragma bss_seg(".payload") char payload_data[BINARY_PAYLOAD_SIZE]; +extern "C" +{ + char* get_payload_data() + { + return &payload_data[0]; + } +} +#endif extern "C" { @@ -17,12 +34,6 @@ extern "C" extern "C" { - // workaround for release build removing 'payload_data' - char* dont_remove_this() - { - return payload_data; - } - int s_read_arc4random(void*, size_t) { return -1; diff --git a/src/client/std_include.hpp b/src/client/std_include.hpp index ceea3f14..e76e0d8d 100644 --- a/src/client/std_include.hpp +++ b/src/client/std_include.hpp @@ -1,6 +1,7 @@ #pragma once #define BINARY_PAYLOAD_SIZE 0x12000000 +#define INJECT_HOST_AS_LIB #pragma warning(push) #pragma warning(disable: 4100)