linux下采用LD_PRELOAD机制动态修改方法和注入代码

LD_PRELOADlinux下的一个环境变量,动态链接器在载入一个程序所需的所有动态库之前,首先会载入LD_PRELOAD环境变量所指定的动态库。运用这个机制,我们可以修改/替换已有动态库中的方法,加入我们自己的逻辑,从而改变程序的执行行为。不过该方法只对动态链接的程序有效,对静态链接的程序无效。


看一个简单的例子:

main.c:

#include 
#include 
#include 
 
int main(){
  srand(time(NULL));
  int i = 10;
  while(i--) printf("%d\n",rand()%100);
  return 0;
}

gcc main.c -o main


该程序产生0-99之间的一个随机数,用到了C运行时库中的rand函数,假如我们实现了自己的rand函数,如下:

myrand.c

int rand(){
    return 42; //the most random number in the universe
}

我们想让main程序使用我们自己实现的rand函数,同时我们只有main程序的可执行文件,无法通过修改源码实现,那怎么办尼?


首先,我们将myrand.c编译成动态库

gcc -shared -fPIC myrand.c -o myrand.so


然后我们指定LD_PRELOAD并运行main,如下:

LD_PRELOAD=$PWD/myrand.so ./main

结果是程序的每次运行都会返回42

由于动态链接器是按照先后顺序进行符号解析的,当myrand.so首先载入之后,动态链接器已经找到了rand函数,所以会忽略C运行库中的rand实现.


再进一步,我们通过ldd查看两种情况下的链接库顺序,

$ldd ./main

linux-vdso.so.1 =>  (0x00007ffe3511d000)

libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5a693ff000)

/lib64/ld-linux-x86-64.so.2 (0x00007f5a697d4000)


$LD_PRELOAD=./myrand.so ldd ./main

linux-vdso.so.1 =>  (0x00007ffdc5594000)

./myrand.so (0x00007f623ff20000)

libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f623fb4d000)

/lib64/ld-linux-x86-64.so.2 (0x00007f6240124000)

可以看到,myrand.soC运行时库libc.so.6之前



你可能感兴趣的:(linux下采用LD_PRELOAD机制动态修改方法和注入代码)