【问题标题】:How to prevent LD_PRELOAD on a binary?如何防止二进制文件上的 LD_PRELOAD?
【发布时间】:2020-02-27 21:06:32
【问题描述】:

我用 C 代码编写二进制文件。如何防止其他用户在我的二进制文件上使用LD_PRELOAD?

在使用LD_PRELOAD时,有没有什么信号可以处理和破坏程序?

如果我静态编译二进制,听说LD_PRELOAD不行,对吧?

还有其他方法吗?

【问题讨论】:

  • 可以查看是否设置了LD_PRELOAD环境变量。但他们可以链接到不同版本的getenv() 来增加难度。
  • 你为什么关心这个?
  • @Barmar 你能解释一下吗?当以LD_PRELOAD 运行的进程是要处理的环境变量吗?我该如何检查,并且可以设置女巫类型的环境变量?
  • 这些用户能否对您提供给他们的二进制文件进行十六进制编辑?或者在dtrace之类的东西下运行它?

标签: c linux hook ld-preload


【解决方案1】:

就像脚本具有通过#! 机制指定的解释器一样,可执行文件的工作方式类似。 ELF 可执行文件在程序头中有一个类型为PT_INTERP 的字段,它为可执行文件提供了一个“解释器”的路径。该“解释器”是动态链接器ld-linux.so。该链接器将处理标头并将文件映射到内存以及所有其余部分。

正是这个ld-linux.so 加载器实现了LD_PRELOAD 功能。

如果您生成此程序的自定义版本,其中删除或禁用了对LD_PRELOAD 的支持,然后将可执行文件的程序头指向使用该ld-linux.so 而不是通常的“解释器”,您应该能够击败LD_PRELOAD。

如果我静态编译二进制,听说 LD_PRELOAD 不起作用,对吧?

虽然这基本上是正确的,但 Glibc 不支持静态链接。今天,如果您想分发静态链接的可执行文件,您正在考虑使用替代 C 库like Musl:“从头开始设计用于静态链接,musl 小心地避免引入大量代码或数据应用程序不会使用。”

【讨论】:

    【解决方案2】:

    ld 预加载通过在运行程序时设置LD_PRELOAD 环境变量来使用。所以你的程序可以检查这个。

    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argv, char *argv) {
        if (getenv("LD_PRELOAD")) {
            fprintf(stderr, "Sorry, you can't use ld preload with this program.\n");
            exit(1);
        }
        ...
    }
    

    除非预加载的库提供自己的隐藏此变量的 getenv(),否则这将起作用。

    【讨论】:

    • 但是 LD_PRELOAD 也可以“预加载”getenv()。
    • 我知道,我在上面的评论中提到过。我已将其添加到答案中。
    猜你喜欢
    • 2012-03-03
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    • 2011-08-13
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多