为了研究出更有效的攻击方法,我们需要对格式规定符的长度修饰符有一些了解。长度修饰符可被使用在格式规定符中来限定输出的整型参数的类型,当使用在 %n上,它控制把参数当作多少个字节的整数。在允许加到 %n的众多长度修饰符选项中,我们将关注下面三个例子:
  • %n:视参数为4字节整型数
  • %hn:视参数为2字节短整型数
  • %hhn:视参数为1字节字符型
为了理解这些长度修饰符选项的使用方法,我们写一个简单的程序,该程序有三个变量 a, b 和 c,它们被初始化为同一个值(0x11223344)。接着我们用 %n 加上不同的长度修饰符来修改它们的值。我们能清楚地看到结果是相当不同的。
 
#include <stdio.h>
void main()
{
  int a, b, c;
  a = b = c = 0x11223344;

  printf("12345%n\n", &a);
  printf("The value of a: 0x%x\n", a);
  printf("12345%hn\n", &b);
  printf("The value of b: 0x%x\n", b);
  printf("12345%hhn\n", &c);
  printf("The value of c: 0x%x\n", c);
}
 
程序运行的结果如下:
 
seed@ubuntu:$ a.out
12345
The value of a: 0x5          ⬅ 四个字节全被修改了
12345
The value of b: 0x11220005   ⬅ 只有两个字节被修改了
12345
The value of c: 0x11223305   ⬅ 只有一个字节被修改了
 
当把 %hhn 用在变量 c 上时,printf() 先得到变量 c 的地址,然后改动从该地址开始的第一个字节。因为我们的计算机用的是小端字节顺序,所以第一个字节里存的是 0x44,它被改成了 0x05。于是变量c变成了 0x11223305。当我们对变量 b 使用 %hn,改动的是从变量 b 的地址开始的前两个字节,所以 b 的值变成了 0x11220005。对于变量 a,我们使用 %n,它的四个字节都被改动了,变成了 0x000005。
Last modified: Friday, 1 August 2025, 7:13 PM