【问题标题】:Replacing symbols without LD_PRELOAD替换没有 LD_PRELOAD 的符号
【发布时间】:2015-04-25 10:04:41
【问题描述】:

是否可以在运行时对系统调用设置挂钩?以可移植的方式,没有asm,也许是一些动态链接器功能? 我想拦截 3rd 方库的系统调用。不想使用 LD_PRELOAD,它需要外部 wrapper-launcher 脚本设置 env var

【问题讨论】:

  • 你不能挂钩真正的系统调用(SYS_open)或包装系统调用的库调用(open)吗?
  • 我想挂钩库调用,只是不知道怎么做。我用 LD_PRELOAD 做到了,但是如何从代码本身做到这一点,而不是从 shell 启动程序时做到这一点?

标签: c linux


【解决方案1】:

您可以通过重新定义函数来覆盖库调用:

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

void abort(void)
{
  // If necessary, get a instance to the "real" function:
  void (*real_abort)(void) = dlsym(RTLD_NEXT, "abort");
  if (!real_abort) {
    fpritnf(stderr, "Could not find real abort\n");
    exit(1);
  }
  fprintf(stderr, "Calling abort\n");
  real_abort();
}

与主

#include <stdlib.h>

int main(int argc, char** argv) {
  abort();
}

导致:

$ ./a.out 
Calling abort
Aborted

如果您想在运行时为任意函数执行此操作(无需编译您自己的函数版本),您可以尝试使用 ELF 对象(可执行对象和共享对象)的重定位信息并在运行时更新重定位.

让我们编译一个简单的地狱世界,看看它的重定位:

$ LANG=C readelf -r ./a.out 

Relocation section '.rela.dyn' at offset 0x348 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008d8  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x360 contains 3 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008f8  000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000600900  000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
000000600908  000300000007 R_X86_64_JUMP_SLO 0000000000000000 __gmon_start__ + 0

这些是动态链接器完成的重定位:.rela.plt 的第一行告诉动态链接器它需要在0x0000006008f8 处为puts 符号设置一个PLT 条目。为了覆盖 put 函数,我们可能会在所有共享对象中找到所有出现的puts 符号并将它们重定位到合适的函数中。

【讨论】:

    猜你喜欢
    • 2012-02-19
    • 2012-06-26
    • 2019-04-06
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多