79、固件逆向(二):嵌入式设备逆向(ARM/MIPS)、U-Boot分析

嵌入式设备逆向,说白了就是跟固件打交道。上一章我们聊了固件提取和文件系统分析,这一章咱们深入底层——ARM和MIPS架构的逆向,以及U-Boot这个引导加载程序的分析。

我个人觉得,嵌入式逆向最迷人的地方在于:你面对的是一个完整的、精简的操作系统,从引导到内核到应用,全在一个芯片里。你想想看,这比分析一个Windows PE文件有意思多了。

ARM vs MIPS:两种主流架构的逆向差异

做嵌入式逆向,ARM和MIPS是绕不开的两座大山。我这些年拆过的设备里,90%以上都是这两种架构。

ARM架构特点

ARM处理器现在几乎统治了移动设备和IoT市场。它的指令集有几个关键点你得记住:

  • Thumb/Thumb-2指令集:ARM有ARM模式和Thumb模式,指令长度分别是4字节和2字节。反汇编时一定要确认当前模式,否则你会看到一堆乱码。
  • 条件执行:ARM指令可以带条件后缀,比如MOVEQ表示相等时才执行。这在反汇编时容易让人困惑,因为指令看起来像是跳过了某些操作。
  • LDM/STM指令:批量加载/存储指令,常用于函数序言和尾声。看到PUSH {R4-R7, LR}这种,基本就是函数开始。

关键点:ARM的函数调用约定是R0-R3传参,R0返回值。R4-R11是保留寄存器,函数内如果用到必须保存恢复。

MIPS架构特点

MIPS在路由器、交换机领域非常常见。它的设计哲学跟ARM完全不同:

  • 延迟槽:这是MIPS最坑的地方。分支指令后面的那条指令一定会执行,不管分支是否跳转。我在分析一个路由器固件时,就因为没注意延迟槽,把关键逻辑完全理解反了。
  • 寄存器约定:MIPS有32个通用寄存器,每个都有特定用途。比如$ra是返回地址寄存器,$sp是栈指针。
  • 无条件执行:MIPS没有ARM那样的条件执行,所有指令都是无条件执行的。
特性 ARM MIPS
指令长度 4字节(ARM)/2字节(Thumb) 4字节(固定)
寄存器数量 16个(通用) 32个(通用)
延迟槽 有(分支后一条指令必执行)
条件执行 支持 不支持
常见设备 手机、平板、IoT 路由器、交换机

U-Boot分析:从引导到漏洞

U-Boot是嵌入式Linux设备最常用的引导加载程序。分析U-Boot,你就能理解设备是怎么启动的,也能找到很多安全漏洞。

U-Boot启动流程

U-Boot的启动分几个阶段:

  1. 第一阶段(SPL):初始化CPU、时钟、内存控制器。代码量很小,通常放在ROM或NAND的固定位置。
  2. 第二阶段(U-Boot proper):完整的引导程序,支持文件系统、网络、命令行。
  3. 加载内核:从Flash、网络或USB加载Linux内核到内存,然后跳转执行。

嗯,这里要注意:很多设备会把U-Boot的配置信息保存在环境变量中。这些变量里经常藏着调试接口、默认密码、甚至私钥。

实战技巧:在固件中搜索"bootargs"字符串,你就能找到内核启动参数。如果看到"init=/bin/sh",说明设备可能开启了调试shell。

U-Boot常见漏洞

我这些年挖到的U-Boot漏洞,归纳起来就几类:

  • 命令注入:U-Boot环境变量如果未正确过滤,攻击者可以通过修改"bootcmd"来执行任意命令。
  • 缓冲区溢出:U-Boot的网络协议栈(TFTP、NFS)经常有缓冲区溢出漏洞。
  • 硬编码凭据:很多设备在U-Boot里硬写了调试密码或SSH密钥。

警告:我曾经分析过一个IP摄像头,U-Boot环境变量里直接写着"password=admin123"。更离谱的是,这个密码还能通过串口直接登录到root shell。嗯,这种设备基本就是裸奔状态。

嵌入式逆向实战:分析一个MIPS路由器固件

咱们来走一遍实际的分析流程。假设你拿到了一个MIPS路由器的固件,想找后门或漏洞。

第一步:识别架构

binwalk扫描固件,找到内核和文件系统的偏移。然后看内核的入口点:

$ binwalk firmware.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             U-Boot version string: "U-Boot 1.1.4"
196608        0x30000         Linux kernel image (MIPS)
1048576       0x100000        Squashfs filesystem

看到"MIPS"了吗?这就是架构信息。接下来用readelf确认:

$ readelf -h vmlinux
ELF Header:
  Class:                             ELF32
  Data:                              2's complement, big endian
  Machine:                           MIPS R3000

第二步:提取U-Boot配置

U-Boot的环境变量通常存储在Flash的特定区域。用strings搜索关键字符串:

$ strings -n 6 firmware.bin | grep -i "boot\|password\|admin\|debug"
bootcmd=tftp 0x80000000 kernel.bin; bootm
bootargs=console=ttyS0,115200 root=/dev/mtdblock5
password=letmein123
debug=1

看到了吗?debug=1说明设备开启了调试模式。password=letmein123就是串口登录密码。

第三步:反汇编关键函数

用Ghidra或IDA加载内核,找到网络相关的函数。我习惯先找httpdtelnetd的入口:

// 伪代码示例
void httpd_main() {
    char username[32];
    char password[32];
    
    get_http_request(username, password);
    
    // 硬编码后门
    if (strcmp(username, "root") == 0 && strcmp(password, "admin123") == 0) {
        shell_exec("/bin/sh");
    }
}

这种硬编码后门在MIPS路由器里太常见了。我见过最离谱的一个设备,后门密码直接写在注释里——"// TODO: remove this before shipping"。

SVG:嵌入式设备逆向知识体系

嵌入式设备逆向知识体系 固件提取与分析 架构识别 ARM架构 Thumb/条件执行/LDM MIPS架构 延迟槽/32寄存器 U-Boot分析 内核/应用逆向 漏洞挖掘:后门/溢出/硬编码

常用工具与命令

做嵌入式逆向,工具链很重要。我列一下我常用的:

工具 用途 备注
binwalk 固件扫描、文件提取 必备工具,没有之一
Ghidra 反汇编、反编译 支持ARM/MIPS,免费
IDA Pro 高级反汇编 商业软件,但功能更强
QEMU 模拟运行固件 可以在PC上跑ARM/MIPS程序
firmware-mod-kit 固件解包/打包 适合批量处理

个人建议:刚开始做嵌入式逆向,先用QEMU模拟运行目标程序。这样你可以动态调试,比纯静态分析快得多。我一般流程是:binwalk解包 → QEMU运行 → Ghidra分析 → 找漏洞。

避坑指南

最后分享几个我踩过的坑:

  • 字节序搞反:MIPS有大小端两种模式。我曾经分析一个固件,反汇编出来全是乱码,折腾了两天才发现是字节序设置错了。
  • 忽略U-Boot环境变量:很多设备的环境变量里藏着关键信息。别只盯着内核代码,先看看环境变量里有没有密码或调试开关。
  • 忘记检查校验和:有些固件有CRC或签名校验。修改固件后如果不更新校验和,设备会拒绝启动。

嗯,嵌入式逆向就是这样——看起来复杂,但只要你掌握了ARM和MIPS的基本特点,理解了U-Boot的启动流程,剩下的就是耐心和细心了。多练几次,你也能像我一样,看到一个新设备就能大概猜出它的内部结构。


公众号:蓝海资料掘金营,微信deep3321