【问题标题】:Copy function in memory内存中的复制功能
【发布时间】:2013-04-10 18:48:54
【问题描述】:

我正在尝试挂钩一个 linux 程序的功能。 基本上是用 mprotect 搜索解除对函数的保护,然后在原始函数地址中放置一个 jmp,重定向到我的函数钩子。

但是我想复制原始函数,以便在不需要修改的函数时调用它。 我会有这样的钩子

int CallHookedFunctionFoobar(int param1, int param2)
{
      if (g_somevariable)
           Foobar_original(param1, param2);
      else
           Foobar_modified(param1, param2);
}

所以我的问题是......我怎么知道函数的大小(以字节为单位),所以我可以将它 memcpy() 到动态分配的缓冲区中执行它?

我考虑过可能嵌入一个小长度的反汇编程序并解析操作码,直到找到 RETN 光码,但我不确定它绝对适用于所有情况(例如,如果多个 RETN 驻留在同一个函数中:[ )

我想这样做的另一个原因是因为同一个函数可能已被另一个库挂钩..

【问题讨论】:

标签: c linux assembly


【解决方案1】:

首先,如果这是特定于 Linux 的,那么您的可执行文件很可能是 ELF 二进制文件。因此,您可以只解析 ELF 标头(例如使用 libelf)来查找/计算函数的长度。

但是,我不明白您为什么需要这个。我能想到的一种更简单的方法是即时修补函数,用JMPCALL 替换它的前几条指令到钩子函数,同时保存那些被覆盖的指令以便以后修补它。比如:

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();
}

【讨论】:

  • 或者,更简单——覆盖 PLT 条目,当然如果符号没有隐藏的话。
  • @VladLazarenko 对,特别是考虑到这将与动态库一起使用。
  • 感谢您的信息。事实上,我可以将信息保存在数组中并重新修补。尽管如此,我这样做主要是为了学习目的,并认为我可以成为父亲。您能否提供有关 ELF 解析的更多信息?看起来很有趣。如何检查 ELF 中的函数长度?通过对 .symtab 中的 syms 偏移和下一个或...的 func 偏移进行排序?原谅我的无知。你能提供一些基本的示例代码吗?谢谢,100 万次。
猜你喜欢
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多