LD_PRELOAD学习
前言
做题遇到这个东西,查了一下,原来是以前disable_functions的,但是没有深入研究过,现在看看。
LD_PRELOAD
在学习LD_PRELOAD前需要了解一下什么是链接
链接
- 静态链接:在程序运行之前先将各个目标模块以及所需要的库函数链接成一个完整的可执行程序,之后不再拆开。
- 装入时动态链接:源程序编译后所得到的一组目标模块,在装入内存时,边装入边链接。
- 运行时动态链接:原程序编译后得到的目标模块,在程序执行过程中需要用到时才对它进行链接。
我们在加载动态链接的时候,需要使用一个动态链接库,其作用在于当动态库中的函数发生变化时,对于可执行程序来说是透明的,可执行程序无需重新编译,方便程序的发布/维护/更新。也就是说可执行程序虽然用得还是那些函数,但是可能函数的内容已经发生了变化,但是可执行程序将直接执行这个变化。但是如果这个动态加载的函数是恶意的(指的就是前面的变化),那么就会带来恶意的执行结果。
定义
1.LD_PRELOAD是linux系统中的一个环境变量
2.它可以影响程序的运行时的链接,允许你定义 :在程序运行前优先加载 的动态链接库。即可以有选择性的载入 不同动态链接库中的相同函数。
通过这个环境变量,我们可以在自定义加载动态链接库,甚至覆盖原本的正常函数库,以达到特定的目的。
LD_PRELOAD Hook
因为LD_PRELOAD可以指定在程序运行前的动态链接库,所我们可以重写程序运行过程中所调用的函数,并编译成动态链接库文件,然后通过修改LD_PRELOAD变量,让程序优先加载这个恶意动态链接库,最后当程序再次运行时便会加载动态链接库里的恶意函数。
具体步骤如下
1.定义与目标函数完全一样的函数,包括名称、变量、及类型返回值 |
实例:
在验证密码的时候,一般是使用strcmp进行对比,
|
进行编译
gcc passcheck.c -o passcheck |
改写一下strcmp同名函数,实现劫持功能:
|
- 此时我们通过LD_PRELOAD劫持了strcmp函数,并启动了一个新进程,为避免陷入劫持循环,必须得删除LD_PRELOAD
执行命令编译生成ho*.so
gcc -shared -fPIC hook_strcmp.c -o hook_strcmp.so |
然后通过设置环境变量,使得hook.strcmp.so能被调用它的程序优先加载
export LD_PRELOAD=$PWD/hook_strcmp.so |
此时结果都为correct,也即劫持了strcmp函数
其实也很好理解,此时strcmp已经丧失原本对比的功能了,此时的strcmp的内部构造为,无论如何都返回0,然后经过!的取反处理,则变成了1.所以都是password correct
要还原的话使用
unset LD_PRELOAD |
否则所有有调用此函数的命令都无法正常使用
LD_PRELOAD制作后门
根据上面的知识,我们可以知道,通过LD_PRELOAD可以动态替换一些已经定义好的函数,但是有几个问题,我们从头捋一下,我们要后门执行命令,就说明需要调用一个进程,然后再去定点修改这个进程所调用的函数。
看了一下,都有一下函数可以使用
先以ls为例,首先查看 ls
这一系统命令会调用哪些库函数:
readelf -Ws /usr/bin/ls |
选择函数进行重写,但是不知道为啥这里查看不到,可能是版本问题吧
直接进行改写
|
此时替换成功
根据此思路 可以使用一些反弹shell的命令
实战
总结一下要使用LD_PRELOAD实现rce需要以下几点
1.具有设置环境变量的权限 |
但是要找到一个函数去替换是比较困难的,所以可以使用 C 语言扩展修饰符 __attribute__((constructor))
,可以让由它修饰的函数在 main()
之前执行,若它出现在动态链接库中,那么一旦动态链接库被系统加载,将立即执行 __attribute__((constructor))
修饰的函数。这样,我们就不用局限于仅劫持某一函数,而应考虑劫持动态链接库了,也可以说是劫持了一个新进程。
#include <stdlib.h> |
蚁剑插件脚本
#define _GNU_SOURCE |
一点思考
其实要想利用这个环境变量,最关键的还是要找到能够自启动的进程。
https://whoamianony.top/2021/10/22/Web%E5%AE%89%E5%85%A8/%E6%9C%89%E8%B6%A3%E7%9A%84%20LD_PRELOAD/
LD_PRELOAD学习