我的代码如下:preload.c,内容如下:

#include <stdio.h>
#include <stdlib.h>

int  __attribute__((constructor))  main_init(void)
{
    printf("Unsetting LD_PRELOAD: %x\n",unsetenv("LD_PRELOAD"));
    FILE *fp = popen("ls", "r");
    pclose(fp);
}

然后在 shell 中(小心执行第二个命令!):
    gcc preload.c -shared -Wl,-soname,mylib -o mylib.so -fPIC
    LD_PRELOAD=./mylib.so bash

!!!请小心最后一条命令,这将导致派生“sh -c ls”的无限循环。 2秒钟后用^ C(或更好的^ Z,然后查看ps)将其停止。

更多信息
  • 这个问题在某种程度上与bash有关。既可以作为用户运行的命令,也可以作为弹出框执行的重击。
  • 其他关键因素:1)从预加载的库中执行popen,2)可能需要在库的初始化部分中执行popen。
  • ,如果您使用:
    LD_DEBUG=all LD_DEBUG_OUTPUT=/tmp/ld-debug LD_PRELOAD=./mylib.so bash
    

    而不是最后一个命令,您将获得许多名为/tmp/ld-debug.*的ld-debug文件。每个 fork 过程一个。在所有这些文件中,您都会看到首先在mylib.so中搜索了符号,即使从环境中删除了LD_PRELOAD。
  • 最佳答案

    编辑:,所以问题/问题实际上是:您怎么无法使用LD_PRELOAD中预先加载的main_init()可靠地取消设置bash

    原因是execve(在您popen之后调用)从(可能的)环境中获取了环境

    extern char **environ;
    

    这是指向您的环境的一些全局状态变量。 unsetenv()通常会修改您的环境,因此会影响**environ的内容。

    如果bash试图对环境做一些特别的事情(好吧……会成为shell吗?),那么您可能会遇到麻烦。

    显然,bash甚至在unsetenv()之前就重载了main_init()。将示例代码更改为:
    extern char**environ;
    
    int  __attribute__((constructor))  main_init(void)
    {
    int i;
    printf("Unsetting LD_PRELOAD: %x\n",unsetenv("LD_PRELOAD"));
    printf("LD_PRELOAD: \"%s\"\n",getenv("LD_PRELOAD"));
    printf("Environ: %lx\n",environ);
    printf("unsetenv: %lx\n",unsetenv);
    for (i=0;environ[i];i++ ) printf("env: %s\n",environ[i]);
    fflush(stdout);
    FILE *fp = popen("ls", "r");
    pclose(fp);
    }
    

    显示问题。在正常运行中(运行catls等),我得到此版本的unsetenv:
    unsetenv: 7f4c78fd5290
    unsetenv: 7f1127317290
    unsetenv: 7f1ab63a2290
    

    但是,运行bashsh:
    unsetenv: 46d170
    

    所以你有它。 bash让你上当了;-)

    因此,只需使用自己的unsetenv修改环境,对**environ进行操作即可:
    for (i=0;environ[i];i++ )
    {
        if ( strstr(environ[i],"LD_PRELOAD=") )
        {
             printf("hacking out LD_PRELOAD from environ[%d]\n",i);
             environ[i][0] = 'D';
        }
    }
    

    可以在strace中看到它:
    execve("/bin/sh", ["sh", "-c", "ls"], [... "DD_PRELOAD=mylib.so" ...]) = 0
    

    Q.E.D.

    关于c - 即使在unsetenv ("LD_PRELOAD"之后,LD_PRELOAD也会影响新的 child ),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3275015/

    10-10 17:48