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 本章知识体系

下面这张图帮你理清整个环境搭建的脉络:

MIPS交叉编译环境搭建知识体系 MIPS交叉编译环境搭建知识体系 交叉编译环境 交叉编译工具链 QEMU用户态模拟 Hello World测试 gcc-mips-linux-gnu gcc-mipsel-linux-gnu binutils-mips-linux-gnu qemu-user 安装 libc6-mips-cross QEMU_LD_PREFIX 配置 编写hello.c 交叉编译 + QEMU运行 file/readelf 验证 大端(mips)和小端(mipsel)工具链建议都安装,实战中两种架构都会遇到

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的世界里自由探索了。记住,环境搭建是基础中的基础——基础不牢,地动山摇。我见过太多人在环境上浪费大量时间,结果真正做漏洞利用时反而没精力了。所以,一次配好,后面就顺畅了。