为什么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到您想要的函数并直接调用它。