Linux 下GCC的编译可分为4个步骤:预处理 --> 编译 --> 汇编 -->链接
这里讲一讲劫持GCC编译的链接过程,这里我们需要了解一下动态链接的一个环境变量,LD_PRELOAD;
LD_PRELOAD 环境变量可以定义在程序运行前优先加载的动态链接库。这使得我们可以有选择性地加载不同动态链接库中的相同函数,即通过设置该变量,在主程序和其动态链接库中间加载别的动态链接库,甚至覆盖原本的库,这就有可能出现劫持程序执行的安全问题。
“ldpreload.c”
#include<stdio.h>
#include<string.h>
void main() {
char passwd[] = "password";
char str[128];
scanf("%s", &str);
if (!strcmp(passwd, str)) {
printf("the password is correct\n");
return;
}
printf("the password is invalid\n");
}
程序很简单,就不多解释了,根据对环境变量LD_PRELOAD的解释,我们要构造一个恶意的动态链接库来重载 strcmp() 函数,编译为动态链接库,并设置 LD_PRELOAD 环境变量:
“hook.c”
#include<stdio.h>
#include<stdio.h>
int strcmp(const char *s1, const char *s2) {
printf("LD_PRELOAD hooked\n");
return 0;
}
//编译hook so库
curits@curits-virtual-machine:~/Desktop/ld_preload$ gcc -shared -o hook.so hook.c
curits@curits-virtual-machine:~/Desktop/ld_preload$ ls
hook.c hook.so ldpreload.c
//正常执行ldpreload程序
curits@curits-virtual-machine:~/Desktop/ld_preload$ gcc ldpreload.c
curits@curits-virtual-machine:~/Desktop/ld_preload$ ./a.out
124
the password is invalid
//链接时替换strcmp结果
curits@curits-virtual-machine:~/Desktop/ld_preload$ export LD_PRELOAD="./hook.so"
curits@curits-virtual-machine:~/Desktop/ld_preload$ ./a.out
123
LD_PRELOAD hooked
the password is correct
//移除hook
curits@curits-virtual-machine:~/Desktop/ld_preload$ ./a.out
ERROR: ld.so: object 'NULL' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
123
the password is invalid