First draft of dynamic detours using Ayuto's DynamicHooks library
https://github.com/Ayuto/DynamicHooks
This commit is contained in:
@@ -3,7 +3,13 @@
|
||||
|
||||
#include "extension.h"
|
||||
#include <sourcehook.h>
|
||||
#include <macro-assembler-x86.h>
|
||||
|
||||
enum CallingConvention
|
||||
{
|
||||
CallConv_CDECL,
|
||||
CallConv_THISCALL,
|
||||
CallConv_STDCALL,
|
||||
};
|
||||
|
||||
enum MRESReturn
|
||||
{
|
||||
@@ -86,29 +92,16 @@ struct ParamInfo
|
||||
SourceHook::PassInfo::PassType pass_type;
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
#define OBJECT_OFFSET sizeof(void *)
|
||||
#else
|
||||
#define OBJECT_OFFSET (sizeof(void *)*2)
|
||||
#endif
|
||||
|
||||
class HookReturnStruct
|
||||
{
|
||||
public:
|
||||
~HookReturnStruct()
|
||||
{
|
||||
if(this->type == ReturnType_String || this->type == ReturnType_Int || this->type == ReturnType_Bool || this->type == ReturnType_Float || this->type == ReturnType_Vector)
|
||||
{
|
||||
free(this->newResult);
|
||||
free(this->orgResult);
|
||||
}
|
||||
else if(this->isChanged)
|
||||
{
|
||||
if(this->type == ReturnType_CharPtr)
|
||||
{
|
||||
delete [] (char *)this->newResult;
|
||||
}
|
||||
else if(this->type == ReturnType_VectorPtr)
|
||||
{
|
||||
delete (SDKVector *)this->newResult;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
~HookReturnStruct();
|
||||
public:
|
||||
ReturnType type;
|
||||
bool isChanged;
|
||||
@@ -162,95 +155,7 @@ bool SetupHookManager(ISmmAPI *ismm);
|
||||
void CleanupHooks(IPluginContext *pContext = NULL);
|
||||
size_t GetParamTypeSize(HookParamType type);
|
||||
SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type);
|
||||
|
||||
#ifndef WIN32
|
||||
static void *GenerateThunk(ReturnType type)
|
||||
{
|
||||
sp::MacroAssemblerX86 masm;
|
||||
static const size_t kStackNeeded = (2) * 4; // 2 args max
|
||||
static const size_t kReserve = ke::Align(kStackNeeded+8, 16)-8;
|
||||
|
||||
masm.push(ebp);
|
||||
masm.movl(ebp, esp);
|
||||
masm.subl(esp, kReserve);
|
||||
if(type != ReturnType_String && type != ReturnType_Vector)
|
||||
{
|
||||
masm.lea(eax, Operand(ebp, 12)); // grab the incoming caller argument vector
|
||||
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
|
||||
masm.movl(eax, Operand(ebp, 8)); // grab the |this|
|
||||
masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/
|
||||
}
|
||||
else
|
||||
{
|
||||
masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector
|
||||
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
|
||||
masm.movl(eax, Operand(ebp, 12)); // grab the |this|
|
||||
masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/
|
||||
}
|
||||
if(type == ReturnType_Float)
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback_float));
|
||||
}
|
||||
else if(type == ReturnType_Vector)
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback_vector));
|
||||
}
|
||||
else if(type == ReturnType_String)
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback_stringt));
|
||||
}
|
||||
else
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback));
|
||||
}
|
||||
masm.addl(esp, kReserve);
|
||||
masm.pop(ebp); // restore ebp
|
||||
masm.ret();
|
||||
|
||||
void *base = g_pSM->GetScriptingEngine()->AllocatePageMemory(masm.length());
|
||||
masm.emitToExecutableMemory(base);
|
||||
return base;
|
||||
}
|
||||
#else
|
||||
// HUGE THANKS TO BAILOPAN (dvander)!
|
||||
static void *GenerateThunk(ReturnType type)
|
||||
{
|
||||
sp::MacroAssemblerX86 masm;
|
||||
static const size_t kStackNeeded = (3 + 1) * 4; // 3 args max, 1 locals max
|
||||
static const size_t kReserve = ke::Align(kStackNeeded+8, 16)-8;
|
||||
|
||||
masm.push(ebp);
|
||||
masm.movl(ebp, esp);
|
||||
masm.subl(esp, kReserve);
|
||||
masm.lea(eax, Operand(esp, 3 * 4)); // ptr to 2nd var after argument space
|
||||
masm.movl(Operand(esp, 2 * 4), eax); // set the ptr as the third argument
|
||||
masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector
|
||||
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
|
||||
masm.movl(Operand(esp, 0 * 4), ecx); // set |this| as the 1st argument
|
||||
if(type == ReturnType_Float)
|
||||
{
|
||||
masm.call(ExternalAddress(Callback_float));
|
||||
}
|
||||
else if(type == ReturnType_Vector)
|
||||
{
|
||||
masm.call(ExternalAddress(Callback_vector));
|
||||
}
|
||||
else
|
||||
{
|
||||
masm.call(ExternalAddress(Callback));
|
||||
}
|
||||
masm.movl(ecx, Operand(esp, 3*4));
|
||||
masm.addl(esp, kReserve);
|
||||
masm.pop(ebp); // restore ebp
|
||||
masm.pop(edx); // grab return address in edx
|
||||
masm.addl(esp, ecx); // remove arguments
|
||||
masm.jmp(edx); // return to caller
|
||||
|
||||
void *base = g_pSM->GetScriptingEngine()->AllocatePageMemory(masm.length());
|
||||
masm.emitToExecutableMemory(base);
|
||||
return base;
|
||||
}
|
||||
#endif
|
||||
void *GenerateThunk(ReturnType type);
|
||||
|
||||
static DHooksCallback *MakeHandler(ReturnType type)
|
||||
{
|
||||
@@ -280,7 +185,7 @@ public:
|
||||
void **orgParams;
|
||||
void **newParams;
|
||||
bool *isChanged;
|
||||
DHooksCallback *dg;
|
||||
DHooksInfo *dg;
|
||||
};
|
||||
|
||||
class HookSetup
|
||||
@@ -291,18 +196,33 @@ public:
|
||||
this->returnType = returnType;
|
||||
this->returnFlag = returnFlag;
|
||||
this->hookType = hookType;
|
||||
this->callConv = CallConv_THISCALL;
|
||||
this->thisType = thisType;
|
||||
this->offset = offset;
|
||||
this->funcAddr = nullptr;
|
||||
this->callback = callback;
|
||||
};
|
||||
HookSetup(ReturnType returnType, unsigned int returnFlag, CallingConvention callConv, ThisPointerType thisType, void *funcAddr)
|
||||
{
|
||||
this->returnType = returnType;
|
||||
this->returnFlag = returnFlag;
|
||||
this->hookType = HookType_Raw;
|
||||
this->callConv = callConv;
|
||||
this->thisType = thisType;
|
||||
this->offset = -1;
|
||||
this->funcAddr = funcAddr;
|
||||
this->callback = nullptr;
|
||||
};
|
||||
~HookSetup(){};
|
||||
public:
|
||||
unsigned int returnFlag;
|
||||
ReturnType returnType;
|
||||
HookType hookType;
|
||||
CallingConvention callConv;
|
||||
ThisPointerType thisType;
|
||||
SourceHook::CVector<ParamInfo> params;
|
||||
int offset;
|
||||
void *funcAddr;
|
||||
IPluginFunction *callback;
|
||||
};
|
||||
|
||||
@@ -335,6 +255,7 @@ public:
|
||||
};
|
||||
|
||||
size_t GetStackArgsSize(DHooksCallback *dg);
|
||||
cell_t GetThisPtr(void *iface, ThisPointerType type);
|
||||
|
||||
extern IBinTools *g_pBinTools;
|
||||
extern HandleType_t g_HookParamsHandle;
|
||||
|
||||
Reference in New Issue
Block a user