From eb06b7d7701c504dea24a5b8a38d2eaf8be68f8d Mon Sep 17 00:00:00 2001 From: Yauhen Pahrabniak Date: Mon, 2 Dec 2024 10:20:01 +0100 Subject: [PATCH] fix: one more parachute exploit fix Co-authored-by: slashkeyvalue --- .../src/CrashFixes.FakeParachuteProp.cpp | 66 +++++++++++++++---- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/code/components/gta-core-five/src/CrashFixes.FakeParachuteProp.cpp b/code/components/gta-core-five/src/CrashFixes.FakeParachuteProp.cpp index 44cc677f12..b1bbb6137b 100644 --- a/code/components/gta-core-five/src/CrashFixes.FakeParachuteProp.cpp +++ b/code/components/gta-core-five/src/CrashFixes.FakeParachuteProp.cpp @@ -14,32 +14,71 @@ std::once_flag traceOnceFlag; uint32_t parachuteObjectOffset = 0; uint32_t drawHandlerOffset = 0; +uint32_t taskTakeOffPedVariationPropOffset = 0; + +template +bool IsTaskFSMEntityAnimDirectorValid(hook::FlexStruct* self) +{ + hook::FlexStruct* taskEntity = self->Get(UseTaskPropEntity ? taskTakeOffPedVariationPropOffset : taskEntityOffset); + + // We only care about validating a entity's animDirector if the entity exists already + // as entity creation might be deferred for tasks such as CTaskParachuteObject + if (taskEntity) + { + hook::FlexStruct* dynamicEntityComponent = taskEntity->Get(dynamicEntityComponentOffset); + + if (!dynamicEntityComponent) + { + return false; + } + + hook::FlexStruct* animDirector = dynamicEntityComponent->Get(animDirectorOffset); + + if (!animDirector) + { + std::call_once(traceOnceFlag, []() + { + trace("Fake parachute model crash prevented [CFX-1907]\n"); + }); + + return false; + } + } + + return true; +} + uint64_t (*g_CTaskParachuteObject_UpdateFSM)(hook::FlexStruct* self, int state, int subState); uint64_t CTaskParachuteObject_UpdateFSM(hook::FlexStruct* self, int state, int subState) { - hook::FlexStruct* taskEntity = self->Get(taskEntityOffset); - if (!taskEntity) + if (!IsTaskFSMEntityAnimDirectorValid(self)) { return 0; } - hook::FlexStruct* dynamicEntityComponent = taskEntity->Get(dynamicEntityComponentOffset); - if (!dynamicEntityComponent) + return g_CTaskParachuteObject_UpdateFSM(self, state, subState); +} + +uint64_t (*g_CTaskTakeOffPedVariation_UpdateFSM)(hook::FlexStruct* self, int state, int subState); +uint64_t CTaskTakeOffPedVariation_UpdateFSM(hook::FlexStruct* self, int state, int subState) +{ + if (!IsTaskFSMEntityAnimDirectorValid(self)) { return 0; } - hook::FlexStruct* animDirector = dynamicEntityComponent->Get(animDirectorOffset); - if (!animDirector) + return g_CTaskTakeOffPedVariation_UpdateFSM(self, state, subState); +} + +uint64_t (*g_CTaskTakeOffPedVariation_AttachProp)(hook::FlexStruct* self); +uint64_t CTaskTakeOffPedVariation_AttachProp(hook::FlexStruct* self) +{ + if (!IsTaskFSMEntityAnimDirectorValid(self)) { - std::call_once(traceOnceFlag, []() - { - trace("Fake parachute model crash prevented [CFX-1907]\n"); - }); return 0; } - return g_CTaskParachuteObject_UpdateFSM(self, state, subState); + return g_CTaskTakeOffPedVariation_AttachProp(self); } void (*g_CTaskParachute_SetParachuteTintIndex)(hook::FlexStruct* self); @@ -116,4 +155,9 @@ static HookFunction hookFunction([] hook::nop(location, 7); hook::jump(location, patchStub.GetCode()); } + + taskTakeOffPedVariationPropOffset = *hook::get_pattern("48 8B 81 ? ? ? ? 33 C9 48 85 C0 74 ? 48 8B 40 ? 48 85 C0", 3); + + g_CTaskTakeOffPedVariation_UpdateFSM = hook::trampoline(hook::get_pattern("48 83 EC ? 4C 8B C9 85 D2 78 ? B8"), &CTaskTakeOffPedVariation_UpdateFSM); + g_CTaskTakeOffPedVariation_AttachProp = hook::trampoline(hook::get_pattern("48 89 5C 24 ? 57 48 83 EC ? 0F 29 74 24 ? 48 8B D9 E8 ? ? ? ? 84 C0"), &CTaskTakeOffPedVariation_AttachProp); });