From b3841d855e666c1409a0cab2082eff92ab99422e Mon Sep 17 00:00:00 2001 From: Future Date: Sat, 20 Apr 2024 10:30:44 +0200 Subject: [PATCH] feat: compile project with clang (with vs on Windows) --- premake5.lua | 13 +- src/client/component/command.cpp | 2 +- src/client/component/console.cpp | 2 +- src/client/component/dvar_patches.cpp | 10 +- src/client/component/exploit.cpp | 15 +- src/client/component/key_catcher.cpp | 4 +- src/client/component/network/network.cpp | 10 +- src/client/component/patches.cpp | 4 +- src/client/component/remove_hooks.cpp | 8 +- src/client/component/scheduler.cpp | 17 +- src/client/game/game.cpp | 5 +- src/common/utils/hook.hpp | 2 + src/common/utils/nt.cpp | 8 - src/common/utils/nt.hpp | 32 +--- src/common/utils/signature.cpp | 191 ----------------------- src/common/utils/signature.hpp | 62 -------- 16 files changed, 58 insertions(+), 327 deletions(-) delete mode 100644 src/common/utils/signature.cpp delete mode 100644 src/common/utils/signature.hpp diff --git a/premake5.lua b/premake5.lua index ba4c670..92676a5 100644 --- a/premake5.lua +++ b/premake5.lua @@ -61,8 +61,15 @@ filter "configurations:release" optimize "Size" defines {"NDEBUG"} flags {"FatalCompileWarnings"} - buildoptions {"/GL"} - linkoptions {"/IGNORE:4702", "/LTCG"} + + filter "action:msc" + buildoptions "/GL" + linkoptions {"/IGNORE:4702", "/LTCG"} + filter {} + + filter "toolset:not msc*" + buildoptions "-Wno-unused-parameter" + filter {} filter {} filter "configurations:debug" @@ -91,8 +98,6 @@ targetname "mw3-server-freezer" pchheader "std_include.hpp" pchsource "src/client/std_include.cpp" -linkoptions {"/PDBCompress"} - files {"./src/client/**.hpp", "./src/client/**.cpp"} includedirs {"./src/client", "./src/common", "%{prj.location}/src"} diff --git a/src/client/component/command.cpp b/src/client/component/command.cpp index 47c376f..f3d9a72 100644 --- a/src/client/component/command.cpp +++ b/src/client/component/command.cpp @@ -6,7 +6,7 @@ #include "command.hpp" #include "console.hpp" -constexpr auto CMD_MAX_NESTING = 8; +[[maybe_unused]] constexpr auto CMD_MAX_NESTING = 8; namespace command { std::unordered_map> handlers; diff --git a/src/client/component/console.cpp b/src/client/component/console.cpp index dbbcc31..8a5dfaf 100644 --- a/src/client/component/console.cpp +++ b/src/client/component/console.cpp @@ -42,7 +42,7 @@ public: } void post_unpack() override { - utils::hook(0x446930, append_text, HOOK_JUMP).install()->quick(); + utils::hook(0x446930, HOOK_CAST(append_text), HOOK_JUMP).install()->quick(); this->initialize(); } diff --git a/src/client/component/dvar_patches.cpp b/src/client/component/dvar_patches.cpp index 8e8dc89..9450633 100644 --- a/src/client/component/dvar_patches.cpp +++ b/src/client/component/dvar_patches.cpp @@ -20,13 +20,15 @@ void dvar_override_cheat_protection_stub(bool /*cheat_override*/) { class component final : public component_interface { public: void post_unpack() override { - utils::hook(0x59C0EF, dvar_set_from_string_by_name_stub, HOOK_CALL) - .install() + utils::hook(0x59C0EF, HOOK_CAST(dvar_set_from_string_by_name_stub), + HOOK_CALL) + .install() // hook* ->quick(); *game::isCheatOverride = true; - utils::hook(0x482CC0, dvar_override_cheat_protection_stub, HOOK_JUMP) - .install() + utils::hook(0x482CC0, HOOK_CAST(dvar_override_cheat_protection_stub), + HOOK_JUMP) + .install() // hook* ->quick(); // Remove read/write protection diff --git a/src/client/component/exploit.cpp b/src/client/component/exploit.cpp index 28f0a93..1872e52 100644 --- a/src/client/component/exploit.cpp +++ b/src/client/component/exploit.cpp @@ -24,9 +24,10 @@ game::dvar_t* cl_exploit; * On the server side the msg_t structure processed as follows: * The first 4 bytes are read but not processed (offset 0) * The following 2 bytes are read but not processed (offset 4) - * The following 1 byte is read and corresponds to the client_t.serverId (offset 6) - * The following 4 bytes are read and correspond to the client_t.messageAcknowledge (offset 7) - * The following 4 bytes are read and correspond to the client_t.reliableAcknowledge (offset 11) + * The following 1 byte is read and corresponds to the client_t.serverId (offset + * 6) The following 4 bytes are read and correspond to the + * client_t.messageAcknowledge (offset 7) The following 4 bytes are read and + * correspond to the client_t.reliableAcknowledge (offset 11) */ /** @@ -80,8 +81,12 @@ public: add_exploit_commands(); add_key_hooks(); - utils::hook(0x420B76, write_message_sequence, HOOK_CALL).install()->quick(); - utils::hook(0x420B86, write_command_sequence, HOOK_CALL).install()->quick(); + utils::hook(0x420B76, HOOK_CAST(write_message_sequence), HOOK_CALL) + .install() // hook* + ->quick(); + utils::hook(0x420B86, HOOK_CAST(write_command_sequence), HOOK_CALL) + .install() // hook* + ->quick(); } private: diff --git a/src/client/component/key_catcher.cpp b/src/client/component/key_catcher.cpp index 8468958..add217d 100644 --- a/src/client/component/key_catcher.cpp +++ b/src/client/component/key_catcher.cpp @@ -41,7 +41,9 @@ void cl_key_event_stub(game::LocalClientNum_t local_client, int key_id, class component final : public component_interface { public: void post_unpack() override { - utils::hook(0x53CC70, cl_key_event_stub, HOOK_CALL).install()->quick(); + utils::hook(0x53CC70, HOOK_CAST(cl_key_event_stub), HOOK_CALL) + .install() // hook* + ->quick(); } }; } // namespace key_catcher diff --git a/src/client/component/network/network.cpp b/src/client/component/network/network.cpp index 25c7bcd..6252099 100644 --- a/src/client/component/network/network.cpp +++ b/src/client/component/network/network.cpp @@ -102,17 +102,13 @@ public: void post_unpack() override { add_network_commands(); - utils::hook(0x5B27E1, packet_interception_handler, HOOK_CALL) - .install() + utils::hook(0x5B27E1, HOOK_CAST(packet_interception_handler), HOOK_CALL) + .install() // hook* ->quick(); } private: - static void add_network_commands() { - on_packet("naughty_reply", [](const game::netadr_s&, const std::string&) { - utils::nt::raise_hard_exception(); - }); - } + static void add_network_commands() {} }; } // namespace network diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index 0a142a9..6e0f38e 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -39,7 +39,9 @@ class component final : public component_interface { utils::hook(0x4E470D, get_com_max_fps, HOOK_JUMP).install()->quick(); utils::hook::nop(0x4E4712, 4); - utils::hook(0x6EA960, bd_log_message_stub, HOOK_JUMP).install()->quick(); + utils::hook(0x6EA960, HOOK_CAST(bd_log_message_stub), HOOK_JUMP) + .install() // hook* + ->quick(); // Another meme static const auto* my_cg_fov = game::Dvar_RegisterFloat( diff --git a/src/client/component/remove_hooks.cpp b/src/client/component/remove_hooks.cpp index dc30ec9..d5488cc 100644 --- a/src/client/component/remove_hooks.cpp +++ b/src/client/component/remove_hooks.cpp @@ -45,11 +45,11 @@ public: void post_start() override { remove_tekno_hooks(); } void post_unpack() override { - utils::hook(0x4E3D42, msg_read_bits_compress_check_sv, HOOK_CALL) - .install() + utils::hook(0x4E3D42, HOOK_CAST(msg_read_bits_compress_check_sv), HOOK_CALL) + .install() // hook* ->quick(); - utils::hook(0x4A9F56, msg_read_bits_compress_check_cl, HOOK_CALL) - .install() + utils::hook(0x4A9F56, HOOK_CAST(msg_read_bits_compress_check_cl), HOOK_CALL) + .install() // hook* ->quick(); } diff --git a/src/client/component/scheduler.cpp b/src/client/component/scheduler.cpp index bdc3c41..0e385e6 100644 --- a/src/client/component/scheduler.cpp +++ b/src/client/component/scheduler.cpp @@ -20,9 +20,8 @@ using task_list = std::vector; class task_pipeline { public: void add(task&& task) { - new_callbacks_.access([&task, this](task_list& tasks) { - tasks.emplace_back(std::move(task)); - }); + new_callbacks_.access( + [&task](task_list& tasks) { tasks.emplace_back(std::move(task)); }); } void clear() { @@ -143,9 +142,15 @@ public: } }); - utils::hook(0x4E4A0D, cl_frame_stub, HOOK_CALL).install()->quick(); - utils::hook(0x5B54D2, r_end_frame_stub, HOOK_CALL).install()->quick(); - utils::hook(0x543B0E, main_frame_stub, HOOK_CALL).install()->quick(); + utils::hook(0x4E4A0D, HOOK_CAST(cl_frame_stub), HOOK_CALL) + .install() + ->quick(); + utils::hook(0x5B54D2, HOOK_CAST(r_end_frame_stub), HOOK_CALL) + .install() // hook* + ->quick(); + utils::hook(0x543B0E, HOOK_CAST(main_frame_stub), HOOK_CALL) + .install() // hook* + ->quick(); } void pre_destroy() override { diff --git a/src/client/game/game.cpp b/src/client/game/game.cpp index 5901396..425bb8c 100644 --- a/src/client/game/game.cpp +++ b/src/client/game/game.cpp @@ -5,10 +5,9 @@ ScreenPlacement* ScrPlace_GetUnsafeFullPlacement() { return scrPlaceFullUnsafe; } +static DWORD Dvar_SetVariant_t = 0x649170; void __declspec(naked) Dvar_SetVariant(dvar_t* /*dvar*/, DvarValue /*value*/, DvarSetSource /*source*/) { - static DWORD func = 0x649170; - __asm { pushad @@ -18,7 +17,7 @@ void __declspec(naked) Dvar_SetVariant(dvar_t* /*dvar*/, DvarValue /*value*/, push [esp + 0x20 + 0x18] // value push [esp + 0x20 + 0x18] // value push [esp + 0x20 + 0x18] // value - call func + call Dvar_SetVariant_t add esp, 0x14 popad diff --git a/src/common/utils/hook.hpp b/src/common/utils/hook.hpp index 39ccc9b..bc09916 100644 --- a/src/common/utils/hook.hpp +++ b/src/common/utils/hook.hpp @@ -5,6 +5,8 @@ #define HOOK_JUMP true #define HOOK_CALL false +#define HOOK_CAST(f) reinterpret_cast(f) + namespace utils { class hook final { public: diff --git a/src/common/utils/nt.cpp b/src/common/utils/nt.cpp index da93ba8..43b8904 100644 --- a/src/common/utils/nt.cpp +++ b/src/common/utils/nt.cpp @@ -191,14 +191,6 @@ void** library::get_iat_entry(const std::string& module_name, return nullptr; } -void raise_hard_exception() { - int data = false; - const library ntdll("ntdll.dll"); - ntdll.invoke_pascal("RtlAdjustPrivilege", 19, true, false, &data); - ntdll.invoke_pascal("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr, - 6, &data); -} - std::string load_resource(const int id) { auto* const res = FindResource(library(), MAKEINTRESOURCE(id), RT_RCDATA); if (!res) diff --git a/src/common/utils/nt.hpp b/src/common/utils/nt.hpp index 5cfd331..f629a62 100644 --- a/src/common/utils/nt.hpp +++ b/src/common/utils/nt.hpp @@ -50,39 +50,14 @@ public: template T get_proc(const std::string& process) const { if (!this->is_valid()) - T{}; + return T{}; return reinterpret_cast(GetProcAddress(this->module_, process.data())); } template std::function get(const std::string& process) const { if (!this->is_valid()) return std::function(); - return static_cast(this->get_proc(process)); - } - - template - T invoke(const std::string& process, Args... args) const { - auto method = this->get(process); - if (method) - return method(args...); - return T(); - } - - template - T invoke_pascal(const std::string& process, Args... args) const { - auto method = this->get(process); - if (method) - return method(args...); - return T(); - } - - template - T invoke_this(const std::string& process, void* this_ptr, - Args... args) const { - auto method = this->get(this_ptr, process); - if (method) - return method(args...); - return T(); + return reinterpret_cast(this->get_proc(process)); } std::vector get_section_headers() const; @@ -98,9 +73,8 @@ private: HMODULE module_; }; -__declspec(noreturn) void raise_hard_exception(); std::string load_resource(int id); void relaunch_self(); -__declspec(noreturn) void terminate(uint32_t code = 0); +void terminate(uint32_t code = 0); } // namespace utils::nt diff --git a/src/common/utils/signature.cpp b/src/common/utils/signature.cpp deleted file mode 100644 index 601a723..0000000 --- a/src/common/utils/signature.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "signature.hpp" -#include -#include - -#include - -namespace utils::hook { -void signature::load_pattern(const std::string& pattern) { - this->mask_.clear(); - this->pattern_.clear(); - - uint8_t nibble = 0; - auto has_nibble = false; - - for (auto val : pattern) { - if (val == ' ') - continue; - if (val == '?') { - this->mask_.push_back(val); - this->pattern_.push_back(0); - } else { - if ((val < '0' || val > '9') && (val < 'A' || val > 'F') && - (val < 'a' || val > 'f')) { - throw std::runtime_error("Invalid pattern"); - } - - char str[] = {val, 0}; - const auto current_nibble = - static_cast(strtol(str, nullptr, 16)); - - if (!has_nibble) { - has_nibble = true; - nibble = current_nibble; - } else { - has_nibble = false; - const uint8_t byte = current_nibble | (nibble << 4); - - this->mask_.push_back('x'); - this->pattern_.push_back(byte); - } - } - } - - while (!this->mask_.empty() && this->mask_.back() == '?') { - this->mask_.pop_back(); - this->pattern_.pop_back(); - } - - if (this->has_sse_support()) { - while (this->pattern_.size() < 16) { - this->pattern_.push_back(0); - } - } - - if (has_nibble) { - throw std::runtime_error("Invalid pattern"); - } -} - -std::vector signature::process_range(uint8_t* start, - const size_t length) const { - if (this->has_sse_support()) - return this->process_range_vectorized(start, length); - return this->process_range_linear(start, length); -} - -std::vector signature::process_range_linear(uint8_t* start, - const size_t length) const { - std::vector result; - - for (size_t i = 0; i < length; ++i) { - const auto address = start + i; - - size_t j = 0; - for (; j < this->mask_.size(); ++j) { - if (this->mask_[j] != '?' && this->pattern_[j] != address[j]) { - break; - } - } - - if (j == this->mask_.size()) { - result.push_back(size_t(address)); - } - } - - return result; -} - -std::vector -signature::process_range_vectorized(uint8_t* start, const size_t length) const { - std::vector result; - __declspec(align(16)) char desired_mask[16] = {0}; - - for (size_t i = 0; i < this->mask_.size(); i++) { - desired_mask[i / 8] |= (this->mask_[i] == '?' ? 0 : 1) << i % 8; - } - - const auto mask = - _mm_load_si128(reinterpret_cast(desired_mask)); - const auto comparand = - _mm_loadu_si128(reinterpret_cast(this->pattern_.data())); - - for (size_t i = 0; i < length; ++i) { - const auto address = start + i; - const auto value = - _mm_loadu_si128(reinterpret_cast(address)); - const auto comparison = - _mm_cmpestrm(value, 16, comparand, static_cast(this->mask_.size()), - _SIDD_CMP_EQUAL_EACH); - - const auto matches = _mm_and_si128(mask, comparison); - const auto equivalence = _mm_xor_si128(mask, matches); - - if (_mm_test_all_zeros(equivalence, equivalence)) { - result.push_back(size_t(address)); - } - } - - return result; -} - -signature::signature_result signature::process() const { - const auto range = this->length_ - this->mask_.size(); - const auto cores = std::max(1u, std::thread::hardware_concurrency()); - - if (range <= cores * 10ull) - return this->process_serial(); - return this->process_parallel(); -} - -signature::signature_result signature::process_serial() const { - const auto sub = this->has_sse_support() ? 16 : this->mask_.size(); - return {this->process_range(this->start_, this->length_ - sub)}; -} - -signature::signature_result signature::process_parallel() const { - const auto sub = this->has_sse_support() ? 16 : this->mask_.size(); - const auto range = this->length_ - sub; - const auto cores = std::max(1u, std::thread::hardware_concurrency() / 2); - // Only use half of the available cores - const auto grid = range / cores; - - std::mutex mutex; - std::vector result; - std::vector threads; - - for (auto i = 0u; i < cores; ++i) { - const auto start = this->start_ + (grid * i); - const auto length = - (i + 1 == cores) ? (this->start_ + this->length_ - sub) - start : grid; - threads.emplace_back([&, start, length]() { - auto local_result = this->process_range(start, length); - if (local_result.empty()) - return; - - std::lock_guard _(mutex); - for (const auto& address : local_result) { - result.push_back(address); - } - }); - } - - for (auto& t : threads) { - if (t.joinable()) { - t.join(); - } - } - - std::sort(result.begin(), result.end()); - return {std::move(result)}; -} - -bool signature::has_sse_support() const { - if (this->mask_.size() <= 16) { - int cpu_id[4]; - __cpuid(cpu_id, 0); - - if (cpu_id[0] >= 1) { - __cpuidex(cpu_id, 1, 0); - return (cpu_id[2] & (1 << 20)) != 0; - } - } - - return false; -} -} // namespace utils::hook - -utils::hook::signature::signature_result operator"" _sig(const char* str, - const size_t len) { - return utils::hook::signature(std::string(str, len)).process(); -} diff --git a/src/common/utils/signature.hpp b/src/common/utils/signature.hpp deleted file mode 100644 index d5b1531..0000000 --- a/src/common/utils/signature.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include "nt.hpp" -#include - -namespace utils::hook { -class signature final { -public: - class signature_result { - public: - signature_result(std::vector&& matches) - : matches_(std::move(matches)) {} - - [[nodiscard]] uint8_t* get(const size_t index) const { - if (index >= this->count()) { - throw std::runtime_error("Invalid index"); - } - - return reinterpret_cast(this->matches_[index]); - } - - [[nodiscard]] size_t count() const { return this->matches_.size(); } - - private: - std::vector matches_; - }; - - explicit signature(const std::string& pattern, const nt::library library = {}) - : signature(pattern, library.get_ptr(), - library.get_optional_header()->SizeOfImage) {} - - signature(const std::string& pattern, void* start, void* end) - : signature(pattern, start, size_t(end) - size_t(start)) {} - - signature(const std::string& pattern, void* start, const size_t length) - : start_(static_cast(start)), length_(length) { - this->load_pattern(pattern); - } - - signature_result process() const; - -private: - std::string mask_; - std::basic_string pattern_; - - uint8_t* start_; - size_t length_; - - void load_pattern(const std::string& pattern); - - signature_result process_parallel() const; - signature_result process_serial() const; - std::vector process_range(uint8_t* start, size_t length) const; - std::vector process_range_linear(uint8_t* start, size_t length) const; - std::vector process_range_vectorized(uint8_t* start, - size_t length) const; - - bool has_sse_support() const; -}; -} // namespace utils::hook - -utils::hook::signature::signature_result operator"" _sig(const char* str, - size_t len);