# 缺失的动态链接库

## 动态库加载顺序

系统运行程序时根据程序的`Dynamic section`的`NEEDED`项 搜索相应的的动态链接库。

```python
Dynamic section at offset 0xda0 contains 27 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x6e8
 .................
```

接着动态加载器`ld-linux/ld.so`搜索动态链接库路径的先后顺序如下：

1.**编译目标代码时指定的动态库搜索路径**； 如果在编译程序时增加参数`-Wl,-rpath='.'` , 这时生成程序的`Dynamic section`会新加一个`RPATH`段

```python
Dynamic section at offset 0x5dd8 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libunicorn.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [/home/b0ldfrev/ctf_lib/./lib]
 0x000000000000000c (INIT)               0x4014e8
```

当然( 后期也可以用工具patchelf --set-rpath `NEWDIRS` xxx修改搜索路径 )

2.**环境变量LD\_LIBRARY\_PATH指定的动态库搜索路径**； ( 可用export LD\_LIBRARY\_PATH="`NEWDIRS`" 命令添加临时环境变量 )

3.**配置文件/etc/ld.so.conf中指定的动态库搜索路径**；(系统默认情况下未设置)

4.**默认的动态库搜索路径/lib**；

5.**默认的动态库搜索路径/usr/lib**；

## LD\_PRELOAD与/etc/ld.so.preload

![](https://1832246008-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LckC1dmB2Mb2F1Bgx_H%2Fsync%2F7c58f69bdf4ec184bdc42d4d7be84583eb2b37c4.png?generation=1599012054501654\&alt=media)

**linux动态链接库预加载机制:** 在linux操作系统的动态链接库加载过程中，动态链接器会读取`LD_PRELOAD`环境变量的值和默认配置文件/etc/ld.so.preload的文件内容，并将读取到的动态链接库进行预加载，即使程序不依赖这些动态链接库，`LD_PRELOAD`环境变量和/etc/ld.so.preload配置文件中指定的动态链接库依然会被装载,它们的优先级比`LD_LIBRARY_PATH`环境变量所定义的链接库查找路径的文件优先级要高，所以能够提前于用户调用的动态库载入。

**全局符号介入:** 全局符号介入指的是应用程序调用库函数时，调用的库函数如果在多个动态链接库中都存在，即存在同名函数，那么链接器只会保留第一个链接的函数，而忽略后面链接进来的函数，所以只要预加载的全局符号中有和后加载的普通共享库中全局符号重名，那么就会覆盖后装载的共享库以及目标文件里的全局符号。

预装载意味着会它的函数会比其他库文件中的同名函数先于调用, 也就使得库函数可以被阻截或替换掉. 多个共享链接库文件的路径可以用冒号或空格进行区分. 显然不会受到`LD_PRELOAD`影响的也就只有那些静态链接的程序了.

如何设置`LD_PRELOAD`？只需要这样运行程序 `LD_PRELOAD="./xxx.so" ./xxx`，这样只是针对程序某次运行

当然也可以全局的设置。直接导入环境变量`export LD_PRELOAD`导出环境变量使该环境变量生效,`unset LD_PRELOAD` 解除设置的LD\_PRELOAD环境变量；或者将恶意动态链接库路径写入/etc/ld.so.preload(没有则创建)配置文件中,如`echo /tmp/xxxr.so >> /etc/ld.so.preload`

## 低(高)版本glibc环境下让程序加载高(低)版本的glibc动态库运行

必须使用patchelf工具手动改变程序的interpreter为低(高)版本的ld.so,才能去加载低(高)版本的libc.so库

可参考我的项目<https://github.com/b0ldfrev/project/tree/master/pwn_glibc/patchelf_lib_ld>
