I have successfully hooked a victim application with dll-injection. I now need to call an un-exported singleton function of the victim process. Is this possible, how would I go about it?
Whilst I have the object files etc of the victim process I am unable to rebuild/deploy new versions, so I can't just create a function with export linkage.
I have tried code in my hook process:
#include "VictimSingleton.h"
//...
void SomeFuncInHook()
{
VictimSingleton *vs = VictimSingleton::Get();
vs->DoThing();
}
internally Get() is implemented like:
VictimSingleton* VictimSingleton::Get()
{
static VictimSingleton singleton;
return &singleton;
}
Expected Result: VictimSingleton::Get() returns same address when called from my hook or my victim process.
Actual result: The pointer returned by Get, whilst valid, refers to a different VictimSingleton than the one used by the victim process.
I guess that is because it is two separate translation units, so it creates a different version of the singleton when called from my hook process.
If the function is not exported, you don't have a PDB and debug symbols aren't embedded then first you must find the function, using a disassembler such as IDA Pro. If it is a virtual function then finding it will be much easier because you can expose the Run Time Type Information with an IDA plugin such as Class Informer, this will give you a list of all the vtable functions.
Once you have the address of the function you need to reverse it's calling convention and it's arguments. Most likely this is a __thiscall function because it's a member function.
Next, in order to call a member function you require a class instance to pass as the this pointer. To do so, you can also find the class's constructor and call that, using it's return as your instance.
Next, you need to call the function. To call a __thiscall function you actually call it as a __fastcall and you pass the address of the object you created as the this pointer as the first argument, and a 0 for the second variables, following by the actual function arguments.
The second argument is a zero because __fastcall expects a variable passed in EDX.
Typedef a function pointer prototype, create an instance of this function pointer, assign it the address of the function and then call it.
typedef void(__fastcall* fFunc)(void* thisptr, void* not_edx, float arg1, int arg2);
fFunc Func = (fFunc)0xDEADC0DE; //address of function
Func(objectPtr, 0, 1.0f, 2);