本系列文章為中國科學技術大學計算機專業學科基礎課《計算機系統》布置的實驗,上課所用教材和内容為黑書CSAPP,當時花費很大精力和彎路,現來總結下各個實驗,本文章為第二個實驗——二進制炸彈(Bomb Lab)。
一、實驗名稱:二進制炸彈
二、實驗學時: 3
三、實驗内容和目的
1.二進制炸彈包含若幹個階段,每個階段需要輸入特定的字元串,所有輸入正确則炸彈被排除,否則…..
任務是找出這些字元串
字元串記錄到檔案中,可按下列方式驗證:
./bomb solution.txt
用換行差別不同階段的字元串
實驗完成後上傳solution.txt的打封包件
2.從教輔系統上下載下傳壓縮包、組隊表格
壓縮包包含48個bomb代碼包
在組隊表格中找到自己的組号
根據“學号%48 + 1”領取自己的代碼
學号191,領取bomb48
解壓後有如下檔案
bomb 二進制可執行檔案,任務目标檔案
bomb.c bomb的源檔案,輔助了解bomb代碼
3.GDB參考
課本3.12(第二版3.11)節,“現實生活:使用GDB調試器”
更詳細一些的資料:
http://heather.cs.ucdavis.edu/~matloff/UnixAndC/CLanguage/Debug.html
官方網站
http://www.gnu.org/software/gdb/
四、實驗原理
檢視bomb.c可知程式利用phase_*函數(*為1~6) 檢查輸入字元串是否合法,不合法就引爆炸彈。我們的任務就是逆向出每個phase的檢查規則,構造出合法字元串。
當然,bomb.c沒有給出phase_*的源碼
逆向方法:gdb,直接反彙編
五、彙編複習
想要完成拆彈任務,不但需要了解不同寄存器的常用方法,也要弄明白具體的操作符是什麼意思:
類型 | 文法 | 例子 | 備注 |
常量 | 符号$開頭 | $-42, $0x15213 | 一定要注意十進制還是十六進制 |
寄存器 | 符号%開頭 | %esi, %rax | 可能存的是值或者位址 |
記憶體位址 | 括号括起來 | (%rbx),0x1c(%rax),0x4(%rcx,%rdi,0x1) | 括号實際上是去尋址的意思 |
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6FEVPVTT65UMNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2gTMyEjM1MTMxEDOwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
一些彙編語句與實際指令的轉換:
指令 | 效果 |
mov %rbx, %rdx | rdx = rbx |
add (%rdx), %r8 | r8 += value at rdx |
mul $3, %r8 | r8 *= 3 |
sub $1, %r8 | r8-- |
lea (%rdx, %rbx, 2), %rdx | rdx = rdx + rbx*2 |
比較與跳轉是拆彈的關鍵,基本所有的字元判斷就是通過比較來實作的,比方說cmp b,a會計算a-b的值,test b, a會計算a&b,注意運算符的順序。例如
cmpl %r9, %r10
jg 8675309
等同于
if %r10 > %r9, jump to 8675309
各種不同的跳轉:
指令 | 效果 | 指令 | 效果 |
jmp | Always jump | ja | Jump if above(unsigned >) |
je/jz | Jump if eq / zero | jae | Jump if above / equal |
jne/jnz | Jump if !eq / !zero | jb | Jump if below(unsigned <) |
jg | Jump if greater | jbe | Jump if below / equal |
jge | Jump if greater / eq | js | Jump if sign bits is 1(neg) |
jl | Jump if less | jns | Jump if sign bit is 0 (pos) |
jle | Jump if less / eq | x | x |
舉幾個例子
cmp $0x15213,
%r12jge deadbeef
若%r12 >= 0x15213,則跳轉到 0xdeadeef
cmp %rax, %rdi
jae 15213b
如果%rdi的無符号值大于等于%rax,則跳轉到0x15213b
test %r8,
%r8jnz (%rsi)
如果%r8 & %r8不為零,那麼跳轉到%rsi存着的位址中。
# 檢查符号表
# 然後可以尋找跟 bomb 有關的内容
objdump -t bomb | less
# 反編譯
# 搜尋 explode_bomb
objdump -d bomb > bomb.txt
# 顯示所有字元
strings bomb | less
GDB 介紹
gdb bomb
# 擷取幫助
help
# 設定斷點
break explode_bomb
break phase_1
# 開始運作
run
# 檢查彙編 會給出對應的代碼的彙編
disas
# 檢視寄存器内容
info registers
# 列印指定寄存器
print $rsp
# 每步執行
stepi
# 檢查寄存器或某個位址
x/4wd $rsp
六、實驗步驟及結果:
1.準備工作
首先反彙編
首先反彙編代碼,objdump –d bomb > bomb.txt,對bomb進行反彙編并将彙編代碼輸出到bomb.txt中。
bomb.txt檔案已經生成,為後面的分析做準備
開始GDB調試break進入調試視窗
2. Phase1
調試函數1
設定斷點break phase_1
接着運作run,就會在斷點處停下,這裡會先讓我們輸入第一關的密碼,随便輸入一個抵達斷點再說。
我們現在到斷點了,可以利用 disas 來看看對應的彙編代碼,其實就和我們之前反彙編出來的一緻。
08048b80 <phase_1>:
0x08048b80 <+0>: push %ebp
0x08048b81 <+1>: mov %esp,%ebp
0x08048b83 <+3>: sub $0x8,%esp
=> 0x08048b86 <+6>: movl $0x80499d8,0x4(%esp)
0x08048b8e <+14>: mov 0x8(%ebp),%eax
0x08048b91 <+17>: mov %eax,(%esp)
0x08048b94 <+20>: call 0x8049113 <strings_not_equal>
0x08048b99 <+25>: test %eax,%eax
0x08048b9b <+27>: je 0x8048ba2 <phase_1+34>
0x08048b9d <+29>: call 0x80496da <explode_bomb>
0x08048ba2 <+34>: leave
0x08048ba3 <+35>: ret
第一步先壓棧,ebp為棧底指針,esp為棧頂指針
第二步把esp指派給ebp
第三步把0x18指派給esp
第四步把記憶體中位址為$0x80499d8的内容指派給*(esp+4)
第五步輸入的字元*(ebp+8)->eax即為所求,理由如後續。
後續比較兩字元串是否相等,如果相等令eax為0 否則為1。
再往後,如果eax=0 則進入phase2 否則爆炸
最後為第二個炸彈做準備。傳回。
用(gdb) x/s 0x80499d8 檢視位于該位址處的内容,可以看到出現
Why make trillions when we could make... billions?
讀出資料後使用RUN指令測試成功,上面字元串即為所求。
然後輸入 quit 退出 gdb,建立一個文本檔案 touch solution.txt,友善以後輸入答案。
下面的phase步驟都是先打斷點,再分析
3. Phase2
調試函數2
0x8048baa<phase_2>:
0x08048ba4 <+0>: push %ebp
0x08048ba5 <+1>: mov %esp,%ebp
0x08048ba7 <+3>: sub $0x28,%esp
=> 0x08048baa <+6>: movl $0x0,-0x4(%ebp)
0x08048bb1 <+13>: lea -0x20(%ebp),%eax
0x08048bb4 <+16>: mov %eax,0x4(%esp)
0x08048bb8 <+20>: mov 0x8(%ebp),%eax
0x08048bbb <+23>: mov %eax,(%esp)
0x08048bbe <+26>: call 0x8049080 <read_six_numbers>
0x08048bc3 <+31>: movl $0x0,-0x8(%ebp)
0x08048bca <+38>: jmp 0x8048bf3 <phase_2+79>
0x08048bcc <+40>: mov -0x8(%ebp),%eax
0x08048bcf <+43>: mov -0x20(%ebp,%eax,4),%edx
0x08048bd3 <+47>: mov -0x8(%ebp),%eax
0x08048bd6 <+50>: add $0x3,%eax
0x08048bd9 <+53>: mov -0x20(%ebp,%eax,4),%eax
0x08048bdd <+57>: cmp %eax,%edx
0x08048bdf <+59>: je 0x8048be6 <phase_2+66>
0x08048be1 <+61>: call 0x80496da <explode_bomb>
0x08048be6 <+66>: mov -0x8(%ebp),%eax
0x08048be9 <+69>: mov -0x20(%ebp,%eax,4),%eax
0x08048bed <+73>: add %eax,-0x4(%ebp)
0x08048bf0 <+76>: incl -0x8(%ebp)
0x08048bf3 <+79>: cmpl $0x2,-0x8(%ebp)
0x08048bf7 <+83>: jle 0x8048bcc <phase_2+40>
0x08048bf9 <+85>: cmpl $0x0,-0x4(%ebp)
0x08048bfd <+89>: jne 0x8048c04 <phase_2+96>
0x08048bff <+91>: call 0x80496da <explode_bomb>
0x08048c04 <+96>: leave
0x08048c05 <+97>: ret
生成的txt檔案中代碼如上所示。
由這句話0x08048bc3 <+31>: movl $0x0,-0x8(%ebp) 表明-0x8(%ebp)裡的值一開始是0
然後根據0x08048bf3 <+79>: cmpl $0x2,-0x8(%ebp)知道循環三次
再根據以下
0x08048bcc <+40>: mov -0x8(%ebp),%eax
0x08048bcf <+43>: mov -0x20(%ebp,%eax,4),%edx
0x08048bd3 <+47>: mov -0x8(%ebp),%eax
0x08048bd6 <+50>: add $0x3,%eax
0x08048bd9 <+53>: mov -0x20(%ebp,%eax,4),%eax
0x08048bdd <+57>: cmp %eax,%edx
0x08048bdf <+59>: je 0x8048be6 <phase_2+66>
這段可知每隔三個數比較數組元素是否相等,不相等則跳轉炸彈爆炸,故輸入4 5 6 4 5 6即可通過。
4. Phase3
調試函數3
08048c06 <phase_3>:
0x08048c06 <+0>: push %ebp
0x08048c07 <+1>: mov %esp,%ebp
0x08048c09 <+3>: sub $0x38,%esp
0x08048c0c <+6>: movl $0x0,-0x8(%ebp)
0x08048c13 <+13>: lea -0x10(%ebp),%eax
0x08048c16 <+16>: mov %eax,0x10(%esp)
0x08048c1a <+20>: lea -0x11(%ebp),%eax
0x08048c1d <+23>: mov %eax,0xc(%esp)
0x08048c21 <+27>: lea -0xc(%ebp),%eax
0x08048c24 <+30>: mov %eax,0x8(%esp)
0x08048c28 <+34>: movl $0x8049a0b,0x4(%esp)
0x08048c30 <+42>: mov 0x8(%ebp),%eax
=> 0x08048c33 <+45>: mov %eax,(%esp)
0x08048c36 <+48>: call 0x8048868 <[email protected]>
0x08048c3b <+53>: mov %eax,-0x8(%ebp)
0x08048c3e <+56>: cmpl $0x2,-0x8(%ebp)
0x08048c42 <+60>: jg 0x8048c49 <phase_3+67>
0x08048c44 <+62>: call 0x80496da <explode_bomb>
0x08048c49 <+67>: mov -0xc(%ebp),%eax
0x08048c4c <+70>: mov %eax,-0x24(%ebp)
0x08048c4f <+73>: cmpl $0x7,-0x24(%ebp)
0x08048c53 <+77>: ja 0x8048d19 <phase_3+275>
0x08048c59 <+83>: mov -0x24(%ebp),%edx
0x08048c5c <+86>: mov 0x8049a14(,%edx,4),%eax
0x08048c63 <+93>: jmp *%eax
0x08048c65 <+95>: movb $0x79,-0x1(%ebp)
0x08048c69 <+99>: mov -0x10(%ebp),%eax
0x08048c6c <+102>: cmp $0x346,%eax
0x08048c71 <+107>: je 0x8048d22 <phase_3+284>
0x08048c77 <+113>: call 0x80496da <explode_bomb>
0x08048c7c <+118>: jmp 0x8048d22 <phase_3+284>
0x08048c81 <+123>: movb $0x69,-0x1(%ebp)
0x08048c85 <+127>: mov -0x10(%ebp),%eax
0x08048c88 <+130>: cmp $0x36f,%eax
0x08048c8d <+135>: je 0x8048d22 <phase_3+284>
0x08048c93 <+141>: call 0x80496da <explode_bomb>
0x08048c98 <+146>: jmp 0x8048d22 <phase_3+284>
0x08048c9d <+151>: movb $0x68,-0x1(%ebp)
0x08048ca1 <+155>: mov -0x10(%ebp),%eax
0x08048ca4 <+158>: cmp $0x274,%eax
0x08048ca9 <+163>: je 0x8048d22 <phase_3+284>
0x08048cab <+165>: call 0x80496da <explode_bomb>
0x08048cb0 <+170>: jmp 0x8048d22 <phase_3+284>
0x08048cb2 <+172>: movb $0x6e,-0x1(%ebp)
0x08048cb6 <+176>: mov -0x10(%ebp),%eax
0x08048cb9 <+179>: cmp $0x46,%eax
0x08048cbc <+182>: je 0x8048d22 <phase_3+284>
0x08048cbe <+184>: call 0x80496da <explode_bomb>
0x08048cc3 <+189>: jmp 0x8048d22 <phase_3+284>
0x08048cc5 <+191>: movb $0x64,-0x1(%ebp)
0x08048cc9 <+195>: mov -0x10(%ebp),%eax
0x08048ccc <+198>: cmp $0x15b,%eax
0x08048cd1 <+203>: je 0x8048d22 <phase_3+284>
0x08048cd3 <+205>: call 0x80496da <explode_bomb>
0x08048cd8 <+210>: jmp 0x8048d22 <phase_3+284>
---Type <return> to continue, or q <return> to quit---
0x08048cda <+212>: movb $0x6b,-0x1(%ebp)
0x08048cde <+216>: mov -0x10(%ebp),%eax
0x08048ce1 <+219>: cmp $0x35c,%eax
0x08048ce6 <+224>: je 0x8048d22 <phase_3+284>
0x08048ce8 <+226>: call 0x80496da <explode_bomb>
0x08048ced <+231>: jmp 0x8048d22 <phase_3+284>
0x08048cef <+233>: movb $0x65,-0x1(%ebp)
0x08048cf3 <+237>: mov -0x10(%ebp),%eax
0x08048cf6 <+240>: cmp $0x29c,%eax
0x08048cfb <+245>: je 0x8048d22 <phase_3+284>
0x08048cfd <+247>: call 0x80496da <explode_bomb>
0x08048d02 <+252>: jmp 0x8048d22 <phase_3+284>
0x08048d04 <+254>: movb $0x63,-0x1(%ebp)
0x08048d08 <+258>: mov -0x10(%ebp),%eax
0x08048d0b <+261>: cmp $0xeb,%eax
0x08048d10 <+266>: je 0x8048d22 <phase_3+284>
0x08048d12 <+268>: call 0x80496da <explode_bomb>
0x08048d17 <+273>: jmp 0x8048d22 <phase_3+284>
0x08048d19 <+275>: movb $0x63,-0x1(%ebp)
0x08048d1d <+279>: call 0x80496da <explode_bomb>
0x08048d22 <+284>: movzbl -0x11(%ebp),%eax
0x08048d26 <+288>: cmp %al,-0x1(%ebp)
0x08048d29 <+291>: je 0x8048d30 <phase_3+298>
0x08048d2b <+293>: call 0x80496da <explode_bomb>
0x08048d30 <+298>: leave
0x08048d31 <+299>: ret
總體彙編代碼如上所示,具體分析如下:
本題代碼整體太長,一點一點解讀既費時間,又可能找不到頭緒。所幸我們找到了裡面一直出現的cmp je語句,這提示我們一個重要資訊,即附近有個switch循環,仔細尋找後如下
0x08048c13 <+13>: lea -0x10(%ebp),%eax
0x08048c16 <+16>: mov %eax,0x10(%esp)
0x08048c1a <+20>: lea -0x11(%ebp),%eax
0x08048c1d <+23>: mov %eax,0xc(%esp)
0x08048c21 <+27>: lea -0xc(%ebp),%eax
0x08048c24 <+30>: mov %eax,0x8(%esp)
0x08048c28 <+34>: movl $0x8049a0b,0x4(%esp)
分析上面幾個lea和mov語句可知,該操作擷取了三個參數,
x/sb 0x8049a0b,得0x8049a0b: "%d %c %d"。依次是int,char,int
再根據如下
0x08048c49 <+67>: mov -0xc(%ebp),%eax
0x08048c4c <+70>: mov %eax,-0x24(%ebp)
0x08048c4f <+73>: cmpl $0x7,-0x24(%ebp)
由上三行可知,比較第一個參數在不在0到7之間,然後後面根據第一個輸入的參數進行跳轉。
如果輸入 0,那麼就直接執行下一條 mov 語句,然後0x08048c6c <+102>: cmp $0x346,%eax是比較第三個參數是否和 0x346 相等,是以我們知道第三個參數是 838(如果第一個參數是 0)的話。如果一切正常,那麼就會跳轉到 +284 的位置,也就是:
0x08048d22 <+284>: movzbl -0x11(%ebp),%eax
0x08048d26 <+288>: cmp %al,-0x1(%ebp)
0x08048d29 <+291>: je 0x8048d30 <phase_3+298>
0x08048d2b <+293>: call 0x80496da <explode_bomb>
0x08048d30 <+298>: leave
0x08048d31 <+299>: ret
我們隻要搞清楚 %al 裡面的值是什麼就好(會和第二個參數進行比較),具體的值,其實就是前面 mov 語句0x08048c65 <+95>: movb $0x79,-0x1(%ebp),讀入的 0x79(121),對應的字元是 y。
是以答案是 0 y 838,當然選擇不同的分支就有不同的答案,其他分支的分析也都是類似的。運作一下,就可以發現這一關又過了。
5. Phase4
調試函數4
08048d72 <phase_4>:
0x08048d72 <+0>: push %ebp
0x08048d73 <+1>: mov %esp,%ebp
0x08048d75 <+3>: sub $0x28,%esp
=> 0x08048d78 <+6>: lea -0xc(%ebp),%eax
0x08048d7b <+9>: mov %eax,0x8(%esp)
0x08048d7f <+13>: movl $0x8049a34,0x4(%esp)
0x08048d87 <+21>: mov 0x8(%ebp),%eax
0x08048d8a <+24>: mov %eax,(%esp)
0x08048d8d <+27>: call 0x8048868 <[email protected]>
0x08048d92 <+32>: mov %eax,-0x4(%ebp)
0x08048d95 <+35>: cmpl $0x1,-0x4(%ebp)
0x08048d99 <+39>: jne 0x8048da2 <phase_4+48>
0x08048d9b <+41>: mov -0xc(%ebp),%eax
0x08048d9e <+44>: test %eax,%eax
0x08048da0 <+46>: jg 0x8048da7 <phase_4+53>
0x08048da2 <+48>: call 0x80496da <explode_bomb>
0x08048da7 <+53>: mov -0xc(%ebp),%eax
0x08048daa <+56>: mov %eax,(%esp)
0x08048dad <+59>: call 0x8048d32 <func4>
0x08048db2 <+64>: mov %eax,-0x8(%ebp)
0x08048db5 <+67>: cmpl $0x262,-0x8(%ebp)
0x08048dbc <+74>: je 0x8048dc3 <phase_4+81>
0x08048dbe <+76>: call 0x80496da <explode_bomb>
0x08048dc3 <+81>: leave
0x08048dc4 <+82>: ret
0x08048d7f <+13>: movl $0x8049a34,0x4(%esp) 可看出此時刻擷取了某個參數,打個斷點看一下x/s 0x8049a34,得0x8049a34: "%d"
說明此刻輸入一個整數
再由
0x08048db5 <+67>: cmpl $0x262,-0x8(%ebp)
0x08048dbc <+74>: je 0x8048dc3 <phase_4+81>
0x08048dbe <+76>: call 0x80496da <explode_bomb>
0x08048dc3 <+81>: leave
得即從斐波那契函數等于0x0x262時是第幾個數,即為輸入,。
F(x) = F(x-1)+F(x-2), F(1)=1,F(2)=1,F(3)=2......F(15)=610即0x262,但是然後看func4裡面有減的,是以要找14。
6. Phase5
調試函數5
08048dc5 <phase_5>:
0x08048dc5 <+0>: push %ebp //壓棧 ebp為棧指針 esp為棧指針
0x08048dc6 <+1>: mov %esp,%ebp //把esp指派給ebp
0x08048dc8 <+3>: sub $0x18,%esp //0x18指派給esp
=> 0x08048dcb <+6>: mov 0x8(%ebp),%eax //*(esp+8)->eax 就是輸入的字元串
0x08048dce <+9>: mov %eax,(%esp) //eax的值指派給*esp
0x08048dd1 <+12>: call 0x80490e9 <string_length>
0x08048dd6 <+17>: mov %eax,-0x4(%ebp)
0x08048dd9 <+20>: cmpl $0x6,-0x4(%ebp)//輸入字元串長6
0x08048ddd <+24>: je 0x8048de4 <phase_5+31>
0x08048ddf <+26>: call 0x80496da <explode_bomb>
0x08048de4 <+31>: movl $0x0,-0x8(%ebp)
0x08048deb <+38>: jmp 0x8048e0d <phase_5+72>
0x08048ded <+40>: mov -0x8(%ebp),%edx
0x08048df0 <+43>: mov -0x8(%ebp),%eax
0x08048df3 <+46>: add 0x8(%ebp),%eax
0x08048df6 <+49>: movzbl (%eax),%eax
0x08048df9 <+52>: movsbl %al,%eax
0x08048dfc <+55>: and $0xf,%eax //取後4位
0x08048dff <+58>: movzbl 0x804a5c0(%eax),%eax
0x08048e06 <+65>: mov %al,-0xf(%ebp,%edx,1)
0x08048e0a <+69>: incl -0x8(%ebp)
0x08048e0d <+72>: cmpl $0x5,-0x8(%ebp)
0x08048e11 <+76>: jle 0x8048ded <phase_5+40>
0x08048e13 <+78>: movb $0x0,-0x9(%ebp)
0x08048e17 <+82>: movl $0x8049a37,0x4(%esp)
0x08048e1f <+90>: lea -0xf(%ebp),%eax
0x08048e22 <+93>: mov %eax,(%esp)
0x08048e25 <+96>: call 0x8049113 <strings_not_equal>
0x08048e2a <+101>: test %eax,%eax
0x08048e2c <+103>: je 0x8048e33 <phase_5+110> //如果eax=0 則進入phase6 否則爆炸
0x08048e2e <+105>: call 0x80496da <explode_bomb>
0x08048e33 <+110>: leave //為結束函數做準備
0x08048e34 <+111>: ret
1.調用string_length測長度3,若不為6則爆炸
8048dd1:e8 13 03 00 00 call 80490e9 <string_length>
8048dd6:89 45 fc mov %eax,-0x4(%ebp)
8048dd9:83 7d fc 06 cmpl $0x6,-0x4(%ebp)//輸入字元串長6
8048ddd:74 05 je 8048de4 <phase_5+0x1f>
8048ddf: e8 f6 08 00 00 call 80496da <explode_bomb>
2.循環6次,取出字元,截取低四位
8048df6: 0f b6 00 movzbl (%eax),%eax
8048df9: 0f be c0 movsbl %al,%eax
8048dfc: 83 e0 0f and $0xf,%eax//取後4位
8048dff: 0f b6 80 c0 a5 04 08 movzbl 0x804a5c0(%eax),%eax
8048e06: 88 44 15 f1 mov %al,-0xf(%ebp,%edx,1)
3.根據輸入字元ASCII碼低四位與索引比較,不同則爆炸。
我們得到的作為參考用,也就是索引表功能的字元串為isrveawhobpnutf,而我們的目的字元串為saints,分别為1位,5位,0位,11位,13位和1位,是以隻要我們輸入的六個字元的相應的低4位的二進制表示為1,5,0,11,13,1 即可。是以這一關我選取的密碼是150km1。
7. Phase6
調試函數6
0x8048e3b <fun6>:
8048e35: 55 push %ebp
8048e36: 89 e5 mov %esp,%ebp
8048e38: 83 ec 10 sub $0x10,%esp # esp-0x10
8048e3b: 8b 45 08 mov 0x8(%ebp),%eax
# eax=arg=local2=0x804a66c
8048e3e: 89 45 f0 mov %eax,-0x10(%ebp) # local4=arg
8048e41: 8b 45 08 mov 0x8(%ebp),%eax
8048e44: 89 45 f0 mov %eax,-0x10(%ebp)
8048e47: 8b 45 08 mov 0x8(%ebp),%eax # eax=arg
# eax=*(arg+8)=*(0x804a66c)
8048e4a: 8b 40 08 mov 0x8(%eax),%eax
# local3=eax=*(0x804a66c)
8048e4d: 89 45 f4 mov %eax,-0xc(%ebp)
# eax=local4=0x804a66c
8048e50: 8b 45 f0 mov -0x10(%ebp),%eax
# *(0x804a66c)=0
8048e53: c7 40 08 00 00 00 00 movl $0x0,0x8(%eax)
8048e5a: eb 62 jmp 8048ebe <fun6+0x89>
#loop
8048e5c: 8b 45 f0 mov -0x10(%ebp),%eax # eax=local4
# local1=local4
8048e5f: 89 45 fc mov %eax,-0x4(%ebp)
8048e62: 8b 45 f0 mov -0x10(%ebp),%eax
# local2=local4
8048e65: 89 45 f8 mov %eax,-0x8(%ebp)
8048e68: eb 0f jmp 8048e79 <fun6+0x44>
8048e6a: 8b 45 fc mov -0x4(%ebp),%eax
8048e6d: 89 45 f8 mov %eax,-0x8(%ebp)
8048e70: 8b 45 fc mov -0x4(%ebp),%eax
8048e73: 8b 40 08 mov 0x8(%eax),%eax
8048e76: 89 45 fc mov %eax,-0x4(%ebp)
8048e79: 83 7d fc 00 cmpl $0x0,-0x4(%ebp)
# if(local1==0)
8048e7d: 74 0e je 8048e8d <fun6+0x58>
8048e7f: 8b 45 fc mov -0x4(%ebp),%eax
8048e82: 8b 10 mov (%eax),%edx
8048e84: 8b 45 f4 mov -0xc(%ebp),%eax
8048e87: 8b 00 mov (%eax),%eax
8048e89: 39 c2 cmp %eax,%edx
8048e8b: 7f dd jg 8048e6a <fun6+0x35>
8048e8d: 8b 45 f8 mov -0x8(%ebp),%eax
8048e90: 3b 45 fc cmp -0x4(%ebp),%eax
8048e93: 74 0b je 8048ea0 <fun6+0x6b>
8048e95: 8b 55 f8 mov -0x8(%ebp),%edx
8048e98: 8b 45 f4 mov -0xc(%ebp),%eax
8048e9b: 89 42 08 mov %eax,0x8(%edx)
8048e9e: eb 06 jmp 8048ea6 <fun6+0x71>
8048ea0: 8b 45 f4 mov -0xc(%ebp),%eax
8048ea3: 89 45 f0 mov %eax,-0x10(%ebp)
8048ea6: 8b 45 f4 mov -0xc(%ebp),%eax
8048ea9: 8b 40 08 mov 0x8(%eax),%eax
8048eac: 89 45 f8 mov %eax,-0x8(%ebp)
8048eaf: 8b 55 f4 mov -0xc(%ebp),%edx
8048eb2: 8b 45 fc mov -0x4(%ebp),%eax
8048eb5: 89 42 08 mov %eax,0x8(%edx)
8048eb8: 8b 45 f8 mov -0x8(%ebp),%eax
8048ebb: 89 45 f4 mov %eax,-0xc(%ebp)
8048ebe: 83 7d f4 00 cmpl $0x0,-0xc(%ebp) #是否為0
#if(local3!=0) jump 39;
8048ec2: 75 98 jne 8048e5c <fun6+0x27>
8048ec4: 8b 45 f0 mov -0x10(%ebp),%eax
8048ec7: c9 leave
8048ec8: c3 ret
0x8048ecf <phase_6>:
0x08048ec9 <+0>: push %ebp
0x08048eca <+1>: mov %esp,%ebp
0x08048ecc <+3>: sub $0x18,%esp
=> 0x08048ecf <+6>: movl $0x804a63c,-0x8(%ebp)
0x08048ed6 <+13>: mov 0x8(%ebp),%eax
0x08048ed9 <+16>: mov %eax,(%esp)
0x08048edc <+19>: call 0x8048858 <[email protected]>
0x08048ee1 <+24>: mov %eax,%edx
0x08048ee3 <+26>: mov -0x8(%ebp),%eax
0x08048ee6 <+29>: mov %edx,(%eax)
0x08048ee8 <+31>: mov -0x8(%ebp),%eax
0x08048eeb <+34>: mov %eax,(%esp)
0x08048eee <+37>: call 0x8048e35 <fun6>
0x08048ef3 <+42>: mov %eax,-0x8(%ebp)
0x08048ef6 <+45>: mov -0x8(%ebp),%eax
0x08048ef9 <+48>: mov %eax,-0x4(%ebp)
0x08048efc <+51>: movl $0x1,-0xc(%ebp)
0x08048f03 <+58>: jmp 0x8048f11 <phase_6+72>
0x08048f05 <+60>: mov -0x4(%ebp),%eax
0x08048f08 <+63>: mov 0x8(%eax),%eax
0x08048f0b <+66>: mov %eax,-0x4(%ebp)
0x08048f0e <+69>: incl -0xc(%ebp)
0x08048f11 <+72>: cmpl $0x7,-0xc(%ebp)
0x08048f15 <+76>: jle 0x8048f05 <phase_6+60>
0x08048f17 <+78>: mov -0x4(%ebp),%eax
0x08048f1a <+81>: mov (%eax),%edx
0x08048f1c <+83>: mov 0x804a63c,%eax
#在這設定一個斷點 break *0x8048f21
0x08048f21 <+88>: cmp %eax,%edx
0x08048f23 <+90>: je 0x8048f2a <phase_6+97>
0x08048f25 <+92>: call 0x80496da <explode_bomb>
0x08048f2a <+97>: leave
0x08048f2b <+98>: ret
看到phase_6的<+88>行是和輸入的數做比較,隻要在這裡設定斷點直接檢視edx中的值即可
0xf8=248,即為答案。
8.實驗總結
是以每個關卡的答案為:
Why make trillions when we could make... billions?
4 5 6 4 5 6
0 y 838
14
150km1
248
一開始接觸這個實驗的時候什麼都不懂或者說是什麼都不敢動。查閱一些料後并學習了一些gdb 的使用方法後,開始着手研究反編譯代碼,并一步一步她開始拆除炸彈。本次實驗後,對湧過gdb 調試工具來調試程式有了一些了解。整個二進制炸彈的程式分别用到了直接她址尋址、循環語句、跳轉、遞歸函數、字元串switch碼轉換和連結清單等知識,涉及内容多覆寫面廣,破解炸彈的過程是一次重要的鞏固和提高的過程。