LD_PRELOAD 不起作用,LD_DEBUG 不显示任何内容

Kev*_*ier 7 bash ld

我用来LD_PRELOAD覆盖该read函数。对于最小的测试应用程序,它工作得很好,但如果我用更大的应用程序测试它,它就不再工作了。也根本LD_DEBUG=all不显示任何内容:

LD_DEBUG=all LD_PRELOAD=./lib.so ./big_app
Run Code Online (Sandbox Code Playgroud)

这只是运行./big_appLD_PRELOAD没有任何效果。有办法调试吗?

A.B*_*A.B 19

这个答案仅对 GNU/Linux 环境有效。

从评论来看,OP 的二进制文件添加了特权功能:功能。这将切换ld.so(8)安全执行模式默认情况下禁用大多数动态链接器相关的环境变量,包括LD_PRELOADLD_DEBUG

安全执行模式

出于安全原因,如果动态链接器确定二进制文件应在安全执行模式下运行,则某些环境变量的影响将被取消或修改[...]

如果 [...] 包含以下内容,则二进制文件将以安全执行模式执行:

  • 进程真实有效的用户ID不同,或者真实有效的组ID不同。[...]

  • 具有非 root 用户 ID 的进程执行了向该进程授予功能的二进制文件。

[...]

但是,通过系统上的root访问权限,可以将其配置为在以非 root 身份运行时满足这两个参数的安全执行模式的先决条件,仍如下所述ld.so(8)

LD_PRELOAD

[...]

在安全执行模式下,包含斜杠的预加载路径名将被忽略。此外,共享对象仅从标准搜索目录预加载,并且仅当它们启用了 set-user-ID 模式位时(这不是典型的)。

标准搜索目录是什么?它们提供了 的输出ld.so --help。例如在 Debian amd64/x86_64 上:

$ ld.so --help
[...]

Shared library search path:
  (libraries located via /etc/ld.so.cache)
  /lib/x86_64-linux-gnu (system search path)
  /usr/lib/x86_64-linux-gnu (system search path)
  /lib (system search path)
  /usr/lib (system search path)

[...]
Run Code Online (Sandbox Code Playgroud)

最后,共享对象文件必须位于这些位置之一。从测试来看:

  • 不必由 root 拥有,只要它u+s设置了模式即可。
  • 可以是指向u+s任何位置的实际文件的符号链接,只要符号链接位于正确的位置即可。
  • 中不应存在任何路径LD_PRELOAD,仅应存在(一个)文件名,而不应存在/任何位置。
  • 如果二进制文件的功能未授予其读取文件的任意访问权限,则共享对象可以设置其模式,以便仅允许单个用户或组(通常chmod o-rwx应应用并设置正确的所有权,然后u+s恢复)。对于 setuid-root 或CAP_DAC_OVERRIDE/CAP_DAC_READ_SEARCH这可能不会阻止任何执行此类特权二进制文件的用户使用该库。

LD_DEBUG

[...] 自 glibc 2.3.4 起,LD_DEBUG在安全执行模式下将被忽略,除非文件/etc/suid-debug存在(文件的内容不相关)。

我没有找到一种方法将其限制为仅适用于用户或组。

示例(使用 root 访问sudo):

$ sudo touch /etc/suid-debug
$ sudo cp -aiL ./lib.so /usr/lib/lib.so
$ sudo chmod u+s /usr/lib/lib.so
Run Code Online (Sandbox Code Playgroud)

现在允许以普通用户身份运行,并考虑两个变量:

LD_DEBUG=all LD_PRELOAD=lib.so ./big_app
Run Code Online (Sandbox Code Playgroud)