Resolve mappin system vtable during tracking probe
This commit is contained in:
@@ -91,9 +91,12 @@ namespace
|
||||
{
|
||||
constexpr uint32_t kGameStateRunning = 2;
|
||||
constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C;
|
||||
constexpr uintptr_t kMappinSystemResolverRva = 0x02BB840;
|
||||
constexpr uintptr_t kTrackMappinWrapperRva = 0x27C4AB4;
|
||||
constexpr uintptr_t kTrackMappinCoreRva = 0x27C11D0;
|
||||
constexpr uintptr_t kSetMappinTrackingAlternativeWrapperRva = 0x1246794;
|
||||
constexpr uintptr_t kMappinSetTrackedSlotOffset = 0x220;
|
||||
constexpr uintptr_t kMappinClearTrackedSlotOffset = 0x228;
|
||||
|
||||
HMODULE gModule = nullptr;
|
||||
std::mutex gLogMutex;
|
||||
@@ -105,16 +108,27 @@ uint32_t gGpsTickLogCount = 0;
|
||||
uint32_t gTrackMappinWrapperLogCount = 0;
|
||||
uint32_t gTrackMappinCoreLogCount = 0;
|
||||
uint32_t gSetMappinTrackingAlternativeLogCount = 0;
|
||||
uint32_t gMappinSystemSlotLogCount = 0;
|
||||
uint32_t gMappinSetTrackedLogCount = 0;
|
||||
uint32_t gMappinClearTrackedLogCount = 0;
|
||||
uint64_t gLogStartTick = 0;
|
||||
uint64_t gLogFrequency = 0;
|
||||
void* gMappinSetTrackedTarget = nullptr;
|
||||
void* gMappinClearTrackedTarget = nullptr;
|
||||
bool gMappinSlotHookAttachAttempted = false;
|
||||
|
||||
using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4);
|
||||
using ScriptNativeVoidFunc = void (*)(void* aThis, void* aStack, void* aResult);
|
||||
using MappinSystemResolverFunc = void* (*)(void* aThis);
|
||||
using TrackMappinCoreFunc = void (*)(void* aThis, void* aMappinHandle);
|
||||
using MappinSetTrackedFunc = void (*)(void* aSystem, void* aMappinId);
|
||||
using MappinClearTrackedFunc = void (*)(void* aSystem);
|
||||
ProbeFunc gOriginalGpsSystemTick = nullptr;
|
||||
ScriptNativeVoidFunc gOriginalTrackMappinWrapper = nullptr;
|
||||
TrackMappinCoreFunc gOriginalTrackMappinCore = nullptr;
|
||||
ScriptNativeVoidFunc gOriginalSetMappinTrackingAlternativeWrapper = nullptr;
|
||||
MappinSetTrackedFunc gOriginalMappinSetTracked = nullptr;
|
||||
MappinClearTrackedFunc gOriginalMappinClearTracked = nullptr;
|
||||
|
||||
std::filesystem::path GetLogPath()
|
||||
{
|
||||
@@ -195,6 +209,28 @@ void LogTrackMappinCoreCall(uint32_t aCount, void* aThis, void* aMappinHandle)
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void LogMappinSystemSlots(uint32_t aCount, void* aSystem, void* aVtable)
|
||||
{
|
||||
auto* vtable = reinterpret_cast<uint8_t*>(aVtable);
|
||||
auto readSlot = [vtable](uintptr_t aOffset) -> void* {
|
||||
if (!vtable)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return *reinterpret_cast<void**>(vtable + aOffset);
|
||||
};
|
||||
|
||||
std::ostringstream line;
|
||||
line << "mappin-system slots call=" << aCount << " system=" << aSystem << " vtable=" << aVtable
|
||||
<< " slot220=" << readSlot(0x220) << " slot228=" << readSlot(0x228)
|
||||
<< " slot250=" << readSlot(0x250) << " slot2e0=" << readSlot(0x2E0)
|
||||
<< " slot368=" << readSlot(0x368) << " slot3a8=" << readSlot(0x3A8);
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void InspectAndHookMappinSystem(void* aThis);
|
||||
|
||||
const char* ReasonToString(RED4ext::v1::EMainReason aReason)
|
||||
{
|
||||
switch (aReason)
|
||||
@@ -389,6 +425,8 @@ void DetourTrackMappinCore(void* aThis, void* aMappinHandle)
|
||||
++gTrackMappinCoreLogCount;
|
||||
}
|
||||
|
||||
InspectAndHookMappinSystem(aThis);
|
||||
|
||||
if (gOriginalTrackMappinCore)
|
||||
{
|
||||
gOriginalTrackMappinCore(aThis, aMappinHandle);
|
||||
@@ -410,6 +448,40 @@ void DetourSetMappinTrackingAlternativeWrapper(void* aThis, void* aStack, void*
|
||||
}
|
||||
}
|
||||
|
||||
void DetourMappinSetTracked(void* aSystem, void* aMappinId)
|
||||
{
|
||||
if (gMappinSetTrackedLogCount < 64)
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << "hook MappinSystem::SetTracked slot220 call=" << gMappinSetTrackedLogCount
|
||||
<< " system=" << aSystem << " mappinId=" << aMappinId;
|
||||
LogRed4ext(line.str());
|
||||
++gMappinSetTrackedLogCount;
|
||||
}
|
||||
|
||||
if (gOriginalMappinSetTracked)
|
||||
{
|
||||
gOriginalMappinSetTracked(aSystem, aMappinId);
|
||||
}
|
||||
}
|
||||
|
||||
void DetourMappinClearTracked(void* aSystem)
|
||||
{
|
||||
if (gMappinClearTrackedLogCount < 64)
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << "hook MappinSystem::ClearTracked slot228 call=" << gMappinClearTrackedLogCount
|
||||
<< " system=" << aSystem;
|
||||
LogRed4ext(line.str());
|
||||
++gMappinClearTrackedLogCount;
|
||||
}
|
||||
|
||||
if (gOriginalMappinClearTracked)
|
||||
{
|
||||
gOriginalMappinClearTracked(aSystem);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachProbeHook(const char* aName, uintptr_t aRva, void* aDetour, void** aOriginal)
|
||||
{
|
||||
if (!gSdk || !gSdk->hooking || !gSdk->hooking->Attach)
|
||||
@@ -427,6 +499,30 @@ void AttachProbeHook(const char* aName, uintptr_t aRva, void* aDetour, void** aO
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void AttachAbsoluteHook(const char* aName, void* aTarget, void* aDetour, void** aOriginal)
|
||||
{
|
||||
if (!gSdk || !gSdk->hooking || !gSdk->hooking->Attach)
|
||||
{
|
||||
LogRed4ext("absolute hook attach skipped: RED4ext hooking API unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aTarget)
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << "absolute hook attach skipped " << aName << ": target=null";
|
||||
LogRed4ext(line.str());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto attached = gSdk->hooking->Attach(gHandle, aTarget, aDetour, aOriginal);
|
||||
|
||||
std::ostringstream line;
|
||||
line << "absolute hook attach " << aName << " target=" << aTarget
|
||||
<< " result=" << (attached ? "ok" : "failed") << " original=" << (aOriginal ? *aOriginal : nullptr);
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void DetachProbeHook(const char* aName, uintptr_t aRva)
|
||||
{
|
||||
if (!gSdk || !gSdk->hooking || !gSdk->hooking->Detach)
|
||||
@@ -442,6 +538,53 @@ void DetachProbeHook(const char* aName, uintptr_t aRva)
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void DetachAbsoluteHook(const char* aName, void* aTarget)
|
||||
{
|
||||
if (!gSdk || !gSdk->hooking || !gSdk->hooking->Detach || !aTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto detached = gSdk->hooking->Detach(gHandle, aTarget);
|
||||
|
||||
std::ostringstream line;
|
||||
line << "absolute hook detach " << aName << " target=" << aTarget
|
||||
<< " result=" << (detached ? "ok" : "failed");
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void InspectAndHookMappinSystem(void* aThis)
|
||||
{
|
||||
auto* resolver = reinterpret_cast<MappinSystemResolverFunc>(
|
||||
reinterpret_cast<uintptr_t>(GetModuleHandleW(nullptr)) + kMappinSystemResolverRva);
|
||||
void* system = resolver ? resolver(aThis) : nullptr;
|
||||
auto* vtable = system ? *reinterpret_cast<void***>(system) : nullptr;
|
||||
|
||||
if (gMappinSystemSlotLogCount < 16)
|
||||
{
|
||||
LogMappinSystemSlots(gMappinSystemSlotLogCount, system, vtable);
|
||||
++gMappinSystemSlotLogCount;
|
||||
}
|
||||
|
||||
if (gMappinSlotHookAttachAttempted || !vtable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gMappinSlotHookAttachAttempted = true;
|
||||
gMappinSetTrackedTarget =
|
||||
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinSetTrackedSlotOffset);
|
||||
gMappinClearTrackedTarget =
|
||||
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinClearTrackedSlotOffset);
|
||||
|
||||
AttachAbsoluteHook("MappinSystem::SetTracked slot220", gMappinSetTrackedTarget,
|
||||
reinterpret_cast<void*>(&DetourMappinSetTracked),
|
||||
reinterpret_cast<void**>(&gOriginalMappinSetTracked));
|
||||
AttachAbsoluteHook("MappinSystem::ClearTracked slot228", gMappinClearTrackedTarget,
|
||||
reinterpret_cast<void*>(&DetourMappinClearTracked),
|
||||
reinterpret_cast<void**>(&gOriginalMappinClearTracked));
|
||||
}
|
||||
|
||||
bool OnRunningEnter(void* aApp)
|
||||
{
|
||||
std::ostringstream line;
|
||||
@@ -531,6 +674,8 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
|
||||
DetachProbeHook("TrackMappinWrapper", kTrackMappinWrapperRva);
|
||||
DetachProbeHook("TrackMappinCore", kTrackMappinCoreRva);
|
||||
DetachProbeHook("SetMappinTrackingAlternativeWrapper", kSetMappinTrackingAlternativeWrapperRva);
|
||||
DetachAbsoluteHook("MappinSystem::SetTracked slot220", gMappinSetTrackedTarget);
|
||||
DetachAbsoluteHook("MappinSystem::ClearTracked slot228", gMappinClearTrackedTarget);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user