feat(NativeHooking): Added dynamic script native hooking

This commit is contained in:
Yimura
2022-01-21 23:13:43 +01:00
parent ee38e194b7
commit 0bfb078d9f
7 changed files with 140 additions and 65 deletions

View File

@ -9,6 +9,7 @@
#include "script_mgr.hpp"
#include "thread_pool.hpp"
#include "native_hooks/native_hooks.hpp"
#include "services/globals_service.hpp"
#include "services/mobile_service.hpp"
#include "services/vehicle_service.hpp"
@ -55,20 +56,26 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
g_hooking->enable();
LOG(INFO) << "Hooking enabled.";
LOG(INFO) << "Registering service instances...";
auto globals_service_instace = std::make_unique<globals_service>();
auto mobile_service_instance = std::make_unique<mobile_service>();
auto vehicle_service_instance = std::make_unique<vehicle_service>();
LOG(INFO) << "Registered service instances...";
auto native_hooks_instance = std::make_unique<native_hooks>();
LOG(INFO) << "Dynamic native hooker initialized.";
while (g_running)
{
std::this_thread::sleep_for(500ms);
}
LOG(INFO) << "Serviceses uninitialized.";
native_hooks_instance.reset();
LOG(INFO) << "Dynamic native hooker uninitialized.";
vehicle_service_instance.reset();
mobile_service_instance.reset();
globals_service_instace.reset();
LOG(INFO) << "Serviceses uninitialized.";
// Make sure that all threads created don't have any blocking loops
// otherwise make sure that they have stopped executing

View File

@ -0,0 +1,37 @@
#pragma once
#include "native_hooks.hpp"
#include "natives.hpp"
namespace big
{
namespace carmod_shop
{
inline void SET_ENTITY_COORDS(rage::scrNativeCallContext* src)
{
if (!g.vehicle.ls_customs)
{
ENTITY::SET_ENTITY_COORDS(
src->get_arg<Entity>(0),
src->get_arg<float>(1),
src->get_arg<float>(2),
src->get_arg<float>(3),
src->get_arg<BOOL>(4),
src->get_arg<BOOL>(5),
src->get_arg<BOOL>(6),
src->get_arg<BOOL>(7)
);
}
}
inline void SET_ENTITY_HEADING(rage::scrNativeCallContext* src)
{
if (!g.vehicle.ls_customs)
{
ENTITY::SET_ENTITY_HEADING(
src->get_arg<Entity>(0),
src->get_arg<float>(1)
);
}
}
}
}

View File

@ -0,0 +1,15 @@
#pragma once
namespace big
{
namespace freemode
{
inline void NETWORK_CAN_BAIL(rage::scrNativeCallContext* src)
{
LOG(INFO) << "NATIVE_HOOK => NETWORK_CAN_BAIL : TRIGGERED";
src->set_return_value<BOOL>(false);
}
}
}

View File

@ -1,16 +1,84 @@
#pragma once
#include "natives.hpp"
#include "gta/joaat.hpp"
#include "gta/script_thread.hpp"
#include "native_hooks/carmod_shop.hpp"
#include "native_hooks/freemode.hpp"
#include "script_hook.hpp"
namespace big::native_hook
namespace big
{
inline void NETWORK_CAN_BAIL(rage::scrNativeCallContext* src);
inline void STAT_SET_INT(rage::scrNativeCallContext* src);
inline void TRIGGER_SCRIPT_EVENT(rage::scrNativeCallContext* src);
class native_hooks;
inline native_hooks* g_native_hooks{};
static std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> natives_replace =
class native_hooks final
{
{ 0x580CE4438479CC61, &NETWORK_CAN_BAIL },
{ 0xB3271D7AB655B441, &STAT_SET_INT },
{ 0x5AE99C571D5BBE5D, &TRIGGER_SCRIPT_EVENT }
typedef std::pair<rage::scrNativeHash, rage::scrNativeHandler> native_detour;
std::map<rage::joaat_t, std::vector<native_detour>> m_native_registrations;
std::map<rage::joaat_t, std::unique_ptr<script_hook>> m_script_hooks;
public:
native_hooks()
{
this->add_native_detour(RAGE_JOAAT("carmod_shop"), 0x06843DA7060A026B, carmod_shop::SET_ENTITY_COORDS);
this->add_native_detour(RAGE_JOAAT("carmod_shop"), 0x8E2530AA8ADA980E, carmod_shop::SET_ENTITY_HEADING);
this->add_native_detour(RAGE_JOAAT("freemode"), 0x580CE4438479CC61, freemode::NETWORK_CAN_BAIL);
g_native_hooks = this;
}
~native_hooks()
{
g_native_hooks = nullptr;
}
void add_native_detour(rage::joaat_t script_hash, rage::scrNativeHash hash, rage::scrNativeHandler detour)
{
if (auto it = m_native_registrations.find(script_hash); it != m_native_registrations.end())
return it->second.push_back({ hash, detour });
m_native_registrations.emplace(script_hash, std::vector<native_detour>({ { hash, detour } }));
}
bool check_for_thread(GtaThread* gta_thread)
{
std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> native_replacements;
rage::joaat_t script_hash = gta_thread->m_script_hash;
std::map<rage::joaat_t, std::vector<native_detour>>::iterator pair = m_native_registrations.find(script_hash);
if (pair == m_native_registrations.end())
return false;
for (native_detour native_hook_reg : pair->second)
native_replacements.insert(native_hook_reg);
if (native_replacements.size())
{
if (m_script_hooks.find(gta_thread->m_script_hash) != m_script_hooks.end())
{
// this should never happen but if it does we catch it
LOG(INFO) << "Dynamic native script hook still active for script, cleaning up...";
m_script_hooks.erase(gta_thread->m_script_hash);
}
m_script_hooks.emplace(
gta_thread->m_script_hash,
std::make_unique<script_hook>(gta_thread->m_script_hash, native_replacements)
);
return true;
}
return false;
}
void do_cleanup_for_thread(GtaThread* gta_thread)
{
if (m_script_hooks.erase(gta_thread->m_script_hash))
{
LOG(INFO) << gta_thread->m_name << " script terminated, cleaning up native hooks";
}
}
};
}

View File

@ -1,8 +1,8 @@
#include "native_hooks.hpp"
namespace big::native_hook
namespace big
{
void NETWORK_CAN_BAIL(rage::scrNativeCallContext* src)
inline void NETWORK_CAN_BAIL(rage::scrNativeCallContext* src)
{
LOG(INFO) << "NATIVE_HOOK => NETWORK_CAN_BAIL : TRIGGERED";

View File

@ -1,28 +0,0 @@
#include "native_hooks.hpp"
#include "gta/joaat.hpp"
namespace big::native_hook
{
void STAT_SET_INT(rage::scrNativeCallContext* src)
{
Hash stat_hash = src->get_arg<Hash>(0);
int value = src->get_arg<int>(1);
BOOL save = src->get_arg<BOOL>(2);
switch (stat_hash)
{
case RAGE_JOAAT("MPPLY_GAME_EXPLOITS"):
case RAGE_JOAAT("MPPLY_VC_HATE"):
case RAGE_JOAAT("MPPLY_EXPLOITS"):
case RAGE_JOAAT("MPPLY_TC_ANNOYINGME"):
case RAGE_JOAAT("MPPLY_TC_HATE"):
src->set_return_value<BOOL>(true);
break;
default:
src->set_return_value<BOOL>(STATS::STAT_SET_INT(stat_hash, value, save));
break;
}
}
}

View File

@ -1,24 +0,0 @@
#include "native_hooks.hpp"
#include "pointers.hpp"
namespace big::native_hook
{
void TRIGGER_SCRIPT_EVENT(rage::scrNativeCallContext* src)
{
int event_group = src->get_arg<int>(0);
Any* event_data = src->get_arg<Any*>(1);
int event_size = src->get_arg<int>(3);
int player_bits = src->get_arg<int>(4);
if (event_group)
{
Hash event_hash = event_data[0];
LOG(INFO) << "Event hash: " << event_hash;
for (size_t i = 1; i < std::min(event_size, 200); i++)
LOG(INFO) << "Arg[#" << i << "] : " << event_data[i];
}
SCRIPT::TRIGGER_SCRIPT_EVENT(event_group, event_data, event_size, player_bits);
}
}