西湖论剑有一道题是mips
环境,看了大佬的WP
,感觉方法还是挺简单的,不过之前没有做过 mips
的环境,所以赛后搭建一个环境试试。
静态分析环境安装
仍然可以使用 IDA 来分析 mips
程序,不过 IDA 缺少了反汇编的插件,不能够看反汇编代码了。但是有一个工具 mipsrop
可以用来查看 mips 程序的 gadget,直接下载然后放到 IDA 的 plugins
目录下即可:
1 | https://github.com/devttys0/ida/tree/master/plugins/mipsrop |
不过需要注意,目前 这个插件只支持到 7.0,对于 7.2不支持,原因是由于 IDA python
里的一些函数接口改变了。
此外看到别人博客,说有一个反编译插件 Retdec
可以反编译,但是目前好像没有破解版。
静态分析时,mips 的汇编指令也发生了改变,可以参看如下:
动态调试环境安装
qemu
是一个能支持多个结构的模拟器,我们可以使用 qemu 来运行 mips
程序。
qemu 支持两种模式:
- 系统模式:模拟运行 mips系统
- 用户模式:模拟运行 mips程序
两者的差别系统模式,可以启一个 mips 系统,里面能支持 Linux系统的各项功能。用户模式仅仅就是为启动这个程序搭建一个虚拟环境,更简单。
系统模式
安装qemu:
1 | sudo apt-get install qemu |
然后要分别下载 qemu 的镜像文件和内核文件,在此处下载,下载 debian_wheezy_mips_standard.qcow2
镜像文件 和 vmlinux-3.2.0-4-4kc-malta
内核文件。
注意:Mips 系统是分小端序和大端序的。小端序 是LSB
,大端序是 MSB
。对应的镜像文件和内核文件也分别不同。我上面给的镜像文件和内核是大端序的,如果需要小端序文件在 此处下载,下载 debian_wheezy_mipsel_standard.qcow2
,vmlinux-3.2.0-4-4kc-malta
。并且 大端序和 小端序对应的 qemu
命令也有不同。
为了方便后续使用 gdb
的远程调试,我们需要配置 qemu
虚拟机和我们的宿主机的网络连接。
创建网桥:
1 | sudo brctl addbr virbr0 |
创建 tap
接口,名字为 tap0
,并添加到 网桥:
1 | sudo tunctl -t tap0 |
随后就可以启动镜像:
1 | 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" -netdev tap,id=tapnet,ifname=tap0,script=no -device rtl8139,netdev=tapnet -nographic |
命令中 qemu-system-mips
指定了系统架构为 大端序,如果使用小端序可用 qemu-system-mipsel
。还指定了我们之前下载的 内核文件和镜像文件,也制定了我们的 网络设备为 tap接口。
随后就输入用户名 root
和密码 root
,即可进入虚拟机。并且网络可以连接到宿主机。
远程调试
此时就可以在我们之前启动的 mips-qemu
虚拟机中运行 pwn
程序,我们可以通过 gdbserver
(下载地址)启动要调试的程序或附加到要调试的程序上:
1 | # 启动要调试的程序 |
我们将程序映射到 12345
端口,然后就可以在 qemu
外使用 gdb-mutiarch
来连接该端口进行调试。可以通过如下命令安装 gdb-mutiarch
:
1 | sudo apt-get install gdb-multiarch |
gdb-mutiarch 命令,第三条指令指定了是大端序,如果是小端序使用 little
1 | gdb-multiarch pwn |
然后即可正常的 gdb 调试了。
我使用这种方法时,我搭建的 mips-qemu
虚拟机虽然可以和宿主机相连,但是无法连接外网,导致我想下一些工具也不能成功。解决了很久网络问题,也没成功。
用户模式
这种模式我觉得更简单,我也用这种方法成功了。
首先查看 mips 程序是什么架构,如下:
1 | file managesystem |
managesystem 是 LSB
小端序。可以先尝试使用 qemu-mipsel
模拟运行该程序,报出没有 /lib/ld-uClibc.so.0: No such file or directory
。缺少相应的库,但是题目中 qemu-mips-static
已经给了我们相应的库。我们可以直接将这些库拷贝到当前文件夹。也可以直接使用 chroot
命令更换工作路径:
1 | sudo chroot . ./qemu-mipsel-static managesystem |
调试方法
用户模式下,可以使用 -g
选项来指定监听的端口,然后在另一个终端使用 gdb-multiarch
连接该终端进行调试:
1 | sudo chroot . ./qemu-mips-static -g 12345 managesystem |
1 | gdb-multiarch managesystem |
注意:这种方法运行程序只能适用于该程序可以独立于系统运行,如果程序中 有读取系统文件或参数等与系统相关的操作时,程序会由于找不到相应文件而退出。此种情况就只有使用系统模式了。
解决调试中数据发送问题
还有个很棘手的问题是,我们调试时通常会发送一些不可见字符到程序中。解决方法可以参考 e3pem 的博客,提到使用 socat
(下载地址) 来做数据转发:
1 | ./socat tcp-l:9999,fork exec:./embedded_heap |
然后我们可以编写脚本使用 pwntools 连接相应端口,但是此时 qemu 的终端就被占用,该如何调试?
可以创建一个 sh
文件,把 socat
命令写到该文件中,然后以后台方式运行 &
运行该 sh
文件。最后 socat
在收到监听端口发送的数据请求后,便会启动程序,获取到程序的进程 id,然后使用 gdbserver 附加到该进程并进行调试。
上面的做法,只是使用在系统模式下运行 socat
,然后端口转发。最近的比赛做了MIPS
和 ARM
的题,如果题目对系统环境没有要求的话,我们可以直接使用用户模式运行,算是我比赛摸出的方法吧。仍然是使用 socat
来实现 与脚本的端口连接 和 gdb 的调试端口连接:
使用:
1 | socat tcp-l:10002,fork exec:"qemu-mipsel -g 1234 -L /home/pwn/ ./pwn",reuseaddr |
其中脚本连接端口 10002
,使用 gdb-multiarch
连接 端口 1234
来进行调试,使用 qemu-mipsel
来运行小端序的 mips 程序,使用 -L
来指定系统库文件。
1 | socat tcp-l:10002,fork exec:"qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./pwn",reuseaddr |
其中脚本连接端口 10002
,使用 gdb-multiarch
连接 端口 1234
来进行调试,使用 qemu-aarch64
来运行 ARM64
程序,使用 -L
来指定系统库文件。
参考
- 本文作者: A1ex
- 本文链接: http://yoursite.com/2020/10/09/mips-pwn环境搭建/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!