为什么 LD_PRELOAD 与系统调用一起工作?的

Why does LD_PRELOAD work with syscalls? ​

LD_PRELOAD的想法是在原来的共享库之前加载一个共享库,比如我可以编译mylib.solibc.so之前加载它,所以当进程想要使用 printf 它在一个一个加载的 so 中搜索并在 mylib.so 中找到它(因为这个 so 首先加载)而不是 libc.so,所以它使用 mylib.so 中的 printf 而不是 libc.so 中的 printf

我理解为什么这适用于 so 中实现的函数,例如 libc.so 中的 printf

但是当我想挂钩 write 函数或另一个 syscall 函数时,为什么它可以工作?进程不搜索so中的函数,直接进入内核

  1. LD_PRELOAD 是否适用于静态编译的二进制文件?为什么? 在此回放中 提到 LD PRELOAD 不适用于静态二进制

  2. 为什么 LD_PRELOAD 在动态编译的二进制文件上工作以挂钩系统调用?

架构为ARM。

The process does not search the function in the so, it goes directly to the kernel.

错了,您使用的系统调用函数(read()write()、...)都是围绕真实系统调用的 libc wrappers,甚至通用 syscall() 函数。 Here's the code 例如 write() 函数。从你的程序直接进入内核的唯一方法是手动发出系统调用(见下文)。

Does LD_PRELOAD work on a binary that is compiled statically? Why?

不,不是。静态二进制文件不需要动态解析任何符号,因此不会调用动态加载程序来解析通常的库函数符号。

Why does LD_PRELOAD work on a binary compiled dynamically to make hooks on syscalls?

因为那些只是普通的 libc 函数,仅此而已。


除了静态编译之外,在不通过 C 库(因此不进行符号解析)的情况下手动调用系统调用的唯一方法是使用 inline assembly. You can take a look at man 2 syscall 查看要使用的寄存器和指令。例如,在 ARM AArch64 上,您可以通过在寄存器 x8 中加载系统调用编号,在 x0x5 中加载参数,然后执行 svc #0 指令来调用系统调用。 =27=]