一个简单的栈溢出攻击
今天研究了一下栈溢出,感觉有点意思。
环境:codeblocks13.12+gcc version 4.7.1 (tdm-1)
先上代码:
首先使用了两个函数指针f和m,f指向overflow,m指向main。在内存中,函数是一段代码,而函数名记录的是这段代码的首地址,因此可以使用一个指针指向这个函数。
我们看一下汇编代码:

其中一个格子长度为4B,一个int的大小。栈地址生长的方向在数值上是递减的,而数组下标的访问在生长方向上是递增的。
显然ss[2]就是返回的地址,只要让ss[2]=f,就会跳转到overflow。如果直接这样处理,会打印一个overflow后出错,但是main函数中间位置的程序地址不太容易获得,所以干脆直接从头调用main函数。
于是这个程序的结果就是无限的输出overflow。
如果我们的ss足够长,比如有4k大小,那么ss[4097]就是返回地址,此时我们让ss[4097]返回到ss[0],并在这里构建程序段,说不定就可以执行这段程序了。我今天尝试的方式没有成功,明天继续尝试。
这就是一个简单的栈溢出攻击了。
环境:codeblocks13.12+gcc version 4.7.1 (tdm-1)
先上代码:
#include <stdio.h>使用watch可以看到disassembly和memory dump,测试中也可以使用。需要注意的是,此段代码仅在debug模式下有用,原因估计是release下堆栈安排不那么一样。
#include <stdlib.h>
int (*f)();
int (*m)();
int test(int* s)
{
int ss[1];
ss[2]=f;
ss[3]=m;
//printf("test\n");
}
int overflow()
{
printf("overflow\n");
}
int main()
{
f=overflow;
m=main;
int strbuf[1];
int a=2;
a++;
test(strbuf);
printf("Hello world!\n");
getchar();
return 0;
}
首先使用了两个函数指针f和m,f指向overflow,m指向main。在内存中,函数是一段代码,而函数名记录的是这段代码的首地址,因此可以使用一个指针指向这个函数。
我们看一下汇编代码:
7 {可以分析得到:
0x00401334 push %ebp
0x00401335 mov %esp,%ebp
0x00401337 sub $0x10,%esp
8 int ss[1];
9 ss[2]=f;
0x0040133A mov 0x405054,%eax
0x0040133F mov %eax,0x4(%ebp)
10 ss[3]=m;
0x00401342 mov 0x405050,%eax
0x00401347 mov %eax,0x8(%ebp)
12 //printf("test\n");
13 }
0x0040134A leave
0x0040134B ret

其中一个格子长度为4B,一个int的大小。栈地址生长的方向在数值上是递减的,而数组下标的访问在生长方向上是递增的。
显然ss[2]就是返回的地址,只要让ss[2]=f,就会跳转到overflow。如果直接这样处理,会打印一个overflow后出错,但是main函数中间位置的程序地址不太容易获得,所以干脆直接从头调用main函数。
于是这个程序的结果就是无限的输出overflow。
如果我们的ss足够长,比如有4k大小,那么ss[4097]就是返回地址,此时我们让ss[4097]返回到ss[0],并在这里构建程序段,说不定就可以执行这段程序了。我今天尝试的方式没有成功,明天继续尝试。
这就是一个简单的栈溢出攻击了。
6 个评论
不明觉厉!直接赞上!程序猿们看过来!
你可以先编译程序,然后查看编译出的结果定位地址,在输入的字符串里面写相应的机器码把栈覆盖掉就行了
当然,只是验证一下原理而已
只是帮助理解吧