从BUPT实验到实战:手把手教你用OllyDbg复现格式化字符串漏洞(含Shellcode注入)

张开发
2026/4/5 7:58:42 15 分钟阅读

分享文章

从BUPT实验到实战:手把手教你用OllyDbg复现格式化字符串漏洞(含Shellcode注入)
从实验室到战场用OllyDbg实战格式化字符串漏洞攻防当我在大学第一次接触格式化字符串漏洞时那些晦涩的%x、%n符号就像天书一样令人困惑。直到在CTF比赛中被这类漏洞反复教育后我才真正明白它的威力。本文将带你跳出枯燥的实验报告用OllyDbg动态调试工具像黑客一样思考和利用这个经典漏洞。1. 漏洞原理为什么printf能成为攻击武器格式化字符串漏洞源于程序员对用户输入数据的天真信任。当攻击者能够控制格式化字符串参数时普通的printf家族函数就会变成内存探针和写入器。这种漏洞在2000年左右被广泛讨论但直到今天仍能在野生软件中见到它的身影。核心攻击向量%x泄露栈内存%s读取任意地址内容%n向指定地址写入数据长度控制符触发缓冲区溢出在OllyDbg中打开一个存在漏洞的程序时你会看到栈空间像被X光照射一样透明。例如下面这个简单的漏洞代码片段void vulnerable() { char buf[128]; scanf(%s, buf); // 用户可控输入 printf(buf); // 格式化字符串漏洞点 }当输入包含%x时程序会开始泄露栈上的数据。更危险的是%n格式化符它可以将已输出的字符数写入指定地址这相当于获得了内存写能力。2. 环境搭建构建可复现的调试战场工欲善其事必先利其器。我们需要准备以下装备OllyDbg 1.10经典的反汇编调试工具Immunity Debugger增强版调试环境可选Windows XP/7虚拟机稳定的调试环境漏洞测试程序可自行编译或使用CTF题目配置关键点在OllyDbg中设置异常处理选项忽略除访问违例外的所有异常配置符号路径以便更好地理解系统调用安装Olly Advanced插件增强反汇编能力提示调试时建议关闭ASLR等防护机制待掌握基础技术后再挑战加固环境3. 实战演练四步攻破格式化字符串防御3.1 栈内存测绘用%x绘制攻击地图在OllyDbg中加载目标程序后首先需要定位格式化字符串在栈中的位置。这就像在陌生城市寻找地标在printf调用处下断点输入测试字符串AAAA%x.%x.%x.%x观察栈帧和输出结果典型的内存布局可能如下表所示栈偏移内容说明ESP00x0012FF60格式化字符串地址ESP40x41414141用户输入的AAAAESP80x00000001其他局部变量当输出中出现41414141时说明找到了用户输入在栈中的位置。这个偏移量将成为后续攻击的基准点。3.2 精确打击用%s读取敏感数据掌握了栈布局后就可以读取特定内存地址的内容。这需要构造特殊的payloadpayload struct.pack(I, 0x00402000) b%s在OllyDbg中执行时前4字节会被解释为内存地址%s会将该地址作为字符串起始点输出遇到NULL字节时停止常见问题排查地址未对齐确保地址是4字节对齐的访问违例验证目标地址是否可读输出截断检查NULL字节位置3.3 内存篡改用%n劫持程序流这是最具破坏性的阶段。通过精心构造的格式化字符串我们可以改写函数指针、返回地址等关键数据。典型攻击流程确定目标写入地址如GOT表项计算需要写入的值构造包含适当数量字符的格式化字符串使用%n或%hn2字节写入完成写入例如要写入0x080491a2到0x00402000# 计算需要输出的字符数 write_value 0x080491a2 written len(payload_prefix) padding (write_value - written) % 0x10000 payload payload_prefix b% str(padding).encode() bx%hn3.4 Shellcode注入实现代码执行结合格式化字符串和缓冲区溢出可以实现完整的攻击链用%n覆盖返回地址或函数指针将控制流重定向到shellcodeshellcode通常包含在格式化字符串中在OllyDbg中调试时需要注意确保shellcode地址计算正确处理坏字符问题特别是NULL字节验证内存保护机制是否被绕过4. 防御之道从攻击者视角看防护理解了攻击手法后防御措施就变得直观开发层面永远使用带格式字符串的printf如printf(%s, buf)启用编译器保护如GCC的-Wformat-security使用现代安全函数如snprintf替代sprintf系统层面启用ASLR和DEP/NX保护限制敏感函数的调用如system实施严格的输入验证在OllyDbg中测试防护措施的有效性时可以启用DEP后观察shellcode执行情况开启ASLR后测试地址预测成功率验证栈保护机制如Canary的作用5. 进阶技巧CTF实战中的奇技淫巧在真实的CTF比赛中格式化字符串漏洞往往与其他漏洞结合出现。一些高阶技巧包括GOT表劫持通过覆盖GOT表项实现任意函数调用堆栈转换将攻击从栈迁移到堆区域部分覆盖利用%hn实现精确内存修改盲打技术在没有直接反馈情况下的漏洞利用例如在最近的某CTF比赛中选手需要结合格式化字符串和堆漏洞才能拿到flag。解题步骤大致如下用%leak出堆地址计算关键数据结构位置用%n修改堆管理元数据触发堆操作实现任意写最终覆盖vtable执行shellcode这类复合型漏洞的调试需要耐心和系统的方法论。在OllyDbg中可以通过以下快捷键提高效率F2设置/取消断点F7单步步入F8单步步过CtrlF9执行到返回AltM查看内存区域调试复杂漏洞时我习惯在笔记中记录以下信息关键函数地址和偏移量重要数据结构的布局每次payload尝试的效果遇到的异常和解决方案这种系统化的记录方式能显著提高调试效率特别是在面对需要多次尝试的复杂漏洞时。

更多文章