0

So, I'm attempting to create a mod for an older game, Fable: The Lost Chapters. I was able to find the MacOS release of the game, which contains symbols, and I was also able to find a leaked debug build for windows, which also contains symbols. Both have made the modding process far easier, however this function specifically I have been unable to call or hook.

Here's what the function looks like within IDA when demangled.

MacOS CThingCreatureBase::SetCurrentAction(CCreatureActionBase const&)

Windows Debug Build bool __thiscall CThingCreatureBase::SetCurrentAction(CThingCreatureBase *this, const CCreatureActionBase *action)

And here's how I'm hooking the function.

typedef bool (__thiscall* tSetCurrentAction)(CThingCreatureBase*, CCreatureActionBase const &);

tSetCurrentAction oSetCurrentAction;

bool __fastcall hSetCurrentAction(CThingCreatureBase* This, CCreatureActionBase const & action)
{
    return oSetCurrentAction(This, action);
}

if (MH_Initialize() == MH_OK)
    std::cout << "MinHook Initialized" << std::endl; 

if(MH_CreateHook((LPVOID)0x6644F0, &hSetCurrentAction, reinterpret_cast<void**>(&oSetCurrentAction)) == MH_OK)
        std::cout << "SetCurrentAction Hooked" << std::endl;

    if (MH_EnableHook((LPVOID)0x6644F0) == MH_OK)
        std::cout << "SetCurrentAction Enabled" << std::endl;

Though for some reason, the game crashes whenever oSetCurrentAction is called.

Here's the exception when debugging Exception thrown at 0x00692F03 in Fable.exe: 0xC0000005: Access violation reading location 0xCCCCCCD0.

I'm hopeful that I'm just missing something obvious, what someone will easily spot, but that's probably not the case. Any help would be greatly appreciated.

5
  • Could you add the crash information? A debugger output maybe. Looking at your code, in MH_CreateHook(...) you use an absolute address: 0x6644F0. If it is taken from the symbols table offsets, it is an offset from the ImageBase that you need to calculate to the correct virtual address.
    – Yotamz
    Mar 2 at 12:31
  • The address is not taken from a symbols table, all I'm doing is comparing what the function looks like in the debug build of the game, and finding is location in release. Also, the function hooks, with the correct arguments being passed through. I've added the debugger output as well.
    – Reaper
    Mar 2 at 13:43
  • 1
    In the first line you define the original function pointer tSetCurrentAction() as a __thiscall. Your hook function, hSetCurrentAction is declared as __fastcall. The hook function will take the action argument from EDX which is undefined. The original function, trying to access the action argument will most likely end up reading some arbitrary memory address and crash.
    – Yotamz
    Mar 2 at 15:16
  • How would I go about hooking a __thiscall function, with minhook it looked like the hooked function had to be static.
    – Reaper
    Mar 2 at 16:03
  • 1
    __thiscall is just a calling convention. Changing the pointer to that should work. Your function is called by the game as __thiscall with a this * in ECX (same as a __fastcall) and action on the stack. Translated to __fastcall terms, the action argument is the third arg passed to your hook function. If you add an unused second arg to your hook function then you can leave the content as is.
    – Yotamz
    Mar 2 at 18:57

1 Answer 1

1

In the first line you define the original function pointer tSetCurrentAction() as a __thiscall.

Your hook function, hSetCurrentAction is declared as __fastcall.

The hook function will take the action argument from EDX which is undefined. The original function, trying to access the action argument will most likely end up reading some arbitrary memory address and crash.

__thiscall is just a calling convention, changing the pointer to that type should work:

Your function is called by the game as __thiscall with a this * in ECX (same as a __fastcall) and action on the stack. Translated to __fastcall terms, the action argument is the third arg passed to your hook function.

If you add an unused second arg to your hook function then you can leave the content as is.

A less important note:

In many debug builds, the space between functions is filled by the compiler with 0xCC bytes. The access violation reading from 0xCCCCCCD0 suggests that the original function tried to dereference the undefined space pointed to by EDX, got 0xCCCCCCCC, added the offset to method or data in the "object" (0xC) and then read or called it at 0xCCCCCCD0.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.