mips - ROP
介绍
本章目前只打算介绍 mips 下的 rop,其他漏洞的利用以后会逐渐介绍
预备知识
架构回顾见: https://ctf-wiki.github.io/ctf-wiki/assembly/mips/readme-zh/ 栈结构如图:
有几个特殊的地方需要注意
MIPS32架构中是没有EBP寄存器的,程序函数调用的时候是将当前栈指针向下移动 n 比特到该函数的 stack frame 存储组空间,函数返回的时候再加上偏移量恢复栈
传参过程中,前四个参数$a0-$a3,多余的会保存在调用函数的预留的栈顶空间内
MIPS调用函数时会把函数的返回地址直接存入$RA 寄存器
简单环境适配
我们目前以用户态的形式调试程序, 所以需要安装 且,qemu-user 等依赖
$ sudo apt install qemu-user
$ sudo apt install libc6-mipsel-cross
$ sudo mkdir /etc/qemu-binfmt
$ sudo ln -s /usr/mipsel-linux-gnu /etc/qemu-binfmt/mipsel题目
1 ropemporium ret2text
跟到 pwnme 函数里
我们可以看到函数一开始,将 ra 寄存器的值,放入 $sp+60 的位置里。即返回地址位于 $sp+60
在看该函数里的 read, a2 为读取的 size 大小,将被赋值为 0x38,buf 为位于 $sp + 0x18 的位置,明显的一个栈溢出漏洞,且能覆盖返回地址。 通过计算,可以计算出 padding 为 36
另外程序有一个 ret2win 函数
所以该题目只需覆盖返回地址为 ret2win 函数的地址即可。所以我们可以构造如下 payload:
即能 get flag 
2 DVRF stack_bof_02.c
题目源码如下
安装交叉编译工具
编译上面的源码
程序保护
代码逻辑很简单,在 strcpy 的地方有一处栈溢出。
程序调试
qemu-mipsel-static -g 1234 -L ./mipsel ./vuln_system PAYLOAD-g 指定调试端口, -L 指定 lib 等文件的目录,当程序起来之后gdb-multiarch stack_bof_02运行如下命令,然后在 gdb 里运行target remote 127.0.0.1:1234即可挂上调试器控制 PC
返回地址位于 $sp+532 , buf 位于 $fp+24 即 padding 为
pay += b'a'*508
如下图所示,即可控制 ra 寄存器,进而控制 PC 
查找使用的 gadget 完成 ret2shellcode 由于程序没有开启 PIE 等 保护,所以我们可以直接在栈上注入 shellcode,然后控制 PC跳转到栈上
找 gadget 我们可以使用 mipsrop.py 这个 ida 插件进行。
由于 mips 流水指令集的特点,存在 cache incoherency 的特性,需要调用 sleep 或者其他函数将数据区刷新到当前指令区中去,才能正常执行 shellcode。为了找到更多的 gadget,以及这是一个 demo ,所有我们在 libc 里查找
1. 调用 sleep 函数
调用 sleep 函数之前,我们需要先找到对 a0 进行设置的 gadget
例如我们这里选择了 0x00E2660 处的 gadget
我们发现,这个 gadget 最后会跳到 s2 寄存器里的值的位置,所以,我下一步需要找到能控制 s2 的寄存器
通常而言,我们这里会使用 mipsrop 插件的 mipsrop.tail() 方法来寻找,从栈上设置寄存器的 gadget
如果没有合适的,我们可以尝试找在一些 "*dir" 的函数结尾来查找,有没有合适的,例如我在 readdir64 函数的末尾发现如下 gadget 
这样我们就能控制 s2 寄存器也能控制 PC,下一步就是跳到 sleep, 但是单纯的跳到 sleep 是不够的,同时我们要保证执行完 sleep 后能跳到下一个 gadget ,所以我们还需要一个既能 执行 sleep 又能控制下一个 PC 地址的 gadget 看了眼寄存器,此时 我们还能控制的还挺多,例如我这里找 $a3 的寄存器
通过这个 gadget 我们先跳到 s3 的寄存器执行 sleep ,再通过控制的 ra 寄存器进行下一步操作
通过这个 gadget 我们先跳到 s3 的寄存器执行 sleep ,再通过控制的 ra 寄存器进行下一步操作
2. jmp shellcode
下一步就是跳到 shellcode ,要跳到shellcode 我们先需要获得栈地址
我们先用 Python>mipsrop.stackfinder()
获得 如下 gadget
该 gadget 可以将栈地址, 即 $sp+24 的值赋值给 $a0 ,那么这个栈就是我们即将填充 shellcode 的地方, $s5 可控,最后这段 gadget 会跳往 $s5 , 那么我们只需要再找一个直接 jr $a0 的gadget 即可
这里使用的是
最后的 exploit
Last updated

