课程导论:格式化字符串漏洞——从入门到异架构实战
大家好,我是你们这门课的教练。做了这么多年二进制安全,我见过太多人在格式化字符串漏洞上栽跟头。说实话,这个漏洞在 x86 下已经算是“老朋友”了,但一旦换到 ARM 或 MIPS 架构,很多人就懵了。今天这第一节课,我们就来聊聊它到底是什么,以及为什么换个架构就变得这么棘手。
什么是格式化字符串漏洞?
简单来说,就是程序把用户输入直接当成了 printf 这类函数的格式化参数。你想想看,如果程序写的是 printf(user_input),而不是 printf("%s", user_input),那会发生什么?
用户输入里如果带了 %x、%n 这些格式化标记,程序就会把它们当成指令来执行。这就像你把家门钥匙交给了陌生人,他不仅能看,还能改你家里的东西。
核心本质:格式化字符串漏洞的本质是 参数解析与栈/寄存器数据泄露 的结合。攻击者通过控制格式化标记,实现任意地址读(%s)和任意地址写(%n)。
我在项目中遇到过最典型的案例,是一个嵌入式设备的 Web 管理界面。开发者为了省事,直接用 printf(request_body) 打印日志。结果呢?攻击者通过一个 %n 标记,直接改写了返回地址,拿到了 shell。嗯,这就是典型的“省一行代码,丢一台设备”。
为什么在异架构(ARM/MIPS)下利用更复杂?
这个问题,我当年刚接触 ARM 下的 Pwn 时也困惑过。后来踩了不少坑,才总结出几个关键点。咱们直接看对比表格:
| 对比维度 | x86 (IA-32) | ARM (32位) | MIPS (32位) |
|---|---|---|---|
| 参数传递方式 | 全部在栈上 | 前4个参数在寄存器 (r0-r3),其余在栈上 | 前4个参数在寄存器 (a0-a3),其余在栈上 |
| 格式化字符串偏移 | 直接栈偏移,容易计算 | 需要先处理寄存器参数,偏移计算复杂 | 同ARM,但寄存器命名和ABI有差异 |
| 指令长度 | 变长 (1-15字节) | 固定4字节 (ARM模式) | 固定4字节 |
| 常见利用难点 | ASLR、PIE绕过 | 寄存器参数干扰 + 指令对齐 + 字节序 | 延迟槽 + 缓存一致性 + 字节序 |
| 字节序 | 小端 (Little-Endian) | 可配置 (通常小端) | 可配置 (通常大端) |
你看,最核心的区别在于 参数传递方式。在 x86 下,格式化字符串的参数全部从栈上取,你只要算好偏移就行。但在 ARM/MIPS 下,前4个参数在寄存器里。这意味着你的格式化字符串本身(通常作为第一个参数,在 r0/a0 里)会占用一个寄存器位置。
为什么会这样?因为 printf 的第一个参数是格式化字符串本身,它已经在 r0 里了。那么 %1$p 取到的第一个参数,其实是 r1 里的值,而不是栈上的第一个值。这个偏移量的计算,就成了异架构利用的第一个门槛。
避坑指南:我曾经在调试一个 MIPS 设备的漏洞时,花了整整两天时间,才发现偏移量算错了。因为 MIPS 的 ABI 规定,printf 的返回值也会占用一个寄存器,导致参数传递的栈布局和 ARM 又有细微差别。所以,千万别拿 ARM 的偏移公式直接套在 MIPS 上。
课程目标与前置知识
这门课不是给纯新手准备的。我希望你已经有了一定的基础,这样我们才能把精力集中在异架构下的特殊技巧上。
课程目标
- 掌握异架构下的格式化字符串利用原理:理解 ARM/MIPS 的 ABI 对参数传递的影响。
- 熟练使用常见工具链:QEMU 用户态模拟、pwntools、GDB-multiarch。
- 独立完成从漏洞分析到 Exploit 编写:包括任意地址读、任意地址写、GOT 表劫持、ROP 链构造。
- 应对真实环境中的限制:如 NX、ASLR、PIE、RELRO 等保护机制的绕过。
前置知识要求
| 知识领域 | 具体要求 |
|---|---|
| C 语言基础 | 理解指针、函数调用、栈帧结构 |
| 汇编基础 | 至少熟悉一种架构的汇编(x86/ARM/MIPS) |
| Pwn 入门 | 了解栈溢出、ROP 基本概念 |
| Linux 基础 | 熟悉命令行、gdb、objdump 等工具 |
| Python 编程 | 能使用 pwntools 编写简单的 exploit |
我的建议:如果你对 x86 下的格式化字符串漏洞还不熟悉,我建议你先去补一下基础。比如 %n 怎么写任意值,%hhn 怎么写单字节。这些在异架构下原理相同,但偏移计算和字节序处理会更绕。基础不牢,后面会非常痛苦。
本章知识体系总览
为了让你对这门课的结构有个整体印象,我画了一张图。它展示了我们从“漏洞原理”到“异架构实战”的完整路径。
从这张图你可以看到,我们的学习路径很清晰:先理解漏洞原理,再分别攻克不同架构下的利用技巧,最后汇总到实战。我个人觉得,ARM 和 MIPS 是异架构 Pwn 里最典型的两个代表,搞定它们,其他架构(比如 RISC-V)你也能很快上手。
好了,第一节课就到这里。记住,格式化字符串漏洞的核心就是“参数解析”和“数据泄露/篡改”。在异架构下,多了一个“寄存器参数”的干扰项。后面的课程,我们会一步步拆解这些干扰项,直到你能写出稳定的 exploit。