Linux LD_PRELOAD 用法

发布时间: 更新时间: 总字数:605 阅读时间:2m 作者: IP上海 分享 网址

Linux在动态链接库加载过程中,会先读取LD_PRELOAD环境变量,并将读取到的动态链接库文件进行预加载

介绍

用途

  • LD_PRELOAD的用途:
    • 动态库劫持
    • 程序调试
    • 库版本控制

工作原理

  • /usr/lib/x86_64-linux-gnu/ld-2.31.so 是一个 动态链接器(dynamic linker),它的主要作用是在程序运行时动态地 加载链接 共享库(shared libraries)
    • 通过环境变量 LD_PRELOAD 加载共享库
    • 当程序需要调用某个 符号(例如函数)时,系统会先在程序自身的符号表中查找。如果找不到,系统会在 LD_PRELOAD 指定的共享库中查找,如果在 LD_PRELOAD 指定的共享库中找到了该符号,则使用代码中的 符号

加载顺序

  • Linux中,通过 /usr/lib/x86_64-linux-gnu/ld-2.31.so 动态链接库加载顺序:
LD_PRELOAD -> LD_LIBRARY_PATH -> /etc/ld.so.cache -> /lib -> /usr/lib

配置文件

  • /etc/ld.so.conf 指向 include /etc/ld.so.conf.d/*.conf
  • /etc/ld.so.conf.d/
  • /etc/ld.so.cache

示例

自动生成随机数示例

  • rund.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char *argv[])
{
	int i;

	srand(time(NULL));
	for(i=0; i<5; i++){
		printf("%d\n", rand() % 100);
	}
	return 0;
}
  • 编译&运行
# 编译 rund
$ gcc -o rund rund.c

# 运行
$ ./rund
8
30
27
69
48
  • 创建 myrand.c 并编译为动态链接库 libmyrand.so

myrand.c

#include<stdio.h>

int rand()
{
	return 99;
}

编译:

  • -shared 生成共享库格式
  • -fPIC 用于编译阶段,编译器会产生与 位置无关(Position-Independent) 的动态库
gcc -o libmyrand.so -shared -fPIC myrand.c
  • 运行,结果都是 99,实际为 libmyrand.so 的执行结果
LD_PRELOAD=$PWD/libmyrand.so ./rund
99
99
99
99
99
  • ldd 对比加载
# 默认
$ ldd ./rund
	linux-vdso.so.1 (0x00007ffd863b6000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fba93ddf000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fba93fec000)

# LD_PRELOAD,可以看到 /root/libmyrand.so 的加载
$ LD_PRELOAD=$PWD/libmyrand.so ldd ./rund
	linux-vdso.so.1 (0x00007ffd5eff0000)
	/root/libmyrand.so (0x00007ffa23a05000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffa237ff000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ffa23a11000)
  • 删除环境变量
    • 方法一:export -n LD_PRELOAD=$PWD/libmyrand.so,且 echo $LD_PRELOAD 其值不变,但已经不生效了
    • 方法二:unset LD_PRELOAD

扩展

参考

  1. https://www.man7.org/linux/man-pages/man8/ld.so.8.html
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数