您的位置:首页 > 运维架构 > Linux

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

2016-04-27 10:59 856 查看
LD_PRELOAD是linux下的一个环境变量,动态链接器在载入一个程序所需的所有动态库之前,首先会载入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.so在C运行时库libc.so.6之前
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: