是否可以在运行时设置系统调用挂钩?以便携方式,没有asm,可能是一些动态链接器功能? 我想拦截第三方库的系统调用。不想使用LD_PRELOAD,它需要外部包装器 - 启动器脚本设置env var
答案 0 :(得分:3)
您可以通过重新定义函数来覆盖库调用:
#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
如果要在运行时为abitrary函数执行此操作(不编译自己的函数版本),可以尝试使用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
符号的所有出现,并将它们重定位到合适的函数。