课程导论:格式化字符串漏洞——从入门到异架构实战

大家好,我是你们这门课的教练。做了这么多年二进制安全,我见过太多人在格式化字符串漏洞上栽跟头。说实话,这个漏洞在 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 怎么写单字节。这些在异架构下原理相同,但偏移计算和字节序处理会更绕。基础不牢,后面会非常痛苦。

本章知识体系总览

为了让你对这门课的结构有个整体印象,我画了一张图。它展示了我们从“漏洞原理”到“异架构实战”的完整路径。

格式化字符串漏洞知识体系 漏洞原理 任意地址读 (%s) 任意地址写 (%n) x86 利用 ARM 利用 MIPS 利用 其他架构 实战技巧:偏移计算 · 字节序处理 · 保护绕过 目标:独立编写异架构 Exploit 本课程覆盖 ARM + MIPS

从这张图你可以看到,我们的学习路径很清晰:先理解漏洞原理,再分别攻克不同架构下的利用技巧,最后汇总到实战。我个人觉得,ARM 和 MIPS 是异架构 Pwn 里最典型的两个代表,搞定它们,其他架构(比如 RISC-V)你也能很快上手。

好了,第一节课就到这里。记住,格式化字符串漏洞的核心就是“参数解析”和“数据泄露/篡改”。在异架构下,多了一个“寄存器参数”的干扰项。后面的课程,我们会一步步拆解这些干扰项,直到你能写出稳定的 exploit。