我正在尝试挂钩linux程序的一个功能。 基本上用mprotect搜索unprotecting函数,然后在原始函数地址中放入一个jmp,重定向到我的函数钩子。
但是我想复制原始函数,以便在不需要修改函数时调用它。 我会有这样的钩子
int CallHookedFunctionFoobar(int param1, int param2)
{
if (g_somevariable)
Foobar_original(param1, param2);
else
Foobar_modified(param1, param2);
}
所以我的问题是......我怎么能知道一个函数的大小,以字节为单位,所以我可以将它memcpy()到一个动态分配的缓冲区来执行它?
我想过可能嵌入一个小长度的反汇编程序并解析操作码,直到找到RETN光电码,但我不确定它是否适用于所有情况(例如,如果多个RETN驻留在同一个函数中:[ )
另一个原因是因为我想这样做是因为同一个函数可能已被另一个库挂钩..
答案 0 :(得分:3)
首先,如果这是特定于Linux的,那么很可能您的可执行文件是ELF
二进制文件。所以你可以解析ELF头(例如使用libelf
)来查找/计算函数的长度。
但是,我不明白你为什么需要这个。我能想到的一个更简单的方法是即时修补函数,用JMP
或CALL
将其前几条指令替换为钩子函数,同时保存那些覆盖的指令以便稍后修补它。类似的东西:
void call_hooked(void (*fn)(), unsigned char *ctx, size_t *n)
{
unsigned char hook_patch[] = { 0x15, 0x20, 0x7f, 0x48 }; // I bluffed
*n = sizeof(hook_patch);
memcpy(ctx, fn, sizeof(hook_patch));
memcpy(fn, hook_patch, sizeof(hook_patch));
fn();
}
void call_orig(void (*fn)(), unsigned char *ctx, size_t n)
{
memcpy(fn, ctx, n);
fn();
}