這個lab主要考察gdb的使用和對匯編代碼的理解。后者在平時的作業中涉及得較多,這里不再贅述,主要介紹一下gdb
其實偶對這個也不是很熟,有錯誤請指正 @@
簡單的說,gdb是一款強大的調試工具,盡管它只有文本界面(需要圖形界面可以使用ddd,不過區別不大),但是功能卻比eclipse等調試環境強很多。
接下來看看怎樣讓它為lab2拆炸彈服務,在命令行下運行gdb bomb就能開始調試這個炸彈程序,提高警惕,恩
首先最重要的,就是如何阻止炸彈的引爆,gdb自然提供了一般調試工具都包括的斷點功能——break命令
在gdb中輸入help break能夠看到相關的信息
(gdb) help break
Set breakpoint at specified line or function.
Argument may be line number, function name, or "*" and an address.
If line number is specified, break at start of code for that line.
If function is specified, break at start of code for that function.
If an address is specified, break at that exact address.
With no arg, uses current execution address of selected stack frame.
This is useful for breaking on return to a stack frame.
Multiple breakpoints at one place are permitted, and useful if conditional.
Do "help breakpoints" for info on other commands dealing with breakpoints.
可以看到break允許我們使用行號、函數名或地址設置斷點
按ctrl+z暫時掛起當前的gdb進程,運行objdump –d bomb | more 查看反編譯后的炸彈文件,可以看到里面有這么一行(開始的那個地址每個人都不同):
08049719 <explode_bomb>:
這個就是萬惡的引爆炸彈的函數了,運行fg返回gdb環境,在這個函數設置斷點:
break explode_bomb (可以使用tab鍵自動補齊)
顯示
Breakpoint 1 at 0x8049707
接下來你可以喘口氣,一般情況下炸彈是不會引爆的了
下面我們來拆第一個炸彈,首先同樣是設置斷點,bomb.c中給出了各個關卡的函數名,第一關就是phase_1,使用break phase_1在第一關設置斷點
接下來就開始運行吧,輸入run
Welcome to my fiendish little bomb. You hava 6 phases with
which to blow yourself up. Hava a nice day!
我們已經設置了炸彈斷點,這些恐嚇可以直接無視。
輸入ABC繼續(輸入這個是為了方便在后面的測試中找到自己的輸入串地址)
提示Breakpoint 2, 0x08048c2e in phase_1 (),說明現在程序已經停在第一個關了
接下來就是分析匯編代碼,使用disassemble phase_1顯示這個函數的匯編代碼
注意其中關鍵的幾行:
8048c2e:68 b4 99 04 08 push $0x80499b4
8048c33:ff 75 08 pushl 0x8(%ebp)
8048c36:e8 b1 03 00 00 call 8048fec <strings_not_equal>
這個lab很厚道的一點就是函數名很明確地說明了函數的功能 ^_^
估計這三行代碼的意思就是比較兩個字符串相等,不相等的話應該就會讓炸彈爆炸了
因為字符串很大,所以傳遞給這個比較函數的肯定是他們的地址,分別為0x80499b4和0x8(%ebp)
我們先來看后者,使用p/x *(int*)($ebp + 8)查看字符串所在的地址
$1 = 0x804a720,繼續使用p/x *0x804a720查看內存中這個地址的內容
$2 = 0x434241,連續的三個數,是不是想起什么了?把這三個數分別轉換為十進制,就是67 66 65,分別為CBA的ASCII碼,看來這里保存了我們輸入的串。
接下來0x80499b4里肯定保存著過關的密碼
p/x *0x80499b4,顯示$3 = 0x62726556,c中的字符串是以0結尾的,看來這個字符串還不止這個長度,繼續使用
p/x *0x80499b4@10查看這個地址及其后面36個字節的內容,終于在第二行中出現了終結符”0x0”(不一定是四個字節)
$4 = {0x62726556, 0x7469736f, 0x656c2079, 0x20736461, 0x75206f74, 0x656c636e, 0x202c7261, 0x72616e69,
0x75636974, 0x6574616c, 0x69687420, 0x2e73676e, 0x0, 0x21776f57, 0x756f5920, 0x20657627, 0x75666564,
0x20646573, 0x20656874, 0x72636573}
把開頭到0x0的所有信息字節下來,通過手算或者自己寫程序得出最后的密碼串(注意little endian中字符的排列方式!)
輸入run重新運行,輸入剛才得出的密碼串,如果前面的計算正確的話,就會提示
Phase 1 defused. How about the next one?
關于這個lab的一些其他心得:
1. VMware中開發很不舒服,屏幕小、字體丑@@、需要Ctrl+Alt切換回windows,不怎么方便,推薦在windows下使用pietty登錄虛擬機中的linux系統(RedHat 9默認安裝了sshd),個人覺得這樣比較方便。
2. ASCII查詢可以在linux終端中運行man ascii。
3. 退出gdb后,再次進入時一定要注意使用break給explode_bomb上斷點,不可大意 ~.~
4. 后面的幾關涉及遞歸等內容,也有和前面幾次作業很相似的東東。
5. gdb中還有一個很好用的jump指令,可以在運行時任意跳轉。
6. 看匯編代碼時,使用objdump -d bomb > bomb.asm把匯編代碼保存到bomb.asm中,然后使用sftp工具把這個文件下載到windows或者直接在vim中查看,這樣比在gdb中看方便一些。
7. 個人認為lab2和期中考試不沖突,這個lab2可以幫你理清很多匯編語言的概念
其他補充:
sfox:
可以通過GDB中的
x /s addr輸出以\0結尾的字符串
ICSLab:
為了防止每次拆的時候都不停的輸入之前的stage的key,可以把key存入文本文件,一行一個key,不要有多余字符
然后GDB run 的時候用
gdb bomb 回車
(gdb)
b .... ....
(gdb)
r password.txt
這樣bomb就會自動從password.txt中讀入之前的密碼
直到到達最后一個空行處,如Lab2的說明文檔中所述。