为什么LD_PRELOAD与syscalls一起工作;
为什么LD_PRELOAD与syscalls一起工作;,c,linux,arm,system-calls,ld-preload,C,Linux,Arm,System Calls,Ld Preload,LD_PRELOAD的思想是在原始共享库之前加载一个共享库,例如我可以编译mylib.so在libc.so之前加载它,所以当进程想要使用printf时,它会在逐个加载的so中搜索并在mylib.so(因为此so是首先加载的)而不是libc.so,因此它使用mylib.so中的printf,而不是libc.so中的printf 我理解为什么这适用于在so中实现的函数,比如libc.so中的printf 但是,当我想挂接write函数或另一个系统调用函数时,它为什么会起作用呢?该过程不会在中搜索函数
LD_PRELOAD
的思想是在原始共享库之前加载一个共享库,例如我可以编译mylib.so
在libc.so
之前加载它,所以当进程想要使用printf
时,它会在逐个加载的so
中搜索并在mylib.so
(因为此so
是首先加载的)而不是libc.so
,因此它使用mylib.so中的printf
,而不是libc.so中的printf
我理解为什么这适用于在so
中实现的函数,比如libc.so中的printf
但是,当我想挂接write
函数或另一个系统调用
函数时,它为什么会起作用呢?该过程不会在中搜索函数,因此它直接进入内核
LD_PRELOAD
对静态编译的二进制文件有效吗?为什么?
在这次重播中提到,LD PRELOAD
在静态二进制上不起作用
为什么LD\u PRELOAD
在动态编译的二进制文件上工作,以便在系统调用上创建钩子
架构是ARM
进程不在中搜索函数,因此它直接进入内核
错了,您使用的系统调用函数(read()
,write()
,…)都是真实系统调用的libc包装,甚至是通用的syscall()
函数。例如,对于write()
函数。从程序直接进入内核的唯一方法是手动发出系统调用(参见下文)
LD_PRELOAD
对静态编译的二进制文件有效吗?为什么
不,不需要。静态二进制文件不需要动态解析任何符号,因此不会调用动态加载程序来解析常用的库函数符号
为什么LD\u PRELOAD
在动态编译的二进制文件上工作,以便在系统调用上创建钩子
因为这些只是普通的libc函数,不多不少
手动调用系统调用而不经过C库(因此不进行符号解析)的唯一方法除了静态编译之外,还需要使用。您可以查看要使用的寄存器和指令。例如,在ARM AArch64上,您可以通过在寄存器x8
中加载syscall编号,通过x0
到x5
中加载参数,然后执行svc\0
指令来调用syscall。n您编写代码调用write
它不是直接调用系统调用。它是调用一个包装器,该包装器设置系统调用,然后将其捕获到内核中。因此LD_PRELOAD可以通过重写包装器调用来工作。@kaylum您确定,write是系统调用,而不是包装的,我可以在汇编中看到它。因此LD_PLELOAD也需要处理静态二进制文件吗re是一个名为write的系统调用,但这不是您直接调用的。libc中有系统调用包装器。预加载仅适用于动态链接的exec。我已经调整了您问题的措辞以使其更清楚,如果可以,请告诉我。简短回答:您被骗了。好的,这有点强,但是“syscalls”和“library functions”是人为的,并不真正准确。它们实际上都是库函数,所谓的“syscalls”不再直接映射到实际的系统调用-实际的系统调用已经发生了变化。open()
,例如,很可能使
系统调用。因此,如果在我的代码中,我将使用syscall
直接调用write
,就像syscall(write\u syscall,fd,buf,nbytes)
LD_PRELOAD
没有人可以在这个进程上应用LD_PRELOAD
即使它是自动编译的?我的解释写了吗?LD_PRELOAD将我的so放在任何so之前,所以加载程序首先找到我的函数吗?不。syscall()
只是另一个libc包装器。正如我所说的,唯一的方法是(1)静态链接或(2)手动写入程序集。如果不希望在动态链接时挂接库函数,则不要使用库函数。谢谢(1)我的解释写入吗?LD_PRELOAD将我的so放在任何so之前,因此加载程序首先查找我的函数,而不是原始函数?(2)我可以在/proc/pid中看到由mylib.so
解析的特殊函数吗?(1)是的,没错。(2)/proc/pid/*
对您没有帮助。如果您想看到函数是通过mylib.so
解析的,那么您应该使用调试信息(-g
)进行编译,然后使用gdb
启动进程并执行next
,直到调用函数为止。调用函数后,使用p funcname
检查其地址,然后检查info proc mappings
以查看地址是否在mylib内。因此
可以绕过LD\u预加载截取的另一种方法是显式打开library您想要的,dlsym到您想要的函数并直接调用它。