缺失的动态链接库

动态库加载顺序

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

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

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与LD_LIBRARY_PATH

  • LD_LIBRARY_PATH 这个环境变量它告诉loader:在哪些目录中可以找到共享库。

  • LD_PRELOAD 这个环境变量它告诉loader:在解析函数地址时,优先使用LD_PRELOAD里指定的共享库中的函数。

正常情况下, Linux 动态加载器ld-linux会搜寻并装载程序所需的共享链接库文件, 而LD_PRELOAD是一个可选的环境变量, 包含一个或多个指向共享链接库文件的路径. 加载器会先于 C 运行库之前载入LD_PRELOAD指定的共享链接库,也就是所谓的预装载 (preload)。

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

如何设置LD_PRELOAD?只需要这样运行程序 LD_PRELOAD="./xxx.so" ./xxx

PS:LD_PRELOAD若加载的是与系统标准libc共享库很相似的共享库(比如程序运行所依赖的所有函数在指定的共享库中都能找到导出shared项,那么加载器就不再会去搜索标准libc共享库,而直接使用当前指定导入的共享库作为标准libc共享库

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

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

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