非常见类型的格式化字符串
字数 1722 2025-08-22 12:23:12
非常见类型的格式化字符串漏洞利用技术详解
1. scanf格式化字符串漏洞利用
1.1 漏洞背景
在传统的格式化字符串漏洞利用中,我们通常关注的是printf系列函数。然而,scanf函数同样存在格式化字符串漏洞,只是相关研究和利用资料较少。
1.2 题目分析
题目特点:
- 使用
read读入的数据作为scanf的第一个参数(格式化字符串) rsi寄存器也指向输入缓冲区(但实际利用中可能不需要)- 程序开启了FULL RELRO保护,因此需要攻击libc的GOT表
1.3 利用原理
scanf函数中的%n格式化符号与printf类似,但作用不同:
scanf的%n将成功读入的字符串数量写入对应的指针所指向的地址- 可以类比
printf的%n,但写入的值是输入的长度而非输出的长度
1.4 利用步骤
-
泄漏libc基址:
p.recvuntil("Welcome to xyctf, this is a gift: ") libcbase = int(p.recv(14), 16) - libc.sym['printf'] -
构造payload:
libcgot = libcbase + 0x1EC040 payload = b'%*s%8$lln' # %*s用于控制输入长度,避免栈溢出 payload = payload.ljust(0x10, b'a') + p64(libcgot) -
触发漏洞:
p.send(payload) payload = b'a' * backdoor p.sendline(payload)
1.5 关键点说明
%*s:用于控制输入长度,避免栈溢出%8$lln:将成功读入的字符数写入第8个参数指向的地址- 需要将目标地址(libc GOT表地址)放在格式化字符串后的特定位置
2. vsnprintf格式化字符串漏洞利用
2.1 漏洞背景
vsnprintf是printf家族函数之一,它将格式化输出写入缓冲区而非直接输出到标准输出。这使得传统的泄漏技术(如泄漏栈地址或堆地址)变得困难。
2.2 题目特点
- 程序通过
mprotect使堆内存可执行 display_current_time函数中存在格式化字符串漏洞- GOT表可写
- 格式化字符串后有一个
puts函数调用
2.3 利用思路
- 劫持
puts的GOT表项,将其指向堆上的shellcode - 利用
%*d格式化字符串技巧控制写入的值
2.4 利用步骤
-
初始化阶段:
p.recvuntil(b"plz input mprotect code") p.sendline(b"a") # 触发mprotect使堆可执行 -
第一次格式化字符串攻击:
payload1 = b"%4210688x%33$ln" # 将特定值写入目标地址 p.sendline(payload1) -
第二次格式化字符串攻击:
payload2 = b"%*d%63$ln" # 关键技巧 p.sendline(payload2) -
写入shellcode:
shellcode = asm(shellcraft.sh()) p.sendline(shellcode) # 将shellcode写入堆
2.5 关键技术点
-
%*d格式化字符串技巧:%*d会从参数中读取一个值作为宽度参数- 可以控制这个宽度值来精确控制写入的值
- 例如:
printf("%*d%63$ln", name, pwd),其中name的值被用作宽度
-
堆地址控制:
- 由于堆可执行,可以将控制流劫持到堆上的shellcode
- 需要精确计算堆地址与写入值的关系
-
GOT表劫持:
- 劫持
puts的GOT表项,使其指向堆上的shellcode - 当后续调用
puts时,实际执行的是shellcode
- 劫持
3. 总结与对比
| 特性 | scanf格式化字符串 | vsnprintf格式化字符串 |
|---|---|---|
| 主要函数 | scanf | vsnprintf |
| 关键格式化符号 | %n | %n, %*d |
| 写入值来源 | 成功读入的字符数 | 格式化输出长度或参数值 |
| 典型利用目标 | libc GOT表 | 程序GOT表 |
| 特殊技巧 | %*s控制输入长度 | %*d控制宽度参数 |
| 内存保护 | 通常需要绕过RELRO | 可能需要可执行内存区域 |
4. 防御建议
-
输入验证:
- 对所有用户提供的格式化字符串进行严格验证
- 禁止用户控制格式化字符串
-
安全编译选项:
- 启用FULL RELRO保护
- 启用栈保护机制
-
代码审计:
- 检查所有格式化字符串函数的使用
- 确保没有用户可控的格式化字符串
-
权限控制:
- 限制内存可执行权限
- 使用地址空间随机化(ASLR)
5. 扩展思考
-
其他非常见格式化函数:
syslog系列函数中的格式化字符串漏洞err/warn系列函数中的格式化字符串
-
组合利用技术:
- 格式化字符串与堆漏洞的结合利用
- 格式化字符串与信息泄漏的结合
-
新型防护技术:
- 格式化字符串防护编译器扩展
- 运行时格式化字符串检测机制
通过深入理解这些非常见类型的格式化字符串漏洞,安全研究人员可以更全面地评估软件安全性,开发人员可以编写更健壮的代码,防御此类安全威胁。