随着物联网(IOT)日益增长,面向IOT硬件的新一波恶意软件如期而至,不过对于安全人员来说,这些恶意软件所面向的系统架构貌似有点生疏:MIPS架构。为了帮助读者熟悉这一架构,本文将详细介绍如何编译、分析和调试基于MIPS的二进制文件。
MIPS是一种精简指令集计算机(RISC),问世于二十世纪八十年代初期,常用于家用网关路由器和交换机等设备。在本文中,我们将为读者详细演示如何在x86系统上编译、运行、分析和调试用C语言编写的MIPS示例程序。虽然这里使用的代码并非恶意软件,但本文中介绍的技术和方法同样适用于分析基于MIPS的二进制文件/恶意软件。
这里,假设使用的虚拟机安装的是Kali Linux 2018系统。为了编译MIPS ELF,还需要安装一些依赖项,具体命令如下所示:
apt-get install linux-libc-dev-mips-cross libc6-mips-cross libc6-dev-mips-cross binutils-mips-linux-gnu gcc-mips-linux-gnu g++-mips-linux-gnu
接下来,我们将使用一些C示例代码来输出当前的PID和PPID,以及WHILE循环当前迭代到哪一步。同时,这个示例还会执行FORK命令,并再次输出当前进程的PID和PPID。读者将会注意到,在执行FORK命令后会出现两个输出:一个来自父进程,另一个来自子进程。 在MIPS中,调试FORK命令是非常重要的技巧,因为调试器在处理它们时比较费时(当然,CLONE也是如此)。
下面是待编译的示例代码。需要注意的是,在将其保存到文件中的时候,一定要使用诸如mips-test.c之类的文件名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(){ printf("PID: %d\n",getpid()); printf("PPID: %d\n",getppid()); int i = 0; while(i < 4){ sleep(1); printf("ITERATION #%d\n",i); i = i + 1; } fork(); for (int w = 0; w <= 10; w=w+1){ printf("%d: %d\t%d\n",getpid(),getppid()); sleep(1); } printf("EXITING: %d\n",getpid()); return 0; } |
利用下面的命令,我们就可以将上面的源代码交叉编译为MIPS-Little Endian代码:
1 |
mipsel-linux-gnu-gcc -xc -static -o mips-test.elf mips-test.c |
这样,我们会得到一个名为mips-test.elf的文件。为了运行该文件,需要执行CHMOD + X mips-test.elf命令。但是,如果试图运行该文件的话,系统会报错,并指出计算机不支持该体系结构。在下一节中,我们将介绍如何在x86机器上运行MIPS ELF程序。
首先,让我们再次安装一些依赖项:
1 2 3 |
apt-get install qemu apt-get install bridge-utils |
QEMU是一个仿真器,在它的帮助下,我们就可以在主机中运行不同体系结构的程序了。稍后,我们还会介绍如何使用bridge-utils来启用网络功能。
QEMU有两种模式:用户模式和完全系统仿真模式。
在用户模式下,我们可以通过命令行执行下列命令,以便在本地运行二进制文件(如我们刚刚编译的那个):
1 |
qemu-mipsel [-strace] [-g 12345] mips-test.elf |
要想按as-is方式来运行二进制代码的话,则需要忽略命令行中的-strace和-g 12345选项,只需使用qemu-mipsel mips-test.elf即可。
其中,选项-strace的作用是将二进制文件的系统调用输出到终端。这样做的好处是,可以帮助了解二进制代码正在从事哪些活动。
-g 12345选项的作用是让QEMU通过一个正在侦听12345端口的GDB Stub Loader来打开ELF。这样的话,系统会让它执行到入口点的时候暂停该程序,并等待GDB建立会话。 我们将在文章后面讨论如何附加到这个GDB Stub loader上。
现在,请读者为接下来史诗般的冒险做好心理准备。首先,我们需要下载几个文件:
https://people.debian.org/~aurel32/qemu/
特别是对于本例,您将面临Debian的MIPS Little Endian风格和相应的内核映像的两项新挑战。
https://people.debian.org/~aurel32/qemu/mipsel/debian_wheezy_mipsel_standard.qcow2
https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta
下载好这两个文件后,请在相同文件夹中创建一个shell脚本,并将其命名诸如start.sh之类的名称。该脚本的代码如下所示(请根据自己的情况修改代码底部的路径变量):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/bin/bash qemu=qemu-system-mipsel path="$HOME/Documents/Debian-MipsEL" hda="$path/debian_wheezy_mipsel_standard.qcow2" kernel="$path/vmlinux-3.2.0-4-4kc-malta" iface=tap0 echo "Stopping eth0, starting tap0" /etc/qemu-ifup tap0 || quit 1 "Failed to start tap0" echo "Starting Debian MIPS" $qemu -net nic -net tap,ifname=$iface,script=no,downscript=no \ -M malta -kernel $kernel -hda $hda -append "root=/dev/sda1 console=tty0" -nographic |
QEMU会自动创建文件/etc/qemu-ifup,正常情况下它应该会为模拟的MIPS系统启用网络连接,但是,我在使用过程中遇到了很多问题,因此,我们将使用修改后的版本。之后,需要备份当前的qemu-ifup文件,因为我们将用下面的代码替换该文件的内容(警告:一定要执行IFCONFIG,并为脚本顶部的前3个变量指定合适的值,这些变量为:ETH0IPADDR、GATEWAY和BROADCAST):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#!/bin/bash ETH0IPADDR=192.168.147.142 GATEWAY=192.168.147.1 BROADCAST=192.168.147.255 USER=root # First take eth0 down, then bring it up with IP address 0.0.0.0 /sbin/ifconfig eth0 down /sbin/ifconfig eth0 0.0.0.0 promisc up # Bring up the tap device (name specified as first argument, by QEMU) /usr/sbin/openvpn --mktun --dev $1 --user $USER /sbin/ifconfig $1 0.0.0.0 promisc up # Create the bridge between eth0 and the tap device /sbin/brctl addbr br0 /sbin/brctl addif br0 eth0 /sbin/brctl addif br0 $1 # Only a single bridge so loops are not possible, turn off spanning tree protocol /sbin/brctl stp br0 off # Bring up the bridge with ETH0IPADDR and add the default route /sbin/ifconfig br0 $ETH0IPADDR netmask 255.255.255.0 broadcast $BROADCAST /sbin/route add default gw $GATEWAY |
接下来,我们需要设法禁用这个桥接网络,为此,可以编辑/etc/qemu-ifdown文件,并用下面的代码替换原来内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#! /bin/sh # Bring down eth0 and br0 /sbin/ifconfig eth0 down /sbin/ifconfig br0 down # Delete the bridge /sbin/brctl delbr br0 # Bring up eth0 in "normal" mode /sbin/ifconfig eth0 -promisc /sbin/ifconfig eth0 up # Delete the tap device /usr/sbin/openvpn --rmtun --dev $1 |
现在,为了启动仿真的MIPS系统,只需运行start.sh脚本(不要忘记CHMOD + X)就行了。当然,启动过程需要一点时间,但如果一切正常,就会看到MIPS Debian仿真系统的登录提示,默认的用户名/密码为root/root:
实际上,我们的仿真系统的功能是非常齐全的,包括联网功能。如若不信的话,可以通过ping一下Google的DNS ping 8.8.8.8来进行验证。当然,我们希望能收到相应的TTL。
现在,要想从新创建的Debian MIPS实例中获取文件的话,python应该是最简单的方法。在Kali宿主虚拟机上(而不是在Debian MIPS机器上)切换到编译好的mips-test.elf文件所在目录。 然后,在终端中输入以下命令:
1 |
python -m SimpleHTTPServer |
该命令将启动mips-test.elf所在文件夹中的HTTP服务器。现在,回到Debian MIPS机器,并输入以下命令:
1 |
wget http://[YOUR KALI ETH0 IP HERE]:8000/mips-test.elf |
这样的话,就会把mips-test.elf文件下载到Debian MIPS系统中。只要借助LS命令,就可以找到这个文件了。然后,通过CHMOD + x mips-test.elf运行它。很好,这样一来我们只需传输相应的文件,就可以在仿真的Debian MIPS Little Endian系统上(而非在Windows/Linux/Mac机器上虚拟化的Kali Linux操作系统中)运行交叉编译的MIPS Little Endian二进制文件了。
为了恢复Kali机器的网络功能,请运行以下命令:
1 |
/etc/qemu-ifdown tap0 |
现在,我们开始介绍如何进行调试MIPS的ELF程序。当前,我们的系统已经可以编译MIPS二进制文件,并使用QEMU用户模式来独立运行它们了,或者使用QEMU系统仿真模式在本地模拟的Debian MIPS系统中运行它们了。
在我们继续学习下文之前,不妨先来熟悉一下radare和gdb-multiarch这两个工具。其中,Gdb-Multiarch是一个支持多种体系结构的GDB调试器,而Radare则可对多体系结构的文件进行反汇编和调试。接下来,我们使用以下命令从GitHub中安装它们的最新版本(虽然Kali已经提供了Radare软件,但提供的版本通常较旧):
1 2 3 4 5 6 7 8 9 |
apt-get install gdb-multiarch git clone https://github.com/radare/radare2 cd radare2/sys chmod +x install.sh ./install.sh |
安装Radare2和GDB-Multiarch后,就可以开始我们的调试之旅了。不过,在选择调试攻击组合时,我们有多种方案可选。当然,每种组合都有自己的优点和缺点,这就要求我们多多尝试,以便找到最适合自己的那种。接下来,将为读者演示启动各个组合所需的命令以及如何附加到所需调试器。
1.) QEMU 用户模式、GDB STUB与 GDB-MULTIARCH
为了启动这些工具,请从Kali终端中输入下列命令:
qemu-mipsel -g 12345 mips-test.elf
gdb-multiarch
target remote 127.0.0.1:12345
2.) QEMU用户模式、GDB STUB和RADARE2 GDB模式
为了启动这些工具,请从Kali终端中输入下列命令:
1 2 3 4 5 6 7 |
qemu-mipsel -g 12345 mips-test.elf radare2 -a mips -b 32 -D gdb -d gdb://127.0.0.1:12345 e dbg.follow.child=true e dbg.forks=true |
3.) QEMU用户模式和RADARE2本地调试器
为了启动这些工具,请从Kali终端中输入下列命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
radare2 -a mips -b 32 -d dbg:///mips-test.elf e dbg.follow.child=true e dbg.forks=true aa s sym.main af VV |
4.) QEMU用户模式和IDAPRO远程GDB
为了启动这些工具,请从Kali终端中输入下列命令:
1 |
qemu-mipsel -g 12345 mips-test.elf |
在运行IDAPRO的机器上运行:
1 2 3 |
select the remoteGDB debugger from the drop down debugger menu specify the IP of your Kali machine and Port 12345 |
5.)QEMU系统仿真模式与GDB-MULTIARCH本地编译
为了启动这些工具,请从Kali终端中输入下列命令:
1 |
./start.sh |
为了启动这些工具,请从Debian MIPS终端中输入下列命令:
1 2 3 |
apt-get install gdb-multiarch gdb-multiarch mips-test.elf |
6.)QEMU系统仿真与RADARE2本地编译
为了启动这些工具,请从Kali终端中输入下列命令:
1 |
./start.sh |
从Debian MIPS终端中输入下列命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
wget https://radare.mikelloc.com/get/2.4.0/radare2_2.4.0_mipsel.deb dpkg -i radare2_2.4.0_mipsel.deb radare2 -a mips -b 32 -d dbg:///mips-test.elf e dbg.follow.child=true e dbg.forks=true aa s sym.main af VV |
7.) QEMU系统仿真、GDBSERVER与远程GDB-MULTIARCH
为了启动这些工具,请从Kali终端中输入下列命令:
1 |
./start.sh |
从Debian MIPS终端中输入下列命令:
1 |
gdbserver 127.0.0.1:12345 mips-test.elf |
从Kali终端中输入下列命令:
1 2 3 |
gdb-multiarch target remote [Debian MIPS IP]:12345 |
8.) QEMU系统仿真、GDBSERVER与远程RADARE2 GDB模式
从Kali终端中输入下列命令:
1 |
./start.sh |
从Debian MIPS终端中输入下列命令:
1 |
gdbserver 127.0.0.1:12345 mips-test.elf |
从Kali终端中输入下列命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
radare2 -a mips -b 32 -D gdb -d gdb:///[Debian MIPS IP]:12345 e dbg.follow.child=true e dbg.forks=true aa s sym.main af VV |
9.) QEMU系统仿真、GDBSERVER与IDAPRO远程附加GDB
从Kali终端中输入下列命令:
1 |
./start.sh |
从Debian MIPS终端中输入下列命令:
1 |
gdbserver 127.0.0.1:12345 mips-test.elf |
在运行IDAPRO的机器上运行:
1 2 3 |
select the remoteGDB debugger from the drop down debugger menu specify the IP of your Debian MIPS machine and Port 12345 |
读者可以从上面的9个组合中找到适合自己的调试方式。下面我来讲一下自己在使用上述组合过程中的一些经验,以及发现的一些难点。
当使用QEMU用户模式运行MIPS二进制文件时,实际的进程空间是QEMU。如果直接附加到PID的话,将会进入QEMU进程空间,但是调试器却将其识别为x86指令集,而非MIPS。此外,在进程的内存空间中定位MIPS入口点以及在有效指令中暂停都是非常困难的:
祝贺您“顽强地”读完本文。虽然网上已经有了许多介绍MIPS仿真、调试和分析的文章,但是我们发现其中大部分都局限于某个方面。例如,某篇文章可能会展示如何编译MIPS,但却没有介绍如何运行它。或者有的文章虽然讲解了如何模拟MIPS,却没有介绍如何正确设置网络。所以,我们打算博采众长,将各个方面汇集在一起,以便于读者全面学习相关知识,最后,祝读者阅读愉快!
相关视频:https://www.youtube.com/watch?v=kQxH3OMIvd8。
原文链接:https://www.ringzerolabs.com/2018/03/the-wonderful-world-of-mips.html