diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..eea3a0b --- /dev/null +++ b/.clang-format @@ -0,0 +1,12 @@ + +--- +Language: Cpp +BasedOnStyle: LLVM +DerivePointerAlignment: false +PointerAlignment: Left +SortIncludes: false + +# Regroup causes unnecessary noise due to clang-format bug. +IncludeBlocks: Preserve + +--- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..136f81a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,55 @@ +name: Build + +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + types: [opened, synchronize, reopened] +jobs: + build: + name: Build binaries + runs-on: windows-2022 + strategy: + matrix: + configuration: + - Debug + - Release + steps: + - name: Wait for previous workflows + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') + uses: softprops/turnstyle@v1 + with: + poll-interval-seconds: 10 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check out files + uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + # NOTE - If LFS ever starts getting used during builds, switch this to true! + lfs: false + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.1 + + - name: Generate project files + run: tools/premake5 vs2022 + + - name: Set up problem matching + uses: ammaraskar/msvc-problem-matcher@master + + - name: Build ${{matrix.configuration}} binaries + run: msbuild /m /v:minimal /p:Configuration=${{matrix.configuration}} /p:Platform=Win32 build/mw3-server-freezer.sln + + - name: Upload ${{matrix.configuration}} binaries + uses: actions/upload-artifact@v2 + with: + name: ${{matrix.configuration}} binaries + path: | + build/bin/Win32/${{matrix.configuration}}/mw3-server-freezer.dll + build/bin/Win32/${{matrix.configuration}}/mw3-server-freezer.pdb diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml new file mode 100644 index 0000000..1bcdb6d --- /dev/null +++ b/.github/workflows/clang-format-check.yml @@ -0,0 +1,20 @@ +name: clang-format Check +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + types: [opened, synchronize, reopened] +jobs: + formatting-check: + name: Formatting Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run clang-format style check for C/C++/Protobuf programs. + uses: jidicula/clang-format-action@v4.6.2 + with: + clang-format-version: '14' + check-path: 'src' diff --git a/README.md b/README.md index 0cda803..5745226 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ If you think your server is vulnerable you should seek help in the appropriate d ## Compile from source - Clone the Git repo. Do NOT download it as ZIP, that won't work. -- Update the submodules and run `premake5 vs2019` or simply use the delivered `generate.bat`. -- Visual Studio Properties -> Linker -> Input -> Module Definition File -> add module.def located in src folder +- Update the submodules and run `premake5 vs2022` or simply use the delivered `generate.bat`. - Build via solution file in `build\mw3-server-freezer.sln`. ## Commands diff --git a/generate.bat b/generate.bat index b319889..2bad27b 100644 --- a/generate.bat +++ b/generate.bat @@ -1,4 +1,4 @@ @echo off echo Updating submodules... call git submodule update --init --recursive -call tools\premake5 %* vs2019 \ No newline at end of file +call tools\premake5 %* vs2022 diff --git a/premake5.lua b/premake5.lua index 49d2976..6a3355c 100644 --- a/premake5.lua +++ b/premake5.lua @@ -36,36 +36,39 @@ workspace "mw3-server-freezer" targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}" targetname "%{prj.name}" - language "C++" - - architecture "x86" - platforms "x86" - - buildoptions "/std:c++latest" - systemversion "latest" - - flags { "NoIncrementalLink", "NoMinimalRebuild", "MultiProcessorCompile", "No64BitChecks" } - configurations {"Debug", "Release"} + language "C++" + cppdialect "C++20" + + architecture "x86" + platforms "Win32" + + systemversion "latest" symbols "On" staticruntime "On" editandcontinue "Off" warnings "Extra" characterset "ASCII" - configuration "Release" + flags {"NoIncrementalLink", "NoMinimalRebuild", "MultiProcessorCompile", "No64BitChecks"} + + filter "platforms:Win*" + defines {"_WINDOWS", "WIN32"} + filter {} + + filter "configurations:Release" optimize "Size" defines {"NDEBUG"} flags {"FatalCompileWarnings"} buildoptions {"/GL"} linkoptions { "/IGNORE:4702", "/LTCG" } - configuration {} + filter {} - configuration "Debug" + filter "configurations:Debug" optimize "Debug" defines {"DEBUG", "_DEBUG"} - configuration {} + filter {} project "mw3-server-freezer" kind "SharedLib" diff --git a/src/component/cheats.cpp b/src/component/cheats.cpp index a3b91b7..652736d 100644 --- a/src/component/cheats.cpp +++ b/src/component/cheats.cpp @@ -9,12 +9,11 @@ namespace cheats { - game::dvar_t* cl_EnableCheats; + game::dvar_t* cl_EnableCheats; - __declspec(naked) void draw_red_box_stub() - { - __asm - { + __declspec(naked) void draw_red_box_stub() + { + __asm { push eax mov eax, cl_EnableCheats cmp byte ptr [eax + 12], 1 @@ -30,13 +29,12 @@ namespace cheats draw: push 0x43056A retn - } - } + } + } - __declspec(naked) void blind_eye_check_stub() - { - __asm - { + __declspec(naked) void blind_eye_check_stub() + { + __asm { push eax mov eax, cl_EnableCheats cmp byte ptr [eax + 12], 1 @@ -45,59 +43,71 @@ namespace cheats je draw test byte ptr [esi], 0x20 - jnz skipBecauseBlindeye + jnz skip_because_blindeye jmp draw - skipBecauseBlindeye: + skip_because_blindeye: push 0x5AA5A2 retn draw: push 0x05AA529 retn - } - } + } + } - class component final : public component_interface - { - public: - void post_unpack() override - { - cl_EnableCheats = game::Dvar_RegisterBool("cl_EnableCheats", false, game::DVAR_FLAG_NONE, "Enable FoF wallhack"); + class component final : public component_interface + { + public: + void post_unpack() override + { + cl_EnableCheats = game::Dvar_RegisterBool( + "cl_EnableCheats", false, game::DVAR_NONE, "Enable FoF wallhack"); - utils::hook::jump(0x430561, draw_red_box_stub); - utils::hook::nop(0x430566, 2); + utils::hook::jump(0x430561, draw_red_box_stub); + utils::hook::nop(0x430566, 2); - utils::hook::jump(0x5AA524, blind_eye_check_stub); + utils::hook::jump(0x5AA524, blind_eye_check_stub); - add_cheat_commands(); - } + add_cheat_commands(); + } - private: - static void add_cheat_commands() - { - key_catcher::on_key_press("Z", [](const game::LocalClientNum_t&) - { - game::Dvar_SetBool(cl_EnableCheats, true); - }); + private: + static void add_cheat_commands() + { + key_catcher::on_key_press( + "Z", + []([[maybe_unused]] const game::LocalClientNum_t& local_client) + { + game::Dvar_SetBool(cl_EnableCheats, true); + }); - key_catcher::on_key_press("X", [](const game::LocalClientNum_t&) - { - game::Dvar_SetBool(cl_EnableCheats, false); - }); + key_catcher::on_key_press( + "X", + []([[maybe_unused]] const game::LocalClientNum_t& local_client) + { + game::Dvar_SetBool(cl_EnableCheats, false); + }); - key_catcher::on_key_press("Y", [](const game::LocalClientNum_t&) - { - command::execute(utils::string::va("cmd mr %i 2 allies", *game::serverId), true); - }); + key_catcher::on_key_press( + "Y", + []([[maybe_unused]] const game::LocalClientNum_t& local_client) + { + command::execute( + utils::string::va("cmd mr %i 2 allies", *game::serverId), true); + }); - key_catcher::on_key_press("8", [](const game::LocalClientNum_t&) - { - command::execute(utils::string::va("cmd mr %i -1 endround", *game::serverId), true); - }); - } - }; -} + key_catcher::on_key_press( + "8", + []([[maybe_unused]] const game::LocalClientNum_t& local_client) + { + command::execute( + utils::string::va("cmd mr %i -1 endround", *game::serverId), + true); + }); + } + }; +} // namespace cheats REGISTER_COMPONENT(cheats::component) diff --git a/src/component/command.cpp b/src/component/command.cpp index 1c450b3..8b1507a 100644 --- a/src/component/command.cpp +++ b/src/component/command.cpp @@ -6,134 +6,119 @@ #include "command.hpp" +constexpr auto CMD_MAX_NESTING = 8; + namespace command { - std::unordered_map> handlers; + std::unordered_map> handlers; - void main_handler() - { - params params = {}; + void main_handler() + { + params params = {}; - const auto command = utils::string::to_lower(params[0]); - if (handlers.find(command) != handlers.end()) - { - handlers[command](params); - } - } + const auto command = utils::string::to_lower(params[0]); + if (!handlers.contains(command)) + { + handlers[command](params); + } + } - params::params() - : nesting_(game::cmd_args->nesting) - { - } + params::params() + : nesting_(game::cmd_args->nesting) + { + assert(game::cmd_args->nesting < CMD_MAX_NESTING); + } - int params::size() const - { - return game::cmd_args->argc[this->nesting_]; - } + int params::size() const + { + return game::cmd_args->argc[this->nesting_]; + } - const char* params::get(const int index) const - { - if (index >= this->size()) - { - return ""; - } + const char* params::get(const int index) const + { + if (index >= this->size()) + { + return ""; + } - return game::cmd_args->argv[this->nesting_][index]; - } + return game::cmd_args->argv[this->nesting_][index]; + } - std::string params::join(const int index) const - { - std::string result = {}; + std::string params::join(const int index) const + { + std::string result = {}; - for (auto i = index; i < this->size(); i++) - { - if (i > index) result.append(" "); - result.append(this->get(i)); - } - return result; - } + for (auto i = index; i < this->size(); i++) + { + if (i > index) result.append(" "); + result.append(this->get(i)); + } - void add_raw(const char* name, void (*callback)()) - { - game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate()); - } + return result; + } - void add(const char* name, const std::function& callback) - { - const auto command = utils::string::to_lower(name); + void add_raw(const char* name, void (*callback)()) + { + game::Cmd_AddCommandInternal( + name, + callback, + utils::memory::get_allocator()->allocate()); + } - if (handlers.find(command) == handlers.end()) - { - add_raw(name, main_handler); - } + void add(const char* name, const std::function& callback) + { + const auto command = utils::string::to_lower(name); - handlers[command] = callback; - } + if (!handlers.contains(command)) + { + add_raw(name, main_handler); + } - std::vector script_commands; - utils::memory::allocator allocator; + handlers[command] = callback; + } - void add_script_command(const std::string& name, const std::function& callback) - { - script_commands.push_back(name); - const auto _name = allocator.duplicate_string(name); - add(_name, callback); - } + void add(const char* name, const std::function& callback) + { + add(name, + [callback](const params&) + { + callback(); + }); + } - void clear_script_commands() - { - for (const auto& name : script_commands) - { - handlers.erase(name); - game::Cmd_RemoveCommand(name.data()); - } + void execute(std::string command, const bool sync) + { + command += "\n"; - allocator.clear(); - script_commands.clear(); - } + if (sync) + { + game::Cmd_ExecuteSingleCommand( + game::LocalClientNum_t::LOCAL_CLIENT_0, 0, command.data()); + } + else + { + game::Cbuf_AddText(game::LocalClientNum_t::LOCAL_CLIENT_0, + command.data()); + } + } - void execute(std::string command, const bool sync) - { - command += "\n"; + class component final : public component_interface + { + public: + void post_unpack() override + { + add_commands_generic(); + } - if (sync) - { - game::Cmd_ExecuteSingleCommand(game::LocalClientNum_t::LOCAL_CLIENT_0, 0, command.data()); - } - else - { - game::Cbuf_AddText(game::LocalClientNum_t::LOCAL_CLIENT_0, command.data()); - } - } + private: + static void add_commands_generic() + { + // Will cause blue screen + add("quit_meme", utils::nt::raise_hard_exception); - class component final : public component_interface - { - public: - void post_unpack() override - { - add_commands_generic(); - } - - void pre_destroy() override - { - clear_script_commands(); - } - - private: - static void add_commands_generic() - { - add("quit_meme", [](const params&) - { - // Will cause blue screen - utils::nt::raise_hard_exception(); - }); - - add("dia_quit", [](const params&) - { - game::Com_Quit_f(); - }); - } - }; -} + add("quit", game::Com_Quit_f); + } + }; +} // namespace command REGISTER_COMPONENT(command::component) diff --git a/src/component/command.hpp b/src/component/command.hpp index 84a3bab..fc04b53 100644 --- a/src/component/command.hpp +++ b/src/component/command.hpp @@ -2,29 +2,28 @@ namespace command { - class params - { - public: - params(); + class params + { + public: + params(); - int size() const; - const char* get(int index) const; - std::string join(int index) const; + [[nodiscard]] int size() const; + [[nodiscard]] const char* get(int index) const; + [[nodiscard]] std::string join(int index) const; - const char* operator[](const int index) const - { - return this->get(index); - } + const char* operator[](const int index) const + { + return this->get(index); + } - private: - int nesting_; - }; + private: + int nesting_; + }; - void add_raw(const char* name, void (*callback)()); - void add(const char* name, const std::function& callback); + void add_raw(const char* name, void (*callback)()); + void add(const char* name, + const std::function& callback); + void add(const char* name, const std::function& callback); - void add_script_command(const std::string& name, const std::function& callback); - void clear_script_commands(); - - void execute(std::string command, bool sync = false); -} + void execute(std::string command, bool sync = false); +} // namespace command diff --git a/src/component/console.cpp b/src/component/console.cpp index 4f27027..3c183bb 100644 --- a/src/component/console.cpp +++ b/src/component/console.cpp @@ -4,49 +4,52 @@ namespace console { - namespace - { - std::thread thread; - std::thread::id async_thread_id; + namespace + { + std::thread thread; + std::thread::id async_thread_id; - LRESULT __stdcall sys_start_console(HWND, UINT, WPARAM, LPARAM) - { - game::Sys_ShowConsole(); - return 0; - } + LRESULT __stdcall sys_start_console(HWND, UINT, WPARAM, LPARAM) + { + game::Sys_ShowConsole(); + return 0; + } - void console_unlock() - { - const auto callBack = SetWindowLongA(*game::g_wv_hWnd, - GWL_WNDPROC, reinterpret_cast(sys_start_console)); + void console_unlock() + { + const auto callback = + SetWindowLongA(*game::g_wv_hWnd, + GWL_WNDPROC, + reinterpret_cast(sys_start_console)); - SendMessage(*game::g_wv_hWnd, WM_QUIT, 0, 0); - SetWindowLongA(*game::g_wv_hWnd, GWL_WNDPROC, callBack); - } + SendMessageA(*game::g_wv_hWnd, WM_QUIT, 0, 0); + SetWindowLongA(*game::g_wv_hWnd, GWL_WNDPROC, callback); + } - void show_console() - { - if (*game::s_wcd_hWnd) - { - ShowWindow(*game::s_wcd_hWnd, SW_SHOW); - } - } - } + void show_console() + { + if (*game::s_wcd_hWnd) + { + ShowWindow(*game::s_wcd_hWnd, SW_SHOW); + } + } + } // namespace - class component final : public component_interface - { - public: - void post_unpack() override - { - thread = std::thread([]() - { - console_unlock(); - show_console(); - }); + class component final : public component_interface + { + public: + void post_unpack() override + { + thread = std::thread( + []() + { + console_unlock(); + show_console(); + }); - async_thread_id = thread.get_id(); - } - }; -} + async_thread_id = thread.get_id(); + } + }; +} // namespace console REGISTER_COMPONENT(console::component) diff --git a/src/component/dvar_patches.cpp b/src/component/dvar_patches.cpp index 9a92435..afbdbfe 100644 --- a/src/component/dvar_patches.cpp +++ b/src/component/dvar_patches.cpp @@ -1,23 +1,20 @@ #include +#include "loader/component_loader.hpp" -#include #include namespace dvar_patches { - void dvar_set_from_string_by_name_stub(const char*, const char*) - { - return; - } + void dvar_set_from_string_by_name_stub(const char*, const char*) {} - class component final : public component_interface - { - public: - void post_unpack() override - { - utils::hook::call(0x59C0EF, dvar_set_from_string_by_name_stub); - } - }; -} + class component final : public component_interface + { + public: + void post_unpack() override + { + utils::hook::call(0x59C0EF, dvar_set_from_string_by_name_stub); + } + }; +} // namespace dvar_patches REGISTER_COMPONENT(dvar_patches::component) \ No newline at end of file diff --git a/src/component/exploit.cpp b/src/component/exploit.cpp index 4e86223..2bc28ff 100644 --- a/src/component/exploit.cpp +++ b/src/component/exploit.cpp @@ -8,111 +8,118 @@ namespace exploit { - game::dvar_t* cl_exploit; + game::dvar_t* cl_exploit; - /* - * void CL_Netchan_Transmit(netchan_t* chan, unsigned char* data, int a3) - * A brief description of data: the first few bytes contain information from clientConnection_t structure - * Offset 0: ServerID Size : 1 - * Offset 1: serverMessageSequence Size: 4 - * Offset 5: serverCommandSequence Size: 4 - * One clean way of sending invalid data to the server is to hook the functions that write the info to the packet - * Credit: https://stackoverflow.com/questions/58981714/how-do-i-change-the-value-of-a-single-byte-in-a-uint32-t-variable - */ + /* + * void CL_Netchan_Transmit(netchan_t* chan, unsigned char* data, int a3) + * A brief description of data: the first few bytes contain information from + * clientConnection_t structure Offset 0: ServerID Size : 1 Offset 1: + * serverMessageSequence Size: 4 Offset 5: serverCommandSequence Size: 4 One + * clean way of sending invalid data to the server is to hook the functions + * that write the info to the packet Credit: + * https://stackoverflow.com/questions/58981714/how-do-i-change-the-value-of-a-single-byte-in-a-uint32-t-variable + */ - void write_message_sequence(game::msg_t* msg, int data) + void write_message_sequence(game::msg_t* msg, int data) + { + if (msg->maxsize - static_cast(msg->cursize) < sizeof(int)) { - if (msg->maxsize - msg->cursize < sizeof(int)) - { - msg->overflowed = TRUE; - return; - } - - if (cl_exploit->current.enabled) - data = (data & 0xFFFFFF00) | 0xAAu; - - auto dest = reinterpret_cast(&msg->data[msg->cursize]); - *dest = data; - msg->cursize += sizeof(int); + msg->overflowed = TRUE; + return; } - void write_command_sequence(game::msg_t* msg, int data) + if (cl_exploit->current.enabled) data = (data & 0xFFFFFF00) | 0xAAu; + + auto* dest = reinterpret_cast(&msg->data[msg->cursize]); + *dest = data; + msg->cursize += sizeof(int); + } + + void write_command_sequence(game::msg_t* msg, int data) + { + if (msg->maxsize - static_cast(msg->cursize) < sizeof(int)) { - if (msg->maxsize - msg->cursize < sizeof(int)) - { - msg->overflowed = TRUE; - return; - } - - if (cl_exploit->current.enabled) - data = (data & 0x00FFFFFF) | (0x80u << 24); - - auto dest = reinterpret_cast(&msg->data[msg->cursize]); - *dest = data; - msg->cursize += sizeof(int); + msg->overflowed = TRUE; + return; } - class component final : public component_interface + if (cl_exploit->current.enabled) data = (data & 0x00FFFFFF) | (0x80u << 24); + + auto* dest = reinterpret_cast(&msg->data[msg->cursize]); + *dest = data; + msg->cursize += sizeof(int); + } + + class component final : public component_interface + { + public: + void post_unpack() override { - public: - void post_unpack() override - { - cl_exploit = game::Dvar_RegisterBool("cl_exploit", false, game::DVAR_FLAG_NONE, "Enable server freezer"); + cl_exploit = game::Dvar_RegisterBool( + "cl_exploit", false, game::DVAR_NONE, "Enable server freezer"); - add_exploit_commands(); - add_key_hooks(); + add_exploit_commands(); + add_key_hooks(); - utils::hook::call(0x420B76, write_message_sequence); - utils::hook::call(0x420B86, write_command_sequence); + utils::hook::call(0x420B76, write_message_sequence); + utils::hook::call(0x420B86, write_command_sequence); + } - // Increase size; - utils::hook::set(0x4639C7, 0x1FFFCu); - utils::hook::set(0x496237, 0x1FFFCu); - } + private: + static void add_key_hooks() + { + key_catcher::on_key_press( + "O", + []([[maybe_unused]] const game::LocalClientNum_t& local_client) + { + command::execute("exploit"); + }); - private: - static void add_key_hooks() - { - key_catcher::on_key_press("O", [](const game::LocalClientNum_t&) - { - command::execute("exploit"); - }); + key_catcher::on_key_press( + "L", + []([[maybe_unused]] const game::LocalClientNum_t& local_client) + { + command::execute("undo_exploit"); + }); - key_catcher::on_key_press("L", [](const game::LocalClientNum_t&) - { - command::execute("undo_exploit"); - }); + key_catcher::on_key_press( + "K", + []([[maybe_unused]] const game::LocalClientNum_t& local_client) + { + command::execute("disconnect"); + }); + } - key_catcher::on_key_press("K", [](const game::LocalClientNum_t&) - { - command::execute("disconnect"); - }); - } + static void add_exploit_commands() + { + command::add("exploit", + []([[maybe_unused]] const command::params& params) + { + game::Dvar_SetBool(cl_exploit, true); + }); - static void add_exploit_commands() - { - command::add("exploit", [](const command::params&) - { - game::Dvar_SetBool(cl_exploit, true); - }); + command::add("undo_exploit", + []([[maybe_unused]] const command::params& params) + { + game::Dvar_SetBool(cl_exploit, false); + }); - command::add("undo_exploit", [](const command::params&) - { - game::Dvar_SetBool(cl_exploit, false); - }); + command::add( + "send_command", + []([[maybe_unused]] const command::params& params) + { + if (params.size() < 2) return; - command::add("send_command", [](const command::params& params) - { - if (params.size() < 2) return; + if (*game::connectionState <= game::connstate_t::CA_CHALLENGING) + return; - if (*game::connectionState <= game::connstate_t::CA_CHALLENGING) - return; - - const auto cmd = std::format("queryserverinfo ;{}", params.join(1)); - game::NET_OutOfBandPrint(game::NS_SERVER, game::localClientConnection->serverAddress, cmd.data()); - }); - } - }; -} + const auto cmd = std::format("queryserverinfo ;{}", params.join(1)); + game::NET_OutOfBandPrint(game::NS_SERVER, + game::localClientConnection->serverAddress, + cmd.data()); + }); + } + }; +} // namespace exploit REGISTER_COMPONENT(exploit::component) diff --git a/src/component/key_catcher.cpp b/src/component/key_catcher.cpp index 5f8c17f..040a14e 100644 --- a/src/component/key_catcher.cpp +++ b/src/component/key_catcher.cpp @@ -7,59 +7,61 @@ namespace key_catcher { - utils::hook::detour cl_key_event_hook; + utils::hook::detour cl_key_event_hook; - namespace - { - std::unordered_map& get_key_callbacks() - { - static std::unordered_map key_callbacks{}; - return key_callbacks; - } + namespace + { + std::unordered_map& get_key_callbacks() + { + static std::unordered_map + key_callbacks{}; + return key_callbacks; + } - void handle_key_event(game::LocalClientNum_t localClient, int keyID) - { - auto result = VkKeyScanA(static_cast(keyID)); - auto VkKey = LOBYTE(result); - auto& callbacks = get_key_callbacks(); + void handle_key_event(game::LocalClientNum_t local_client, int key_id) + { + const auto result = VkKeyScanA(static_cast(key_id)); + const auto vk_key = LOBYTE(result); + const auto& callbacks = get_key_callbacks(); - for (auto const& i : callbacks) - { - auto gameVkKey = game::Key_StringToKeynum(i.first.data()); - if (static_cast(gameVkKey) == VkKey) - { - i.second(localClient); - return; - } - } - } - } + for (auto const& [key, value] : callbacks) + { + const auto game_vk_key = game::Key_StringToKeynum(key.data()); + if (static_cast(game_vk_key) == vk_key) + { + value(local_client); + return; + } + } + } + } // namespace - void on_key_press(const std::string& command, const callback& callback) - { - get_key_callbacks()[command] = callback; - } + void on_key_press(const std::string& command, const callback& callback) + { + get_key_callbacks()[command] = callback; + } - void cl_key_event_stub(game::LocalClientNum_t localClient, int keyID, int a3) - { - handle_key_event(localClient, keyID); + void cl_key_event_stub(game::LocalClientNum_t local_client, int key_id, + int a3) + { + handle_key_event(local_client, key_id); - cl_key_event_hook.invoke(localClient, keyID, a3); - } + cl_key_event_hook.invoke(local_client, key_id, a3); + } - class component final : public component_interface - { - public: - void post_unpack() override - { - cl_key_event_hook.create(0x4CD840, &cl_key_event_stub); - } + class component final : public component_interface + { + public: + void post_unpack() override + { + cl_key_event_hook.create(0x4CD840, &cl_key_event_stub); + } - void pre_destroy() override - { - cl_key_event_hook.clear(); - } - }; -} + void pre_destroy() override + { + cl_key_event_hook.clear(); + } + }; +} // namespace key_catcher REGISTER_COMPONENT(key_catcher::component) diff --git a/src/component/key_catcher.hpp b/src/component/key_catcher.hpp index 0e96e1c..d79c98c 100644 --- a/src/component/key_catcher.hpp +++ b/src/component/key_catcher.hpp @@ -2,7 +2,7 @@ namespace key_catcher { - using callback = std::function; + using callback = std::function; - void on_key_press(const std::string& command, const callback& callback); -} + void on_key_press(const std::string& command, const callback& callback); +} // namespace key_catcher diff --git a/src/component/network.cpp b/src/component/network.cpp index afa4230..df4e9c0 100644 --- a/src/component/network.cpp +++ b/src/component/network.cpp @@ -9,67 +9,75 @@ namespace network { - namespace - { - std::unordered_map& get_callbacks() - { - static std::unordered_map network_callbacks{}; - return network_callbacks; - } + namespace + { + std::unordered_map& get_callbacks() + { + static std::unordered_map + network_callbacks{}; + return network_callbacks; + } - bool handle_command(game::netadr_s* address, const char* command, game::msg_t* message) - { - const auto cmd_string = utils::string::to_lower(command); - auto& callbacks = get_callbacks(); - const auto handler = callbacks.find(cmd_string); + bool handle_command(game::netadr_s* address, const char* command, + game::msg_t* msg) + { + const auto cmd_string = utils::string::to_lower(command); + auto& callbacks = get_callbacks(); + const auto handler = callbacks.find(cmd_string); + const auto offset = cmd_string.size() + 5; - if (handler == callbacks.end()) - { - return false; - } + if (static_cast(msg->cursize) < offset || + handler == callbacks.end()) + { + return false; + } - const auto offset = cmd_string.size() + 5; - const std::string_view data(reinterpret_cast(message->data) + offset, message->cursize - offset); + const std::string_view data(reinterpret_cast(msg->data) + offset, + msg->cursize - offset); - handler->second(*address, data); - return true; - } - } + handler->second(*address, data); + return true; + } + } // namespace - int packet_interception_handler(game::netadr_s* from, const char* command, game::msg_t* message) - { - if (!handle_command(from, command, message)) - { - return reinterpret_cast(0x525730)(from, command, message); - } + int packet_interception_handler(game::netadr_s* from, const char* command, + game::msg_t* message) + { + if (!handle_command(from, command, message)) + { + return reinterpret_cast(0x525730)( + from, command, message); + } - return TRUE; - } + return TRUE; + } - void on_packet(const std::string& command, const callback& callback) - { - get_callbacks()[utils::string::to_lower(command)] = callback; - } + void on_packet(const std::string& command, const callback& callback) + { + get_callbacks()[utils::string::to_lower(command)] = callback; + } - class component final : public component_interface - { - public: - void post_unpack() override - { - add_network_commands(); + class component final : public component_interface + { + public: + void post_unpack() override + { + add_network_commands(); - utils::hook::call(0x5B27E1, packet_interception_handler); - } + utils::hook::call(0x5B27E1, packet_interception_handler); + } - private: - static void add_network_commands() - { - on_packet("naughty_reply", [](const game::netadr_s&, const std::string_view&) - { - command::execute("quit_meme"); - }); - } - }; -} + private: + static void add_network_commands() + { + on_packet("naughty_reply", + [](const game::netadr_s&, const std::string_view&) + { + command::execute("quit_meme"); + }); + } + }; +} // namespace network REGISTER_COMPONENT(network::component) diff --git a/src/component/network.hpp b/src/component/network.hpp index f8c7a7e..b2f87c1 100644 --- a/src/component/network.hpp +++ b/src/component/network.hpp @@ -2,7 +2,8 @@ namespace network { - using callback = std::function; + using callback = + std::function; - void on_packet(const std::string& command, const callback& callback); -} + void on_packet(const std::string& command, const callback& callback); +} // namespace network diff --git a/src/component/remove_hooks.cpp b/src/component/remove_hooks.cpp index cab62f5..cedcd66 100644 --- a/src/component/remove_hooks.cpp +++ b/src/component/remove_hooks.cpp @@ -1,34 +1,34 @@ #include - #include + #include namespace remove_hooks { - class component final : public component_interface - { - public: - void post_unpack() override - { - remove_tekno_hooks(); - } + class component final : public component_interface + { + public: + void post_unpack() override + { + remove_tekno_hooks(); + } - private: - static void remove_tekno_hooks() - { - utils::hook::set(0x4E3D42, 0xE8); - utils::hook::set(0x4E3D43, 0xA9); - utils::hook::set(0x4E3D44, 0x25); - utils::hook::set(0x4E3D45, 0xFE); - utils::hook::set(0x4E3D46, 0xFF); + private: + static void remove_tekno_hooks() + { + utils::hook::set(0x4E3D42, 0xE8); + utils::hook::set(0x4E3D43, 0xA9); + utils::hook::set(0x4E3D44, 0x25); + utils::hook::set(0x4E3D45, 0xFE); + utils::hook::set(0x4E3D46, 0xFF); - utils::hook::set(0x6EA960, 0x55); - utils::hook::set(0x6EA961, 0x8B); - utils::hook::set(0x6EA962, 0xEC); - utils::hook::set(0x6EA963, 0x81); - utils::hook::set(0x6EA964, 0xEC); - } - }; -} + utils::hook::set(0x6EA960, 0x55); + utils::hook::set(0x6EA961, 0x8B); + utils::hook::set(0x6EA962, 0xEC); + utils::hook::set(0x6EA963, 0x81); + utils::hook::set(0x6EA964, 0xEC); + } + }; +} // namespace remove_hooks REGISTER_COMPONENT(remove_hooks::component) diff --git a/src/component/scheduler.cpp b/src/component/scheduler.cpp index 8c83c00..21627b5 100644 --- a/src/component/scheduler.cpp +++ b/src/component/scheduler.cpp @@ -1,170 +1,186 @@ #include -#include "loader/component_loader.hpp" +#include -#include "utils/concurrency.hpp" -#include "utils/hook.hpp" +#include +#include #include "scheduler.hpp" namespace scheduler { - std::thread::id async_thread_id; + std::thread::id async_thread_id; - namespace - { - struct task - { - std::function handler{}; - std::chrono::milliseconds interval{}; - std::chrono::high_resolution_clock::time_point last_call{}; - }; + namespace + { + struct task + { + std::function handler{}; + std::chrono::milliseconds interval{}; + std::chrono::high_resolution_clock::time_point last_call{}; + }; - using task_list = std::vector; + 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)); - }); - } + class task_pipeline + { + public: + void add(task&& task) + { + new_callbacks_.access( + [&task, this](task_list& tasks) + { + tasks.emplace_back(std::move(task)); + }); + } - void clear() - { - callbacks_.access([&](task_list& tasks) - { - this->merge_callbacks(); - tasks.clear(); - }); - } + void clear() + { + callbacks_.access( + [&](task_list& tasks) + { + this->merge_callbacks(); + tasks.clear(); + }); + } - void execute() - { - callbacks_.access([&](task_list& tasks) - { - this->merge_callbacks(); + void execute() + { + callbacks_.access( + [&](task_list& tasks) + { + this->merge_callbacks(); - for (auto i = tasks.begin(); i != tasks.end();) - { - const auto now = std::chrono::high_resolution_clock::now(); - const auto diff = now - i->last_call; + for (auto i = tasks.begin(); i != tasks.end();) + { + const auto now = std::chrono::high_resolution_clock::now(); + const auto diff = now - i->last_call; - if (diff < i->interval) - { - ++i; - continue; - } + if (diff < i->interval) + { + ++i; + continue; + } - i->last_call = now; + i->last_call = now; - const auto res = i->handler(); - if (res == cond_end) - { - i = tasks.erase(i); - } - else - { - ++i; - } - } - }); - } + const auto res = i->handler(); + if (res == cond_end) + { + i = tasks.erase(i); + } + else + { + ++i; + } + } + }); + } - private: - utils::concurrency::container new_callbacks_; - utils::concurrency::container callbacks_; + private: + utils::concurrency::container new_callbacks_; + utils::concurrency::container callbacks_; - void merge_callbacks() - { - callbacks_.access([&](task_list& tasks) - { - new_callbacks_.access([&](task_list& new_tasks) - { - tasks.insert(tasks.end(), std::move_iterator(new_tasks.begin()), std::move_iterator(new_tasks.end())); - new_tasks = {}; - }); - }); - } - }; + void merge_callbacks() + { + callbacks_.access( + [&](task_list& tasks) + { + new_callbacks_.access( + [&](task_list& new_tasks) + { + tasks.insert(tasks.end(), + std::move_iterator( + new_tasks.begin()), + std::move_iterator( + new_tasks.end())); + new_tasks = {}; + }); + }); + } + }; - std::thread thread; - task_pipeline pipelines[pipeline::count]; + std::thread thread; + task_pipeline pipelines[pipeline::count]; - void execute(const pipeline type) - { - assert(type >= 0 && type < pipeline::count); - pipelines[type].execute(); - } + void execute(const pipeline type) + { + assert(type >= 0 && type < pipeline::count); + pipelines[type].execute(); + } - void cl_frame_stub(game::LocalClientNum_t local) - { - reinterpret_cast(0x41C9B0)(local); - execute(pipeline::client); - } - } + void cl_frame_stub(game::LocalClientNum_t local) + { + reinterpret_cast(0x41C9B0)(local); + execute(pipeline::client); + } + } // namespace - void clear_tasks(const pipeline type) - { - return pipelines[type].clear(); - } + void clear_tasks(const pipeline type) + { + return pipelines[type].clear(); + } - void schedule(const std::function& callback, const pipeline type, - const std::chrono::milliseconds delay) - { - assert(type >= 0 && type < pipeline::count); + void schedule(const std::function& callback, const pipeline type, + const std::chrono::milliseconds delay) + { + assert(type >= 0 && type < pipeline::count); - task task; - task.handler = callback; - task.interval = delay; - task.last_call = std::chrono::high_resolution_clock::now(); + task task; + task.handler = callback; + task.interval = delay; + task.last_call = std::chrono::high_resolution_clock::now(); - pipelines[type].add(std::move(task)); - } + pipelines[type].add(std::move(task)); + } - void loop(const std::function& callback, const pipeline type, - const std::chrono::milliseconds delay) - { - schedule([callback]() - { - callback(); - return cond_continue; - }, type, delay); - } + void loop(const std::function& callback, const pipeline type, + const std::chrono::milliseconds delay) + { + schedule( + [callback]() + { + callback(); + return cond_continue; + }, + type, + delay); + } - void once(const std::function& callback, const pipeline type, - const std::chrono::milliseconds delay) - { - schedule([callback]() - { - callback(); - return cond_end; - }, type, delay); - } + void once(const std::function& callback, const pipeline type, + const std::chrono::milliseconds delay) + { + schedule( + [callback]() + { + callback(); + return cond_end; + }, + type, + delay); + } - unsigned int thread_id; + unsigned int thread_id; - class component final : public component_interface - { - public: - void post_unpack() override - { - thread = std::thread([]() - { - while (true) - { - execute(pipeline::async); - std::this_thread::sleep_for(10ms); - } - }); + class component final : public component_interface + { + public: + void post_unpack() override + { + thread = std::thread( + []() + { + while (true) + { + execute(pipeline::async); + std::this_thread::sleep_for(10ms); + } + }); - async_thread_id = thread.get_id(); + async_thread_id = thread.get_id(); - utils::hook::call(0x4E4A0D, cl_frame_stub); - } - }; -} + utils::hook::call(0x4E4A0D, cl_frame_stub); + } + }; +} // namespace scheduler REGISTER_COMPONENT(scheduler::component) diff --git a/src/component/scheduler.hpp b/src/component/scheduler.hpp index 09336b9..0a8bb50 100644 --- a/src/component/scheduler.hpp +++ b/src/component/scheduler.hpp @@ -2,24 +2,27 @@ namespace scheduler { - extern std::thread::id async_thread_id; + extern std::thread::id async_thread_id; - enum pipeline - { - client, - async, - count, - }; + enum pipeline + { + client, + async, + count, + }; - static const bool cond_continue = false; - static const bool cond_end = true; + static const bool cond_continue = false; + static const bool cond_end = true; - void clear_tasks(const pipeline type); + void clear_tasks(const pipeline type); - void schedule(const std::function& callback, pipeline type = pipeline::client, - std::chrono::milliseconds delay = 0ms); - void loop(const std::function& callback, pipeline type = pipeline::client, - std::chrono::milliseconds delay = 0ms); - void once(const std::function& callback, pipeline type = pipeline::client, - std::chrono::milliseconds delay = 0ms); -} + void schedule(const std::function& callback, + pipeline type = pipeline::client, + std::chrono::milliseconds delay = 0ms); + void loop(const std::function& callback, + pipeline type = pipeline::client, + std::chrono::milliseconds delay = 0ms); + void once(const std::function& callback, + pipeline type = pipeline::client, + std::chrono::milliseconds delay = 0ms); +} // namespace scheduler diff --git a/src/component/user_info.cpp b/src/component/user_info.cpp index f58bdb7..c96a165 100644 --- a/src/component/user_info.cpp +++ b/src/component/user_info.cpp @@ -1,52 +1,53 @@ #include #include -#include "utils/hook.hpp" -#include "utils/info_string.hpp" -#include "utils/string.hpp" + +#include +#include +#include #include "scheduler.hpp" namespace user_info { - namespace - { - int a1 = 0; - void cl_check_user_info(int _a1, int force) - { - a1 = _a1; + namespace + { + int a1 = 0; + void cl_check_user_info(int _a1, const int force) + { + a1 = _a1; - if (*game::connectionState <= game::connstate_t::CA_CHALLENGING) - return; + if (*game::connectionState <= game::connstate_t::CA_CHALLENGING) return; - if (game::cl_paused->current.enabled && !force) - return; + if (game::cl_paused->current.enabled && !force) return; - const std::string infoString = game::Dvar_InfoString(_a1, 0x200); - utils::info_string info(infoString); + const std::string info_string = game::Dvar_InfoString(_a1, 0x200); + utils::info_string info(info_string); - const auto colorCode = rand() % 10; + const auto color_code = std::rand() % 10; - char name[16]; + char name[16]; - const auto& numbers = std::to_string(rand() % 10000); - _snprintf_s(name, sizeof(name), _TRUNCATE, "^%d%s", colorCode, numbers.data()); + const auto numbers = std::to_string(std::rand() % 10000); + _snprintf_s( + name, sizeof(name), _TRUNCATE, "^%d%s", color_code, numbers.data()); - info.set("name", name); + info.set("name", name); - info.set("ec_usingTag", "1"); - info.set("ec_TagText", utils::string::va("^%dGG", colorCode)); + info.set("ec_usingTag", "1"); + info.set("ec_TagText", utils::string::va("^%dGG", color_code)); - const auto& bigTitle = std::to_string(rand() % 512); - info.set("ec_TitleBg", bigTitle); + const auto big_title = std::to_string(std::rand() % 512); + info.set("ec_TitleBg", big_title); - game::CL_AddReliableCommand(_a1, utils::string::va("userinfo \"%s\"", info.build().data())); - } + game::CL_AddReliableCommand( + _a1, utils::string::va("userinfo \"%s\"", info.build().data())); + } - __declspec(naked) void cl_check_user_info_stub() - { - __asm - { + __declspec(naked) void cl_check_user_info_stub() + { + __asm + { pushad push 0 @@ -56,23 +57,26 @@ namespace user_info popad ret - } - } - } + } + } + } // namespace - class component final : public component_interface - { - public: - void post_unpack() override - { - utils::hook::call(0x41CA53, cl_check_user_info_stub); + class component final : public component_interface + { + public: + void post_unpack() override + { + utils::hook::call(0x41CA53, cl_check_user_info_stub); - scheduler::loop([] - { - cl_check_user_info(a1, TRUE); - }, scheduler::pipeline::client, 4s); - } - }; -} + scheduler::loop( + [] + { + cl_check_user_info(a1, TRUE); + }, + scheduler::pipeline::client, + 4s); + } + }; +} // namespace user_info REGISTER_COMPONENT(user_info::component) diff --git a/src/dllmain.cpp b/src/dllmain.cpp index fc48d19..961eead 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -1,21 +1,17 @@ #include #include "loader/component_loader.hpp" -BOOL APIENTRY DllMain(HMODULE /*hModule*/, - DWORD ul_reason_for_call, +BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/ -) -{ - if (ul_reason_for_call == DLL_PROCESS_ATTACH) - { - srand(uint32_t(time(nullptr))); - component_loader::post_unpack(); - } +) { + if (ul_reason_for_call == DLL_PROCESS_ATTACH) { + std::srand(uint32_t(time(nullptr))); + component_loader::post_unpack(); + } - else if (ul_reason_for_call == DLL_PROCESS_DETACH) - { - component_loader::pre_destroy(); - } + else if (ul_reason_for_call == DLL_PROCESS_DETACH) { + component_loader::pre_destroy(); + } - return TRUE; + return TRUE; } diff --git a/src/game/game.cpp b/src/game/game.cpp index 63d1a9a..7080bae 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1,5 +1,3 @@ #include -namespace game -{ -} +namespace game {} diff --git a/src/game/game.hpp b/src/game/game.hpp index 760b347..edc0075 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -1,34 +1,19 @@ #pragma once -namespace game -{ - template - class symbol - { - public: - symbol(const size_t dedi) - : dedi_(reinterpret_cast(dedi)) - { - } +namespace game { +template class symbol { +public: + symbol(const size_t dedi) : dedi_(reinterpret_cast(dedi)) {} - T* get() const - { - return dedi_; - } + T* get() const { return dedi_; } - operator T* () const - { - return this->get(); - } + operator T*() const { return this->get(); } - T* operator->() const - { - return this->get(); - } + T* operator->() const { return this->get(); } - private: - T* dedi_; - }; -} +private: + T* dedi_; +}; +} // namespace game #include "symbols.hpp" diff --git a/src/game/structs.hpp b/src/game/structs.hpp index c9e1a1b..eb1d522 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -1,1033 +1,311 @@ #pragma once #pragma warning(push) -#pragma warning(disable: 4324) - -namespace game -{ - typedef float vec_t; - typedef vec_t vec2_t[2]; - typedef vec_t vec3_t[3]; - typedef vec_t vec4_t[4]; - - struct cmd_function_t - { - cmd_function_t* next; - const char* name; - const char* autoCompleteDir; - const char* autoCompleteExt; - void(__cdecl* function)(); - int flags; - }; - - struct CmdArgs - { - int nesting; - int localClientNum[8]; - int controllerIndex[8]; - int argc[8]; - const char** argv[8]; - }; - - typedef enum - { - K_NONE = 0x0, - K_FIRSTGAMEPADBUTTON_RANGE_1 = 0x1, // First Gamepad 1 - K_BUTTON_A = 0x1, - K_BUTTON_B = 0x2, - K_BUTTON_X = 0x3, - K_BUTTON_Y = 0x4, - K_BUTTON_LSHLDR = 0x5, - K_BUTTON_RSHLDR = 0x6, - K_LASTGAMEPADBUTTON_RANGE_1 = 0x6, // Last Gamepad 1 - K_TAB = 0x9, - K_ENTER = 0xD, - K_FIRSTGAMEPADBUTTON_RANGE_2 = 0xE, // First Gamepad 2 - K_BUTTON_START = 0xE, - K_BUTTON_BACK = 0xF, - K_BUTTON_LSTICK = 0x10, - K_BUTTON_RSTICK = 0x11, - K_BUTTON_LTRIG = 0x12, - K_BUTTON_RTRIG = 0x13, - K_FIRSTDPAD = 0x14, // First Dpad - K_DPAD_UP = 0x14, - K_DPAD_DOWN = 0x15, - K_DPAD_LEFT = 0x16, - K_DPAD_RIGHT = 0x17, - K_LASTDPAD = 0x17, // Last Dpad - K_DPAD_LEFTRIGHT = 0x18, - K_DPAD_UPDOWN = 0x19, - K_LASTGAMEPADBUTTON_RANGE_2 = 0x19, // Last Gamepad 2 - K_ESCAPE = 0x1B, - K_FIRSTGAMEPADBUTTON_RANGE_3 = 0x1C, // First Gamepad 3 - K_FIRSTAPAD = 0x1C, // First APad - K_APAD_UP = 0x1C, - K_APAD_DOWN = 0x1D, - K_APAD_LEFT = 0x1E, - K_APAD_RIGHT = 0x1F, - K_LASTAPAD = 0x1F, // Last APad - K_LASTGAMEPADBUTTON_RANGE_3 = 0x1F, // Last Gamepad 3 - K_SPACE = 0x20, - K_BACKSPACE = 0x7F, - K_ASCII_FIRST = 0x80, - K_ASCII_181 = 0x80, - K_ASCII_191 = 0x81, - K_ASCII_223 = 0x82, - K_ASCII_224 = 0x83, - K_ASCII_225 = 0x84, - K_ASCII_228 = 0x85, - K_ASCII_229 = 0x86, - K_ASCII_230 = 0x87, - K_ASCII_231 = 0x88, - K_ASCII_232 = 0x89, - K_ASCII_233 = 0x8A, - K_ASCII_236 = 0x8B, - K_ASCII_241 = 0x8C, - K_ASCII_242 = 0x8D, - K_ASCII_243 = 0x8E, - K_ASCII_246 = 0x8F, - K_ASCII_248 = 0x90, - K_ASCII_249 = 0x91, - K_ASCII_250 = 0x92, - K_ASCII_252 = 0x93, - K_END_ASCII_CHARS = 0x94, - K_COMMAND = 0x96, - K_CAPSLOCK = 0x97, - K_POWER = 0x98, - K_PAUSE = 0x99, - K_UPARROW = 0x9A, - K_DOWNARROW = 0x9B, - K_LEFTARROW = 0x9C, - K_RIGHTARROW = 0x9D, - K_ALT = 0x9E, - K_CTRL = 0x9F, - K_SHIFT = 0xA0, - K_INS = 0xA1, - K_DEL = 0xA2, - K_PGDN = 0xA3, - K_PGUP = 0xA4, - K_HOME = 0xA5, - K_END = 0xA6, - K_F1 = 0xA7, - K_F2 = 0xA8, - K_F3 = 0xA9, - K_F4 = 0xAA, - K_F5 = 0xAB, - K_F6 = 0xAC, - K_F7 = 0xAD, - K_F8 = 0xAE, - K_F9 = 0xAF, - K_F10 = 0xB0, - K_F11 = 0xB1, - K_F12 = 0xB2, - K_F13 = 0xB3, - K_F14 = 0xB4, - K_F15 = 0xB5, - K_KP_HOME = 0xB6, - K_KP_UPARROW = 0xB7, - K_KP_PGUP = 0xB8, - K_KP_LEFTARROW = 0xB9, - K_KP_5 = 0xBA, - K_KP_RIGHTARROW = 0xBB, - K_KP_END = 0xBC, - K_KP_DOWNARROW = 0xBD, - K_KP_PGDN = 0xBE, - K_KP_ENTER = 0xBF, - K_KP_INS = 0xC0, - K_KP_DEL = 0xC1, - K_KP_SLASH = 0xC2, - K_KP_MINUS = 0xC3, - K_KP_PLUS = 0xC4, - K_KP_NUMLOCK = 0xC5, - K_KP_STAR = 0xC6, - K_KP_EQUALS = 0xC7, - K_MOUSE1 = 0xC8, - K_MOUSE2 = 0xC9, - K_MOUSE3 = 0xCA, - K_MOUSE4 = 0xCB, - K_MOUSE5 = 0xCC, - K_MWHEELDOWN = 0xCD, - K_MWHEELUP = 0xCE, - K_AUX1 = 0xCF, - K_AUX2 = 0xD0, - K_AUX3 = 0xD1, - K_AUX4 = 0xD2, - K_AUX5 = 0xD3, - K_AUX6 = 0xD4, - K_AUX7 = 0xD5, - K_AUX8 = 0xD6, - K_AUX9 = 0xD7, - K_AUX10 = 0xD8, - K_AUX11 = 0xD9, - K_AUX12 = 0xDA, - K_AUX13 = 0xDB, - K_AUX14 = 0xDC, - K_AUX15 = 0xDD, - K_AUX16 = 0xDE, - K_LAST_KEY = 0xDF - } keyNum_t; - - struct kbutton_t - { - int down[2]; - unsigned int downtime; - unsigned int msec; - bool active; - bool wasPressed; - }; - - static_assert(sizeof(kbutton_t) == 20); - - typedef enum - { - NS_CLIENT1 = 0, - NS_CLIENT2 = 1, - NS_CLIENT3 = 2, - NS_CLIENT4 = 3, - NS_MAXCLIENTS = 4, - NS_SERVER = 4, - NS_PACKET = 5, - NS_INVALID_NETSRC = 6 - } netsrc_t; - - enum netadrtype_t - { - NA_BOT = 0x0, - NA_BAD = 0x1, - NA_LOOPBACK = 0x2, - NA_BROADCAST = 0x3, - NA_IP = 0x4 - }; - - struct netadr_s - { - netadrtype_t type; - unsigned char ip[4]; - unsigned __int16 port; - unsigned char ipx[10]; - unsigned int addrHandleIndex; - }; - - static_assert(sizeof(netadr_s) == 24); - - typedef enum - { - BD_ECC_KEY_UNINITIALIZED = 0x0, - BD_ECC_KEY_INITIALIZED = 0x1 - } bdECCKeyStatus; - - typedef enum - { - BD_DTLS_INIT = 0x1, - BD_DTLS_INIT_ACK = 0x2, - BD_DTLS_COOKIE_ECHO = 0x3, - BD_DTLS_COOKIE_ACK = 0x4, - BD_DTLS_ERROR = 0x5, - BD_DTLS_DATA = 0x6 - } bdDTLSPacketTypes; - - typedef enum - { - BD_DTLS_CLOSED = 0x0, - BD_DTLS_COOKIE_WAIT = 0x1, - BD_DTLS_COOKIE_ECHOED = 0x2, - BD_DTLS_ESTABLISHED = 0x3 - } bdDTLSStatus; - - typedef enum - { - BD_DTLS_ERROR_BAD_SECID = 0x0, - BD_DTLS_INVALID_STATE = 0x1 - } bdDTLSErrorType; - - typedef enum - { - BD_NAT_OPEN = 0x1, - BD_NAT_MODERATE = 0x2, - BD_NAT_STRICT = 0x3 - } bdNATType; - - typedef enum - { - BD_SOCKET_IDLE = 0x0, - BD_SOCKET_PENDING = 0x1, - BD_SOCKET_CONNECTED = 0x2, - BD_SOCKET_LOST = 0x3 - } bdDTLSAssociationStatus; - - typedef enum - { - ERR_FATAL = 0x0, - ERR_DROP = 0x1, - ERR_SERVERDISCONNECT = 0x2, - ERR_DISCONNECT = 0x3, - ERR_SCRIPT = 0x4, - ERR_SCRIPT_DROP = 0x5, - ERR_LOCALIZATION = 0x6, - ERR_MAPLOADERRORSUMMARY = 0x7 - } errorParm_t; - - enum class LocalClientNum_t - { - LOCAL_CLIENT_0 = 0, - LOCAL_CLIENT_1 = 1, - LOCAL_CLIENT_2 = 2, - LOCAL_CLIENT_3 = 3, - LOCAL_CLIENT_LAST = 3, - LOCAL_CLIENT_COUNT = 4 - }; - - typedef enum - { - CA_DISCONNECTED = 0, - CA_CINEMATIC = 1, - CA_LOGO = 2, - CA_CONNECTING = 3, - CA_CHALLENGING = 4, - CA_CONNECTED = 5, - CA_SENDINGSTATS = 6, - CA_REQUESTING_MATCH_RULES = 7, - CA_LOADING = 8, - CA_PRIMED = 9, - CA_ACTIVE = 10 - } connstate_t; - - struct msg_t - { - int overflowed; - int readOnly; - unsigned char* data; - unsigned char* splitData; - int maxsize; - int cursize; - int splitSize; - int readcount; - int bit; - int lastEntityRef; - }; - - struct netProfilePacket_t - { - int iTime; - int iSize; - int bFragment; - }; - - struct netProfileStream_t - { - netProfilePacket_t packets[60]; - int iCurrPacket; - int iBytesPerSeconds; - int iLastBPSCalcTime; - int iCountedPackets; - int iCountedFragments; - int iFragmentPercentage; - int iLargestPacket; - int iSmallestPacket; - }; - - struct netProfileInfo_t - { - netProfileStream_t send; - netProfileStream_t recieve; - }; - - struct netchan_t - { - int outgoingSequence; - netsrc_t sock; - int dropped; - int incomingSequence; - netadr_s remoteAddress; - int qport; - int fragmentSequence; - int fragmentLength; - unsigned char* fragmentBuffer; - int fragmentBufferSize; - int unsentFragments; - int unsentFragmentStart; - int unsentLength; - unsigned char* unsentBuffer; - int unsentBufferSize; - netProfileInfo_t prof; - }; - - static_assert(sizeof(netchan_t) == 0x630); - static_assert(sizeof(netProfileInfo_t) == 0x5E0); - - struct XZoneInfo - { - const char* name; - int allocFlags; - int freeFlags; - }; - - struct scr_entref_t - { - unsigned __int16 entnum; - unsigned __int16 classnum; - }; - - typedef void(__cdecl* scr_call_t)(int entref); - - enum MeansOfDeath - { - MOD_UNKNOWN = 0, - MOD_PISTOL_BULLET = 1, - MOD_RIFLE_BULLET = 2, - MOD_EXPLOSIVE_BULLET = 3, - MOD_GRENADE = 4, - MOD_GRENADE_SPLASH = 5, - MOD_PROJECTILE = 6, - MOD_PROJECTILE_SPLASH = 7, - MOD_MELEE = 8, - MOD_HEAD_SHOT = 9, - MOD_CRUSH = 10, - MOD_FALLING = 11, - MOD_SUICIDE = 12, - MOD_TRIGGER_HURT = 13, - MOD_EXPLOSIVE = 14, - MOD_IMPACT = 15, - MOD_NUM = 16 - }; - - enum scriptType_e - { - SCRIPT_NONE = 0, - SCRIPT_OBJECT = 1, - SCRIPT_STRING = 2, - SCRIPT_ISTRING = 3, - SCRIPT_VECTOR = 4, - SCRIPT_FLOAT = 5, - SCRIPT_INTEGER = 6, - SCRIPT_END = 8, - SCRIPT_FUNCTION = 9, - SCRIPT_STRUCT = 19, - SCRIPT_ARRAY = 22, - }; - - struct VariableStackBuffer - { - const char* pos; - unsigned __int16 size; - unsigned __int16 bufLen; - unsigned __int16 localId; - char time; - char buf[1]; - }; - - union VariableUnion - { - int intValue; - float floatValue; - unsigned int stringValue; - const float* vectorValue; - const char* codePosValue; - unsigned int pointerValue; - VariableStackBuffer* stackValue; - unsigned int entityId; - unsigned int uintValue; - }; - - struct VariableValue - { - VariableUnion u; - scriptType_e type; - }; - - struct function_stack_t - { - const char* pos; - unsigned int localId; - unsigned int localVarCount; - VariableValue* top; - VariableValue* startTop; - }; - - struct function_frame_t - { - function_stack_t fs; - int topType; - }; - - struct scrVmPub_t - { - unsigned int* localVars; - VariableValue* maxstack; - int function_count; - function_frame_t* function_frame; - VariableValue* top; - /*bool debugCode; - bool abort_on_error; - bool terminal_error; - bool block_execution;*/ - unsigned int inparamcount; - unsigned int outparamcount; - unsigned int breakpointOutparamcount; - bool showError; - function_frame_t function_frame_start[32]; - VariableValue stack[2048]; - }; - - struct scr_classStruct_t - { - unsigned __int16 id; - unsigned __int16 entArrayId; - char charId; - const char* name; - }; - - struct ObjectVariableChildren - { - unsigned __int16 firstChild; - unsigned __int16 lastChild; - }; - - struct ObjectVariableValue_u_f - { - unsigned __int16 prev; - unsigned __int16 next; - }; - - union ObjectVariableValue_u_o_u - { - unsigned __int16 size; - unsigned __int16 entnum; - unsigned __int16 nextEntId; - unsigned __int16 self; - }; - - struct ObjectVariableValue_u_o - { - unsigned __int16 refCount; - ObjectVariableValue_u_o_u u; - }; - - union ObjectVariableValue_w - { - unsigned int type; - unsigned int classnum; - unsigned int notifyName; - unsigned int waitTime; - unsigned int parentLocalId; - }; - - struct ChildVariableValue_u_f - { - unsigned __int16 prev; - unsigned __int16 next; - }; - - union ChildVariableValue_u - { - ChildVariableValue_u_f f; - VariableUnion u; - }; - - struct ChildBucketMatchKeys_keys - { - unsigned __int16 name_hi; - unsigned __int16 parentId; - }; - - union ChildBucketMatchKeys - { - ChildBucketMatchKeys_keys keys; - unsigned int match; - }; - - struct ChildVariableValue - { - ChildVariableValue_u u; - unsigned __int16 next; - char type; - char name_lo; - ChildBucketMatchKeys k; - unsigned __int16 nextSibling; - unsigned __int16 prevSibling; - }; - - union ObjectVariableValue_u - { - ObjectVariableValue_u_f f; - ObjectVariableValue_u_o o; - }; - - struct ObjectVariableValue - { - ObjectVariableValue_u u; - ObjectVariableValue_w w; - }; - - struct scrVarGlob_t - { - ObjectVariableValue objectVariableValue[36864]; - ObjectVariableChildren objectVariableChildren[36864]; - unsigned __int16 childVariableBucket[65536]; - ChildVariableValue childVariableValue[102400]; - }; - - enum dvar_flags : std::uint16_t - { - DVAR_FLAG_NONE = 0, - DVAR_FLAG_SAVED = 1, - DVAR_FLAG_LATCHED = 2, - DVAR_FLAG_CHEAT = 4, - DVAR_FLAG_REPLICATED = 0x8, - DVAR_FLAG_UNK1 = 0x40, - DVAR_FLAG_UNK2 = 0x200, - DVAR_FLAG_SYSTEM = 0x400, - DVAR_FLAG_WRITE = 0x800, - DVAR_FLAG_READONLY = 0x2000, - }; - - union DvarValue - { - bool enabled; - int integer; - unsigned int unsignedInt; - float value; - float vector[4]; - const char* string; - char color[4]; - }; - - struct enum_limit - { - int stringCount; - const char** strings; - }; - - struct int_limit - { - int min; - int max; - }; - - struct float_limit - { - float min; - float max; - }; - - union DvarLimits - { - enum_limit enumeration; - int_limit integer; - float_limit value; - float_limit vector; - }; - - struct dvar_t - { - const char* name; - unsigned int flags; - char type; - bool modified; - DvarValue current; - DvarValue latched; - DvarValue reset; - DvarLimits domain; - bool(__cdecl* domainFunc)(dvar_t*, DvarValue); - dvar_t* hashNext; - }; - - struct usercmd_s - { - int serverTime; - int buttons; - int angles[3]; - unsigned int weapon; - unsigned int offHand; - char forwardmove; - char rightmove; - unsigned __int16 airburstMarkDistance; - unsigned __int16 meleeChargeEnt; - unsigned char meleeChargeDist; - char selectedLoc[2]; - char selectedLocAngle; - char remoteControlAngles[2]; - int remoteControlMove; - }; - - enum LocSelInputState - { - LOC_SEL_INPUT_NONE = 0, - LOC_SEL_INPUT_CONFIRM = 1, - LOC_SEL_INPUT_CANCEL = 2 - }; - - struct field_t - { - int cursor; - int scroll; - int drawWidth; - int widthInPixels; - float charHeight; - int fixedSize; - char buffer[256]; - }; - - struct KeyState - { - int down; - int repeats; - int binding; - const char* bindingCheat; - }; - - static_assert(sizeof(field_t) == 280); - - struct PlayerKeyState - { - field_t chatField; - int chat_team; - int overstrikeMode; - int anyKeyDown; - KeyState keys[256]; - LocSelInputState locSelInputState; - }; - - static_assert(sizeof(PlayerKeyState) == 4392); - - enum EffectiveStance - { - PM_EFF_STANCE_DEFAULT = 0, - PM_EFF_STANCE_PRONE = 1, - PM_EFF_STANCE_DUCKED = 2, - PM_EFF_STANCE_LASTSTANDCRAWL = 3, - PM_EFF_STANCE_COUNT = 4 - }; - - enum clientState_t : std::int32_t - { - CS_FREE = 0, - CS_ZOMBIE = 1, - CS_UNKNOWN = 2, - CS_CONNECTED = 3, - CS_PRIMED = 4, - CS_ACTIVE = 5 - }; - - struct MantleState - { - float yaw; - int timer; - int transIndex; - int flags; - }; - - struct SprintState_s - { - int sprintButtonUpRequired; // 0x20C - int sprintDelay; // 0x210 - int lastSprintStart; - int lastSprintEnd; // 0x218 - int sprintStartMaxLength; - }; - - struct PlayerVehicleState - { - int entity; - int flags; - float origin[3]; - float angles[3]; - float velocity[3]; - float angVelocity[3]; - float tilt[2]; - float tiltVelocity[2]; - }; - - struct PlayerActiveWeaponState - { - int weapAnim; - int weaponTime; - int weaponDelay; - int weaponRestrictKickTime; - int weaponState; - int weaponHandFlags; - int weaponShotCount; - }; - - struct PlayerEquippedWeaponState - { - bool usedBefore; - bool dualWielding; - bool inAltMode; - bool needsRechamber[2]; - int zoomLevelIndex; - }; - - static_assert(sizeof(PlayerEquippedWeaponState) == 12); - - struct EntityEvent - { - int eventType; - int eventParm; - }; - - struct playerEvents_t - { - int eventSequence; - EntityEvent events[4]; - int oldEventSequence; - int timeADSCameUp; - }; - - static_assert(sizeof(playerEvents_t) == 44); - - enum ViewLockTypes - { - PLAYERVIEWLOCK_NONE = 0, - PLAYERVIEWLOCK_FULL = 1, - PLAYERVIEWLOCK_WEAPONJITTER = 2, - PLAYERVIEWLOCKCOUNT = 3 - }; - - enum TraceHitType - { - TRACE_HITTYPE_NONE = 0, - TRACE_HITTYPE_ENTITY = 1, - TRACE_HITTYPE_DYNENT_MODEL = 2, - TRACE_HITTYPE_DYNENT_BRUSH = 3, - TRACE_HITTYPE_GLASS = 4 - }; - -#pragma pack(push, 1) - struct playerState_s - { - int commandTime; - int pm_type; - int pm_time; - int pm_flags; - int otherFlags; - int linkFlags; - int bobCycle; - float origin[3]; - float velocity[3]; - int grenadeTimeLeft; - int throwbackGrenadeOwner; - int throwbackGrenadeTimeLeft; - unsigned int throwbackWeapon; - int remoteEyesEnt; - int remoteEyesTagname; - int remoteControlEnt; - int remoteTurretEnt; - int foliageSoundTime; - int gravity; - int speed; - float delta_angles[3]; - int groundEntityNum; - float vLadderVec[3]; - int jumpTime; - float jumpOriginZ; - int legsTimer; - int legsAnim; - int torsoTimer; - int torsoAnim; - int legsAnimDuration; - int torsoAnimDuration; - int damageTimer; - int damageDuration; - int flinchYawAnim; - int corpseIndex; - PlayerVehicleState vehicleState; - int movementDir; - int eFlags; - playerEvents_t pe; - int unpredictableEventSequence; - int unpredictableEventSequenceOld; - int unpredictableEvents[4]; - char unpredictableEventParms[16]; - int clientNum; - int viewmodelIndex; - float viewangles[3]; - int viewHeightTarget; - float viewHeightCurrent; - int viewHeightLerpTime; - int viewHeightLerpTarget; - int viewHeightLerpDown; - char viewAngleClampBase[8]; - char viewAngleClampRange[8]; - int damageEvent; - int damageYaw; - int damagePitch; - int damageCount; - int damageFlags; - int stats[4]; - float proneDirection; - float proneDirectionPitch; - float proneTorsoPitch; - ViewLockTypes viewlocked; - int viewlocked_entNum; - float linkAngles[3]; - float linkWeaponAngles[3]; - int linkWeaponEnt; - int loopSound; - int cursorHint; - int cursorHintString; - int cursorHintEntIndex; - int cursorHintDualWield; - int iCompassPlayerInfo; - int radarEnabled; - int radarBlocked; - int radarMode; - int radarStrength; - int radarShowEnemyDirection; - int locationSelectionInfo; - SprintState_s sprintState; - float holdBreathScale; - int holdBreathTimer; - float moveSpeedScaleMultiplier; - MantleState mantleState; - PlayerActiveWeaponState weapState[2]; - unsigned int weaponsEquipped[15]; - PlayerEquippedWeaponState weapEquippedData[15]; - char weapCommon[376]; - int meleeChargeDist; - int meleeChargeTime; - int meleeChargeEnt; - int airburstMarkDistance; - unsigned int perks[2]; - unsigned int perkSlots[9]; - char __pad0[11752]; - }; - - struct pmove_t - { - playerState_s* ps; - usercmd_s cmd; - usercmd_s oldcmd; - int tracemask; - int numtouch; - int touchents[32]; - char bounds[24]; - float speed; - int proneChange; - float maxSprintTimeMultiplier; - bool mantleStarted; - float mantleEndPos[3]; - int mantleDuration; - int viewChangeTime; - float viewChange; - float fTorsoPitch; - float fWaistPitch; - int remoteTurretFireTime; - int lastUpdateCMDServerTime; - unsigned char handler; - }; -#pragma pack(pop) - - static_assert(sizeof(playerState_s) == 13056); - - struct gclient_s - { - playerState_s ps; - char __pad0[716]; - int flags; - int spectatorClient; - int lastCmdTime; -// int mpviewer; // Debug ? - int buttons; - int oldButtons; - int latched_buttons; - int buttonsSinceLastFrame; - float oldOrigin[3]; - float fGunPitch; - float fGunYaw; - int damage_blood; - int damage_stun; - float damage_from[3]; - int damage_fromWorld; - int accurateCount; - int accuracy_shots; - int accuracy_hits; - int inactivityTime; - int inactivityWarning; - int lastVoiceTime; - int switchTeamTime; - float currentAimSpreadScale; - float prevLinkedInvQuat[4]; - bool prevLinkAnglesSet; - bool link_rotationMovesEyePos; - bool link_doCollision; - bool link_useTagAnglesForViewAngles; - bool link_useBaseAnglesForViewClamp; - float linkAnglesFrac; - char link_viewClamp[64]; - char persistantPowerup[4]; - int portalID; - int dropWeaponTime; - int sniperRifleFiredTime; - float sniperRifleMuzzleYaw; - int PCSpecialPickedUpCount; - int useHoldEntity; - int useHoldTime; - int useButtonDone; - int iLastCompassPlayerInfoEnt; - int compassPingTime; - int damageTime; - float v_dmg_roll; - float v_dmg_pitch; - float baseAngles[3]; - float baseOrigin[3]; - float swayViewAngles[3]; - float swayOffset[3]; - float swayAngles[3]; - float recoilAngles[3]; - float recoilSpeed[3]; - float fLastIdleFactor; - int lastServerTime; - int lastWeapon; - bool lastWeaponAltStatus; - bool previouslyFiring; - bool previouslyFiringLeftHand; - bool previouslyUsingNightVision; - bool previouslySprinting; - int visionDuration[6]; - char visionName[384]; - int lastStand; - int lastStandTime; - int hudElemLastAssignedSoundID; - float lockedTargetOffset[3]; - unsigned __int16 attachShieldTagName; - int hintForcedType; - int hintForcedString; - }; - - struct clientConnection_t - { - int qport; // 0 - int clientNum; // 4 - int lastPacketSentTime; // 8 - int lastPacketTime; // 12 - netadr_s serverAddress; // 16 - int connectTime; // 40 - int connectPacketCount; // 44 - char serverMessage[256]; // 48 - int challenge; // 304 - int checksumFeed; // 308 - int reliableSequence; // 312 - int reliableAcknowledge; // 316 - char reliableCommands[128][1024]; // 320 - int serverMessageSequence; // 131392 - int serverCommandSequence; // 131396 - int lastExecutedServerCommand; // 131400 - char serverCommands[128][1024]; // 131404 - bool isServerRestarting; // 262476 - char clientDemo[16592]; // 262480 - netchan_t netchan; // 279072 - char netchanOutgoingBuffer[2048]; // 280656 - char netchanIncomingBuffer[65536]; // 282704 - netProfileInfo_t OOBProf; // 348240 - short statPacketsToSend; // 349744 - int statPacketSendTime[10]; // From here it might be wrong - int currentGamestatePacket; - }; - - struct clientStatic_t - { - }; -} +#pragma warning(disable : 4324) + +namespace game { +typedef float vec_t; +typedef vec_t vec2_t[2]; +typedef vec_t vec3_t[3]; +typedef vec_t vec4_t[4]; + +struct cmd_function_t { + cmd_function_t* next; + const char* name; + const char* autoCompleteDir; + const char* autoCompleteExt; + void(__cdecl* function)(); + int flags; +}; + +struct CmdArgs { + int nesting; + int localClientNum[8]; + int controllerIndex[8]; + int argc[8]; + const char** argv[8]; +}; + +struct kbutton_t { + int down[2]; + unsigned int downtime; + unsigned int msec; + bool active; + bool wasPressed; +}; + +static_assert(sizeof(kbutton_t) == 20); + +typedef enum { + NS_CLIENT1 = 0, + NS_CLIENT2 = 1, + NS_CLIENT3 = 2, + NS_CLIENT4 = 3, + NS_MAXCLIENTS = 4, + NS_SERVER = 4, + NS_PACKET = 5, + NS_INVALID_NETSRC = 6 +} netsrc_t; + +enum netadrtype_t { + NA_BOT = 0x0, + NA_BAD = 0x1, + NA_LOOPBACK = 0x2, + NA_BROADCAST = 0x3, + NA_IP = 0x4 +}; + +struct netadr_s { + netadrtype_t type; + unsigned char ip[4]; + unsigned __int16 port; + unsigned char ipx[10]; + unsigned int addrHandleIndex; +}; + +static_assert(sizeof(netadr_s) == 24); + +typedef enum { + ERR_FATAL = 0x0, + ERR_DROP = 0x1, + ERR_SERVERDISCONNECT = 0x2, + ERR_DISCONNECT = 0x3, + ERR_SCRIPT = 0x4, + ERR_SCRIPT_DROP = 0x5, + ERR_LOCALIZATION = 0x6, + ERR_MAPLOADERRORSUMMARY = 0x7 +} errorParm_t; + +enum class LocalClientNum_t { + LOCAL_CLIENT_0 = 0, + LOCAL_CLIENT_1 = 1, + LOCAL_CLIENT_2 = 2, + LOCAL_CLIENT_3 = 3, + LOCAL_CLIENT_LAST = 3, + LOCAL_CLIENT_COUNT = 4 +}; + +typedef enum { + CA_DISCONNECTED = 0, + CA_CINEMATIC = 1, + CA_LOGO = 2, + CA_CONNECTING = 3, + CA_CHALLENGING = 4, + CA_CONNECTED = 5, + CA_SENDINGSTATS = 6, + CA_REQUESTING_MATCH_RULES = 7, + CA_LOADING = 8, + CA_PRIMED = 9, + CA_ACTIVE = 10 +} connstate_t; + +struct msg_t { + int overflowed; + int readOnly; + unsigned char* data; + unsigned char* splitData; + int maxsize; + int cursize; + int splitSize; + int readcount; + int bit; + int lastEntityRef; +}; + +struct netProfilePacket_t { + int iTime; + int iSize; + int bFragment; +}; + +struct netProfileStream_t { + netProfilePacket_t packets[60]; + int iCurrPacket; + int iBytesPerSeconds; + int iLastBPSCalcTime; + int iCountedPackets; + int iCountedFragments; + int iFragmentPercentage; + int iLargestPacket; + int iSmallestPacket; +}; + +struct netProfileInfo_t { + netProfileStream_t send; + netProfileStream_t recieve; +}; + +static_assert(sizeof(netProfileInfo_t) == 0x5E0); + +struct netchan_t { + int outgoingSequence; + netsrc_t sock; + int dropped; + int incomingSequence; + netadr_s remoteAddress; + int qport; + int fragmentSequence; + int fragmentLength; + unsigned char* fragmentBuffer; + int fragmentBufferSize; + int unsentFragments; + int unsentFragmentStart; + int unsentLength; + unsigned char* unsentBuffer; + int unsentBufferSize; + netProfileInfo_t prof; +}; + +static_assert(sizeof(netchan_t) == 0x630); + +enum dvar_flags : std::uint16_t { + DVAR_NONE = 0x0, + DVAR_ARCHIVE = 0x1, + DVAR_CHEAT = 0x4, + DVAR_CODINFO = 0x8, + DVAR_SCRIPTINFO = 0x10, + DVAR_SERVERINFO = 0x400, + DVAR_WRITEPROTECTED = 0x800, + DVAR_READONLY = 0x2000, +}; + +union DvarValue { + bool enabled; + int integer; + unsigned int unsignedInt; + float value; + float vector[4]; + const char* string; + char color[4]; +}; + +struct enum_limit { + int stringCount; + const char** strings; +}; + +struct int_limit { + int min; + int max; +}; + +struct float_limit { + float min; + float max; +}; + +union DvarLimits { + enum_limit enumeration; + int_limit integer; + float_limit value; + float_limit vector; +}; + +struct dvar_t { + const char* name; + unsigned int flags; + char type; + bool modified; + DvarValue current; + DvarValue latched; + DvarValue reset; + DvarLimits domain; + bool(__cdecl* domainFunc)(dvar_t*, DvarValue); + dvar_t* hashNext; +}; + +struct usercmd_s { + int serverTime; + int buttons; + int angles[3]; + unsigned int weapon; + unsigned int offHand; + char forwardmove; + char rightmove; + unsigned __int16 airburstMarkDistance; + unsigned __int16 meleeChargeEnt; + unsigned char meleeChargeDist; + char selectedLoc[2]; + char selectedLocAngle; + char remoteControlAngles[2]; + int remoteControlMove; +}; + +enum LocSelInputState { + LOC_SEL_INPUT_NONE = 0, + LOC_SEL_INPUT_CONFIRM = 1, + LOC_SEL_INPUT_CANCEL = 2 +}; + +struct field_t { + int cursor; + int scroll; + int drawWidth; + int widthInPixels; + float charHeight; + int fixedSize; + char buffer[256]; +}; + +struct KeyState { + int down; + int repeats; + int binding; + const char* bindingCheat; +}; + +static_assert(sizeof(field_t) == 280); + +struct PlayerKeyState { + field_t chatField; + int chat_team; + int overstrikeMode; + int anyKeyDown; + KeyState keys[256]; + LocSelInputState locSelInputState; +}; + +static_assert(sizeof(PlayerKeyState) == 4392); + +enum clientState_t { + CS_FREE = 0, + CS_ZOMBIE = 1, + CS_RECONNECTING = 2, + CS_CONNECTED = 3, + CS_PRIMED = 4, + CS_ACTIVE = 5 +}; + +struct clientConnection_t { + int qport; // 0 + int clientNum; // 4 + int lastPacketSentTime; // 8 + int lastPacketTime; // 12 + netadr_s serverAddress; // 16 + int connectTime; // 40 + int connectPacketCount; // 44 + char serverMessage[256]; // 48 + int challenge; // 304 + int checksumFeed; // 308 + int reliableSequence; // 312 + int reliableAcknowledge; // 316 + char reliableCommands[128][1024]; // 320 + int serverMessageSequence; // 131392 + int serverCommandSequence; // 131396 + int lastExecutedServerCommand; // 131400 + char serverCommands[128][1024]; // 131404 + bool isServerRestarting; // 262476 + char clientDemo[16592]; // 262480 + netchan_t netchan; // 279072 + char netchanOutgoingBuffer[2048]; // 280656 + char netchanIncomingBuffer[65536]; // 282704 + netProfileInfo_t OOBProf; // 348240 + short statPacketsToSend; // 349744 + int statPacketSendTime[10]; // From here it might be wrong + int currentGamestatePacket; +}; + +struct clientStatic_t {}; +} // namespace game #pragma warning(pop) diff --git a/src/game/symbols.hpp b/src/game/symbols.hpp index 7c37493..79ba04f 100644 --- a/src/game/symbols.hpp +++ b/src/game/symbols.hpp @@ -2,66 +2,78 @@ #define WEAK __declspec(selectany) -namespace game -{ - // Functions - WEAK symbol Sys_ShowConsole{0x515CD0}; - WEAK symbol Sys_CreateConsole{0x51B770}; - WEAK symbol Sys_Error{0x434000}; - WEAK symbol Conbuf_AppendText{0x4F7300}; - WEAK symbol Com_Error{0x4A6660}; - WEAK symbol ConcatArgs{0x539060}; - WEAK symbol Cbuf_AddText{0x4C1030}; - WEAK symbol Cbuf_InsertText{0x429920}; - WEAK symbol Cmd_AddCommandInternal{0x537E70}; - WEAK symbol Cmd_ExecuteSingleCommand{0x4EB8F0}; - WEAK symbol Cmd_RemoveCommand{0x4EAF30}; - WEAK symbol Cmd_Argv{0x5580E0}; +namespace game { +// Functions +WEAK symbol Sys_ShowConsole{0x515CD0}; +WEAK symbol Sys_CreateConsole{0x51B770}; +WEAK symbol Sys_Error{0x434000}; +WEAK symbol Conbuf_AppendText{0x4F7300}; +WEAK symbol Com_Error{0x4A6660}; +WEAK symbol ConcatArgs{0x539060}; +WEAK symbol Cbuf_AddText{0x4C1030}; +WEAK symbol Cbuf_InsertText{0x429920}; +WEAK symbol + Cmd_AddCommandInternal{0x537E70}; +WEAK symbol + Cmd_ExecuteSingleCommand{0x4EB8F0}; +WEAK symbol Cmd_RemoveCommand{0x4EAF30}; +WEAK symbol Cmd_Argv{0x5580E0}; - WEAK symbol Dvar_FindVar{0x4EBB50}; - WEAK symbol - Dvar_RegisterInt{0x50C760}; - WEAK symbol - Dvar_RegisterBool{0x4A3300}; - WEAK symbol - Dvar_RegisterString{0x4157E0}; - WEAK symbol - Dvar_RegisterFloat{0x4A5CF0}; - WEAK symbol Dvar_SetBool{0x46DD70}; - WEAK symbol Dvar_SetBoolByName{0x48C7D0}; - WEAK symbol Dvar_InfoString{0x4028C0}; +WEAK symbol Dvar_FindVar{0x4EBB50}; +WEAK symbol + Dvar_RegisterInt{0x50C760}; +WEAK symbol + Dvar_RegisterBool{0x4A3300}; +WEAK symbol + Dvar_RegisterString{0x4157E0}; +WEAK symbol + Dvar_RegisterFloat{0x4A5CF0}; +WEAK symbol Dvar_SetBool{0x46DD70}; +WEAK symbol Dvar_SetBoolByName{ + 0x48C7D0}; +WEAK symbol Dvar_InfoString{0x4028C0}; - WEAK symbol Key_GetBindingForCmd{0x47D300}; - WEAK symbol Key_StringToKeynum{0x50A710}; // Virtual-Key Code - WEAK symbol Key_SetBinding{0x50B770}; +WEAK symbol Key_GetBindingForCmd{0x47D300}; +WEAK symbol Key_StringToKeynum{ + 0x50A710}; // Virtual-Key Code +WEAK symbol Key_SetBinding{0x50B770}; - WEAK symbol SV_Cmd_ArgvBuffer{0x4F6B00}; +WEAK symbol SV_Cmd_ArgvBuffer{ + 0x4F6B00}; - WEAK symbol NET_OutOfBandPrint{0x496230}; - WEAK symbol NET_OutOfBandData{0x4639C0}; - WEAK symbol dwSendTo{0x673B20}; - WEAK symbol NetadrToSockadr{0x48B460}; - WEAK symbol NET_StringToAdr{0x4E09A0}; - WEAK symbol query_socket{0x5A861EC}; - WEAK symbol Com_Quit_f{0x556060}; +WEAK symbol + NET_OutOfBandPrint{0x496230}; +WEAK symbol + NET_OutOfBandData{0x4639C0}; +WEAK symbol dwSendTo{0x673B20}; +WEAK symbol NetadrToSockadr{0x48B460}; +WEAK symbol NET_StringToAdr{ + 0x4E09A0}; +WEAK symbol query_socket{0x5A861EC}; +WEAK symbol Com_Quit_f{0x556060}; - WEAK symbol MSG_Init{0x40E030}; - WEAK symbol MSG_WriteString{0x42A560}; - WEAK symbol MSG_WriteInt64{0x4906B0}; - WEAK symbol MSG_WriteShort{0x4ACD80}; - WEAK symbol MSG_WriteData{0x4F8C20}; - WEAK symbol CL_AddReliableCommand{0x4EE3A0}; +WEAK symbol MSG_Init{0x40E030}; +WEAK symbol MSG_WriteString{0x42A560}; +WEAK symbol MSG_WriteInt64{0x4906B0}; +WEAK symbol MSG_WriteShort{0x4ACD80}; +WEAK symbol MSG_WriteData{0x4F8C20}; +WEAK symbol CL_AddReliableCommand{0x4EE3A0}; - WEAK symbol LiveSteam_GetUid{0x4A4050}; - WEAK symbol LiveSteam_Client_ConnectToSteamServer{0x4D6980}; +WEAK symbol LiveSteam_GetUid{0x4A4050}; +WEAK symbol + LiveSteam_Client_ConnectToSteamServer{0x4D6980}; - // Variables - WEAK symbol cmd_args{0x1C96850}; - WEAK symbol playerKeys{0xB3A38C}; - WEAK symbol localClientConnection{0xB3D360}; - WEAK symbol g_wv_hWnd{0x5A86AF0}; - WEAK symbol s_wcd_hWnd{0x5A86330}; - WEAK symbol serverId{0xFF5058}; - WEAK symbol connectionState{0x1060214}; - WEAK symbol cl_paused{0x1CE6190}; -} +// Variables +WEAK symbol cmd_args{0x1C96850}; +WEAK symbol playerKeys{0xB3A38C}; +WEAK symbol localClientConnection{0xB3D360}; +WEAK symbol g_wv_hWnd{0x5A86AF0}; +WEAK symbol s_wcd_hWnd{0x5A86330}; +WEAK symbol serverId{0xFF5058}; +WEAK symbol connectionState{0x1060214}; +WEAK symbol cl_paused{0x1CE6190}; +} // namespace game diff --git a/src/loader/component_interface.hpp b/src/loader/component_interface.hpp index e1ee433..e839963 100644 --- a/src/loader/component_interface.hpp +++ b/src/loader/component_interface.hpp @@ -1,35 +1,21 @@ #pragma once -class component_interface -{ +class component_interface { public: - virtual ~component_interface() - { - } + virtual ~component_interface() {} - virtual void post_start() - { - } + virtual void post_start() {} - virtual void post_load() - { - } + virtual void post_load() {} - virtual void pre_destroy() - { - } + virtual void pre_destroy() {} - virtual void post_unpack() - { - } + virtual void post_unpack() {} - virtual void* load_import([[maybe_unused]] const std::string& library, [[maybe_unused]] const std::string& function) - { - return nullptr; - } + virtual void* load_import([[maybe_unused]] const std::string& library, + [[maybe_unused]] const std::string& function) { + return nullptr; + } - virtual bool is_supported() - { - return true; - } + virtual bool is_supported() { return true; } }; diff --git a/src/loader/component_loader.cpp b/src/loader/component_loader.cpp index d6a0090..c6e3f18 100644 --- a/src/loader/component_loader.cpp +++ b/src/loader/component_loader.cpp @@ -1,127 +1,111 @@ #include #include "component_loader.hpp" -void component_loader::register_component(std::unique_ptr&& component_) -{ - get_components().push_back(std::move(component_)); +void component_loader::register_component( + std::unique_ptr&& component_) { + get_components().push_back(std::move(component_)); } -bool component_loader::post_start() -{ - static auto handled = false; - if (handled) return true; - handled = true; +bool component_loader::post_start() { + static auto handled = false; + if (handled) + return true; + handled = true; - try - { - for (const auto& component_ : get_components()) - { - component_->post_start(); - } - } - catch (premature_shutdown_trigger&) - { - return false; - } + try { + for (const auto& component_ : get_components()) { + component_->post_start(); + } + } catch (premature_shutdown_trigger&) { + return false; + } - return true; + return true; } -bool component_loader::post_load() -{ - static auto handled = false; - if (handled) return true; - handled = true; +bool component_loader::post_load() { + static auto handled = false; + if (handled) + return true; + handled = true; - clean(); + clean(); - try - { - for (const auto& component_ : get_components()) - { - component_->post_load(); - } - } - catch (premature_shutdown_trigger&) - { - return false; - } + try { + for (const auto& component_ : get_components()) { + component_->post_load(); + } + } catch (premature_shutdown_trigger&) { + return false; + } - return true; + return true; } -void component_loader::post_unpack() -{ - static auto handled = false; - if (handled) return; - handled = true; +void component_loader::post_unpack() { + static auto handled = false; + if (handled) + return; + handled = true; - for (const auto& component_ : get_components()) - { - component_->post_unpack(); - } + for (const auto& component_ : get_components()) { + component_->post_unpack(); + } } -void component_loader::pre_destroy() -{ - static auto handled = false; - if (handled) return; - handled = true; +void component_loader::pre_destroy() { + static auto handled = false; + if (handled) + return; + handled = true; - for (const auto& component_ : get_components()) - { - component_->pre_destroy(); - } + for (const auto& component_ : get_components()) { + component_->pre_destroy(); + } } -void component_loader::clean() -{ - auto& components = get_components(); - for (auto i = components.begin(); i != components.end();) - { - if (!(*i)->is_supported()) - { - (*i)->pre_destroy(); - i = components.erase(i); - } - else - { - ++i; - } - } +void component_loader::clean() { + auto& components = get_components(); + for (auto i = components.begin(); i != components.end();) { + if (!(*i)->is_supported()) { + (*i)->pre_destroy(); + i = components.erase(i); + } else { + ++i; + } + } } -void* component_loader::load_import(const std::string& library, const std::string& function) -{ - void* function_ptr = nullptr; +void* component_loader::load_import(const std::string& library, + const std::string& function) { + void* function_ptr = nullptr; - for (const auto& component_ : get_components()) - { - auto* const component_function_ptr = component_->load_import(library, function); - if (component_function_ptr) - { - function_ptr = component_function_ptr; - } - } + for (const auto& component_ : get_components()) { + auto* const component_function_ptr = + component_->load_import(library, function); + if (component_function_ptr) { + function_ptr = component_function_ptr; + } + } - return function_ptr; + return function_ptr; } -void component_loader::trigger_premature_shutdown() -{ - throw premature_shutdown_trigger(); +void component_loader::trigger_premature_shutdown() { + throw premature_shutdown_trigger(); } -std::vector>& component_loader::get_components() -{ - using component_vector = std::vector>; - using component_vector_container = std::unique_ptr>; +std::vector>& +component_loader::get_components() { + using component_vector = std::vector>; + using component_vector_container = + std::unique_ptr>; - static component_vector_container components(new component_vector, [](component_vector* component_vector) - { - pre_destroy(); - delete component_vector; - }); + static component_vector_container components( + new component_vector, [](component_vector* component_vector) { + pre_destroy(); + delete component_vector; + }); - return *components; + return *components; } diff --git a/src/loader/component_loader.hpp b/src/loader/component_loader.hpp index 1f6b4d1..5d94b52 100644 --- a/src/loader/component_loader.hpp +++ b/src/loader/component_loader.hpp @@ -1,61 +1,51 @@ #pragma once #include "component_interface.hpp" -class component_loader final -{ +class component_loader final { public: - class premature_shutdown_trigger final : public std::exception - { - [[nodiscard]] const char* what() const noexcept override - { - return "Premature shutdown requested"; - } - }; + class premature_shutdown_trigger final : public std::exception { + [[nodiscard]] const char* what() const noexcept override { + return "Premature shutdown requested"; + } + }; - template - class installer final - { - static_assert(std::is_base_of::value, "component has invalid base class"); + template class installer final { + static_assert(std::is_base_of::value, + "component has invalid base class"); - public: - installer() - { - register_component(std::make_unique()); - } - }; + public: + installer() { register_component(std::make_unique()); } + }; - template - static T* get() - { - for (const auto& component_ : get_components()) - { - if (typeid(*component_.get()) == typeid(T)) - { - return reinterpret_cast(component_.get()); - } - } + template static T* get() { + for (const auto& component_ : get_components()) { + if (typeid(*component_.get()) == typeid(T)) { + return reinterpret_cast(component_.get()); + } + } - return nullptr; - } + return nullptr; + } - static void register_component(std::unique_ptr&& component); + static void + register_component(std::unique_ptr&& component); - static bool post_start(); - static bool post_load(); - static void post_unpack(); - static void pre_destroy(); - static void clean(); + static bool post_start(); + static bool post_load(); + static void post_unpack(); + static void pre_destroy(); + static void clean(); - static void* load_import(const std::string& library, const std::string& function); + static void* load_import(const std::string& library, + const std::string& function); - static void trigger_premature_shutdown(); + static void trigger_premature_shutdown(); private: - static std::vector>& get_components(); + static std::vector>& get_components(); }; -#define REGISTER_COMPONENT(name) \ -namespace \ -{ \ - static component_loader::installer __component; \ -} +#define REGISTER_COMPONENT(name) \ + namespace { \ + static component_loader::installer __component; \ + } diff --git a/src/stdinc.hpp b/src/stdinc.hpp index 434a8d7..bb3cf05 100644 --- a/src/stdinc.hpp +++ b/src/stdinc.hpp @@ -4,23 +4,21 @@ #define WIN32_LEAN_AND_MEAN -#include #include +#include -#include +#include #include +#include +#include #include #include -#include -#include -#include -#include -#include -#include #pragma comment(lib, "ntdll.lib") using namespace std::literals; +// clang-format off #include "game/structs.hpp" #include "game/game.hpp" +// clang-format on diff --git a/src/utils/concurrency.hpp b/src/utils/concurrency.hpp index 05c5d3a..cfcb6cc 100644 --- a/src/utils/concurrency.hpp +++ b/src/utils/concurrency.hpp @@ -2,45 +2,35 @@ #include -namespace utils::concurrency -{ - template - class container - { - public: - template - R access(F&& accessor) const - { - std::lock_guard _{mutex_}; - return accessor(object_); - } +namespace utils::concurrency { +template class container { +public: + template R access(F&& accessor) const { + std::lock_guard _{mutex_}; + return accessor(object_); + } - template - R access(F&& accessor) - { - std::lock_guard _{mutex_}; - return accessor(object_); - } + template R access(F&& accessor) { + std::lock_guard _{mutex_}; + return accessor(object_); + } - template - R access_with_lock(F&& accessor) const - { - std::unique_lock lock{mutex_}; - return accessor(object_, lock); - } + template + R access_with_lock(F&& accessor) const { + std::unique_lock lock{mutex_}; + return accessor(object_, lock); + } - template - R access_with_lock(F&& accessor) - { - std::unique_lock lock{mutex_}; - return accessor(object_, lock); - } + template R access_with_lock(F&& accessor) { + std::unique_lock lock{mutex_}; + return accessor(object_, lock); + } - T& get_raw() { return object_; } - const T& get_raw() const { return object_; } + T& get_raw() { return object_; } + const T& get_raw() const { return object_; } - private: - mutable MutexType mutex_{}; - T object_{}; - }; -} +private: + mutable MutexType mutex_{}; + T object_{}; +}; +} // namespace utils::concurrency diff --git a/src/utils/hook.cpp b/src/utils/hook.cpp index 81e7f78..6fbac56 100644 --- a/src/utils/hook.cpp +++ b/src/utils/hook.cpp @@ -5,191 +5,154 @@ #include -namespace utils::hook -{ - namespace - { - [[maybe_unused]] class _ - { - public: - _() - { - if (MH_Initialize() != MH_OK) - { - throw std::runtime_error("Failed to initialize MinHook"); - } - } +namespace utils::hook { +namespace { +[[maybe_unused]] class _ { +public: + _() { + if (MH_Initialize() != MH_OK) { + throw std::runtime_error("Failed to initialize MinHook"); + } + } - ~_() - { - MH_Uninitialize(); - } - } __; - } + ~_() { MH_Uninitialize(); } +} __; +} // namespace - detour::detour(const size_t place, void* target) : detour(reinterpret_cast(place), target) - { - } +detour::detour(const size_t place, void* target) + : detour(reinterpret_cast(place), target) {} - detour::detour(void* place, void* target) - { - this->create(place, target); - } +detour::detour(void* place, void* target) { this->create(place, target); } - detour::~detour() - { - this->clear(); - } +detour::~detour() { this->clear(); } - void detour::enable() const - { - MH_EnableHook(this->place_); - } +void detour::enable() const { MH_EnableHook(this->place_); } - void detour::disable() const - { - MH_DisableHook(this->place_); - } +void detour::disable() const { MH_DisableHook(this->place_); } - void detour::create(void* place, void* target) - { - this->clear(); - this->place_ = place; +void detour::create(void* place, void* target) { + this->clear(); + this->place_ = place; - if (MH_CreateHook(this->place_, target, &this->original_) != MH_OK) - { - throw std::runtime_error(string::va("Unable to create hook at location: %p", this->place_)); - } + if (MH_CreateHook(this->place_, target, &this->original_) != MH_OK) { + throw std::runtime_error( + string::va("Unable to create hook at location: %p", this->place_)); + } - this->enable(); - } - - void detour::create(const size_t place, void* target) - { - this->create(reinterpret_cast(place), target); - } - - void detour::clear() - { - if (this->place_) - { - MH_RemoveHook(this->place_); - } - - this->place_ = nullptr; - this->original_ = nullptr; - } - - void* detour::get_original() const - { - return this->original_; - } - - void nop(void* place, const size_t length) - { - DWORD old_protect{}; - VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect); - - std::memset(place, 0x90, length); - - VirtualProtect(place, length, old_protect, &old_protect); - FlushInstructionCache(GetCurrentProcess(), place, length); - } - - void nop(const size_t place, const size_t length) - { - nop(reinterpret_cast(place), length); - } - - void copy(void* place, const void* data, const size_t length) - { - DWORD old_protect{}; - VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect); - - std::memmove(place, data, length); - - VirtualProtect(place, length, old_protect, &old_protect); - FlushInstructionCache(GetCurrentProcess(), place, length); - } - - void copy(const size_t place, const void* data, const size_t length) - { - copy(reinterpret_cast(place), data, length); - } - - bool is_relatively_far(const void* pointer, const void* data, const int offset) - { - const int64_t diff = size_t(data) - (size_t(pointer) + offset); - const auto small_diff = int32_t(diff); - return diff != int64_t(small_diff); - } - - void call(void* pointer, void* data) - { - if (is_relatively_far(pointer, data)) - { - throw std::runtime_error("Too far away to create 32bit relative branch"); - } - - auto* patch_pointer = PBYTE(pointer); - set(patch_pointer, 0xE8); - set(patch_pointer + 1, int32_t(size_t(data) - (size_t(pointer) + 5))); - } - - void call(const size_t pointer, void* data) - { - return call(reinterpret_cast(pointer), data); - } - - void call(const size_t pointer, const size_t data) - { - return call(pointer, reinterpret_cast(data)); - } - - void set(std::uintptr_t address, std::vector&& bytes) - { - DWORD oldProtect = 0; - - auto* place = reinterpret_cast(address); - VirtualProtect(place, bytes.size(), PAGE_EXECUTE_READWRITE, &oldProtect); - memcpy(place, bytes.data(), bytes.size()); - VirtualProtect(place, bytes.size(), oldProtect, &oldProtect); - FlushInstructionCache(GetCurrentProcess(), place, bytes.size()); - } - - void set(std::uintptr_t address, void* buffer, size_t size) - { - DWORD oldProtect = 0; - - auto* place = reinterpret_cast(address); - VirtualProtect(place, size, PAGE_EXECUTE_READWRITE, &oldProtect); - memcpy(place, buffer, size); - VirtualProtect(place, size, oldProtect, &oldProtect); - FlushInstructionCache(GetCurrentProcess(), place, size); - } - - void jump(std::uintptr_t address, void* destination) - { - if (!address) return; - - std::uint8_t* bytes = new std::uint8_t[5]; - *bytes = 0xE9; - *reinterpret_cast(bytes + 1) = CalculateRelativeJMPAddress(address, destination); - - set(address, bytes, 5); - - delete[] bytes; - } - - void redirect_jump(void* pointer, void* data) - { - char* operand_ptr = static_cast(pointer) + 2; - int new_operand = reinterpret_cast(data) - (reinterpret_cast(pointer) + 6); - set(operand_ptr, new_operand); - } - - void redirect_jump(size_t pointer, void* data) - { - redirect_jump(reinterpret_cast(pointer), data); - } + this->enable(); } + +void detour::create(const size_t place, void* target) { + this->create(reinterpret_cast(place), target); +} + +void detour::clear() { + if (this->place_) { + MH_RemoveHook(this->place_); + } + + this->place_ = nullptr; + this->original_ = nullptr; +} + +void* detour::get_original() const { return this->original_; } + +void nop(void* place, const size_t length) { + DWORD old_protect{}; + VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect); + + std::memset(place, 0x90, length); + + VirtualProtect(place, length, old_protect, &old_protect); + FlushInstructionCache(GetCurrentProcess(), place, length); +} + +void nop(const size_t place, const size_t length) { + nop(reinterpret_cast(place), length); +} + +void copy(void* place, const void* data, const size_t length) { + DWORD old_protect{}; + VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &old_protect); + + std::memmove(place, data, length); + + VirtualProtect(place, length, old_protect, &old_protect); + FlushInstructionCache(GetCurrentProcess(), place, length); +} + +void copy(const size_t place, const void* data, const size_t length) { + copy(reinterpret_cast(place), data, length); +} + +bool is_relatively_far(const void* pointer, const void* data, + const int offset) { + const int64_t diff = size_t(data) - (size_t(pointer) + offset); + const auto small_diff = int32_t(diff); + return diff != int64_t(small_diff); +} + +void call(void* pointer, void* data) { + if (is_relatively_far(pointer, data)) { + throw std::runtime_error("Too far away to create 32bit relative branch"); + } + + auto* patch_pointer = PBYTE(pointer); + set(patch_pointer, 0xE8); + set(patch_pointer + 1, + int32_t(size_t(data) - (size_t(pointer) + 5))); +} + +void call(const size_t pointer, void* data) { + return call(reinterpret_cast(pointer), data); +} + +void call(const size_t pointer, const size_t data) { + return call(pointer, reinterpret_cast(data)); +} + +void set(std::uintptr_t address, std::vector&& bytes) { + DWORD oldProtect = 0; + + auto* place = reinterpret_cast(address); + VirtualProtect(place, bytes.size(), PAGE_EXECUTE_READWRITE, &oldProtect); + memcpy(place, bytes.data(), bytes.size()); + VirtualProtect(place, bytes.size(), oldProtect, &oldProtect); + FlushInstructionCache(GetCurrentProcess(), place, bytes.size()); +} + +void set(std::uintptr_t address, void* buffer, size_t size) { + DWORD oldProtect = 0; + + auto* place = reinterpret_cast(address); + VirtualProtect(place, size, PAGE_EXECUTE_READWRITE, &oldProtect); + memcpy(place, buffer, size); + VirtualProtect(place, size, oldProtect, &oldProtect); + FlushInstructionCache(GetCurrentProcess(), place, size); +} + +void jump(std::uintptr_t address, void* destination) { + if (!address) + return; + + std::uint8_t* bytes = new std::uint8_t[5]; + *bytes = 0xE9; + *reinterpret_cast(bytes + 1) = + CalculateRelativeJMPAddress(address, destination); + + set(address, bytes, 5); + + delete[] bytes; +} + +void redirect_jump(void* pointer, void* data) { + char* operand_ptr = static_cast(pointer) + 2; + int new_operand = + reinterpret_cast(data) - (reinterpret_cast(pointer) + 6); + set(operand_ptr, new_operand); +} + +void redirect_jump(size_t pointer, void* data) { + redirect_jump(reinterpret_cast(pointer), data); +} +} // namespace utils::hook diff --git a/src/utils/hook.hpp b/src/utils/hook.hpp index a80740e..6cae5d3 100644 --- a/src/utils/hook.hpp +++ b/src/utils/hook.hpp @@ -1,120 +1,102 @@ #pragma once #include "signature.hpp" -#define CalculateRelativeJMPAddress(X, Y) (((std::uintptr_t)Y - (std::uintptr_t)X) - 5) +#define CalculateRelativeJMPAddress(X, Y) \ + (((std::uintptr_t)Y - (std::uintptr_t)X) - 5) -namespace utils::hook -{ - class detour - { - public: - detour() = default; - detour(void* place, void* target); - detour(size_t place, void* target); - ~detour(); +namespace utils::hook { +class detour { +public: + detour() = default; + detour(void* place, void* target); + detour(size_t place, void* target); + ~detour(); - detour(detour&& other) noexcept - { - this->operator=(std::move(other)); - } + detour(detour&& other) noexcept { this->operator=(std::move(other)); } - detour& operator= (detour&& other) noexcept - { - if (this != &other) - { - this->~detour(); + detour& operator=(detour&& other) noexcept { + if (this != &other) { + this->~detour(); - this->place_ = other.place_; - this->original_ = other.original_; + this->place_ = other.place_; + this->original_ = other.original_; - other.place_ = nullptr; - other.original_ = nullptr; - } + other.place_ = nullptr; + other.original_ = nullptr; + } - return *this; - } + return *this; + } - detour(const detour&) = delete; - detour& operator= (const detour&) = delete; + detour(const detour&) = delete; + detour& operator=(const detour&) = delete; - void enable() const; - void disable() const; + void enable() const; + void disable() const; - void create(void* place, void* target); - void create(size_t place, void* target); - void clear(); + void create(void* place, void* target); + void create(size_t place, void* target); + void clear(); - template - T* get() const - { - return static_cast(this->get_original()); - } + template T* get() const { + return static_cast(this->get_original()); + } - template - T invoke(Args... args) - { - return static_cast(this->get_original())(args...); - } + template T invoke(Args... args) { + return static_cast(this->get_original())(args...); + } - [[nodiscard]] void* get_original() const; + [[nodiscard]] void* get_original() const; - private: - void* place_{}; - void* original_{}; - }; +private: + void* place_{}; + void* original_{}; +}; - void nop(void* place, size_t length); - void nop(size_t place, size_t length); +void nop(void* place, size_t length); +void nop(size_t place, size_t length); - void copy(void* place, const void* data, size_t length); - void copy(size_t place, const void* data, size_t length); +void copy(void* place, const void* data, size_t length); +void copy(size_t place, const void* data, size_t length); - bool is_relatively_far(const void* pointer, const void* data, int offset = 5); +bool is_relatively_far(const void* pointer, const void* data, int offset = 5); - void call(void* pointer, void* data); - void call(size_t pointer, void* data); - void call(size_t pointer, size_t data); +void call(void* pointer, void* data); +void call(size_t pointer, void* data); +void call(size_t pointer, size_t data); - void jump(std::uintptr_t address, void* destination); +void jump(std::uintptr_t address, void* destination); - void redirect_jump(void* pointer, void* data); - void redirect_jump(size_t pointer, void* data); +void redirect_jump(void* pointer, void* data); +void redirect_jump(size_t pointer, void* data); - template - T extract(void* address) - { - const auto data = static_cast(address); - const auto offset = *reinterpret_cast(data); - return reinterpret_cast(data + offset + 4); - } - - template - static void set(void* place, T value) - { - DWORD old_protect; - VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &old_protect); - - *static_cast(place) = value; - - VirtualProtect(place, sizeof(T), old_protect, &old_protect); - FlushInstructionCache(GetCurrentProcess(), place, sizeof(T)); - } - - template - static void set(const size_t place, T value) - { - return set(reinterpret_cast(place), value); - } - - template - static T invoke(size_t func, Args ... args) - { - return reinterpret_cast(func)(args...); - } - - template - static T invoke(void* func, Args ... args) - { - return static_cast(func)(args...); - } +template T extract(void* address) { + const auto data = static_cast(address); + const auto offset = *reinterpret_cast(data); + return reinterpret_cast(data + offset + 4); } + +template static void set(void* place, T value) { + DWORD old_protect; + VirtualProtect(place, sizeof(T), PAGE_EXECUTE_READWRITE, &old_protect); + + *static_cast(place) = value; + + VirtualProtect(place, sizeof(T), old_protect, &old_protect); + FlushInstructionCache(GetCurrentProcess(), place, sizeof(T)); +} + +template static void set(const size_t place, T value) { + return set(reinterpret_cast(place), value); +} + +template +static T invoke(size_t func, Args... args) { + return reinterpret_cast(func)(args...); +} + +template +static T invoke(void* func, Args... args) { + return static_cast(func)(args...); +} +} // namespace utils::hook diff --git a/src/utils/info_string.cpp b/src/utils/info_string.cpp index 0a9415f..b82ad7a 100644 --- a/src/utils/info_string.cpp +++ b/src/utils/info_string.cpp @@ -3,64 +3,50 @@ #include "info_string.hpp" #include "string.hpp" -namespace utils -{ - info_string::info_string(const std::string& buffer) - { - this->parse(buffer); - } +namespace utils { +info_string::info_string(const std::string& buffer) { this->parse(buffer); } - info_string::info_string(const std::string_view& buffer) - : info_string(std::string{buffer}) - { - } +info_string::info_string(const std::string_view& buffer) + : info_string(std::string{buffer}) {} - void info_string::set(const std::string& key, const std::string& value) - { - this->key_value_pairs_[key] = value; - } - - std::string info_string::get(const std::string& key) const - { - const auto value = this->key_value_pairs_.find(key); - if (value != this->key_value_pairs_.end()) - { - return value->second; - } - - return ""; - } - - void info_string::parse(std::string buffer) - { - if (buffer[0] == '\\') - { - buffer = buffer.substr(1); - } - - auto key_values = string::split(buffer, '\\'); - for (size_t i = 0; !key_values.empty() && i < (key_values.size() - 1); i += 2) - { - const auto& key = key_values[i]; - const auto& value = key_values[i + 1]; - this->key_value_pairs_[key] = value; - } - } - - std::string info_string::build() const - { - //auto first = true; - std::string info_string; - for (auto i = this->key_value_pairs_.begin(); i != this->key_value_pairs_.end(); ++i) - { - //if (first) first = false; - /*else*/ info_string.append("\\"); - - info_string.append(i->first); // Key - info_string.append("\\"); - info_string.append(i->second); // Value - } - - return info_string; - } +void info_string::set(const std::string& key, const std::string& value) { + this->key_value_pairs_[key] = value; } + +std::string info_string::get(const std::string& key) const { + const auto value = this->key_value_pairs_.find(key); + if (value != this->key_value_pairs_.end()) { + return value->second; + } + + return {}; +} + +void info_string::parse(std::string buffer) { + if (buffer[0] == '\\') { + buffer = buffer.substr(1); + } + + const auto key_values = string::split(buffer, '\\'); + for (size_t i = 0; !key_values.empty() && i < (key_values.size() - 1); + i += 2) { + const auto& key = key_values[i]; + const auto& value = key_values[i + 1]; + this->key_value_pairs_[key] = value; + } +} + +std::string info_string::build() const { + std::string info_string; + for (auto i = this->key_value_pairs_.begin(); + i != this->key_value_pairs_.end(); ++i) { + info_string.append("\\"); + + info_string.append(i->first); // Key + info_string.append("\\"); + info_string.append(i->second); // Value + } + + return info_string; +} +} // namespace utils diff --git a/src/utils/info_string.hpp b/src/utils/info_string.hpp index 7391041..d722dff 100644 --- a/src/utils/info_string.hpp +++ b/src/utils/info_string.hpp @@ -3,22 +3,20 @@ #include #include -namespace utils -{ - class info_string - { - public: - info_string() = default; - info_string(const std::string& buffer); - info_string(const std::string_view& buffer); +namespace utils { +class info_string { +public: + info_string() = default; + explicit info_string(const std::string& buffer); + explicit info_string(const std::string_view& buffer); - void set(const std::string& key, const std::string& value); - std::string get(const std::string& key) const; - std::string build() const; + void set(const std::string& key, const std::string& value); + [[nodiscard]] std::string get(const std::string& key) const; + [[nodiscard]] std::string build() const; - private: - std::unordered_map key_value_pairs_{}; +private: + std::unordered_map key_value_pairs_; - void parse(std::string buffer); - }; -} + void parse(std::string buffer); +}; +} // namespace utils diff --git a/src/utils/memory.cpp b/src/utils/memory.cpp index af843e0..2fabec9 100644 --- a/src/utils/memory.cpp +++ b/src/utils/memory.cpp @@ -3,165 +3,134 @@ #include "memory.hpp" #include "nt.hpp" -namespace utils -{ - memory::allocator memory::mem_allocator_; +namespace utils { +memory::allocator memory::mem_allocator_; - memory::allocator::~allocator() - { - this->clear(); - } +memory::allocator::~allocator() { this->clear(); } - void memory::allocator::clear() - { - std::lock_guard _(this->mutex_); +void memory::allocator::clear() { + std::lock_guard _(this->mutex_); - for (auto& data : this->pool_) - { - memory::free(data); - } + for (const auto& data : this->pool_) { + memory::free(data); + } - this->pool_.clear(); - } - - void memory::allocator::free(void* data) - { - std::lock_guard _(this->mutex_); - - const auto j = std::find(this->pool_.begin(), this->pool_.end(), data); - if (j != this->pool_.end()) - { - memory::free(data); - this->pool_.erase(j); - } - } - - void memory::allocator::free(const void* data) - { - this->free(const_cast(data)); - } - - void* memory::allocator::allocate(const size_t length) - { - std::lock_guard _(this->mutex_); - - const auto data = memory::allocate(length); - this->pool_.push_back(data); - return data; - } - - bool memory::allocator::empty() const - { - return this->pool_.empty(); - } - - char* memory::allocator::duplicate_string(const std::string& string) - { - std::lock_guard _(this->mutex_); - - const auto data = memory::duplicate_string(string); - this->pool_.push_back(data); - return data; - } - - void* memory::allocate(const size_t length) - { - return calloc(length, 1); - } - - char* memory::duplicate_string(const std::string& string) - { - const auto new_string = allocate_array(string.size() + 1); - std::memcpy(new_string, string.data(), string.size()); - return new_string; - } - - void memory::free(void* data) - { - if (data) - { - ::free(data); - } - } - - void memory::free(const void* data) - { - free(const_cast(data)); - } - - bool memory::is_set(const void* mem, const char chr, const size_t length) - { - const auto mem_arr = static_cast(mem); - - for (size_t i = 0; i < length; ++i) - { - if (mem_arr[i] != chr) - { - return false; - } - } - - return true; - } - - bool memory::is_bad_read_ptr(const void* ptr) - { - MEMORY_BASIC_INFORMATION mbi = {}; - if (VirtualQuery(ptr, &mbi, sizeof(mbi))) - { - const DWORD mask = (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | - PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); - auto b = !(mbi.Protect & mask); - // check the page is not a guard page - if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true; - - return b; - } - return true; - } - - bool memory::is_bad_code_ptr(const void* ptr) - { - MEMORY_BASIC_INFORMATION mbi = {}; - if (VirtualQuery(ptr, &mbi, sizeof(mbi))) - { - const DWORD mask = (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); - auto b = !(mbi.Protect & mask); - // check the page is not a guard page - if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true; - - return b; - } - return true; - } - - bool memory::is_rdata_ptr(void* pointer) - { - const std::string rdata = ".rdata"; - const auto pointer_lib = utils::nt::library::get_by_address(pointer); - - for (const auto& section : pointer_lib.get_section_headers()) - { - const auto size = sizeof(section->Name); - char name[size + 1]; - name[size] = 0; - std::memcpy(name, section->Name, size); - - if (name == rdata) - { - const auto target = size_t(pointer); - const size_t source_start = size_t(pointer_lib.get_ptr()) + section->PointerToRawData; - const size_t source_end = source_start + section->SizeOfRawData; - - return target >= source_start && target <= source_end; - } - } - - return false; - } - - memory::allocator* memory::get_allocator() - { - return &memory::mem_allocator_; - } + this->pool_.clear(); } + +void memory::allocator::free(void* data) { + std::lock_guard _(this->mutex_); + + const auto j = std::find(this->pool_.begin(), this->pool_.end(), data); + if (j != this->pool_.end()) { + memory::free(data); + this->pool_.erase(j); + } +} + +void memory::allocator::free(const void* data) { + this->free(const_cast(data)); +} + +void* memory::allocator::allocate(const size_t length) { + std::lock_guard _(this->mutex_); + + const auto data = memory::allocate(length); + this->pool_.push_back(data); + return data; +} + +bool memory::allocator::empty() const { return this->pool_.empty(); } + +char* memory::allocator::duplicate_string(const std::string& string) { + std::lock_guard _(this->mutex_); + + const auto data = memory::duplicate_string(string); + this->pool_.push_back(data); + return data; +} + +void* memory::allocate(const size_t length) { return calloc(length, 1); } + +char* memory::duplicate_string(const std::string& string) { + const auto new_string = allocate_array(string.size() + 1); + std::memcpy(new_string, string.data(), string.size()); + return new_string; +} + +void memory::free(void* data) { + if (data) { + ::free(data); + } +} + +void memory::free(const void* data) { free(const_cast(data)); } + +bool memory::is_set(const void* mem, const char chr, const size_t length) { + const auto mem_arr = static_cast(mem); + + for (size_t i = 0; i < length; ++i) { + if (mem_arr[i] != chr) { + return false; + } + } + + return true; +} + +bool memory::is_bad_read_ptr(const void* ptr) { + MEMORY_BASIC_INFORMATION mbi = {}; + if (VirtualQuery(ptr, &mbi, sizeof(mbi))) { + const DWORD mask = + (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | + PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); + auto b = !(mbi.Protect & mask); + // check the page is not a guard page + if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) + b = true; + + return b; + } + return true; +} + +bool memory::is_bad_code_ptr(const void* ptr) { + MEMORY_BASIC_INFORMATION mbi = {}; + if (VirtualQuery(ptr, &mbi, sizeof(mbi))) { + const DWORD mask = + (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); + auto b = !(mbi.Protect & mask); + // check the page is not a guard page + if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) + b = true; + + return b; + } + return true; +} + +bool memory::is_rdata_ptr(void* ptr) { + const std::string rdata = ".rdata"; + const auto pointer_lib = utils::nt::library::get_by_address(ptr); + + for (const auto& section : pointer_lib.get_section_headers()) { + constexpr auto size = sizeof(section->Name); + char name[size + 1]; + name[size] = 0; + std::memcpy(name, section->Name, size); + + if (name == rdata) { + const auto target = size_t(ptr); + const size_t source_start = + size_t(pointer_lib.get_ptr()) + section->PointerToRawData; + const size_t source_end = source_start + section->SizeOfRawData; + + return target >= source_start && target <= source_end; + } + } + + return false; +} + +memory::allocator* memory::get_allocator() { return &memory::mem_allocator_; } +} // namespace utils diff --git a/src/utils/memory.hpp b/src/utils/memory.hpp index 5af5645..cacf25f 100644 --- a/src/utils/memory.hpp +++ b/src/utils/memory.hpp @@ -3,73 +3,58 @@ #include #include -namespace utils -{ - class memory final - { - public: - class allocator final - { - public: - ~allocator(); +namespace utils { +class memory final { +public: + class allocator final { + public: + ~allocator(); - void clear(); + void clear(); - void free(void* data); + void free(void* data); - void free(const void* data); + void free(const void* data); - void* allocate(size_t length); + void* allocate(size_t length); - template - inline T* allocate() - { - return this->allocate_array(1); - } + template T* allocate() { return this->allocate_array(1); } - template - inline T* allocate_array(const size_t count = 1) - { - return static_cast(this->allocate(count * sizeof(T))); - } + template T* allocate_array(const size_t count = 1) { + return static_cast(this->allocate(count * sizeof(T))); + } - bool empty() const; + bool empty() const; - char* duplicate_string(const std::string& string); + char* duplicate_string(const std::string& string); - private: - std::mutex mutex_; - std::vector pool_; - }; + private: + std::mutex mutex_; + std::vector pool_; + }; - static void* allocate(size_t length); + static void* allocate(size_t length); - template - static inline T* allocate() - { - return allocate_array(1); - } + template static T* allocate() { return allocate_array(1); } - template - static inline T* allocate_array(const size_t count = 1) - { - return static_cast(allocate(count * sizeof(T))); - } + template static T* allocate_array(const size_t count = 1) { + return static_cast(allocate(count * sizeof(T))); + } - static char* duplicate_string(const std::string& string); + static char* duplicate_string(const std::string& string); - static void free(void* data); - static void free(const void* data); + static void free(void* data); + static void free(const void* data); - static bool is_set(const void* mem, char chr, size_t length); + static bool is_set(const void* mem, char chr, size_t length); - static bool is_bad_read_ptr(const void* ptr); - static bool is_bad_code_ptr(const void* ptr); - static bool is_rdata_ptr(void* ptr); + static bool is_bad_read_ptr(const void* ptr); + static bool is_bad_code_ptr(const void* ptr); + static bool is_rdata_ptr(void* ptr); - static allocator* get_allocator(); + static allocator* get_allocator(); - private: - static allocator mem_allocator_; - }; -} +private: + static allocator mem_allocator_; +}; +} // namespace utils diff --git a/src/utils/nt.cpp b/src/utils/nt.cpp index 5d95ea6..fa5af71 100644 --- a/src/utils/nt.cpp +++ b/src/utils/nt.cpp @@ -2,255 +2,241 @@ #include "nt.hpp" -namespace utils::nt -{ - library library::load(const std::string& name) - { - return library(LoadLibraryA(name.data())); - } - - library library::load(const std::filesystem::path& path) - { - return library::load(path.generic_string()); - } - - library library::get_by_address(void* address) - { - HMODULE handle = nullptr; - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, static_cast(address), &handle); - return library(handle); - } - - library::library() - { - this->module_ = GetModuleHandleA(nullptr); - } - - library::library(const std::string& name) - { - this->module_ = GetModuleHandleA(name.data()); - } - - library::library(const HMODULE handle) - { - this->module_ = handle; - } - - bool library::operator==(const library& obj) const - { - return this->module_ == obj.module_; - } - - library::operator bool() const - { - return this->is_valid(); - } - - library::operator HMODULE() const - { - return this->get_handle(); - } - - PIMAGE_NT_HEADERS library::get_nt_headers() const - { - if (!this->is_valid()) return nullptr; - return reinterpret_cast(this->get_ptr() + this->get_dos_header()->e_lfanew); - } - - PIMAGE_DOS_HEADER library::get_dos_header() const - { - return reinterpret_cast(this->get_ptr()); - } - - PIMAGE_OPTIONAL_HEADER library::get_optional_header() const - { - if (!this->is_valid()) return nullptr; - return &this->get_nt_headers()->OptionalHeader; - } - - std::vector library::get_section_headers() const - { - std::vector headers; - - auto nt_headers = this->get_nt_headers(); - auto section = IMAGE_FIRST_SECTION(nt_headers); - - for (uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i, ++section) - { - if (section) headers.push_back(section); - else OutputDebugStringA("There was an invalid section :O"); - } - - return headers; - } - - std::uint8_t* library::get_ptr() const - { - return reinterpret_cast(this->module_); - } - - void library::unprotect() const - { - if (!this->is_valid()) return; - - DWORD protection; - VirtualProtect(this->get_ptr(), this->get_optional_header()->SizeOfImage, PAGE_EXECUTE_READWRITE, - &protection); - } - - size_t library::get_relative_entry_point() const - { - if (!this->is_valid()) return 0; - return this->get_nt_headers()->OptionalHeader.AddressOfEntryPoint; - } - - void* library::get_entry_point() const - { - if (!this->is_valid()) return nullptr; - return this->get_ptr() + this->get_relative_entry_point(); - } - - bool library::is_valid() const - { - return this->module_ != nullptr && this->get_dos_header()->e_magic == IMAGE_DOS_SIGNATURE; - } - - std::string library::get_name() const - { - if (!this->is_valid()) return ""; - - auto path = this->get_path(); - const auto pos = path.find_last_of("/\\"); - if (pos == std::string::npos) return path; - - return path.substr(pos + 1); - } - - std::string library::get_path() const - { - if (!this->is_valid()) return ""; - - char name[MAX_PATH] = {0}; - GetModuleFileNameA(this->module_, name, sizeof name); - - return name; - } - - std::string library::get_folder() const - { - if (!this->is_valid()) return ""; - - const auto path = std::filesystem::path(this->get_path()); - return path.parent_path().generic_string(); - } - - void library::free() - { - if (this->is_valid()) - { - FreeLibrary(this->module_); - this->module_ = nullptr; - } - } - - HMODULE library::get_handle() const - { - return this->module_; - } - - void** library::get_iat_entry(const std::string& module_name, const std::string& proc_name) const - { - if (!this->is_valid()) return nullptr; - - const library other_module(module_name); - if (!other_module.is_valid()) return nullptr; - - auto* const target_function = other_module.get_proc(proc_name); - if (!target_function) return nullptr; - - auto* header = this->get_optional_header(); - if (!header) return nullptr; - - auto* import_descriptor = reinterpret_cast(this->get_ptr() + header->DataDirectory - [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); - - while (import_descriptor->Name) - { - if (!_stricmp(reinterpret_cast(this->get_ptr() + import_descriptor->Name), module_name.data())) - { - auto* original_thunk_data = reinterpret_cast(import_descriptor-> - OriginalFirstThunk + this->get_ptr()); - auto* thunk_data = reinterpret_cast(import_descriptor->FirstThunk + this-> - get_ptr()); - - while (original_thunk_data->u1.AddressOfData) - { - const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF; - - if (ordinal_number > 0xFFFF) continue; - - if (GetProcAddress(other_module.module_, reinterpret_cast(ordinal_number)) == - target_function) - { - return reinterpret_cast(&thunk_data->u1.Function); - } - - ++original_thunk_data; - ++thunk_data; - } - - //break; - } - - ++import_descriptor; - } - - 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) return {}; - - auto* const handle = LoadResource(nullptr, res); - if (!handle) return {}; - - return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res)); - } - - void relaunch_self() - { - const utils::nt::library self; - - STARTUPINFOA startup_info; - PROCESS_INFORMATION process_info; - - ZeroMemory(&startup_info, sizeof(startup_info)); - ZeroMemory(&process_info, sizeof(process_info)); - startup_info.cb = sizeof(startup_info); - - char current_dir[MAX_PATH]; - GetCurrentDirectoryA(sizeof(current_dir), current_dir); - auto* const command_line = GetCommandLineA(); - - CreateProcessA(self.get_path().data(), command_line, nullptr, nullptr, false, NULL, nullptr, current_dir, - &startup_info, &process_info); - - if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE) CloseHandle(process_info.hThread); - if (process_info.hProcess && process_info.hProcess != INVALID_HANDLE_VALUE) CloseHandle(process_info.hProcess); - } - - void terminate(const uint32_t code) - { - TerminateProcess(GetCurrentProcess(), code); - } +namespace utils::nt { +library library::load(const std::string& name) { + return library(LoadLibraryA(name.data())); } + +library library::load(const std::filesystem::path& path) { + return library::load(path.generic_string()); +} + +library library::get_by_address(void* address) { + HMODULE handle = nullptr; + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + static_cast(address), &handle); + return library(handle); +} + +library::library() { this->module_ = GetModuleHandleA(nullptr); } + +library::library(const std::string& name) { + this->module_ = GetModuleHandleA(name.data()); +} + +library::library(const HMODULE handle) { this->module_ = handle; } + +bool library::operator==(const library& obj) const { + return this->module_ == obj.module_; +} + +library::operator bool() const { return this->is_valid(); } + +library::operator HMODULE() const { return this->get_handle(); } + +PIMAGE_NT_HEADERS library::get_nt_headers() const { + if (!this->is_valid()) + return nullptr; + return reinterpret_cast(this->get_ptr() + + this->get_dos_header()->e_lfanew); +} + +PIMAGE_DOS_HEADER library::get_dos_header() const { + return reinterpret_cast(this->get_ptr()); +} + +PIMAGE_OPTIONAL_HEADER library::get_optional_header() const { + if (!this->is_valid()) + return nullptr; + return &this->get_nt_headers()->OptionalHeader; +} + +std::vector library::get_section_headers() const { + std::vector headers; + + auto nt_headers = this->get_nt_headers(); + auto section = IMAGE_FIRST_SECTION(nt_headers); + + for (uint16_t i = 0; i < nt_headers->FileHeader.NumberOfSections; + ++i, ++section) { + if (section) + headers.push_back(section); + else + OutputDebugStringA("There was an invalid section :O"); + } + + return headers; +} + +std::uint8_t* library::get_ptr() const { + return reinterpret_cast(this->module_); +} + +void library::unprotect() const { + if (!this->is_valid()) + return; + + DWORD protection; + VirtualProtect(this->get_ptr(), this->get_optional_header()->SizeOfImage, + PAGE_EXECUTE_READWRITE, &protection); +} + +size_t library::get_relative_entry_point() const { + if (!this->is_valid()) + return 0; + return this->get_nt_headers()->OptionalHeader.AddressOfEntryPoint; +} + +void* library::get_entry_point() const { + if (!this->is_valid()) + return nullptr; + return this->get_ptr() + this->get_relative_entry_point(); +} + +bool library::is_valid() const { + return this->module_ != nullptr && + this->get_dos_header()->e_magic == IMAGE_DOS_SIGNATURE; +} + +std::string library::get_name() const { + if (!this->is_valid()) + return ""; + + auto path = this->get_path(); + const auto pos = path.find_last_of("/\\"); + if (pos == std::string::npos) + return path; + + return path.substr(pos + 1); +} + +std::string library::get_path() const { + if (!this->is_valid()) + return ""; + + char name[MAX_PATH] = {0}; + GetModuleFileNameA(this->module_, name, sizeof name); + + return name; +} + +std::string library::get_folder() const { + if (!this->is_valid()) + return ""; + + const auto path = std::filesystem::path(this->get_path()); + return path.parent_path().generic_string(); +} + +void library::free() { + if (this->is_valid()) { + FreeLibrary(this->module_); + this->module_ = nullptr; + } +} + +HMODULE library::get_handle() const { return this->module_; } + +void** library::get_iat_entry(const std::string& module_name, + const std::string& proc_name) const { + if (!this->is_valid()) + return nullptr; + + const library other_module(module_name); + if (!other_module.is_valid()) + return nullptr; + + auto* const target_function = other_module.get_proc(proc_name); + if (!target_function) + return nullptr; + + auto* header = this->get_optional_header(); + if (!header) + return nullptr; + + auto* import_descriptor = reinterpret_cast( + this->get_ptr() + + header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + + while (import_descriptor->Name) { + if (!_stricmp( + reinterpret_cast(this->get_ptr() + import_descriptor->Name), + module_name.data())) { + auto* original_thunk_data = reinterpret_cast( + import_descriptor->OriginalFirstThunk + this->get_ptr()); + auto* thunk_data = reinterpret_cast( + import_descriptor->FirstThunk + this->get_ptr()); + + while (original_thunk_data->u1.AddressOfData) { + const size_t ordinal_number = + original_thunk_data->u1.AddressOfData & 0xFFFFFFF; + + if (ordinal_number > 0xFFFF) + continue; + + if (GetProcAddress(other_module.module_, + reinterpret_cast(ordinal_number)) == + target_function) { + return reinterpret_cast(&thunk_data->u1.Function); + } + + ++original_thunk_data; + ++thunk_data; + } + + // break; + } + + ++import_descriptor; + } + + 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) + return {}; + + auto* const handle = LoadResource(nullptr, res); + if (!handle) + return {}; + + return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res)); +} + +void relaunch_self() { + const utils::nt::library self; + + STARTUPINFOA startup_info; + PROCESS_INFORMATION process_info; + + ZeroMemory(&startup_info, sizeof(startup_info)); + ZeroMemory(&process_info, sizeof(process_info)); + startup_info.cb = sizeof(startup_info); + + char current_dir[MAX_PATH]; + GetCurrentDirectoryA(sizeof(current_dir), current_dir); + auto* const command_line = GetCommandLineA(); + + CreateProcessA(self.get_path().data(), command_line, nullptr, nullptr, false, + NULL, nullptr, current_dir, &startup_info, &process_info); + + if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE) + CloseHandle(process_info.hThread); + if (process_info.hProcess && process_info.hProcess != INVALID_HANDLE_VALUE) + CloseHandle(process_info.hProcess); +} + +void terminate(const uint32_t code) { + TerminateProcess(GetCurrentProcess(), code); +} +} // namespace utils::nt diff --git a/src/utils/nt.hpp b/src/utils/nt.hpp index 86001be..5cfd331 100644 --- a/src/utils/nt.hpp +++ b/src/utils/nt.hpp @@ -12,99 +12,95 @@ #undef min #endif -#include -#include #include +#include +#include -namespace utils::nt -{ - class library final - { - public: - static library load(const std::string& name); - static library load(const std::filesystem::path& path); - static library get_by_address(void* address); +namespace utils::nt { +class library final { +public: + static library load(const std::string& name); + static library load(const std::filesystem::path& path); + static library get_by_address(void* address); - library(); - explicit library(const std::string& name); - explicit library(HMODULE handle); + library(); + explicit library(const std::string& name); + explicit library(HMODULE handle); - library(const library& a) : module_(a.module_) - { - } + library(const library& a) : module_(a.module_) {} - bool operator!=(const library& obj) const { return !(*this == obj); }; - bool operator==(const library& obj) const; + bool operator!=(const library& obj) const { return !(*this == obj); }; + bool operator==(const library& obj) const; - operator bool() const; - operator HMODULE() const; + operator bool() const; + operator HMODULE() const; - void unprotect() const; - void* get_entry_point() const; - size_t get_relative_entry_point() const; + void unprotect() const; + void* get_entry_point() const; + size_t get_relative_entry_point() const; - bool is_valid() const; - std::string get_name() const; - std::string get_path() const; - std::string get_folder() const; - std::uint8_t* get_ptr() const; - void free(); + bool is_valid() const; + std::string get_name() const; + std::string get_path() const; + std::string get_folder() const; + std::uint8_t* get_ptr() const; + void free(); - HMODULE get_handle() const; + HMODULE get_handle() const; - template - T get_proc(const std::string& process) const - { - if (!this->is_valid()) T{}; - return reinterpret_cast(GetProcAddress(this->module_, process.data())); - } + template T get_proc(const std::string& process) const { + if (!this->is_valid()) + 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 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(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_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(); - } + 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(); + } - std::vector get_section_headers() const; + std::vector get_section_headers() const; - PIMAGE_NT_HEADERS get_nt_headers() const; - PIMAGE_DOS_HEADER get_dos_header() const; - PIMAGE_OPTIONAL_HEADER get_optional_header() const; + PIMAGE_NT_HEADERS get_nt_headers() const; + PIMAGE_DOS_HEADER get_dos_header() const; + PIMAGE_OPTIONAL_HEADER get_optional_header() const; - void** get_iat_entry(const std::string& module_name, const std::string& proc_name) const; + void** get_iat_entry(const std::string& module_name, + const std::string& proc_name) const; - private: - HMODULE module_; - }; +private: + HMODULE module_; +}; - __declspec(noreturn) void raise_hard_exception(); - std::string load_resource(int id); +__declspec(noreturn) void raise_hard_exception(); +std::string load_resource(int id); - void relaunch_self(); - __declspec(noreturn) void terminate(uint32_t code = 0); -} +void relaunch_self(); +__declspec(noreturn) void terminate(uint32_t code = 0); +} // namespace utils::nt diff --git a/src/utils/signature.cpp b/src/utils/signature.cpp index 85f3b49..18b736e 100644 --- a/src/utils/signature.cpp +++ b/src/utils/signature.cpp @@ -5,209 +5,188 @@ #include -namespace utils::hook -{ - void signature::load_pattern(const std::string& pattern) - { - this->mask_.clear(); - this->pattern_.clear(); +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; + 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"); - } + 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)); + 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); + 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); - } - } - } + 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(); - } + 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 (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; - } + if (has_nibble) { + throw std::runtime_error("Invalid pattern"); + } } -utils::hook::signature::signature_result operator"" _sig(const char* str, const size_t len) -{ - return utils::hook::signature(std::string(str, len)).process(); +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/utils/signature.hpp b/src/utils/signature.hpp index a372832..d5b1531 100644 --- a/src/utils/signature.hpp +++ b/src/utils/signature.hpp @@ -2,72 +2,61 @@ #include "nt.hpp" #include -namespace utils::hook -{ - class signature final - { - public: - class signature_result - { - public: - signature_result(std::vector&& matches) : matches_(std::move(matches)) - { - } +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"); - } + [[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]); - } + return reinterpret_cast(this->matches_[index]); + } - [[nodiscard]] size_t count() const - { - return this->matches_.size(); - } + [[nodiscard]] size_t count() const { return this->matches_.size(); } - private: - std::vector matches_; - }; + private: + std::vector matches_; + }; - explicit signature(const std::string& pattern, const nt::library library = {}) - : signature(pattern, library.get_ptr(), library.get_optional_header()->SizeOfImage) - { - } + 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, 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(const std::string& pattern, void* start, const size_t length) + : start_(static_cast(start)), length_(length) { + this->load_pattern(pattern); + } - signature_result process() const; + signature_result process() const; - private: - std::string mask_; - std::basic_string pattern_; +private: + std::string mask_; + std::basic_string pattern_; - uint8_t* start_; - size_t length_; + uint8_t* start_; + size_t length_; - void load_pattern(const std::string& pattern); + 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; + 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; - }; -} + bool has_sse_support() const; +}; +} // namespace utils::hook -utils::hook::signature::signature_result operator"" _sig(const char* str, size_t len); +utils::hook::signature::signature_result operator"" _sig(const char* str, + size_t len); diff --git a/src/utils/string.cpp b/src/utils/string.cpp index f60d109..73fe42d 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -1,186 +1,131 @@ #include #include "string.hpp" -#include -#include #include +#include +#include #include "nt.hpp" -namespace utils::string -{ - const char* va(const char* fmt, ...) - { - static thread_local va_provider<8, 256> provider; +namespace utils::string { +const char* va(const char* fmt, ...) { + static thread_local va_provider<8, 256> provider; - va_list ap; - va_start(ap, fmt); + va_list ap; + va_start(ap, fmt); - const char* result = provider.get(fmt, ap); + const char* result = provider.get(fmt, ap); - va_end(ap); - return result; - } - - std::vector split(const std::string& s, const char delim) - { - std::stringstream ss(s); - std::string item; - std::vector elems; - - while (std::getline(ss, item, delim)) - { - elems.push_back(item); // elems.push_back(std::move(item)); // if C++11 (based on comment from @mchiasson) - } - - return elems; - } - - std::string to_lower(std::string text) - { - std::transform(text.begin(), text.end(), text.begin(), [](const char input) - { - return static_cast(tolower(input)); - }); - - return text; - } - - std::string to_upper(std::string text) - { - std::transform(text.begin(), text.end(), text.begin(), [](const char input) - { - return static_cast(toupper(input)); - }); - - return text; - } - - bool starts_with(const std::string& text, const std::string& substring) - { - return text.find(substring) == 0; - } - - bool ends_with(const std::string& text, const std::string& substring) - { - if (substring.size() > text.size()) return false; - return std::equal(substring.rbegin(), substring.rend(), text.rbegin()); - } - - std::string dump_hex(const std::string& data, const std::string& separator) - { - std::string result; - - for (unsigned int i = 0; i < data.size(); ++i) - { - if (i > 0) - { - result.append(separator); - } - - result.append(va("%02X", data[i] & 0xFF)); - } - - return result; - } - - std::string get_clipboard_data() - { - if (OpenClipboard(nullptr)) - { - std::string data; - - auto* const clipboard_data = GetClipboardData(1u); - if (clipboard_data) - { - auto* const cliptext = static_cast(GlobalLock(clipboard_data)); - if (cliptext) - { - data.append(cliptext); - GlobalUnlock(clipboard_data); - } - } - CloseClipboard(); - - return data; - } - return {}; - } - - void strip(const char* in, char* out, int max) - { - if (!in || !out) return; - - max--; - auto current = 0; - while (*in != 0 && current < max) - { - const auto color_index = (*(in + 1) - 48) >= 0xC ? 7 : (*(in + 1) - 48); - - if (*in == '^' && (color_index != 7 || *(in + 1) == '7')) - { - ++in; - } - else - { - *out = *in; - ++out; - ++current; - } - - ++in; - } - *out = '\0'; - } - -#pragma warning(push) -#pragma warning(disable: 4100) - std::string convert(const std::wstring& wstr) - { - std::string result; - result.reserve(wstr.size()); - - for (const auto& chr : wstr) - { - result.push_back(static_cast(chr)); - } - - return result; - } - - std::wstring convert(const std::string& str) - { - std::wstring result; - result.reserve(str.size()); - - for (const auto& chr : str) - { - result.push_back(static_cast(chr)); - } - - return result; - } -#pragma warning(pop) - - std::string replace(std::string str, const std::string& from, const std::string& to) - { - if (from.empty()) - { - return str; - } - - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::string::npos) - { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); - } - - return str; - } - - bool contains(const std::string& str1, const std::string& str2) - { - return str1.find(str2) != std::string::npos; - } + va_end(ap); + return result; } + +std::vector split(const std::string& s, const char delim) { + std::stringstream ss(s); + std::string item; + std::vector elems; + + while (std::getline(ss, item, delim)) { + elems.push_back(item); // elems.push_back(std::move(item)); // if C++11 + // (based on comment from @mchiasson) + } + + return elems; +} + +std::string to_lower(std::string text) { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) { + return static_cast(tolower(input)); + }); + + return text; +} + +std::string to_upper(std::string text) { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) { + return static_cast(toupper(input)); + }); + + return text; +} + +bool starts_with(const std::string& text, const std::string& substring) { + return text.find(substring) == 0; +} + +bool ends_with(const std::string& text, const std::string& substring) { + if (substring.size() > text.size()) + return false; + return std::equal(substring.rbegin(), substring.rend(), text.rbegin()); +} + +std::string dump_hex(const std::string& data, const std::string& separator) { + std::string result; + + for (unsigned int i = 0; i < data.size(); ++i) { + if (i > 0) { + result.append(separator); + } + + result.append(va("%02X", data[i] & 0xFF)); + } + + return result; +} + +std::string get_clipboard_data() { + if (OpenClipboard(nullptr)) { + std::string data; + + auto* const clipboard_data = GetClipboardData(1u); + if (clipboard_data) { + auto* const cliptext = static_cast(GlobalLock(clipboard_data)); + if (cliptext) { + data.append(cliptext); + GlobalUnlock(clipboard_data); + } + } + CloseClipboard(); + + return data; + } + return {}; +} + +std::string convert(const std::wstring& wstr) { + std::string result; + result.reserve(wstr.size()); + + for (const auto& chr : wstr) { + result.push_back(static_cast(chr)); + } + + return result; +} + +std::wstring convert(const std::string& str) { + std::wstring result; + result.reserve(str.size()); + + for (const auto& chr : str) { + result.push_back(static_cast(chr)); + } + + return result; +} + +std::string replace(std::string str, const std::string& from, + const std::string& to) { + if (from.empty()) { + return str; + } + + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + + return str; +} +} // namespace utils::string diff --git a/src/utils/string.hpp b/src/utils/string.hpp index 050998a..a113f2d 100644 --- a/src/utils/string.hpp +++ b/src/utils/string.hpp @@ -1,102 +1,90 @@ #pragma once #include "memory.hpp" -#include -#ifndef ARRAYSIZE -template -size_t ARRAYSIZE(Type (&)[n]) { return n; } -#endif +namespace utils::string { +template class va_provider final { +public: + static_assert(Buffers != 0 && MinBufferSize != 0, + "Buffers and MinBufferSize mustn't be 0"); -namespace utils::string -{ - template - class va_provider final - { - public: - static_assert(Buffers != 0 && MinBufferSize != 0, "Buffers and MinBufferSize mustn't be 0"); + va_provider() : current_buffer_(0) {} - va_provider() : current_buffer_(0) - { - } + char* get(const char* format, const va_list ap) { + ++this->current_buffer_ %= ARRAYSIZE(this->string_pool_); + auto entry = &this->string_pool_[this->current_buffer_]; - char* get(const char* format, const va_list ap) - { - ++this->current_buffer_ %= ARRAYSIZE(this->string_pool_); - auto entry = &this->string_pool_[this->current_buffer_]; + if (!entry->size || !entry->buffer) { + throw std::runtime_error("String pool not initialized"); + } - if (!entry->size || !entry->buffer) - { - throw std::runtime_error("String pool not initialized"); - } + while (true) { + const int res = + vsnprintf_s(entry->buffer, entry->size, _TRUNCATE, format, ap); + if (res > 0) + break; // Success + if (res == 0) + return nullptr; // Error - while (true) - { - const int res = vsnprintf_s(entry->buffer, entry->size, _TRUNCATE, format, ap); - if (res > 0) break; // Success - if (res == 0) return nullptr; // Error + entry->double_size(); + } - entry->double_size(); - } + return entry->buffer; + } - return entry->buffer; - } +private: + class entry final { + public: + explicit entry(const size_t _size = MinBufferSize) + : size(_size), buffer(nullptr) { + if (this->size < MinBufferSize) + this->size = MinBufferSize; + this->allocate(); + } - private: - class entry final - { - public: - explicit entry(const size_t _size = MinBufferSize) : size(_size), buffer(nullptr) - { - if (this->size < MinBufferSize) this->size = MinBufferSize; - this->allocate(); - } + ~entry() { + if (this->buffer) + memory::get_allocator()->free(this->buffer); + this->size = 0; + this->buffer = nullptr; + } - ~entry() - { - if (this->buffer) memory::get_allocator()->free(this->buffer); - this->size = 0; - this->buffer = nullptr; - } + void allocate() { + if (this->buffer) + memory::get_allocator()->free(this->buffer); + this->buffer = + memory::get_allocator()->allocate_array(this->size + 1); + } - void allocate() - { - if (this->buffer) memory::get_allocator()->free(this->buffer); - this->buffer = memory::get_allocator()->allocate_array(this->size + 1); - } + void double_size() { + this->size *= 2; + this->allocate(); + } - void double_size() - { - this->size *= 2; - this->allocate(); - } + size_t size; + char* buffer; + }; - size_t size; - char* buffer; - }; + size_t current_buffer_; + entry string_pool_[Buffers]; +}; - size_t current_buffer_; - entry string_pool_[Buffers]; - }; +const char* va(const char* fmt, ...); - const char* va(const char* fmt, ...); +std::vector split(const std::string& s, char delim); - std::vector split(const std::string& s, char delim); +std::string to_lower(std::string text); +std::string to_upper(std::string text); +bool starts_with(const std::string& text, const std::string& substring); +bool ends_with(const std::string& text, const std::string& substring); - std::string to_lower(std::string text); - std::string to_upper(std::string text); - bool starts_with(const std::string& text, const std::string& substring); - bool ends_with(const std::string& text, const std::string& substring); +std::string dump_hex(const std::string& data, + const std::string& separator = " "); - std::string dump_hex(const std::string& data, const std::string& separator = " "); +std::string get_clipboard_data(); - std::string get_clipboard_data(); +std::string convert(const std::wstring& wstr); +std::wstring convert(const std::string& str); - void strip(const char* in, char* out, int max); - - std::string convert(const std::wstring& wstr); - std::wstring convert(const std::string& str); - - std::string replace(std::string str, const std::string& from, const std::string& to); - - bool contains(const std::string& str1, const std::string& str2); -} +std::string replace(std::string str, const std::string& from, + const std::string& to); +} // namespace utils::string