Mipsel固件Fuzzing小记
Mipsel固件Fuzzing小记
0x01 准备
1.1 安装必要工具链
首先需要安装 MIPS 交叉编译工具链和相关依赖:
sudo apt-get install -y gcc-mipsel-linux-gnu g++-mipsel-linux-gnu binwalk qemu-user-static afl++
这些工具分别用于:交叉编译、固件解包、二进制程序模拟执行以及模糊测试。
1.2 编译afl-qemu-trace
然后需要在AFLPlusPlus/qemu-mode目录下,
CPU_TARGET=mipsel ./build_qemu_support.sh
进行编译afl-qemu-trace,并复制到/usr/local/bin/目录下
1.3 使用 ramdisk
由于 fuzz 比较消耗硬盘读写,所以通过下面的命令,使用内存盘减少硬盘消耗。
mkdir /mnt/ramdisk
mount -t tmpfs -o size=2048M tmpfs /mnt/ramdisk
1.4 固件提取
使用 binwalk 解包固件并确认目标 CGI 程序的架构:
binwalk -Me firmware.bin # 解包固件
cd _firmware.bin.extractedfile squashfs-root/usr/sbin/cgibin
0x02 模拟执行
2.1 依赖检查
使用 QEMU 模拟执行 CGI 程序,检查是否能正常启动:
# 使用qemu模拟执行,查看缺失的依赖
qemu-mipsel-static -L squashfs-root squashfs-root/usr/sbin/cgibin -h
2.2 处理文件依赖与环境变量配置
如果启动失败,要想办法满足程序启动条件,如劫持函数、生成模拟文件等等。这里我需要copy一份cgibin,重命名为hedwig.cgi,因为程序以文件名为参数
[ 4:02上午 ]
$ export REQUEST_METHOD=POST
[ 4:07上午 ]
$ qemu-mipsel-static -L squashfs-root squashfs-root/htdocs/hedwig.cgi
Error while loading htdocs/hedwig.cgi: No such file or directory
[ 4:07上午 ]
$ ln -s htdocs/cgibin htdocs/hedwig.cgi
[ 4:10上午 ]
$ cp squashfs-root/htdocs/cgibin squashfs-root/htdocs/hedwig.cgi
[ 4:11上午 ]
$ qemu-mipsel-static -L squashfs-root squashfs-root//hedwig.cgi
HTTP/1.1 200 OK
Content-Type: text/xml<hedwig><result>FAILED</result><message>unsupported HTTP request</message></hedwig>%
2.3 程序入口分析
查看 CGI 程序的 main 函数源码,可以发现程序根据不同的文件名调用不同的处理函数:
int __fastcall main(int argc, const char **argv, const char **envp)
{const char *v3; // $s0// ... 代码省略 ...if ( !strcmp(v3, "hedwig.cgi") ){v8 = (void (__noreturn *)())&hedwigcgi_main;v9 = argc;return ((int (__fastcall *)(_DWORD, _DWORD, _DWORD))v8)(v9, argv, envp);}// ... 代码省略 ...printf("CGI.BIN, unknown command %s\n", v3);return 1;
}
这就是为什么我们需要复制或链接到 hedwig.cgi 文件名的原因。
0x03 AFL++异架构fuzzing
3.1 准备初始语料库
创建包含有效输入的初始语料库:
mkdir -p corpusecho "<?xml version="1.0"?><postxml><module><service>DEVICE.TIME</service><device><time><ntp><server>test</server></ntp></time></device></module></postxml>" > corpus/test.txt
3.2 设置环境变量
CGI 程序依赖特定的环境变量来处理 HTTP 请求,我们设置环境变量
export REQUEST_METHOD=POST
export SCRIPT_NAME=/hedwig.cgi
export CONTENT_TYPE=text/xml
export CONTENT_LENGTH=1024
3.3 基础AFL++命令
启动 AFL++ 进行模糊测试:
export QEMU_LD_PREFIX=$(pwd)/squashfs-root
export LD_PRELOAD=$(pwd)/main_hook.so # 如果用了hook库
export AFL_INST_LIBS=1
export AFL_NO_FORKSRV=1afl-fuzz -Q -m none -i corpus/ -o output/ ./htdocs/hedwig.cgi @@
3.4 高级配置选项
使用字典和并行模糊测试提高效率:
# 使用字典引导Fuzz(基于HTTP协议)
afl-fuzz -Q -i corpus -o output -x /path/to/http.dict \-- qemu-mipsel-static squashfs-root/usr/sbin/cgibin @@# 并行Fuzz(1个master + 多个slave)
# 终端1(master)
afl-fuzz -Q -M master -i corpus -o output -- qemu-mipsel-static squashfs-root/usr/sbin/cgibin @@
# 终端2及以后(slave)
afl-fuzz -Q -S slave1 -i- -o output -- qemu-mipsel-static squashfs-root/usr/sbin/cgibin @@
0x04 分析样本
4.1 分析崩溃样本
当发现崩溃时,首先查看崩溃样本:
ls output/crashes/# 联合gdb调试
qemu-mipsel-static -g 1234 squashfs-root/usr/sbin/cgibin output/crashes/id:000000,sig:11,src:000000,op:flip1,pos:0# 另开终端连接GDB
mipsel-linux-gnu-gdb squashfs-root/usr/sbin/cgibin
(gdb) target remote :1234