ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

MIPS逆向工程入门:从babymips解析到实战技巧

MIPS逆向工程入门:从babymips解析到实战技巧

1. 逆向工程入门:从babymips开始

第一次接触逆向工程时,我盯着那个名为babymips的CTF题目发了半小时呆。作为攻防世界(CTF比赛平台)中经典的逆向入门题,它完美诠释了什么叫"看似简单实则暗藏玄机"。MIPS架构的逆向分析对于大多数从x86入门的逆向新手来说,就像突然被扔到了异国他乡——指令集不同、寄存器用法不同、甚至连字节序都是反的。

提示:MIPS架构采用大端序存储,而x86是小端序,这是逆向分析时第一个需要注意的关键差异点。

我清楚地记得第一次用IDA Pro打开babymips时的困惑:那些$v0、$a0寄存器是什么?为什么跳转指令长得这么奇怪?lw和sw指令又在操作什么?经过十几个小时的折腾和查阅资料,终于搞明白这道题在考察逆向工程师最基础的三项能力:

  • 静态分析工具的使用熟练度(IDA/Ghidra)
  • 对非x86架构的适应能力
  • 基础密码算法的识别与破解

2. 环境搭建与工具链配置

2.1 模拟器选择与配置

分析MIPS架构程序首先需要合适的运行环境。我尝试过三种方案:

  1. QEMU用户模式:最轻量但调试功能有限
    qemu-mips -g 1234 ./babymips
  2. QEMU系统模式:需要下载Debian MIPS镜像(约2GB)
    qemu-system-mips -kernel vmlinux -hda debian.img -append "root=/dev/sda1"
  3. Docker容器:最推荐的方式,快速部署且资源占用小
    FROM multiarch/debian-debootstrap:mips-jessie RUN apt-get update && apt-get install -y gdb-multiarch

实测发现第三种方案配合gef插件效果最佳。安装完成后需要特别注意:

# 设置qemu静态解释器路径 export QEMU_LD_PREFIX=/usr/mips-linux-gnu # 使用gdb-multiarch连接 gdb-multiarch -q ./babymips -ex "target remote :1234"

2.2 逆向工具链配置

静态分析推荐组合使用:

  • IDA Pro 7.7+:必须安装MIPS处理器模块
  • Ghidra 10.1+:免费但反编译质量稍差
  • Binwalk:用于固件提取(本题不需要)

动态调试必备插件:

  • GEF:增强版GDB调试界面
  • Pwndbg:专为CTF优化的调试工具
  • radare2:命令行逆向瑞士军刀

特别要注意IDA的MIPS处理器设置:

  1. Options->General中勾选Show full instruction
  2. 设置Analysis->Processor optionsmipsb(大端模式)
  3. 启用Cross references中的Create function tails

3. babymips题目深度解析

3.1 初始文件分析

拿到题目文件首先执行常规检查:

file babymips # 输出: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 checksec --file=babymips # 结果: 无NX保护、无PIE、部分RELRO

用IDA加载后立即注意到几个关键点:

  1. 入口函数start最终调用main(地址0x00400740)
  2. 存在明显的字符串比较逻辑(xref到"Correct!")
  3. 发现可疑函数sub_4007F0包含大量算术运算

3.2 核心算法逆向

在地址0x00400884处发现关键比较:

lui $v0, 0x41 lw $v1, 0x28+var_10($fp) lw $v0, 0x28+var_14($fp) nop bne $v1, $v0, loc_4008C8

通过交叉引用追踪发现输入验证流程:

  1. 用户输入被存入$s2寄存器
  2. 经过sub_4007F0函数处理
  3. 结果与硬编码值0x41比较

重点分析sub_4007F0函数:

// 伪代码还原 int check(char* input) { int sum = 0; for(int i=0; i<8; i++) { sum += (input[i] ^ 0x20) + 0x10; } return sum == 0x41; }

3.3 密码学特征识别

这个算法表现出典型的线性校验和特征:

  • 每个字节独立处理(无雪崩效应)
  • 使用固定异或值0x20(空格字符的ASCII)
  • 累加和检查(容易碰撞)

通过数学推导可建立方程:

Σ(input[i] ^ 0x20 + 0x10) = 0x41 即 Σ(input[i]) = 0x41 - 8*0x10 + 8*0x20 = 0xE1

这意味着任何8字节输入,只要ASCII码总和为225即可通过验证。例如:

"aaaaaaae" (97*7 + 101 = 225) "ABCDEFGH" (65+66+67+68+69+70+71+72=548) → 不符合

4. 漏洞利用与Payload构造

4.1 基础解法

根据上述分析,最简单的解法是:

print('a'*7 + chr(225-97*7)) # 输出: aaaaaaae

但作为CTF题目,通常需要更通用的解法脚本:

from z3 import * s = Solver() inp = [BitVec(f'c_{i}', 8) for i in range(8)] for c in inp: s.add(c >= 0x20, c <= 0x7e) # 可打印字符 sum_val = sum((c ^ 0x20) + 0x10 for c in inp) s.add(sum_val == 0x41) if s.check() == sat: m = s.model() print(''.join([chr(m[c].as_long()) for c in inp])) # 可能输出: "!\"#$%&'("

4.2 进阶技巧

在实际比赛中,还可以采用以下方法:

  1. 暴力破解:由于密钥空间小(8字节可打印字符)
    from itertools import product for p in product(range(0x20,0x7f), repeat=8): if sum((x^0x20)+0x10 for x in p) == 0x41: print(bytes(p)) break
  2. 符号执行:使用angr框架
    import angr p = angr.Project("./babymips") state = p.factory.entry_state() simgr = p.factory.simulation_manager(state) simgr.explore(find=0x4008B0) # Correct分支 print(simgr.found[0].posix.dumps(0))
  3. 动态插桩:使用QEMU模式下的PIN工具

5. MIPS逆向的特殊技巧

5.1 寄存器使用惯例

MIPS架构有固定的寄存器用途:

寄存器别名用途
$v0-$v1函数返回值
$a0-$a3函数参数
$t0-$t9临时寄存器
$s0-$s7保存寄存器
$gp全局指针
$sp栈指针
$ra返回地址

在babymips中观察到:

  • $s2存储用户输入指针
  • $v0常用于系统调用号
  • $a0常作为printf参数

5.2 延迟槽机制

MIPS特有的分支延迟槽特性:

beq $a0, $a1, loc_400800 move $v0, $zero # 这条指令总会执行

无论分支是否跳转,延迟槽中的指令都会执行。逆向时容易误判执行流。

5.3 常见指令速查

指令等效C代码说明
lwreg = *addr加载字
sw*addr = reg存储字
luireg = imm << 16加载高位立即数
orireg= imm
jalcall func跳转并链接
jrreturn跳转寄存器
sltreg = (a < b)设置条件

6. 逆向工程学习路线建议

通过babymips这道题,我总结出逆向新手的进阶路径:

  1. 工具熟练阶段(1-2周)

    • 掌握IDA基本操作:交叉引用(X)、重命名(N)、注释(:)
    • 熟悉GDB调试命令:break、stepi、x/i、info registers
    • 学会使用Hex-Rays反编译器(F5快捷键)
  2. 架构适应阶段(按优先级):

    • x86 → ARM → MIPS → PowerPC
    • 32位 → 64位
    • 小端序 → 大端序
  3. 算法识别训练

    • 常见加密算法特征(AES的S盒、RC4的KSA等)
    • 压缩算法特征(zlib头、LZMA字典等)
    • 编码特征(Base64的=填充、Hex的0x前缀)
  4. CTF专项突破

    • 先从简单逆向题开始(如攻防世界新手区)
    • 逐步挑战复杂保护机制(UPX壳、ollvm混淆等)
    • 最后研究真实恶意软件样本

我个人的练习方法是每天分析1个CTF题目+1个真实世界软件的小功能。坚持三个月后,再看babymips这类题目会觉得异常简单。逆向工程最关键的还是经验积累,没有捷径可走。

返回列表