From 05575a63570aaa6e7d5f7e94320eababd8641543 Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Sat, 7 Oct 2023 15:19:46 +0000 Subject: [PATCH] Bypass integrity checks (#2216) Closes #2215 Closes #2218 Closes #2220 Closes #2212 --- src/call_hook.cpp | 62 +++++++++++++++++++ src/call_hook.hpp | 49 +++++++++++++++ src/function_types.hpp | 2 + src/gta_pointers.hpp | 10 +++ src/hooking.cpp | 10 ++- src/hooking.hpp | 6 ++ src/hooks/misc/game_skeleton_update.cpp | 24 +++++++ .../misc/remove_player_from_sender_list.cpp | 11 ++++ src/pointers.cpp | 36 +++++++++++ 9 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 src/call_hook.cpp create mode 100644 src/call_hook.hpp create mode 100644 src/hooks/misc/game_skeleton_update.cpp create mode 100644 src/hooks/misc/remove_player_from_sender_list.cpp diff --git a/src/call_hook.cpp b/src/call_hook.cpp new file mode 100644 index 00000000..abee5d11 --- /dev/null +++ b/src/call_hook.cpp @@ -0,0 +1,62 @@ +#include "common.hpp" +#include "call_hook.hpp" + +namespace +{ + big::call_hook_memory g_call_hook_memory; +} + +// https://github.com/martonp96/ClosedIV/blob/master/src/utils/memory.h#L64 + +namespace big +{ + call_hook_memory::call_hook_memory() + { + m_memory = VirtualAlloc((void*)((uintptr_t)GetModuleHandle(0) + 0x20000000), 1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + m_offset = 0; + } + + call_hook_memory::~call_hook_memory() + { + VirtualFree(m_memory.as(), 0, MEM_RELEASE); + } + + void* call_hook_memory::allocate_jump_sequence(void* func) + { + m_offset = m_offset + ((16 - (m_offset % 16)) % 16); // align + + *m_memory.add(m_offset).as() = 0xB848; + *m_memory.add(m_offset).add(2).as() = func; + *m_memory.add(m_offset).add(10).as() = 0xE0FF; + + m_offset += 12; + + return m_memory.add(m_offset).sub(12).as(); + } + + call_hook::call_hook(void* location, void* hook) : + m_location(location), + m_hook(hook) + { + auto seq = g_call_hook_memory.allocate_jump_sequence(hook); + m_patched_bytes[0] = 0xE8; + *(int32_t*)&m_patched_bytes[1] = (int32_t)((uint64_t)seq - (uint64_t)location - 5); + memcpy(m_original_bytes, location, 5); + m_original_function = memory::handle(location).add(1).rip().as(); + } + + call_hook::~call_hook() + { + disable(); + } + + void call_hook::enable() + { + memcpy(m_location, m_patched_bytes, 5); + } + + void call_hook::disable() + { + memcpy(m_location, m_original_bytes, 5); + } +} diff --git a/src/call_hook.hpp b/src/call_hook.hpp new file mode 100644 index 00000000..20e3cb37 --- /dev/null +++ b/src/call_hook.hpp @@ -0,0 +1,49 @@ +#pragma once +#include "common.hpp" +#include "memory/handle.hpp" + +namespace big +{ + class call_hook_memory + { + memory::handle m_memory; + int m_offset; + + public: + call_hook_memory(); + ~call_hook_memory(); + + void* allocate_jump_sequence(void* func); + }; + + class call_hook + { + public: + explicit call_hook(void* location, void* hook); + ~call_hook(); + + call_hook(call_hook&& that) = delete; + call_hook& operator=(call_hook&& that) = delete; + call_hook(call_hook const&) = delete; + call_hook& operator=(call_hook const&) = delete; + + template + T get_original(); + + void enable(); + void disable(); + + private: + void* m_location; + void* m_hook; + uint8_t m_patched_bytes[5]; + uint8_t m_original_bytes[5]; + void* m_original_function; + }; + + template + inline T call_hook::get_original() + { + return static_cast(m_original_function); + } +} diff --git a/src/function_types.hpp b/src/function_types.hpp index e912cfc4..126575c6 100644 --- a/src/function_types.hpp +++ b/src/function_types.hpp @@ -188,4 +188,6 @@ namespace big::functions using delete_object = bool (*)(CObject* object, bool unk); using decal_manager_remove = void(*)(PVOID manager, rage::fwEntity*, DWORD a3, DWORD64 a4, DWORD ignore_bitset); + + using remove_player_from_sender_list = bool(*)(void* list, uint64_t* rockstar_id); } diff --git a/src/gta_pointers.hpp b/src/gta_pointers.hpp index c941ea53..c6738a61 100644 --- a/src/gta_pointers.hpp +++ b/src/gta_pointers.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include "function_types.hpp" class CCommunications; class FriendRegistry; @@ -28,6 +29,9 @@ namespace rage class rlGamerInfo; } +template +class HashTable; + namespace big { // needed for serialization of the pointers cache @@ -339,6 +343,12 @@ namespace big PVOID m_decal_manager; bool* m_is_social_club_overlay_active; + + functions::remove_player_from_sender_list m_remove_player_from_sender_list; + PVOID m_remove_player_from_sender_list_caller_1; + PVOID m_remove_player_from_sender_list_caller_2; + + PVOID m_game_skeleton_update; }; #pragma pack(pop) static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); diff --git a/src/hooking.cpp b/src/hooking.cpp index cbc1299c..c8be9e87 100644 --- a/src/hooking.cpp +++ b/src/hooking.cpp @@ -17,7 +17,9 @@ namespace big { hooking::hooking() : m_swapchain_hook(*g_pointers->m_gta.m_swapchain, hooks::swapchain_num_funcs), - m_sync_data_reader_hook(g_pointers->m_gta.m_sync_data_reader_vtable, 27) + m_sync_data_reader_hook(g_pointers->m_gta.m_sync_data_reader_vtable, 27), + m_remove_player_from_sender_list_caller_1_hook(g_pointers->m_gta.m_remove_player_from_sender_list_caller_1, hooks::remove_player_from_sender_list), + m_remove_player_from_sender_list_caller_2_hook(g_pointers->m_gta.m_remove_player_from_sender_list_caller_2, hooks::remove_player_from_sender_list) { m_swapchain_hook.hook(hooks::swapchain_present_index, &hooks::swapchain_present); m_swapchain_hook.hook(hooks::swapchain_resizebuffers_index, &hooks::swapchain_resizebuffers); @@ -147,6 +149,8 @@ namespace big detour_hook_helper::add("RBS", g_pointers->m_gta.m_read_bits_single); + detour_hook_helper::add("GSU", g_pointers->m_gta.m_game_skeleton_update); + g_hooking = this; } @@ -165,6 +169,8 @@ namespace big m_swapchain_hook.enable(); m_sync_data_reader_hook.enable(); m_og_wndproc = WNDPROC(SetWindowLongPtrW(g_pointers->m_hwnd, GWLP_WNDPROC, LONG_PTR(&hooks::wndproc))); + m_remove_player_from_sender_list_caller_1_hook.enable(); + m_remove_player_from_sender_list_caller_2_hook.enable(); for (auto& detour_hook_helper : m_detour_hook_helpers) { @@ -188,6 +194,8 @@ namespace big SetWindowLongPtrW(g_pointers->m_hwnd, GWLP_WNDPROC, reinterpret_cast(m_og_wndproc)); m_sync_data_reader_hook.disable(); m_swapchain_hook.disable(); + m_remove_player_from_sender_list_caller_1_hook.disable(); + m_remove_player_from_sender_list_caller_2_hook.disable(); MH_ApplyQueued(); diff --git a/src/hooking.hpp b/src/hooking.hpp index 56c6e207..d37393bd 100644 --- a/src/hooking.hpp +++ b/src/hooking.hpp @@ -7,6 +7,7 @@ #include "gta/script_thread.hpp" #include "vmt_hook.hpp" #include "vtable_hook.hpp" +#include "call_hook.hpp" #include @@ -180,6 +181,9 @@ namespace big static bool sync_reader_serialize_vec3(void* _this, rage::fvector3* vec, float divisor, int size); static bool sync_reader_serialize_vec3_signed(void* _this, rage::fvector3* vec, float divisor, int size); static bool sync_reader_serialize_array(void* _this, void* array, int size); + + static bool remove_player_from_sender_list(void* list, uint64_t rockstar_id); + static void game_skeleton_update(__int64 update_group); }; class minhook_keepalive @@ -269,6 +273,8 @@ namespace big vmt_hook m_swapchain_hook; vtable_hook m_sync_data_reader_hook; + call_hook m_remove_player_from_sender_list_caller_1_hook; + call_hook m_remove_player_from_sender_list_caller_2_hook; WNDPROC m_og_wndproc = nullptr; diff --git a/src/hooks/misc/game_skeleton_update.cpp b/src/hooks/misc/game_skeleton_update.cpp new file mode 100644 index 00000000..fd90dbd0 --- /dev/null +++ b/src/hooks/misc/game_skeleton_update.cpp @@ -0,0 +1,24 @@ +#include "hooking.hpp" + +namespace big +{ +#pragma pack(push, 8) + struct game_skeleton_item + { + virtual ~game_skeleton_item() = default; + virtual void run() = 0; // 0x08 + + char m_pad[0x8]; // 0x08 + uint32_t m_hash; // 0x10 + game_skeleton_item* m_next; // 0x18 + }; + static_assert(sizeof(game_skeleton_item) == 0x20); +#pragma pack(pop) + + void hooks::game_skeleton_update(__int64 update_group) + { + for (auto item = *(game_skeleton_item**)(update_group + 0x20); item; item = item->m_next) + if (item->m_hash != 0xA0F39FB6) + item->run(); + } +} diff --git a/src/hooks/misc/remove_player_from_sender_list.cpp b/src/hooks/misc/remove_player_from_sender_list.cpp new file mode 100644 index 00000000..6098399d --- /dev/null +++ b/src/hooks/misc/remove_player_from_sender_list.cpp @@ -0,0 +1,11 @@ +#include "hooking.hpp" +#include "pointers.hpp" + +namespace big +{ + bool hooks::remove_player_from_sender_list(void* list, uint64_t rockstar_id) + { + g_pointers->m_gta.m_remove_player_from_sender_list(list, &rockstar_id); + return true; + } +} \ No newline at end of file diff --git a/src/pointers.cpp b/src/pointers.cpp index 990a6753..c2791e68 100644 --- a/src/pointers.cpp +++ b/src/pointers.cpp @@ -1438,6 +1438,15 @@ namespace big g_pointers->m_gta.m_delete_object = ptr.as(); } }, + // Remove Player From Sender List + { + "RPFSL", + "48 89 5C 24 08 48 89 74 24 10 57 48 83 EC 20 33 F6 48 8B FA 48 8B D9 66 39 71 08 76", + [](memory::handle ptr) + { + g_pointers->m_gta.m_remove_player_from_sender_list = ptr.as(); + } + }, // Max Wanted Level { "MWL", @@ -1658,6 +1667,33 @@ namespace big { g_pointers->m_gta.m_is_social_club_overlay_active = ptr.add(2).rip().as(); } + }, + // Remove Player From Sender List Caller 1 + { + "RPFSLC1", + "E8 ? ? ? ? 84 C0 74 0D B0 01 EB 1E", + [](memory::handle ptr) + { + g_pointers->m_gta.m_remove_player_from_sender_list_caller_1 = ptr.as(); + } + }, + // Remove Player From Sender List Caller 2 + { + "RPFSLC2", + "E8 ? ? ? ? 84 C0 74 0A B0 01 EB 08", + [](memory::handle ptr) + { + g_pointers->m_gta.m_remove_player_from_sender_list_caller_2 = ptr.as(); + } + }, + // Game Skeleton Update + { + "GSU", + "40 53 48 83 EC 20 48 8B 59 20 EB 0D", + [](memory::handle ptr) + { + g_pointers->m_gta.m_game_skeleton_update = ptr.as(); + } } >(); // don't leave a trailing comma at the end