2、MIPS交叉编译环境搭建
做MIPS漏洞利用,第一件事不是学指令集,而是先把环境搭起来。我见过太多人拿着IDA反汇编看半天,结果自己连个测试程序都跑不起来——这不行。今天咱们就把交叉编译工具链、QEMU用户态模拟、还有第一个Hello World,一口气搞定。
2.1 为什么需要交叉编译?
你想想看,你的电脑是x86架构,MIPS路由器是MIPS架构。x86上编译出来的二进制,MIPS CPU根本看不懂。反过来,MIPS上编译的程序,x86也跑不了。这就是交叉编译存在的意义——在一台机器上生成另一种架构的可执行文件。
核心概念:交叉编译 = 在A架构上编译出能在B架构上运行的程序。我们这里就是x86编译,MIPS执行。
我个人习惯把交叉编译环境装在Ubuntu 20.04或22.04上,依赖问题少,社区支持好。如果你用其他发行版,包名可能略有不同,但思路完全一样。
2.2 安装mips-linux-gnu-gcc工具链
最省事的方法是用apt直接装。Ubuntu官方源里就有完整的MIPS交叉编译工具链,省去自己编译的痛苦。我自己编译过一次,折腾了整整两天——嗯,从那以后我再也不自己编译工具链了。
# 更新包索引
sudo apt update
# 安装MIPS大端工具链
sudo apt install gcc-mips-linux-gnu
# 安装MIPS小端工具链(可选,但建议装)
sudo apt install gcc-mipsel-linux-gnu
# 安装相关工具
sudo apt install binutils-mips-linux-gnu
sudo apt install binutils-mipsel-linux-gnu
装完之后验证一下:
mips-linux-gnu-gcc --version
# 输出类似:mips-linux-gnu-gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
小提示:MIPS分大端(Big Endian)和小端(Little Endian)。大端用 mips-linux-gnu-*,小端用 mipsel-linux-gnu-*。家用路由器大多是MIPS小端,但很多嵌入式设备用大端。我建议两个都装,实战中你永远不知道下一个目标是什么。
2.3 配置QEMU用户态模拟环境
光有编译器还不够,你总不能在MIPS路由器上跑程序调试吧?QEMU用户态模式可以让你直接在x86电脑上运行MIPS二进制文件,就像运行本地程序一样。
# 安装QEMU用户态模拟器
sudo apt install qemu-user
# 安装MIPS相关的动态链接库
sudo apt install libc6-mips-cross
sudo apt install libc6-mipsel-cross
装好后测试一下:
# 查看QEMU是否支持MIPS
qemu-mips --version
qemu-mipsel --version
这里有个坑——我曾经遇到过QEMU版本太旧,跑某些MIPS指令直接崩掉。建议装最新版:
# 从源码编译最新QEMU(可选,但推荐)
sudo apt build-dep qemu
wget https://download.qemu.org/qemu-8.0.0.tar.xz
tar xf qemu-8.0.0.tar.xz
cd qemu-8.0.0
./configure --target-list=mips-linux-user,mipsel-linux-user
make -j$(nproc)
sudo make install
注意:QEMU用户态模式只能模拟单个进程,不能模拟整个系统。如果你想调试完整的MIPS系统(比如路由器固件),需要QEMU系统模式。但做漏洞利用,用户态模式基本够用。
2.4 编写第一个MIPS Hello World
环境搭好了,写个程序跑一下。新建一个 hello.c:
#include <stdio.h>
int main() {
printf("Hello, MIPS World!\n");
printf("This is my first MIPS program.\n");
return 0;
}
用交叉编译器编译:
# 编译大端版本
mips-linux-gnu-gcc -o hello_mips hello.c
# 编译小端版本
mipsel-linux-gnu-gcc -o hello_mipsel hello.c
用QEMU运行:
# 运行大端版本
qemu-mips ./hello_mips
# 运行小端版本
qemu-mipsel ./hello_mipsel
如果看到输出:
Hello, MIPS World!
This is my first MIPS program.
恭喜,你的MIPS交叉编译环境搭建成功了!
2.5 验证二进制文件
跑起来只是第一步,我们还得确认生成的确实是MIPS代码。用 file 命令看看:
file hello_mips
# 输出:hello_mips: ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, not stripped
file hello_mipsel
# 输出:hello_mipsel: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, not stripped
看到 MSB(大端)和 LSB(小端)的区别了吧?这就是MIPS架构的两个分支。
再用 readelf 看看更详细的信息:
mips-linux-gnu-readelf -h hello_mips
重点关注 Machine 字段,应该是 MIPS R3000。这说明我们的工具链工作正常。
2.6 环境搭建常见问题
我整理了几个新手最容易踩的坑:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 编译报错:找不到stdio.h | 缺少交叉编译用的头文件 | 安装 libc6-mips-cross 或 libc6-mipsel-cross |
| 运行报错:无法加载动态库 | QEMU找不到MIPS的动态链接库 | 设置 QEMU_LD_PREFIX 环境变量指向交叉编译的lib目录 |
| 运行报错:Illegal instruction | QEMU版本太旧,不支持某些指令 | 升级QEMU到最新版,或编译时加 -march=mips32r2 |
| 编译出的程序在QEMU里跑不起来 | 动态链接问题,缺少解释器 | 尝试静态编译:-static 参数 |
避坑指南:我曾经在编译一个CTF题目时,死活跑不起来,折腾了两小时才发现是QEMU版本太旧。从那以后,我每次搭建环境第一件事就是检查QEMU版本。建议用 qemu-mips --version 确认版本号不低于5.0。
2.7 本章知识体系
下面这张图帮你理清整个环境搭建的脉络:
2.8 进阶:静态编译与动态编译
刚才我们用的是动态编译,生成的二进制依赖系统的动态链接库。这在QEMU里跑需要额外配置 QEMU_LD_PREFIX。如果你嫌麻烦,可以直接静态编译:
mips-linux-gnu-gcc -static -o hello_mips_static hello.c
qemu-mips ./hello_mips_static
静态编译的好处是二进制文件自包含,不依赖任何外部库。坏处是文件体积大——一个Hello World能到700KB。动态编译只有7KB左右。做漏洞利用时,我建议用动态编译,更接近真实目标设备的运行环境。
实战建议:做Pwn题时,先用动态编译测试,确认漏洞利用逻辑。最后提交exploit时,再根据目标设备的libc版本调整偏移量。静态编译的二进制在漏洞利用中很少见,因为真实设备不会这么干。
好了,环境搭好了,工具链也验证了。接下来你就可以在MIPS的世界里自由探索了。记住,环境搭建是基础中的基础——基础不牢,地动山摇。我见过太多人在环境上浪费大量时间,结果真正做漏洞利用时反而没精力了。所以,一次配好,后面就顺畅了。