csapp bomblab1—6+secret,較為全面,每個人的題不一樣。

wait for u發表於2020-12-20

csapp bomblab1—6+secret,較為全面,每個人的題不一樣。

bomb-1

黑盒子,裡面又一句口令,找到口令即可。
1.反彙編 命令列輸入objdump -d bomp >asm.txt
:>為輸出檔案,也可以寫成myname,txt,無所謂。
2.然後開啟,找到函式<phase_1>
080488a0 <phase_1>:
80488a0: 55 push %ebp
80488a1: 89 e5 mov %esp,%ebp
80488a3: 83 ec 10 sub $0x10,%esp
80488a6: 68 a4 92 04 08 push $0x80492a4
80488ab: ff 75 08 pushl 0x8(%ebp)
80488ae: e8 27 05 00 00 call 8048dda <strings_not_equal>
80488b3: 83 c4 10 add $0x10,%esp
80488b6: 85 c0 test %eax,%eax
80488b8: 74 05 je 80488bf <phase_1+0x1f>
80488ba: e8 1e 06 00 00 call 8048edd <explode_bomb>
80488bf: c9 leave
80488c0: c3 ret
關鍵在於8048b36: 68 44 a2 04 08 push $0x80492a4
把這個壓棧的地址拿出來看看就行,需要用到gdb工具,自行百度安裝。命令依次輸入 1.bomb-test
2. b main
3. r
4.x /s 0x80492a4
我的是這樣的,每個人應該不一樣
返回的字串:
Crikey! I have lost my mojo!就是答案。

bomb-2

找phase_2函式,但是每個人的題目應該是不一樣。
我見過是:斐波拉契數列,加序號增,程式設計師數列
我的是斐波拉契數列:
080488c1 <phase_2>:
80488c1: 55 push %ebp
80488c2: 89 e5 mov %esp,%ebp
80488c4: 56 push %esi
80488c5: 53 push %ebx
80488c6: 83 ec 28 sub $0x28,%esp
80488c9: 65 a1 14 00 00 00 mov %gs:0x14,%eax
80488cf: 89 45 f4 mov %eax,-0xc(%ebp)
80488d2: 31 c0 xor %eax,%eax
80488d4: 8d 45 dc lea -0x24(%ebp),%eax
80488d7: 50 push %eax
80488d8: ff 75 08 pushl 0x8(%ebp)
80488db: e8 25 06 00 00 call 8048f05 <read_six_numbers>
80488e0: 83 c4 10 add $0x10,%esp
80488e3: 83 7d dc 00 cmpl $0x0,-0x24(%ebp)
80488e7: 75 06 jne 80488ef <phase_2+0x2e>
80488e9: 83 7d e0 01 cmpl $0x1,-0x20(%ebp)
80488ed: 74 05 je 80488f4 <phase_2+0x33>
80488ef: e8 e9 05 00 00 call 8048edd <explode_bomb>
80488f4: 8d 5d dc lea -0x24(%ebp),%ebx
80488f7: 8d 75 ec lea -0x14(%ebp),%esi
80488fa: 8b 43 04 mov 0x4(%ebx),%eax
80488fd: 03 03 add (%ebx),%eax
80488ff: 39 43 08 cmp %eax,0x8(%ebx)
8048902: 74 05 je 8048909 <phase_2+0x48>
8048904: e8 d4 05 00 00 call 8048edd <explode_bomb>
8048909: 83 c3 04 add $0x4,%ebx
804890c: 39 f3 cmp %esi,%ebx
804890e: 75 ea jne 80488fa <phase_2+0x39>
8048910: 8b 45 f4 mov -0xc(%ebp),%eax
8048913: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
804891a: 74 05 je 8048921 <phase_2+0x60>
804891c: e8 7f fc ff ff call 80485a0 __stack_chk_fail@plt
8048921: 8d 65 f8 lea -0x8(%ebp),%esp
8048924: 5b pop %ebx
8048925: 5e pop %esi
8048926: 5d pop %ebp
8048927: c3 ret
具體的彙編程式碼不分析了,有時間有需求就慢慢分析一遍。
自行判別是哪種情況:
斐波拉契數列:
0 1 1 2 3 5
加序號增:
0 1 3 6 10 15
程式設計師數列:
1 2 4 8 16 32

bomb-3

總體思路:switch語句,第一個輸入0—7,根據你的第一個輸入,得到後面的結果。
我見過二種,一種輸入是“%d %d”
另一種是“%d %c %d ”
第一種網上資料比較全,很常見,建議先看看那些
我剛好遇到 了第二種,
8048928: 55 push %ebp
8048929: 89 e5 mov %esp,%ebp
804892b: 83 ec 24 sub $0x24,%esp
804892e: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048934: 89 45 f4 mov %eax,-0xc(%ebp)
8048937: 31 c0 xor %eax,%eax
8048939: 8d 45 f0 lea -0x10(%ebp),%eax
804893c: 50 push %eax
804893d: 8d 45 eb lea -0x15(%ebp),%eax
8048940: 50 push %eax
8048941: 8d 45 ec lea -0x14(%ebp),%eax
8048944: 50 push %eax
8048945: 68 c1 92 04 08 push $0x80492c1
804894a: ff 75 08 pushl 0x8(%ebp)
804894d: e8 9e fc ff ff call 80485f0 <__isoc99_sscanf@plt>

在呼叫函式 call 80485f0 <__isoc99_sscanf@plt>
之前有一個壓棧操作 push $0x80492c1
根據這個地址push $0x80492c1
通過命令列檢視到底你的實驗屬於哪種情況:

我的是一個int 一個char 一個int。
看如下重點程式碼:
804895f: 83 7d ec 07 cmpl $0x7,-0x14(%ebp)
8048963: 0f 87 ec 00 00 00 ja 8048a55 <phase_3+0x12d>
8048969: 8b 45 ec mov -0x14(%ebp),%eax
804896c: ff 24 85 e0 92 04 08 jmp *0x80492e0(,%eax,4)
8048973: b8 66 00 00 00 mov $0x66,%eax
8048978: 81 7d f0 c2 00 00 00 cmpl $0xc2,-0x10(%ebp)
804897f: 0f 84 da 00 00 00 je 8048a5f <phase_3+0x137>
8048985: e8 53 05 00 00 call 8048edd <explode_bomb>
804898a: b8 66 00 00 00 mov $0x66,%eax
804898f: e9 cb 00 00 00 jmp 8048a5f <phase_3+0x137>
8048994: b8 63 00 00 00 mov $0x63,%eax
8048999: 83 7d f0 43 cmpl $0x43,-0x10(%ebp)
804899d: 0f 84 bc 00 00 00 je 8048a5f <phase_3+0x137>
80489a3: e8 35 05 00 00 call 8048edd <explode_bomb>

解析:
804895f: 83 7d ec 07 cmpl $0x7,-0x14(%ebp)
8048963: 0f 87 ec 00 00 00 ja 8048a55 <phase_3+0x12d>
;第一個int在大於7,就會bomb。
mov -0x14(%ebp),%eax
;將第一個輸入傳給eax,我輸的是1。
804896c: ff 24 85 e0 92 04 08 jmp *0x80492e0(,%eax,4)
;根據你的選擇給你跳轉到不同位置, *0x80492e0反彙編程式碼裡面沒有這個地址,我猜是在別處引用的巨集?或者由其他程式操作好了的記憶體空間?我第一個數是1,所以到第二個分支。
8048994: b8 63 00 00 00 mov $0x63,%eax
8048999: 83 7d f0 43 cmpl $0x43,-0x10(%ebp)
804899d: 0f 84 bc 00 00 00 je 8048a5f <phase_3+0x137>
80489a3: e8 35 05 00 00 call 8048edd <explode_bomb>
;第一句把0x63給eax
;第二句,比較第三個int型別的數是否為0x43,即67
;第三句,如果是,就跳轉到 0x8048a5f處執行
;第四句,如果第三個數不等於67繼續執行,召喚雷暴(天空龍的召雷彈,沒玩過遊戲王的小夥伴忽略),call 8048edd <explode_bomb>。
所以第一個數是1.第三個就是67,接下來,跳轉到 0x8048a5f處執行:
8048a5f: 3a 45 eb cmp -0x15(%ebp),%al
8048a62: 74 05 je 8048a69 <phase_3+0x141>
8048a64: e8 74 04 00 00 call 8048edd <explode_bomb>
;比較第二個char字元是不是等於eax的第八位,之前賦值了,mov $0x63,%eax(自行往上看看程式碼),那就是看看ASCII是不是ox63,即99,即c
;是c,就跳轉
;不是,召雷彈,bomb
所以答案是 1 c 67;
不唯一,你可以試試第一個數是其他,把程式碼過一遍,

bomb-4

我見過二種情況的程式碼,一種特別簡單出答案,還有一種需要看程式碼,二種情況都是輸入2 個數。
第一種:
主要找到這段程式碼:
8048ce4: e8 6a ff ff ff 8048c53 call func4
8048ce9: 83 c4 10 add $0x10,%esp
8048cec: 3b 45 f0 cmp -0x10(%ebp),%eax
8048cef: 74 05 je 8048cf6 <phase_4+0x58>
;呼叫了函式func4,返回結果存在eax。
;esp棧指標加0x10,忽略
;第三句把函式返回的eax和輸入的第一個數相比,相等就跳轉,意味著成功。
其實你可以,先輸入1 3,然後,執行到這裡設定斷點,
在gdb下,設定斷點的技巧如下,
1.用b +地址/label,設定斷點
2.已經ni +num代表 從當前往走num步
3.stepi,走一步
設定 b 0x 8048cec斷點(上面字型加重處),然後使用
print $eax
檢視eax的值,把第一個數設定為這個值就好。不用看func4。
第二種:
可以慢慢看func4函式,也可以通過上面的方法估算出來,現在看程式碼的要求:
8048b01: 83 7d ec 0e cmpl $0xe,-0x14(%ebp)
8048b05: 76 05 jbe 8048b0c <phase_4+0x39>
這說明,第一個輸入不超過0xe,即14;
8048b0f: 6a 0e push $0xe
8048b11: 6a 00 push $0x0
8048b13: ff 75 ec pushl -0x14(%ebp)
;傳參給func4
8048b16: e8 61 ff ff ff call 8048a7c func4
8048b1b: 83 c4 10 add $0x10,%esp
8048b1e: 83 f8 1b cmp $0x1b,%eax
8048b21: 75 06 jne 8048b29 <phase_4+0x56>
8048b23: 83 7d f0 1b cmpl $0x1b,-0x10(%ebp)
8048b27: 74 05 je 8048b2e <phase_4+0x5b>
8048b29: e8 af 03 00 00 call 8048edd <explode_bomb>
;呼叫func4,返回給eax
;看eax的值是不是0x1b即27,如果不是,召雷
;如果是,再判斷第二個引數是不是等於0x1b,即27
;否則召雷
;讀到這裡,我們知道第一個引數是小於等於14
;第二個引數是27
;這時候,需要去讀func4,看看函式的邏輯,也可以不,就把第一個數從0到14遍歷的試一遍,也可以得到解。
;我的程式碼算出來是 9 27。

bomb-5

主要就是陣列操作。
我見過二種情況,第一種情況網上的參考資料比較多,直接搜bomblab,基本上絕大多數講的都是一個字元尋找的故事。
我遇到的情況是第二種,這裡講一下。

8048b4c: e8 67 02 00 00 call 8048db8 <string_length>
8048b51: 83 c4 10 add $0x10,%esp
8048b54: 83 f8 06 cmp $0x6,%eax
8048b57: 74 05 je 8048b5e <phase_5+0x1d>
8048b59: e8 7f 03 00 00 call 8048edd <explode_bomb>
;上面的程式碼功能簡單自行閱讀,就是輸入六個字串,不允許多也不允許少。
8048b5e: 89 d8 mov %ebx,%eax
8048b60: 83 c3 06 add $0x6,%ebx
;ebx=eax+6,後面迴圈每次eax加一,當ebx==eax時,迴圈結束,遍歷了6個字元。
8048b63: b9 00 00 00 00 mov $0x0,%ecx
;ecx初始化,這是最關鍵的遍歷。
8048b68: 0f b6 10 movzbl (%eax),%edx
8048b6b: 83 e2 0f and $0xf,%edx
;依次取出eax的值,賦給edx,and操作是與操作,edx與0xf,只要字元所對應ASCII碼的二進位制數的後四位,賦給edx,作為後面的偏移量
8048b6e: 03 0c 95 add 0x8049300(,%edx,4),%ecx
8048b75: 83 c0 01 add $0x1,%eax
8048b78: 39 d8 cmp %ebx,%eax
;0x8049300是陣列的第一個數字所在位置,0x8049300(,%edx,4)=0x8049300+edx*4,就是把edx作為偏移量,取出陣列中的值,加到ecx中
;然後,eax加一,遍歷下一個字元
;比較ebx和eax相等與否,相等結束迴圈。
8048b7c: 83 f9 3f cmp $0x3f,%ecx
;最後看ecx的累加和是不是0x3f,即63.
現在我們看看陣列裡面有什麼值吧,先再gdb中用
1.b phase_5
2.run answer(用一個檔案把前面的結果寫在一個名為answer的檔案中)
新建文件,名為answer
answer裡面的編輯
3.在 phase_5處產生了斷點停頓,再輸入
x /64w 0x8049300
如下圖:
執行結果

現在就是找6個字元,他們的二進位制最後四位最為偏移(起始點為2,然後是10,6,1.。。。每個人的程式碼可能不一樣),從陣列中取出6個數,其何為63(每個人的程式碼不一樣,見上面程式碼分析)。

bomb-6

我的程式碼是一個連結串列,然後讓你a[i]=7-a[i],最後降序排列,把排序順序輸出。
8048b8b: 55 push %ebp
8048b8c: 89 e5 mov %esp,%ebp
8048b8e: 56 push %esi
8048b8f: 53 push %ebx
8048b90: 83 ec 48 sub $0x48,%esp
8048b93: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048b99: 89 45 f4 mov %eax,-0xc(%ebp)
8048b9c: 31 c0 xor %eax,%eax
8048b9e: 8d 45 c4 lea -0x3c(%ebp),%eax
8048ba1: 50 push %eax
8048ba2: ff 75 08 pushl 0x8(%ebp)
8048ba5: e8 5b 03 00 00 call 8048f05 <read_six_numbers>
;有了前面5題基礎,很顯然,初始化棧幀,讀六個數
8048baa: 83 c4 10 add $0x10,%esp
8048bad: be 00 00 00 00 mov $0x0,%esi
8048bb2: 8b 44 b5 c4 mov -0x3c(%ebp,%esi,4),%eax
8048bb6: 83 e8 01 sub $0x1,%eax
8048bb9: 83 f8 05 cmp $0x5,%eax
8048bbc: 76 05 jbe 8048bc3 <phase_6+0x38>
8048bbe: e8 1a 03 00 00 call 8048edd <explode_bomb>
8048bc3: 83 c6 01 add $0x1,%esi;esi=0+1
8048bc6: 83 fe 06 cmp $0x6,%esi
8048bc9: 74 1b je 8048be6 <phase_6+0x5b>
8048bcb: 89 f3 mov %esi,%ebx
8048bcd: 8b 44 9d c4 mov -0x3c(%ebp,%ebx,4),%eax
8048bd1: 39 44 b5 c0 cmp %eax,-0x40(%ebp,%esi,4)
8048bd5: 75 05 jne 8048bdc <phase_6+0x51>
8048bd7: e8 01 03 00 00 call 8048edd <explode_bomb>
8048bdc: 83 c3 01 add $0x1,%ebx
8048bdf: 83 fb 05 cmp $0x5,%ebx
8048be2: 7e e9 jle 8048bcd <phase_6+0x42>
8048be4: eb cc jmp 8048bb2 <phase_6+0x27>
;輸入的數進行限制,不許大於6,有二個迴圈巢狀,不許用值相同。

8048be6: 8d 45 c4 lea -0x3c(%ebp),%eax
8048be9: 8d 5d dc lea -0x24(%ebp),%ebx
8048bec: b9 07 00 00 00 mov $0x7,%ecx
8048bf1: 89 ca mov %ecx,%edx
8048bf3: 2b 10 sub (%eax),%edx
8048bf5: 89 10 mov %edx,(%eax)
8048bf7: 83 c0 04 add $0x4,%eax
8048bfa: 39 c3 cmp %eax,%ebx
8048bfc: 75 f3 jne 8048bf1 <phase_6+0x66>
;讓a[i]=7-a[i];
8048bfe: bb 00 00 00 00 mov $0x0,%ebx
8048c03: eb 16 jmp 8048c1b <phase_6+0x90>
8048c05: 8b 52 08 mov 0x8(%edx),%edx
8048c08: 83 c0 01 add $0x1,%eax
8048c0b: 39 c8 cmp %ecx,%eax
8048c0d: 75 f6 jne 8048c05 <phase_6+0x7a>
8048c0f: 89 54 b5 dc mov %edx,-0x24(%ebp,%esi,4)
8048c13: 83 c3 01 add $0x1,%ebx
8048c16: 83 fb 06 cmp $0x6,%ebx
8048c19: 74 17 je 8048c32 <phase_6+0xa7>
8048c1b: 89 de mov %ebx,%esi
8048c1d: 8b 4c 9d c4 mov -0x3c(%ebp,%ebx,4),%ecx
8048c21: b8 01 00 00 00 mov $0x1,%eax
8048c26: ba 34 b1 04 08 mov $0x804b134,%edx
8048c2b: 83 f9 01 cmp $0x1,%ecx
8048c2e: 7f d5 jg 8048c05 <phase_6+0x7a>
8048c30: eb dd jmp 8048c0f <phase_6+0x84>
8048c32: 8b 5d dc mov -0x24(%ebp),%ebx
8048c35: 8d 45 dc lea -0x24(%ebp),%eax
8048c38: 8d 75 f0 lea -0x10(%ebp),%esi
8048c3b: 89 d9 mov %ebx,%ecx
8048c3d: 8b 50 04 mov 0x4(%eax),%edx
8048c40: 89 51 08 mov %edx,0x8(%ecx)
8048c43: 83 c0 04 add $0x4,%eax
8048c46: 89 d1 mov %edx,%ecx
8048c48: 39 c6 cmp %eax,%esi
8048c4a: 75 f1 jne 8048c3d <phase_6+0xb2>
8048c4c: c7 42 08 00 00 00 00 movl $0x0,0x8(%edx)
8048c53: be 05 00 00 00 mov $0x5,%esi
8048c58: 8b 43 08 mov 0x8(%ebx),%eax
8048c5b: 8b 00 mov (%eax),%eax
8048c5d: 39 03 cmp %eax,(%ebx)
8048c5f: 7d 05 jge 8048c66 <phase_6+0xdb>
8048c61: e8 77 02 00 00 call 8048edd <explode_bomb>
8048c66: 8b 5b 08 mov 0x8(%ebx),%ebx
8048c69: 83 ee 01 sub $0x1,%esi
8048c6c: 75 ea jne 8048c58 <phase_6+0xcd>
8048c6e: 8b 45 f4 mov -0xc(%ebp),%eax
8048c71: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048c78: 74 05 je 8048c7f <phase_6+0xf4>
;根據每個序號下的數值,進行倒序排列
那數值是多少?它是事先寫好在程式中的,可以檢視。其地址為:
0x804b134,可以理解它為連結串列的頭指標
我們通過gdb檢視:
連結串列
檢視步驟還是設斷點,run answer,再用x /20dw 0x804b134。

需要我們輸入的就是這個排列的順序:
996 6
934 1
529 2
345 3
211 4
133 5
別忘了,a[i]=7-a[i],所以結果是:
1 6 5 4 3 2

secret

開啟彙編程式,找到函式phase_defused
08049042 <phase_defused>:
8049042: 55 push %ebp
8049043: 89 e5 mov %esp,%ebp
8049045: 83 ec 68 sub $0x68,%esp
8049048: 65 a1 14 00 00 00 mov %gs:0x14,%eax
804904e: 89 45 f4 mov %eax,-0xc(%ebp)
8049051: 31 c0 xor %eax,%eax
8049053: 83 3d ac b7 04 08 06 cmpl $0x6,0x804b7ac
804905a: 75 6f jne 80490cb <phase_defused+0x89>
804905c: 83 ec 0c sub $0xc,%esp
804905f: 8d 45 a4 lea -0x5c(%ebp),%eax
8049062: 50 push %eax
8049063: 8d 45 a0 lea -0x60(%ebp),%eax
8049066: 50 push %eax
8049067: 8d 45 9c lea -0x64(%ebp),%eax
804906a: 50 push %eax
804906b: 68 d3 94 04 08 push $0x80494d3
8049070: 68 b0 b8 04 08 push $0x804b8b0
8049075: e8 76 f5 ff ff call 80485f0 __isoc99_sscanf@plt
804907a: 83 c4 20 add $0x20,%esp
804907d: 83 f8 03 cmp $0x3,%eax
8049080: 75 39 jne 80490bb <phase_defused+0x79>
8049082: 83 ec 08 sub $0x8,%esp
8049085: 68 dc 94 04 08 push $0x80494dc
804908a: 8d 45 a4 lea -0x5c(%ebp),%eax
804908d: 50 push %eax
804908e: e8 47 fd ff ff call 8048dda <strings_not_equal>
8049093: 83 c4 10 add $0x10,%esp
8049096: 85 c0 test %eax,%eax
8049098: 75 21 jne 80490bb <phase_defused+0x79>
804909a: 83 ec 0c sub $0xc,%esp
804909d: 68 a0 93 04 08 push $0x80493a0
80490a2: e8 19 f5 ff ff call 80485c0 puts@plt
80490a7: c7 04 24 c8 93 04 08 movl $0x80493c8,(%esp)
80490ae: e8 0d f5 ff ff call 80485c0 puts@plt
80490b3: e8 20 fc ff ff call 8048cd8 <secret_phase>
80490b8: 83 c4 10 add $0x10,%esp
80490bb: 83 ec 0c sub $0xc,%esp
80490be: 68 00 94 04 08 push $0x8049400
80490c3: e8 f8 f4 ff ff call 80485c0 puts@plt
80490c8: 83 c4 10 add $0x10,%esp
80490cb: 8b 45 f4 mov -0xc(%ebp),%eax
80490ce: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
80490d5: 74 05 je 80490dc <phase_defused+0x9a>
80490d7: e8 c4 f4 ff ff call 80485a0 __stack_chk_fail@plt
80490dc: c9 leave
80490dd: c3 ret
80490de: 66 90 xchg %ax,%ax
;把加粗的字串列印出來 x /s 地址

有第一個可知,在輸入為 %d %d後有一個%s,然而有連續二個int輸入就是第四關,而%s的字串就是密碼。這個密碼是最後一個,我的是hamster。(每個人可能不同)。
因此在回答第四關結果的時候,輸入:9 27 hamster
hmaster為開啟祕密關卡的鑰匙,沒有這個,第六關結束後不會祕密關卡不會爆出。加上這個口令才會觸發祕密關卡,是不是很有趣呢?

祕密關卡,根據上面6個實驗g觀賞彙編的經驗,自己去做吧,不會的話可以求助網際網路,也可以問我。

相關文章