:::warning 二者区别:

  • LIBRARYPATH环境变量用于在程序编译期间_查找动态链接库时指定查找共享库的路径
  • LDLIBRARY_PATH环境变量用于在程序加载运行期间_查找动态链接库时指定除了系统默认路径之外的其他路径,注意,LD_LIBRARY_PATH中指定的路径会在系统默认路径之前进行查找

:::

LD_PRELOAD

Linux操作系统的动态链接库在加载过程中,动态链接器会先读取LD_PRELOAD环境变量和默认配置文件/etc/ld.so.preload,并将读取到的动态链接库文件进行预加载。即使程序不依赖这些动态链接库,LD_PRELOAD环境变量和/etc/ld.so.preload配置文件中指定的动态链接库依然会被加载,因为它们的优先级比 LD_LIBRARY_PATH 环境变量所定义的链接库查找路径的文件优先级要高,所以能够提前于用户调用的动态库载入。 简单来说LD_PRELOAD的加载是最优先级的我们可以用他来做一些有趣的操作(骚操作).

:::warning 一般情况下,ld-linux.so加载动态链接库的顺序为:

LD_PRELOAD > LD_LIBRARY_PATH > /etc/ld.so.cache > /lib > /usr/lib

:::

测试阶段

  1. 编写 rund.c 程序
    该程序的目的是: 随机生成 10 个数字
  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. int main(int argc, char *argv[])
  5. {
  6. int i;
  7. srand(time(NULL));
  8. for(i=0;i<10;i++){
  9. printf("%d\n",rand()%100);
  10. }
  11. return 0;
  12. }
  1. 我们正常执行该程序
  1. # gcc -o rund rund.c
  2. # ./rund
  3. 18
  4. 48
  5. 5
  6. 32
  7. 51
  8. 80
  9. 89
  10. 23
  11. 20
  12. 26
  1. 现在我们创建 libmyrand.so 动态链接库
  1. #include<stdio.h>
  2. int rand()
  3. {
  4. return 55;
  5. }

将 myrand.c 编译为 libmyrand.so 文件

  1. # gcc -o libmyrand.so -shared -fPIC myrand.c
  2. # ls
  3. libmyrand.so myrand.c rund rund.c

:::warning gcc 参数介绍:

  • -shared : 表明是生成共享库格式
  • -fPIC : 选项作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code);这样一来,产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

:::

  1. 使用 LD_PRELOAD 替换 glibc 中的 rand
  1. # LD_PRELOAD=$PWD/libmyrand.so ./rund
  2. 55
  3. 55
  4. 55
  5. 55
  6. 55
  7. 55
  8. 55
  9. 55
  10. 55
  11. 55

从结果中我们可以看到,rand 方法调用的是我们自己编译的 rand 方法,这就是 LD_PRELOAD 优先级,当然我们也可以一些方法将其写入环境变量,并且我们可以使用 ldd 来查看程序在运行时所依赖的动态链接库

  1. # export LD_PRELOAD=$PWD/libmyrand.so
  2. # ldd ./rund
  3. linux-vdso.so.1 => (0x00007ffc0fe1e000)
  4. /root/workdir/libmyrand.so (0x00007f719568b000)
  5. libc.so.6 => /lib64/libc.so.6 (0x00007f71952bd000)
  6. /lib64/ld-linux-x86-64.so.2 (0x00007f719588d000)
  7. # export -n LD_PRELOAD=$PWD/libmyrand.so # 删除变量

LD_LIBRARY_PATH

我们在日常开发中,可能会自己编译一些库文件,然后指定程序去这些相应位置调用,这一切没什么问题,但是如果我们可以覆盖这些配置文件呢?

那么我们就可以执行和 LD_PRELOAD 相同的提权方式,劫持函数,并执行我们提供的命令

设置

  • export LD_LIBRARY_PATH=LD_LIBRARY_PATH:/XXX 但是登出后就失效
  • 修改~/.bashrc或~/.bash_profile或系统级别的/etc/profile - 在其中添加例如export PATH=/opt/ActiveP/lib:$LD_LIBRARY_PATH - source .bashrc (Source命令也称为“点命令”,也就是一个点符号(.)
    source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录)

共享库

参考

参考文章