缓冲区溢出

shuaiwang_01 2008-10-24 09:14:07
我遇到了一个题目,是关于缓冲区溢出攻击的,但在vs环境下,当改变%ebp和返回地址的时候,不允许,怎么设置才能达到效果啊?
...全文
207 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
zsl6658 2008-10-27
  • 打赏
  • 举报
回复
lz不要动不动就拿牛人来压我嘛。你老师,作者,我一个都不如。
我只知道写自己理解的代码。做自己明白在做什么的事情。
不明白的一步一步弄明白。
intel的cpu是人发明的,但是是从在理解晶体管工作原理基础上发明的。
Unix是人写的,是在理解理解cpu工作原理的基础上写出来的。
Linux是人写的,是在理解unix基础和cpu的工作原理上写的。
ok????????????????????????????


zsl6658 2008-10-26
  • 打赏
  • 举报
回复
看楼上的回答的那么认真,
我还是严重的怀疑你的溢出和测试是否成功。
太乙 2008-10-26
  • 打赏
  • 举报
回复

[code=C/C++]
看lz那么认真,我给写下详细过程吧!!

以下全在vc6.0下测试
----------------------------------------------------------------

首先,得明白一点:

函数在调用的时候,都有什么东西在栈里,顺序是啥?

在栈上:函数首先入栈的,是函数参数(从右到左),然后是函数的return地址,然后是ebp,然后就是局部变量!

如下:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
|local var(局部变量) |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
|函数参数第1个 |
+-------------------------------+
|. |
|. |
|. |
+-------------------------------+
|函数参数第 n-1 个 |
+-------------------------------+
|函数参数 n 个 |
+-------------------------------+高地址


明白这个了,下面进行调试:
-----------------------------------------------------------------------------

先,看我们应该做些什么,我相信,lz应该能明白了,题目也写得很清楚,也就是对getbuf这个函数里定义的char buf[12]做手脚,可以看到
在getxs函数里的while循环,结束条件只是以回车或者是eof结束符为判断标准,所以,根本没对char输入的数量做判断!这样的话,我们可以输入
多于12个的数,从而缓冲区溢出!

其次:按照我上面说的函数栈的存放情况,在getbuf这个函数里,函数参数没有,我们不管,然后就是return返回地址,然后就是ebp指针,然后就是
char buf[12]

如下:

+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+高地址


所以:如果我们对buf溢出,能改写ebp和return地址!


下面看看,ebp是多少,return地址是多少??


----------------------------------------------------------------------------------------


那么我们要返回到哪儿:

看test函数的汇编代码(我只摘录重要的):

44: void test()
45: {
00416300 push ebp

46: int val;
48: val = getbuf();
00416325 call @ILT+20(getbuf) (00401019)
0041632A mov dword ptr [ebp-4],eax
49: printf("getbuf returned 0x%x\n", val);
0041632D mov eax,dword ptr [ebp-4]
00416330 push eax
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
00416336 call printf (00401280)
50: }

看以下两行:
00416300 push ebp

00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)

在函数返回的时候,pop ebp,得恢复断点的ebp,

+--------------------------------------------------+
|所以,我们知道,上面我们填充的ebp应该是这个ebp |
+--------------------------------------------------+


在pringf打印之前,push了eax,还有一个字串。

那么显然,我们不能通过这个eax来push进栈去,因为这样的话,eax怎么改掉呢?所以,在call完getbuf后,应该跳转到
第二句:也就是:
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
+---------------------------------------------------+
|所以,我们的返回地址应该是这里:00416331 |
+---------------------------------------------------+


然后,需要的输出字符咋办??

看堆栈,我刚说了,在printf前,有这个push eax,而我们没有push进去,那么打印什么呢?肯定一点,printf打印的是push进栈的东西

那么假如上面输入不出栈不就得了么?

所以:

+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
| 如果在这里 |
| 写上点儿啥 |
| 的话,不会出栈 |
| 不用push, |
| 从而能打印 |
+-------------------------------+高地址

所以,输入应该不仅要把返回地址覆盖掉,还要继续往下写,写入我们的返回地址!


综上,输入应该是:

前12个任意数+test函数中ebp的指针+return的地址(printf前面push那句)+需要显示的地址!
















[/code]
太乙 2008-10-26
  • 打赏
  • 举报
回复

看lz那么认真,我给写下详细过程吧!!

以下全在vc6.0下测试
----------------------------------------------------------------

首先,得明白一点:

函数在调用的时候,都有什么东西在栈里,顺序是啥?

在栈上:函数首先入栈的,是函数参数(从右到左),然后是函数的return地址,然后是ebp,然后就是局部变量!

如下:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
|local var(局部变量) |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
|函数参数第1个 |
+-------------------------------+
|. |
|. |
|. |
+-------------------------------+
|函数参数第 n-1 个 |
+-------------------------------+
|函数参数 n 个 |
+-------------------------------+高地址


明白这个了,下面进行调试:
-----------------------------------------------------------------------------

先,看我们应该做些什么,我相信,lz应该能明白了,题目也写得很清楚,也就是对getbuf这个函数里定义的char buf[12]做手脚,可以看到
在getxs函数里的while循环,结束条件只是以回车或者是eof结束符为判断标准,所以,根本没对char输入的数量做判断!这样的话,我们可以输入
多于12个的数,从而缓冲区溢出!

其次:按照我上面说的函数栈的存放情况,在getbuf这个函数里,函数参数没有,我们不管,然后就是return返回地址,然后就是ebp指针,然后就是
char buf[12]

如下:

+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+高地址


所以:如果我们对buf溢出,能改写ebp和return地址!


下面看看,ebp是多少,return地址是多少??


----------------------------------------------------------------------------------------


那么我们要返回到哪儿:

看test函数的汇编代码(我只摘录重要的):

44: void test()
45: {
00416300 push ebp

46: int val;
48: val = getbuf();
00416325 call @ILT+20(getbuf) (00401019)
0041632A mov dword ptr [ebp-4],eax
49: printf("getbuf returned 0x%x\n", val);
0041632D mov eax,dword ptr [ebp-4]
00416330 push eax
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
00416336 call printf (00401280)
50: }

看以下两行:
00416300 push ebp

00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)

在函数返回的时候,pop ebp,得恢复断点的ebp,

+--------------------------------------------------+
|所以,我们知道,上面我们填充的ebp应该是这个ebp |
+--------------------------------------------------+


在pringf打印之前,push了eax,还有一个字串。

那么显然,我们不能通过这个eax来push进栈去,因为这样的话,eax怎么改掉呢?所以,在call完getbuf后,应该跳转到
第二句:也就是:
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
+---------------------------------------------------+
|所以,我们的返回地址应该是这里:00416331 |
+---------------------------------------------------+


然后,需要的输出字符咋办??

看堆栈,我刚说了,在printf前,有这个push eax,而我们没有push进去,那么打印什么呢?肯定一点,printf打印的是push进栈的东西

那么假如上面输入不出栈不就得了么?

所以:

+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
| 如果在这里 |
| 写上点儿啥 |
| 的话,不会出栈 |
| 不用push, |
| 从而能打印 |
+-------------------------------+高地址

所以,输入应该不仅要把返回地址覆盖掉,还要继续往下写,写入我们的返回地址!


综上,输入应该是:

前12个任意数+test函数中ebp的指针+return的地址(printf前面push那句)+需要显示的地址!







太乙 2008-10-26
  • 打赏
  • 举报
回复


test函数:

00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)

getbuf函数:

第一句:00401120 push ebp 这个ebp的值!(1240992 = 0x 0012EFA0)


输入:前面十二个数随便,后面接着是:ebp的值:a0 ef 12 00 然后是最上面那句的地址: 31 63 41 00

后面就是题目要求的东西:ef be ad de



cba_v 2008-10-25
  • 打赏
  • 举报
回复
能否解释一下 这个代码不是很明白
#include <iostream>
using namespace std;
void hacking()
{
cout << "hacked" << endl;
exit(0);
}

void foo()
{
int n;
*(&n+2) = (int)hacking;
}
int main()
{
foo();
return 0;
}
dongchenghuozi 2008-10-25
  • 打赏
  • 举报
回复
只要在函数定义里面 ,定义局部变量数组.给他赋值.因为数组没有边界检测 .这样 只要你赋值的数量比数组的SIZE多出8个字节.那么这样 ,在栈中关于RET 返回执行地址的信息就被你覆盖了./


那么函数结束后.就是去执行你赋值决定的那些地址拉!
shuaiwang_01 2008-10-25
  • 打赏
  • 举报
回复
大家请看http://topic.csdn.net/u/20081025/15/14c5ebbc-b0ac-4482-80de-db9956d36f52.html
Big鹏 2008-10-25
  • 打赏
  • 举报
回复

MARK 下!
baihacker 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 shuaiwang_01 的回复:]
Run-time Check Failure #2 - stack around the varibale 'buf' was corrupted
[/Quote]
...编译器有一个Gz选项,貌似要去掉.
shuaiwang_01 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 kiffa 的回复:]
编译器提示什么?
[/Quote]
Run-time Check Failure #2 - stack around the varibale 'buf' was corrupted
shuaiwang_01 2008-10-24
  • 打赏
  • 举报
回复
Run-time Check Failure #2 - stack around the varibale 'buf' was corrupted
kiffa 2008-10-24
  • 打赏
  • 举报
回复
编译器提示什么?
shuaiwang_01 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 baihacker 的回复:]
呵,楼主想改的是eip,而不是ebp.

我的代码修改了eip,指向了不同的函数.
楼主在2005下使用的话,这个改变可能会被发现.
VC6,g++下没有问题的.
[/Quote]
http://blog.csdn.net/Besich/archive/2005/04/27/365626.aspx
我的思路就跟他一样,通过字符串覆盖%ebp(当然不想修改它),想修改的是返回地址,但必须越过%ebp,我同学在gcc环境下也出现不允许,我在vs上也不允许。
baihacker 2008-10-24
  • 打赏
  • 举报
回复
呵,楼主想改的是eip,而不是ebp.

我的代码修改了eip,指向了不同的函数.
楼主在2005下使用的话,这个改变可能会被发现.
VC6,g++下没有问题的.
shuaiwang_01 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 Shatty 的回复:]
你要写操作系统,都修改%ebp了!!!!!!!!!!!!!
你想重写windows????????????????????
你知道%ebp是干吗的吗????
修改它的值代表什么意思吗??????????
不要整天在那里试那些自己都不知道在干什么的代码,试出来了又怎样????、
你就能写出来个缓冲区溢出的病毒不成!!!!!!!
还是把一些基本的东西搞明白,ok??????????
[/Quote]

深入理解计算机系统上的那个缓冲区溢出问题,怎么,难道你比icarnegie大学的老师还牛,比我们老师还牛,他让我做这,是让我们了解函数是如何调用的以及帧栈结构,不要一来就愤青。
zsl6658 2008-10-24
  • 打赏
  • 举报
回复
你要写操作系统,都修改%ebp了!!!!!!!!!!!!!
你想重写windows????????????????????
你知道%ebp是干吗的吗????
修改它的值代表什么意思吗??????????
不要整天在那里试那些自己都不知道在干什么的代码,试出来了又怎样????、
你就能写出来个缓冲区溢出的病毒不成!!!!!!!
还是把一些基本的东西搞明白,ok??????????
baihacker 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 shuaiwang_01 的回复:]
引用 6 楼 baihacker 的回复:
我的那个代码已经示例了.

产生错误了啊!
[/Quote]
你换个编译器.
或者要修改编译选项.
shuaiwang_01 2008-10-24
  • 打赏
  • 举报
回复
深入理解计算机系统上的那个经典缓冲区溢出问题,运行时总是说不能修改%ebp和返回地址的值。
shuaiwang_01 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 baihacker 的回复:]
我的那个代码已经示例了.
[/Quote]
产生错误了啊!
加载更多回复(6)

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧