ChatGPT解决这个技术问题 Extra ChatGPT

什么是 LD_PRELOAD 技巧?

我最近在 proggit 上看到了对它的引用,并且(截至目前)它没有被解释。

我怀疑 this 可能是它,但我不确定。

这不是一个真正的答案,所以我不会将它作为一个答案发布,但是...... Stephen Kell 在此视频中将 LD_PRELOAD 用于他的 liballocs 库,如果您观看前面的部分,您可能会更好地理解如何/为什么。 liballocs 似乎正在被使用,因此其他动态语言可以相互交谈。这个谈话有一些深刻的内部解释。 youtu.be/LwicN2u6Dro?t=24m10s

u
user

如果您将 LD_PRELOAD 设置为共享对象的路径,则该文件将在任何其他库(包括 C 运行时 libc.so)之前加载。因此,要使用您的特殊 malloc() 实现运行 ls,请执行以下操作:

$ LD_PRELOAD=/path/to/my/malloc.so /bin/ls

我不知道这存在......它似乎将成为安全攻击的主要载体。知道它是如何保护的吗?
如果 ruid != euid 加载程序将忽略 LD_PRELOAD -- Joshua
@Joshua:什么是 ruid 和 euid?
@heinrich5991 真实有效的用户 ID:lst.de/~okir/blackhats/node23.html
需要牢记的一件重要事情是:您通常希望为 LD_PRELOAD 指定一个绝对路径。原因是它是一个环境变量,它是由子进程继承的——它可能具有与父进程不同的工作目录。因此,任何相对路径都无法找到要预加载的库。
K
Kalle Richter

您可以通过创建具有相同符号的库并在 LD_PRELOAD 中指定库来覆盖库存库中的符号。

有些人使用它来指定非标准位置的库,但 LD_LIBRARY_PATH 更适合此目的。


“有些人用它来指定非标准位置的库”......真的吗?听起来像“有些人用错了”!
LD_PRELOAD 可以凭借加载顺序拦截应用程序指定的硬编码路径。
预加载不同版本的库是否会被滥用 - 假设它们是兼容的?
我已经看到它用于加载调试或检测变体,或者加载与基本库完全不同的库,就好像模拟其他系统一样。
在库未正确编译的情况下(过去常常与 mysql 一起运行,因为它与通用 libmysql_client 松散耦合,覆盖了旧版本的符号链接 - 取决于您使用的 perl 版本,您必须指定/ 用 LD_PRELOAD 强制它.. 有用的技巧。如果我没记错的话,valgrind 使用这种技术为二进制文件提供调试能力,而无需重新编译.. 它非常有用。
Y
Yun

正如许多人提到的,使用 LD_PRELOAD 预加载库。顺便说一句,如果设置可用 ldd 命令,您可以CHECK

示例:假设您需要预加载自己的 libselinux.so.1

> ldd /bin/ls
    ...
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f3927b1d000)
    libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007f3927914000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f392754f000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f3927311000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f392710c000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f3927d65000)
    libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007f3926f07000)

因此,设置您的预加载环境:

export LD_PRELOAD=/home/patric/libselinux.so.1

再次检查您的图书馆:

>ldd /bin/ls
    ...
    libselinux.so.1 =>
    /home/patric/libselinux.so.1 (0x00007fb9245d8000)
    ...

Y
Yu Hao

使用 LD_PRELOAD,您可以为库提供优先权。

例如,您可以编写一个实现 mallocfree 的库。通过使用 LD_PRELOAD 加载这些,您的 mallocfree 将被执行,而不是标准的。


但是如果程序使用 calloc 怎么办?那不是把一切都搞砸了吗?
@JanusTroelsen 如果您编写的库没有实现某个部分,则该部分将从原始库中加载。
@JanusTroelsen,换句话说, LD_PRELOAD 允许您指定使用特定符号的哪个实现。如果预加载的库没有导出符号,则会在 elsehwere 中找到它。
@JanusTroelsen:事实证明 malloc 和 free 是在 glibc 中专门设计的,以允许这样做,并且 stock calloc 设法调用您导入的 malloc。不要尝试使用任何其他功能。它不会工作得那么好。
K
Kalle Richter

LD_PRELOAD 列出了具有覆盖标准集的函数的共享库,就像 /etc/ld.so.preload 一样。这些由加载程序 /lib/ld-linux.so 实现。如果您只想覆盖几个选定的函数,您可以通过创建一个覆盖目标文件并设置 LD_PRELOAD 来做到这一点;此目标文件中的函数将仅覆盖那些函数,而其他函数则保持原样。

有关共享库的更多信息,请访问 http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html


J
JulienGenoud

要将 mylib.so 导出到 env:

$ export LD_PRELOAD=/path/mylib.so
$ ./mybin

要禁用它:

$ unset LD_PRELOAD

unset LD_PRELOAD
unsetexport VAR= 并不完全相同。 unset 是要走的路。
a
asn

这是有关预加载的详细博客文章:

https://blog.cryptomilk.org/2014/07/21/what-is-preloading/


感谢您发布您的答案!请注意,您应该在此处或本网站上发布答案的基本部分,否则您的帖子可能会被删除See the FAQ where it mentions answers that are 'barely more than a link'.如果您愿意,您仍可以包含该链接,但仅作为“参考”。答案应该是独立的,不需要链接。
d
dnahc araknayirp

使用 LD_PRELOAD 路径,您可以强制应用程序加载程序加载提供的共享对象,而不是提供的默认值。

开发人员通过提供不同版本的共享对象来使用它来调试他们的应用程序。

我们用它来破解某些应用程序,通过使用准备好的共享对象覆盖现有函数。


Y
Yun

当使用 LD_PRELOAD 时,该文件将在任何其他文件之前加载。使用 $export LD_PRELOAD=/path/lib 预加载 lib。这甚至可以在程序中使用。