From 245d717834cea4c92fe3b11ebdfea2195e6a82ca Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Thu, 4 May 2017 16:55:39 +0300 Subject: [PATCH] multiplatform offset support + faster hooks --- src/common.h | 1 + src/hack.cpp | 82 ++++++++++---------------- src/hacks/Misc.cpp | 9 ++- src/hooks.cpp | 114 ++++++++++++++++++------------------ src/hooks.h | 88 +++++++++++++--------------- src/hooks/BeginFrame.cpp | 14 ----- src/hooks/CreateMove.cpp | 20 ++++--- src/hooks/PaintTraverse.cpp | 5 +- src/hooks/hookedmethods.h | 38 ++++++------ src/hooks/others.cpp | 82 +++++++++++++------------- src/offsets.hpp | 66 +++++++++++++++++++++ 11 files changed, 273 insertions(+), 246 deletions(-) delete mode 100644 src/hooks/BeginFrame.cpp create mode 100644 src/offsets.hpp diff --git a/src/common.h b/src/common.h index fdd0772d..dd0f9dd4 100644 --- a/src/common.h +++ b/src/common.h @@ -27,6 +27,7 @@ #include #include #include "aftercheaders.h" +#include "offsets.hpp" #include "drawing.h" #include "resource.hpp" #include "entitycache.h" diff --git a/src/hack.cpp b/src/hack.cpp index 1432a221..f36d2423 100644 --- a/src/hack.cpp +++ b/src/hack.cpp @@ -127,49 +127,39 @@ void hack::Initialize() { InitNetVars(); g_pLocalPlayer = new LocalPlayer(); g_pPlayerResource = new TFPlayerResource(); - hooks::hkPanel = new hooks::VMTHook(); - hooks::hkPanel->Init(g_IPanel, 0); - //hooks::hkPanel->HookMethod((void*)&hack::Hk_PaintTraverse, hooks::offPaintTraverse); - hooks::hkPanel->HookMethod((void*)PaintTraverse_hook, hooks::offPaintTraverse); - hooks::hkPanel->Apply(); - hooks::hkClientMode = new hooks::VMTHook(); + + /* + * TIME FOR HOOKING! wow + */ + hooks::panel.Set(g_IPanel); + hooks::panel.HookMethod((void*)PaintTraverse_hook, offsets::PaintTraverse()); + hooks::panel.Apply(); uintptr_t* clientMode = 0; + // Bad way to get clientmode. + // FIXME [MP]? while(!(clientMode = **(uintptr_t***)((uintptr_t)((*(void***)g_IBaseClient)[10]) + 1))) { sleep(1); } - //hooks::hkMatSurface = new hooks::VMTHook(); - //hooks::hkMatSurface->Init((void*)matsurface, 0); - //hooks::hkMatSurface->HookMethod((void*)test_handleevent, 1); - hooks::hkClientMode->Init((void*)clientMode, 0); - //hooks::hkClientMode->HookMethod((void*)&hack::Hk_CreateMove, hooks::offCreateMove); - hooks::hkClientMode->HookMethod((void*)CreateMove_hook, hooks::offCreateMove); - hooks::hkClientMode->HookMethod((void*)OverrideView_hook, hooks::offOverrideView); - hooks::hkClientMode->HookMethod((void*)LevelInit_hook, hooks::offLevelInit); - hooks::hkClientMode->HookMethod((void*)LevelShutdown_hook, hooks::offLevelShutdown); - hooks::hkClientMode->Apply(); - hooks::hkStudioRender = new hooks::VMTHook(); - hooks::hkStudioRender->Init((void*)g_IStudioRender, 0); - hooks::hkStudioRender->HookMethod((void*)BeginFrame_hook, hooks::offBeginFrame); - hooks::hkStudioRender->Apply(); - hooks::hkClient = new hooks::VMTHook(); - hooks::hkClient->Init((void*)g_IBaseClient, 0); - hooks::hkClient->HookMethod((void*)FrameStageNotify_hook, hooks::offFrameStageNotify); - hooks::hkClient->HookMethod((void*)DispatchUserMessage_hook, hooks::offFrameStageNotify + 1); - hooks::hkClient->HookMethod((void*)IN_KeyEvent_hook, hooks::offKeyEvent); - hooks::hkClient->Apply(); - hooks::hkInput = new hooks::VMTHook(); - hooks::hkInput->Init((void*)g_IInput, 0); - hooks::hkInput->HookMethod((void*)GetUserCmd_hook, hooks::offGetUserCmd); - hooks::hkInput->Apply(); - //logging::Info("Before hacking: %s", g_ISteamFriends->GetPersonaName()); - hooks::hkIVModelRender = new hooks::VMTHook(); - hooks::hkIVModelRender->Init(g_IVModelRender, 0); - hooks::hkIVModelRender->HookMethod((void*)DrawModelExecute_hook, hooks::offDrawModelExecute); - hooks::hkIVModelRender->Apply(); - hooks::hkSteamFriends = new hooks::VMTHook(); - hooks::hkSteamFriends->Init(g_ISteamFriends, 0); - hooks::hkSteamFriends->HookMethod((void*)GetFriendPersonaName_hook, hooks::offGetFriendPersonaName); - hooks::hkSteamFriends->Apply(); + hooks::clientmode.Set((void*)clientMode); + hooks::clientmode.HookMethod((void*)CreateMove_hook, offsets::CreateMove()); + hooks::clientmode.HookMethod((void*)OverrideView_hook, offsets::OverrideView()); + hooks::clientmode.HookMethod((void*)LevelInit_hook, offsets::LevelInit()); + hooks::clientmode.HookMethod((void*)LevelShutdown_hook, offsets::LevelShutdown()); + hooks::clientmode.Apply(); + hooks::client.Set(g_IBaseClient); + hooks::client.HookMethod((void*)FrameStageNotify_hook, offsets::FrameStageNotify()); + hooks::client.HookMethod((void*)DispatchUserMessage_hook, offsets::DispatchUserMessage()); + hooks::client.HookMethod((void*)IN_KeyEvent_hook, offsets::IN_KeyEvent()); + hooks::client.Apply(); + hooks::input.Set(g_IInput); + hooks::input.HookMethod((void*)GetUserCmd_hook, offsets::GetUserCmd()); + hooks::input.Apply(); + hooks::modelrender.Set(g_IVModelRender); + hooks::modelrender.HookMethod((void*)DrawModelExecute_hook, offsets::DrawModelExecute()); + hooks::modelrender.Apply(); + hooks::steamfriends.Set(g_ISteamFriends); + hooks::steamfriends.HookMethod((void*)GetFriendPersonaName_hook, offsets::GetFriendPersonaName()); + hooks::steamfriends.Apply(); //logging::Info("After hacking: %s", g_ISteamFriends->GetPersonaName()); // Sadly, it doesn't work as expected :( /*hooks::hkBaseClientState = new hooks::VMTHook(); @@ -181,6 +171,8 @@ void hack::Initialize() { //hooks::hkBaseClientState8->HookMethod((void*)ProcessSetConVar_hook, hooks::offProcessSetConVar); //hooks::hkBaseClientState8->HookMethod((void*)ProcessGetCvarValue_hook, hooks::offProcessGetCvarValue); //hooks::hkBaseClientState8->Apply(); + + // FIXME [MP] if (TF2) g_GlowObjectManager = *reinterpret_cast(gSignatures.GetClientSignature("C1 E0 05 03 05") + 5); InitStrings(); hacks::shared::killsay::Init(); @@ -211,18 +203,6 @@ void hack::Shutdown() { if (hack::shutdown) return; hack::shutdown = true; playerlist::Save(); - logging::Info("Killing hooks.."); - if (hooks::hkPanel) hooks::hkPanel->Kill(); - if (hooks::hkClientMode) hooks::hkClientMode->Kill(); - if (hooks::hkClient) hooks::hkClient->Kill(); - if (hooks::hkMatSurface) hooks::hkMatSurface->Kill(); - if (hooks::hkNetChannel) hooks::hkNetChannel->Kill(); - if (hooks::hkStudioRender) hooks::hkStudioRender->Kill(); - if (hooks::hkInput) hooks::hkInput->Kill(); - if (hooks::hkIVModelRender) hooks::hkIVModelRender->Kill(); - if (hooks::hkBaseClientState) hooks::hkBaseClientState->Kill(); - if (hooks::hkBaseClientState8) hooks::hkBaseClientState8->Kill(); - //if (hooks::hkCTFPlayer) hooks::hkCTFPlayer->Kill(); logging::Info("Unregistering convars.."); ConVar_Unregister(); logging::Info("Shutting down killsay..."); diff --git a/src/hacks/Misc.cpp b/src/hacks/Misc.cpp index 3a33c915..ecde5b93 100644 --- a/src/hacks/Misc.cpp +++ b/src/hacks/Misc.cpp @@ -112,16 +112,15 @@ static int last_number = 0; void CreateMove() { static bool flswitch = false; - - // TODO FIXME HOOKING WITHOUT UNHOOKING = 100% SEGV ON UNINJECT. + // TODO FIXME this should be moved out of here IClientEntity* localplayer = g_IEntityList->GetClientEntity(g_IEngine->GetLocalPlayer()); if (TF && render_zoomed && localplayer) { void** vtable = *(void***)(localplayer); - if (vtable[hooks::offShouldDraw] != C_TFPlayer__ShouldDraw_hook) { - C_TFPlayer__ShouldDraw_original = vtable[hooks::offShouldDraw]; + if (vtable[offsets::ShouldDraw()] != C_TFPlayer__ShouldDraw_hook) { + C_TFPlayer__ShouldDraw_original = vtable[offsets::ShouldDraw()]; void* page = (void*)((uintptr_t)vtable &~ 0xFFF); mprotect(page, 0xFFF, PROT_READ | PROT_WRITE | PROT_EXEC); - vtable[hooks::offShouldDraw] = (void*)C_TFPlayer__ShouldDraw_hook; + vtable[offsets::ShouldDraw()] = (void*)C_TFPlayer__ShouldDraw_hook; mprotect(page, 0xFFF, PROT_READ | PROT_EXEC); } } diff --git a/src/hooks.cpp b/src/hooks.cpp index 1c3c0fce..1ae0eae0 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -10,78 +10,78 @@ #include "logging.h" #include +#include -unsigned int hooks::offCreateMove = 22; -unsigned int hooks::offPaintTraverse = 42; -unsigned int hooks::offOverrideView = 17; -unsigned int hooks::offFrameStageNotify = 35; -unsigned int hooks::offCanPacket = 57; -unsigned int hooks::offSendNetMsg = 41; -unsigned int hooks::offShutdown = 37; -unsigned int hooks::offKeyEvent = 20; -unsigned int hooks::offHandleInputEvent = 78; -unsigned int hooks::offLevelInit = 23; -unsigned int hooks::offLevelShutdown = 24; -unsigned int hooks::offBeginFrame = 5; +namespace hooks { -// This thing had been copypasted from somewhere, maybe from F1Public. - -bool hooks::IsHooked(void* inst) { - return hooks::GetVMT(inst, 0)[-2] == (void*)VMTHook::GUARD; -} - -unsigned int hooks::CountMethods(void** vmt) { +unsigned CountMethods(method_table_t table) { unsigned int i = -1; - do ++i; while (vmt[i]); + do ++i; while (table[i]); return i; } -void**& hooks::GetVMT(void* inst, unsigned int offset) { - return *reinterpret_cast((char*)inst + offset); +table_ref_t GetVMT(ptr_t inst, uint32_t offset) { + return *reinterpret_cast((uint32_t)inst + offset); } -void hooks::VMTHook::Init(void* inst, unsigned int offset) { - vmt = &GetVMT(inst, offset); - oldvmt = *vmt; - unsigned int cnt = CountMethods(oldvmt); - void **arr = array = (void**)malloc((cnt + 4) * sizeof(void*)); - arr[0] = this; - arr[1] = (void* )GUARD; - (arr + 3)[cnt] = 0; - unsigned int i = -1; - do arr[i + 3] = oldvmt[i]; while (++i < cnt); +bool IsHooked(ptr_t inst, uint32_t offset) { + return GetVMT(inst, offset)[-1] == (method_t)GUARD; } -void hooks::VMTHook::Kill() { - if (vmt) - *vmt = oldvmt; - vmt = 0; - free(array); - array = 0; +VMTHook::VMTHook() { + static_assert(ptr_size == 4, "Pointer size must be DWORD."); +}; + +VMTHook::~VMTHook() { + Release(); } -void hooks::VMTHook::HookMethod(void* func, unsigned int idx) { - array[idx + 3] = func; +void VMTHook::Set(ptr_t inst, uint32_t offset) { + Release(); + vtable_ptr = &GetVMT(inst, offset); + vtable_original = *vtable_ptr; + int mc = CountMethods(vtable_original); + vtable_hooked = static_cast(calloc(mc + 3, sizeof(ptr_t))); + memcpy(&vtable_hooked[2], vtable_original, sizeof(ptr_t) * mc); + vtable_hooked[0] = this; + vtable_hooked[1] = (void*)GUARD; } -void* hooks::VMTHook::GetMethod(unsigned int idx) const { - return oldvmt[idx]; +void VMTHook::Release() { + if (vtable_ptr) { + if ((*vtable_ptr)[-1] == (method_t)GUARD) { + *vtable_ptr = vtable_original; + } + free(vtable_hooked); + vtable_ptr = nullptr; + vtable_hooked = nullptr; + vtable_original = nullptr; + } } -void hooks::VMTHook::Apply() { - *vmt = array + 3; +void* VMTHook::GetMethod(uint32_t idx) const { + return vtable_original[idx]; } -//hooks::VMTHook* hooks::hkCTFPlayer = nullptr; -hooks::VMTHook* hooks::hkInput = nullptr; -hooks::VMTHook* hooks::hkSteamFriends = nullptr; -hooks::VMTHook* hooks::hkBaseClientState = nullptr; -hooks::VMTHook* hooks::hkBaseClientState8 = nullptr; -hooks::VMTHook* hooks::hkClientMode = 0; -hooks::VMTHook* hooks::hkPanel = 0; -hooks::VMTHook* hooks::hkClient = 0; -hooks::VMTHook* hooks::hkNetChannel = 0; -hooks::VMTHook* hooks::hkClientDLL = 0; -hooks::VMTHook* hooks::hkMatSurface = 0; -hooks::VMTHook* hooks::hkStudioRender = 0; -hooks::VMTHook* hooks::hkIVModelRender = nullptr; +void VMTHook::HookMethod(ptr_t func, uint32_t idx) { + vtable_hooked[2 + idx] = func; +} + +void VMTHook::Apply() { + *vtable_ptr = &vtable_hooked[2]; +} + +VMTHook input {}; +VMTHook steamfriends {}; +VMTHook baseclientstate {}; +VMTHook baseclientstate8 {}; +VMTHook clientmode {}; +VMTHook panel {}; +VMTHook client {}; +VMTHook netchannel {}; +VMTHook clientdll {}; +VMTHook matsurface {}; +VMTHook studiorender {}; +VMTHook modelrender {}; + +} diff --git a/src/hooks.h b/src/hooks.h index 1a75bfdb..74af6205 100644 --- a/src/hooks.h +++ b/src/hooks.h @@ -8,62 +8,56 @@ #ifndef HOOKS_H_ #define HOOKS_H_ -namespace hooks { - // Parts of copypasted code // Credits: Casual_Hacker -unsigned int CountMethods(void** vmt); -void**& GetVMT(void* inst, unsigned int offset); -bool IsHooked(void* inst); +#include +#include + +namespace hooks { + +typedef void* ptr_t; +typedef void* method_t; +typedef method_t* method_table_t; +typedef method_table_t* table_ptr_t; +typedef method_table_t& table_ref_t; + +constexpr size_t ptr_size = sizeof(ptr_t); + +unsigned CountMethods(method_table_t table); +table_ref_t GetVMT(ptr_t inst, uint32_t offset = 0); +bool IsHooked(ptr_t inst, uint32_t offset = 0); + +constexpr uint32_t GUARD = 0xD34DC477; class VMTHook { public: - enum { GUARD = 0xD34DC477 }; - void Init(void* inst, unsigned int offset); - void Kill(); - void HookMethod(void* func, unsigned int idx); - void* GetMethod(unsigned int idx) const; + VMTHook(); + ~VMTHook(); + void Set(ptr_t inst, uint32_t offset = 0); + void Release(); + void HookMethod(ptr_t func, uint32_t idx); + void* GetMethod(uint32_t idx) const; void Apply(); -protected: - void ***vmt; - void **oldvmt; - void **array; +public: + ptr_t object { nullptr }; + table_ptr_t vtable_ptr { nullptr }; + method_table_t vtable_original { nullptr }; + method_table_t vtable_hooked { nullptr }; }; -//extern VMTHook* hkCTFPlayer; -extern VMTHook* hkPanel; -extern VMTHook* hkClientMode; -extern VMTHook* hkClient; -extern VMTHook* hkNetChannel; -extern VMTHook* hkClientDLL; -extern VMTHook* hkMatSurface; -extern VMTHook* hkStudioRender; -extern VMTHook* hkInput; -extern VMTHook* hkIVModelRender; -extern VMTHook* hkBaseClientState; -extern VMTHook* hkBaseClientState8; -extern VMTHook* hkSteamFriends; - -constexpr unsigned int offGetUserCmd = 8; -constexpr unsigned int offShouldDraw = 136; -constexpr unsigned int offDrawModelExecute = 19; -constexpr unsigned int offGetClientName = 44; -constexpr unsigned int offProcessSetConVar = 4; -constexpr unsigned int offProcessGetCvarValue = 29; -constexpr unsigned int offGetFriendPersonaName = 7; -extern unsigned int offHandleInputEvent; -extern unsigned int offPaintTraverse; -extern unsigned int offCreateMove; -extern unsigned int offOverrideView; -extern unsigned int offFrameStageNotify; -extern unsigned int offCanPacket; -extern unsigned int offSendNetMsg; -extern unsigned int offShutdown; -extern unsigned int offKeyEvent; -extern unsigned int offLevelInit; -extern unsigned int offLevelShutdown; -extern unsigned int offBeginFrame; +extern VMTHook panel; +extern VMTHook clientmode; +extern VMTHook client; +extern VMTHook netchannel; +extern VMTHook clientdll; +extern VMTHook matsurface; +extern VMTHook studiorender; +extern VMTHook input; +extern VMTHook modelrender; +extern VMTHook baseclientstate; +extern VMTHook baseclientstate8; +extern VMTHook steamfriends; } diff --git a/src/hooks/BeginFrame.cpp b/src/hooks/BeginFrame.cpp deleted file mode 100644 index 63a25206..00000000 --- a/src/hooks/BeginFrame.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * BeginFrame.cpp - * - * Created on: Feb 10, 2017 - * Author: nullifiedcat - */ - -#include "hookedmethods.h" -#include "../common.h" -#include "../sdk.h" - -void BeginFrame_hook(IStudioRender* _this) { - ((BeginFrame_t*)hooks::hkStudioRender->GetMethod(hooks::offBeginFrame))(_this); -} diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index 7295211d..22dfa88a 100644 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -12,6 +12,7 @@ #include "../common.h" #include "hookedmethods.h" +// FIXME remove this temporary code already! float AngleDiff( float destAngle, float srcAngle ) { float delta; @@ -28,7 +29,7 @@ float AngleDiff( float destAngle, float srcAngle ) delta += 360; } return delta; -}//TODO temporary +} #include "../profiler.h" @@ -70,7 +71,9 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) { if (TF2C && CE_GOOD(LOCAL_W) && minigun_jump && LOCAL_W->m_iClassID == g_pClassID->CTFMinigun) { CE_INT(LOCAL_W, netvar.iWeaponState) = 0; } - bool ret = ((CreateMove_t*)hooks::hkClientMode->GetMethod(hooks::offCreateMove))(thisptr, inputSample, cmd); + + static CreateMove_t original_method = (CreateMove_t)hooks::clientmode.GetMethod(offsets::CreateMove()); + bool ret = original_method(thisptr, inputSample, cmd); PROF_SECTION(CreateMove); @@ -90,13 +93,12 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) { // PROF_BEGIN(); INetChannel* ch = (INetChannel*)g_IEngine->GetNetChannelInfo(); - if (ch && !hooks::IsHooked((void*)((uintptr_t)ch))) { - hooks::hkNetChannel = new hooks::VMTHook(); - hooks::hkNetChannel->Init(ch, 0); - hooks::hkNetChannel->HookMethod((void*)CanPacket_hook, hooks::offCanPacket); - hooks::hkNetChannel->HookMethod((void*)SendNetMsg_hook, hooks::offSendNetMsg); - hooks::hkNetChannel->HookMethod((void*)Shutdown_hook, hooks::offShutdown); - hooks::hkNetChannel->Apply(); + if (ch && !hooks::IsHooked((void*)ch)) { + hooks::netchannel.Set(ch); + hooks::netchannel.HookMethod((void*)CanPacket_hook, offsets::CanPacket()); + hooks::netchannel.HookMethod((void*)SendNetMsg_hook, offsets::SendNetMsg()); + hooks::netchannel.HookMethod((void*)Shutdown_hook, offsets::Shutdown()); + hooks::netchannel.Apply(); } //logging::Info("canpacket: %i", ch->CanPacket()); //if (!cmd) return ret; diff --git a/src/hooks/PaintTraverse.cpp b/src/hooks/PaintTraverse.cpp index bcfb49d0..a775d499 100644 --- a/src/hooks/PaintTraverse.cpp +++ b/src/hooks/PaintTraverse.cpp @@ -26,7 +26,8 @@ void** pure_addr = nullptr; CatEnum software_cursor_enum({"KEEP", "ALWAYS", "NEVER", "MENU ON", "MENU OFF"}); CatVar software_cursor_mode(software_cursor_enum, "software_cursor_mode", "1", "Software cursor", "Try to change this and see what works best for you"); -void PaintTraverse_hook(void* p, unsigned int vp, bool fr, bool ar) { +void PaintTraverse_hook(void* _this, unsigned int vp, bool fr, bool ar) { + static const PaintTraverse_t original = (PaintTraverse_t)hooks::panel.GetMethod(offsets::PaintTraverse()); #if DEBUG_SEGV == true if (!segvcatch::handler_fpe || !segvcatch::handler_segv) { if (!segvcatch::handler_fpe) segvcatch::init_segv(); @@ -83,7 +84,7 @@ void PaintTraverse_hook(void* p, unsigned int vp, bool fr, bool ar) { } } - if (call_default) SAFE_CALL(((PaintTraverse_t*)hooks::hkPanel->GetMethod(hooks::offPaintTraverse))(p, vp, fr, ar)); + if (call_default) SAFE_CALL(original(_this, vp, fr, ar)); // To avoid threading problems. PROF_SECTION(PaintTraverse); diff --git a/src/hooks/hookedmethods.h b/src/hooks/hookedmethods.h index c93787d4..85436c8b 100644 --- a/src/hooks/hookedmethods.h +++ b/src/hooks/hookedmethods.h @@ -10,36 +10,32 @@ #include "../common.h" -typedef bool(CreateMove_t)(void*, float, CUserCmd*); -typedef void(PaintTraverse_t)(void*, unsigned int, bool, bool); -typedef bool(CanPacket_t)(void*); -typedef int(IN_KeyEvent_t)(void*, int, int, const char*); -typedef bool(SendNetMsg_t)(void*, INetMessage&, bool, bool); -typedef void(Shutdown_t)(void*, const char*); -typedef void(OverrideView_t)(void*, CViewSetup*); -typedef bool(DispatchUserMessage_t)(void*, int, bf_read&); -typedef void(FrameStageNotify_t)(void*, int); -typedef void(LevelInit_t)(void*, const char*); -typedef void(LevelShutdown_t)(void*); -typedef void(BeginFrame_t)(IStudioRender*); +typedef bool(*CreateMove_t)(void*, float, CUserCmd*); +typedef void(*PaintTraverse_t)(void*, unsigned int, bool, bool); +typedef bool(*CanPacket_t)(void*); +typedef int(*IN_KeyEvent_t)(void*, int, int, const char*); +typedef bool(*SendNetMsg_t)(void*, INetMessage&, bool, bool); +typedef void(*Shutdown_t)(void*, const char*); +typedef void(*OverrideView_t)(void*, CViewSetup*); +typedef bool(*DispatchUserMessage_t)(void*, int, bf_read&); +typedef void(*FrameStageNotify_t)(void*, int); +typedef void(*LevelInit_t)(void*, const char*); +typedef void(*LevelShutdown_t)(void*); +typedef void(*BeginFrame_t)(IStudioRender*); typedef bool(*CanInspect_t)(IClientEntity*); typedef void(*DrawModelExecute_t)(IVModelRender*, const DrawModelState_t&, const ModelRenderInfo_t&, matrix3x4_t*); -typedef CUserCmd*(GetUserCmd_t)(IInput*, int); -typedef const char*(GetClientName_t)(CBaseClientState*); -typedef bool(ProcessSetConVar_t)(CBaseClientState*, NET_SetConVar*); -typedef bool(ProcessGetCvarValue_t)(CBaseClientState*, SVC_GetCvarValue*); +typedef CUserCmd*(*GetUserCmd_t)(IInput*, int); +typedef const char*(*GetClientName_t)(CBaseClientState*); +typedef bool(*ProcessSetConVar_t)(CBaseClientState*, NET_SetConVar*); +typedef bool(*ProcessGetCvarValue_t)(CBaseClientState*, SVC_GetCvarValue*); const char* GetClientName_hook(CBaseClientState* _this); bool ProcessSetConVar_hook(CBaseClientState* _this, NET_SetConVar* msg); bool ProcessGetCvarValue_hook(CBaseClientState* _this, SVC_GetCvarValue* msg); //typedef void(*CInput__CreateMove_t)(void*, int, float, bool); //void CInput__CreateMove_hook(void*, int sequence_number, float input_sample_frametime, bool active); -bool CanInspect_hook(IClientEntity*); -const unsigned int offCanInspect = 512; - -typedef const char*(GetFriendPersonaName_t)(ISteamFriends*, CSteamID); +typedef const char*(*GetFriendPersonaName_t)(ISteamFriends*, CSteamID); const char* GetFriendPersonaName_hook(ISteamFriends* _this, CSteamID steamID); -void BeginFrame_hook(IStudioRender*); CUserCmd* GetUserCmd_hook(IInput*, int); void DrawModelExecute_hook(IVModelRender* _this, const DrawModelState_t& state, const ModelRenderInfo_t& info, matrix3x4_t* matrix); diff --git a/src/hooks/others.cpp b/src/hooks/others.cpp index 603d6a9a..b62a18fb 100644 --- a/src/hooks/others.cpp +++ b/src/hooks/others.cpp @@ -12,6 +12,7 @@ static CatVar no_invisibility(CV_SWITCH, "no_invis", "0", "Remove Invisibility", "Useful with chams!"); +// This hook isn't used yet! int C_TFPlayer__DrawModel_hook(IClientEntity* _this, int flags) { float old_invis = *(float*)((uintptr_t)_this + 79u); if (no_invisibility) { @@ -27,17 +28,9 @@ static CatVar no_arms(CV_SWITCH, "no_arms", "0", "No Arms", "Removes arms from f static CatVar no_hats(CV_SWITCH, "no_hats", "0", "No Hats", "Removes non-stock hats"); void DrawModelExecute_hook(IVModelRender* _this, const DrawModelState_t& state, const ModelRenderInfo_t& info, matrix3x4_t* matrix) { - /*IClientUnknown* unknown = info.pRenderable->GetIClientUnknown(); - if (unknown) { - IClientEntity* entity = unknown->GetIClientEntity(); - if (entity && entity->entindex() != -1) { - if (entity->GetClientClass()->m_ClassID == g_pClassID->C_Player) { - //CMatRenderContextPtr ptr(); - } - } - }*/ + static const DrawModelExecute_t original = (DrawModelExecute_t)hooks::modelrender.GetMethod(offsets::DrawModelExecute()); if (!cathook || !(no_arms || no_hats || (clean_screenshots && g_IEngine->IsTakingScreenshot()))) { - ((DrawModelExecute_t)(hooks::hkIVModelRender->GetMethod(hooks::offDrawModelExecute)))(_this, state, info, matrix); + original(_this, state, info, matrix); return; } @@ -63,18 +56,20 @@ void DrawModelExecute_hook(IVModelRender* _this, const DrawModelState_t& state, } } - ((DrawModelExecute_t)(hooks::hkIVModelRender->GetMethod(hooks::offDrawModelExecute)))(_this, state, info, matrix); + original(_this, state, info, matrix); } -bool CanPacket_hook(void* thisptr) { +bool CanPacket_hook(void* _this) { + const CanPacket_t original = (CanPacket_t)hooks::netchannel.GetMethod(offsets::CanPacket()); SEGV_BEGIN; - return send_packets && ((CanPacket_t*)hooks::hkNetChannel->GetMethod(hooks::offCanPacket))(thisptr); + return send_packets && original(_this); SEGV_END; return false; } -CUserCmd* GetUserCmd_hook(IInput* thisptr, int sequence_number) { - CUserCmd* def = ((GetUserCmd_t*)(hooks::hkInput->GetMethod(hooks::offGetUserCmd)))(thisptr, sequence_number); +CUserCmd* GetUserCmd_hook(IInput* _this, int sequence_number) { + static const GetUserCmd_t original = (GetUserCmd_t)hooks::input.GetMethod(offsets::GetUserCmd()); + CUserCmd* def = original(_this, sequence_number); if (def && command_number_mod.find(def->command_number) != command_number_mod.end()) { logging::Info("Replacing command %i with %i", def->command_number, command_number_mod[def->command_number]); int oldcmd = def->command_number; @@ -85,12 +80,13 @@ CUserCmd* GetUserCmd_hook(IInput* thisptr, int sequence_number) { return def; } -int IN_KeyEvent_hook(void* thisptr, int eventcode, int keynum, const char* pszCurrentBinding) { +int IN_KeyEvent_hook(void* _this, int eventcode, int keynum, const char* pszCurrentBinding) { + static const IN_KeyEvent_t original = (IN_KeyEvent_t)hooks::client.GetMethod(offsets::IN_KeyEvent()); SEGV_BEGIN; if (g_pGUI->ConsumesKey((ButtonCode_t)keynum) && g_pGUI->Visible()) { return 0; } - return ((IN_KeyEvent_t*)hooks::hkClient->GetMethod(hooks::offKeyEvent))(thisptr, eventcode, keynum, pszCurrentBinding); + return original(_this, eventcode, keynum, pszCurrentBinding); SEGV_END; return 0; } @@ -112,7 +108,9 @@ static CatVar newlines_msg(CV_INT, "chat_newlines", "0", "Prefix newlines", "Add // TODO name \\n = \n //static CatVar queue_messages(CV_SWITCH, "chat_queue", "0", "Queue messages", "Use this if you want to use spam/killsay and still be able to chat normally (without having your msgs eaten by valve cooldown)"); -bool SendNetMsg_hook(void* thisptr, INetMessage& msg, bool bForceReliable = false, bool bVoice = false) { +bool SendNetMsg_hook(void* _this, INetMessage& msg, bool bForceReliable = false, bool bVoice = false) { + // This is a INetChannel hook - it SHOULDN'T be static because netchannel changes. + const SendNetMsg_t original = (SendNetMsg_t)hooks::netchannel.GetMethod(offsets::SendNetMsg()); SEGV_BEGIN; // net_StringCmd if (msg.GetType() == 4 && (newlines_msg)) { @@ -128,7 +126,7 @@ bool SendNetMsg_hook(void* thisptr, INetMessage& msg, bool bForceReliable = fals str = str.substr(16, str.length() - 17); //if (queue_messages && !chat_stack::CanSend()) { NET_StringCmd stringcmd(str.c_str()); - return ((SendNetMsg_t*)hooks::hkNetChannel->GetMethod(hooks::offSendNetMsg))(thisptr, stringcmd, bForceReliable, bVoice); + return original(_this, stringcmd, bForceReliable, bVoice); //} } } @@ -145,19 +143,21 @@ bool SendNetMsg_hook(void* thisptr, INetMessage& msg, bool bForceReliable = fals } logging::Info("%i bytes => %s", buffer.GetNumBytesWritten(), bytes.c_str()); } - return ((SendNetMsg_t*)hooks::hkNetChannel->GetMethod(hooks::offSendNetMsg))(thisptr, msg, bForceReliable, bVoice); + return original(_this, msg, bForceReliable, bVoice); SEGV_END; return false; } CatVar disconnect_reason(CV_STRING, "disconnect_reason", "", "Disconnect reason", "A custom disconnect reason"); -void Shutdown_hook(void* thisptr, const char* reason) { +void Shutdown_hook(void* _this, const char* reason) { + // This is a INetChannel hook - it SHOULDN'T be static because netchannel changes. + const Shutdown_t original = (Shutdown_t)hooks::netchannel.GetMethod(offsets::Shutdown()); SEGV_BEGIN; if (cathook && (disconnect_reason.convar_parent->m_StringLength > 3) && strstr(reason, "user")) { - ((Shutdown_t*)hooks::hkNetChannel->GetMethod(hooks::offShutdown))(thisptr, disconnect_reason.GetString()); + original(_this, disconnect_reason.GetString()); } else { - ((Shutdown_t*)hooks::hkNetChannel->GetMethod(hooks::offShutdown))(thisptr, reason); + original(_this, reason); } SEGV_END; } @@ -167,13 +167,15 @@ static CatVar glow_alpha(CV_FLOAT, "glow_old_alpha", "1", "Alpha", "Glow Transpa static CatVar resolver(CV_SWITCH, "resolver", "0", "Resolve angles"); const char* GetFriendPersonaName_hook(ISteamFriends* _this, CSteamID steamID) { + static const GetFriendPersonaName_t original = (GetFriendPersonaName_t)hooks::steamfriends.GetMethod(offsets::GetFriendPersonaName()); if ((force_name.convar->m_StringLength > 2) && steamID == g_ISteamUser->GetSteamID()) { return force_name.GetString(); } - return ((GetFriendPersonaName_t*)(hooks::hkSteamFriends->GetMethod(hooks::offGetFriendPersonaName)))(_this, steamID); + return original(_this, steamID); } -void FrameStageNotify_hook(void* thisptr, int stage) { +void FrameStageNotify_hook(void* _this, int stage) { + static const FrameStageNotify_t original = (FrameStageNotify_t)hooks::client.GetMethod(offsets::FrameStageNotify()); SEGV_BEGIN; if (!g_IEngine->IsInGame()) g_Settings.bInvalid = true; // TODO hack FSN hook @@ -255,16 +257,17 @@ void FrameStageNotify_hook(void* thisptr, int stage) { } } } - SAFE_CALL(((FrameStageNotify_t*)hooks::hkClient->GetMethod(hooks::offFrameStageNotify))(thisptr, stage)); + SAFE_CALL(original(_this, stage)); SEGV_END; } CatVar override_fov_zoomed(CV_FLOAT, "fov_zoomed", "0", "FOV override (zoomed)", "Overrides FOV with this value when zoomed in (default FOV when zoomed is 20)"); CatVar override_fov(CV_FLOAT, "fov", "0", "FOV override", "Overrides FOV with this value"); -void OverrideView_hook(void* thisptr, CViewSetup* setup) { +void OverrideView_hook(void* _this, CViewSetup* setup) { + static const OverrideView_t original = (OverrideView_t)hooks::clientmode.GetMethod(offsets::OverrideView()); SEGV_BEGIN; - ((OverrideView_t*)hooks::hkClientMode->GetMethod(hooks::offOverrideView))(thisptr, setup); + original(_this, setup); if (!cathook) return; bool zoomed = g_pLocalPlayer->bZoomed; if (zoomed && override_fov_zoomed) { @@ -280,7 +283,8 @@ void OverrideView_hook(void* thisptr, CViewSetup* setup) { static CatVar clean_chat(CV_SWITCH, "clean_chat", "0", "Clean chat", "Removes newlines from chat"); static CatVar dispatch_log(CV_SWITCH, "debug_log_usermessages", "0", "Log dispatched user messages"); -bool DispatchUserMessage_hook(void* thisptr, int type, bf_read& buf) { +bool DispatchUserMessage_hook(void* _this, int type, bf_read& buf) { + static const DispatchUserMessage_t original = (DispatchUserMessage_t)hooks::client.GetMethod(offsets::DispatchUserMessage()); SEGV_BEGIN; if (clean_chat) { if (type == 4) { @@ -301,31 +305,29 @@ bool DispatchUserMessage_hook(void* thisptr, int type, bf_read& buf) { if (dispatch_log) { logging::Info("D> %i", type); } - //if (type != net_Tick) logging::Info("Got message: %s", type); - return ((DispatchUserMessage_t*)hooks::hkClient->GetMethod(hooks::offFrameStageNotify + 1))(thisptr, type, buf); - SEGV_END; return false; + return original(_this, type, buf); + SEGV_END; + return false; } -void LevelInit_hook(void* thisptr, const char* newmap) { +void LevelInit_hook(void* _this, const char* newmap) { + static const LevelInit_t original = (LevelInit_t)hooks::clientmode.GetMethod(offsets::LevelInit()); playerlist::Save(); - ((LevelInit_t*) hooks::hkClientMode->GetMethod(hooks::offLevelInit))(thisptr, newmap); g_IEngine->ClientCmd_Unrestricted("exec cat_matchexec"); hacks::shared::aimbot::Reset(); -// LEVEL_SHUTDOWN(FollowBot); - //if (TF) LEVEL_INIT(SpyAlert); chat_stack::Reset(); hacks::shared::spam::Reset(); + original(_this, newmap); } -bool CanInspect_hook(IClientEntity*) { return true; } - -void LevelShutdown_hook(void* thisptr) { +void LevelShutdown_hook(void* _this) { + static const LevelShutdown_t original = (LevelShutdown_t)hooks::clientmode.GetMethod(offsets::LevelShutdown()); need_name_change = true; playerlist::Save(); - ((LevelShutdown_t*) hooks::hkClientMode->GetMethod(hooks::offLevelShutdown))(thisptr); g_Settings.bInvalid = true; hacks::shared::aimbot::Reset(); chat_stack::Reset(); hacks::shared::spam::Reset(); + original(_this); } diff --git a/src/offsets.hpp b/src/offsets.hpp new file mode 100644 index 00000000..c634ed19 --- /dev/null +++ b/src/offsets.hpp @@ -0,0 +1,66 @@ +/* + * offsets.hpp + * + * Created on: May 4, 2017 + * Author: nullifiedcat + */ + +#ifndef OFFSETS_HPP_ +#define OFFSETS_HPP_ + +#include +#include + +enum class platform { + PLATFORM_LINUX, + PLATFORM_WINDOWS, + PLATFORM_OSX, + PLATFORM_UNSUPPORTED +}; + +#ifdef LINUX +constexpr platform PLATFORM = platform::PLATFORM_LINUX; +#else +constexpr platform PLATFORM = platform::PLATFORM_UNSUPPORTED; +#endif + +struct offsets { + static constexpr uint32_t PlatformOffset(uint32_t offset_linux, uint32_t offset_windows, uint32_t offset_osx) { + uint32_t result = -1; + switch (PLATFORM) { + case platform::PLATFORM_LINUX: + result = offset_linux; break; + case platform::PLATFORM_WINDOWS: + result = offset_windows; break; + case platform::PLATFORM_OSX: + result = offset_osx; break; + } + if (result == -1) { + throw std::logic_error("No offset defined for this platform!"); + } + return result; + } + static constexpr uint32_t GetUserCmd() { return PlatformOffset(8, -1, -1); } + static constexpr uint32_t ShouldDraw() { return PlatformOffset(136, -1, -1); } + static constexpr uint32_t DrawModelExecute() { return PlatformOffset(19, -1, -1); } + static constexpr uint32_t GetClientName() { return PlatformOffset(44, -1, -1); } + static constexpr uint32_t ProcessSetConVar() { return PlatformOffset(4, -1, -1); } + static constexpr uint32_t ProcessGetCvarValue() { return PlatformOffset(29, -1, -1); } + static constexpr uint32_t GetFriendPersonaName() { return PlatformOffset(7, -1, -1); } + static constexpr uint32_t CreateMove() { return PlatformOffset(22, -1, -1); } + static constexpr uint32_t PaintTraverse() { return PlatformOffset(42, -1, -1); } + static constexpr uint32_t OverrideView() { return PlatformOffset(17, -1, -1); } + static constexpr uint32_t FrameStageNotify() { return PlatformOffset(35, -1, -1); } + static constexpr uint32_t DispatchUserMessage() { return PlatformOffset(36, -1, -1); } + static constexpr uint32_t CanPacket() { return PlatformOffset(57, -1, -1); } + static constexpr uint32_t SendNetMsg() { return PlatformOffset(41, -1, -1); } + static constexpr uint32_t Shutdown() { return PlatformOffset(37, -1, -1); } + static constexpr uint32_t IN_KeyEvent() { return PlatformOffset(20, -1, -1); } + static constexpr uint32_t HandleInputEvent() { return PlatformOffset(78, -1, -1); } + static constexpr uint32_t LevelInit() { return PlatformOffset(23, -1, -1); } + static constexpr uint32_t LevelShutdown() { return PlatformOffset(24, -1, -1); } + static constexpr uint32_t BeginFrame() { return PlatformOffset(5, -1, -1); } + +}; + +#endif /* OFFSETS_HPP_ */