You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

格式化字符串漏洞(Format string vulnerability):无法修改指定字符变量值时构造输入触发目标代码输出"Print me!"

构造输入触发"Print me!"的解决方案

要让程序输出"Print me!",我们需要同时满足两个核心条件:

  1. 把locals.iNeedSomeOverflow的初始值大写'P'改为小写'p'
  2. 让全局变量best_days的值不等于初始的0xdead

分析漏洞与内存布局

先拆解局部结构体locals的内存布局(以32位系统为例,指针和unsigned类型均占4字节):

  • int* pbest_days:4字节,已初始化为&best_days(全局变量best_days的内存地址)
  • unsigned hereToHelp:4字节
  • char array[60]:60字节,是scanf的输入目标,无边界检查
  • char iNeedSomeOverflow:1字节,紧跟在array的内存区域之后

这里有两个可利用的漏洞:

  • 缓冲区溢出:scanf("%s", locals.array)不限制输入长度,我们可以填满60字节的array后,直接覆盖后续的iNeedSomeOverflow为'p'。
  • 格式化字符串漏洞:printf(locals.array)会把输入字符串当作格式串解析,我们可以用%n指令,借助结构体中已有的pbest_days指针,修改best_days的值。

构造输入的具体步骤

1. 覆盖iNeedSomeOverflow为'p'

先用60个任意字符(比如'A')填满array,然后在第61个字符的位置写入'p',这一步就能完成第一个条件的触发。

2. 利用格式化字符串修改best_days

结构体里的pbest_days已经存储了best_days的地址,我们需要先找到这个地址在printf参数栈中的偏移:

  • 先构造测试输入:60个'A' + 'p' + "%08x%08x%08x%08x%08x%08x",运行程序后观察输出的十六进制值,找到对应best_days地址的那个偏移位(假设是第5个%08x)。
  • 把测试用的%08x替换为%k$n(k是找到的偏移位,比如5),%n会将当前已打印的字符数写入到第k个参数指向的地址(也就是best_days的地址),这样best_days的值就会被修改,不再等于0xdead。

最终输入示例

假设偏移位为5,最终的输入字符串如下:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp%5$n

(前60个字符为'A',第61个为'p',后续是格式化指令)

程序执行流程:

  1. scanf读取输入,填满array后覆盖iNeedSomeOverflow为'p'。
  2. printf解析输入的格式串,执行%5$n将已打印的字符数写入best_days,改变其值。
  3. 两个条件均满足,程序输出"Print me!"。

内容的提问来源于stack exchange,提问作者nullptrexception

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:08:14