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

来源:互联网 发布:js文本框无法更改 编辑:程序博客网 时间:2024/06/16 00:11

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


看一个简单的例子:

main.c:

#include <stdio.h>#include <stdlib.h>#include <time.h> 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之前



0 0
原创粉丝点击