第一題比較簡單,但本菜雞也做了兩個小時(╯‵□′)╯︵┻━┻。。。
首先開啟事先已經反彙編的 bomb.s 檔案,通過 bomb.c
已經知道每一關都是一個函式,它們的命名都是 phase_x
,x 代表該關卡的數字,如果某個關卡輸入的不正確,就會引爆炸彈 explode_bomb
。首先看 main 函式的這幾行
400e1e: bf 38 23 40 00 mov $0x402338,%edi
400e23: e8 e8 fc ff ff callq 400b10 <puts@plt>
400e28: bf 78 23 40 00 mov $0x402378,%edi
400e2d: e8 de fc ff ff callq 400b10 <puts@plt>
400e32: e8 67 06 00 00 callq 40149e <read_line>
400e37: 48 89 c7 mov %rax,%rdi
400e3a: e8 a1 00 00 00 callq 400ee0 <phase_1>
400e3f: e8 80 07 00 00 callq 4015c4 <phase_defused>
400e44: bf a8 23 40 00 mov $0x4023a8,%edi
開啟 gdb,先給這一行打上斷點 break *0x400e23
,然後 run
起來。這裡可以看到呼叫了 puts
這個函式,暫存器 %edi
儲存的是函式的第一個引數,我們把它的結果列印出來 x/s 0x402338
、x/s 0x402378
,發現得到了執行 bomb 後輸出的字串。說明第一關就是從這裡開始的。
由於返回值是存在 %rax
中的,這裡 mov %rax %rdi
,說明輸入的內容傳參給了 phase_1
。在 gdb 裡給 phase_1 打斷點 break phase_1
。
0000000000400ee0 <phase_1>:
400ee0: 48 83 ec 08 sub $0x8,%rsp
400ee4: be 00 24 40 00 mov $0x402400,%esi
400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>
400eee: 85 c0 test %eax,%eax
400ef0: 74 05 je 400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
400ef7: 48 83 c4 08 add $0x8,%rsp
400efb: c3 retq
通過這裡的程式碼,就可以分析出來,通過呼叫 string_not_equal
比較輸入的字串與 0x402400
儲存的字串是否相等,來決定是不是 explode_bomb
。通過這個函式名也可以知道一定要輸入與 0x402400
相同的字串就可以通過第一關了。所以在這裡打個斷點 break *0x400ee9
,然後 x/s 0x402400
列印出來這裡的字串,我這裡是 Border relations with Canada have never been better.
,然後輸入這個字串,第一關就過了~
string_not_equal
雖然這樣就過關了,但是我還是對這裡的程式碼好奇,畢竟是學習嘛,看看這裡的程式碼熟悉熟悉彙編。
0000000000401338 <strings_not_equal>:
401338: 41 54 push %r12
40133a: 55 push %rbp
40133b: 53 push %rbx
40133c: 48 89 fb mov %rdi,%rbx
40133f: 48 89 f5 mov %rsi,%rbp
401342: e8 d4 ff ff ff callq 40131b <string_length>
401347: 41 89 c4 mov %eax,%r12d
40134a: 48 89 ef mov %rbp,%rdi
40134d: e8 c9 ff ff ff callq 40131b <string_length>
401352: ba 01 00 00 00 mov $0x1,%edx
401357: 41 39 c4 cmp %eax,%r12d
40135a: 75 3f jne 40139b <strings_not_equal+0x63>
40135c: 0f b6 03 movzbl (%rbx),%eax
40135f: 84 c0 test %al,%al
401361: 74 25 je 401388 <strings_not_equal+0x50>
401363: 3a 45 00 cmp 0x0(%rbp),%al
401366: 74 0a je 401372 <strings_not_equal+0x3a>
401368: eb 25 jmp 40138f <strings_not_equal+0x57>
40136a: 3a 45 00 cmp 0x0(%rbp),%al
40136d: 0f 1f 00 nopl (%rax)
401370: 75 24 jne 401396 <strings_not_equal+0x5e>
401372: 48 83 c3 01 add $0x1,%rbx
401376: 48 83 c5 01 add $0x1,%rbp
40137a: 0f b6 03 movzbl (%rbx),%eax
40137d: 84 c0 test %al,%al
40137f: 75 e9 jne 40136a <strings_not_equal+0x32>
401381: ba 00 00 00 00 mov $0x0,%edx
401386: eb 13 jmp 40139b <strings_not_equal+0x63>
401388: ba 00 00 00 00 mov $0x0,%edx
40138d: eb 0c jmp 40139b <strings_not_equal+0x63>
40138f: ba 01 00 00 00 mov $0x1,%edx
401394: eb 05 jmp 40139b <strings_not_equal+0x63>
401396: ba 01 00 00 00 mov $0x1,%edx
40139b: 89 d0 mov %edx,%eax
40139d: 5b pop %rbx
40139e: 5d pop %rbp
40139f: 41 5c pop %r12
4013a1: c3 retq
看程式碼,發現很符合書上講的,%r12
、%rbp
、%rbx
都是被呼叫者儲存的暫存器。
首先 0x401342 ~ 0x40135a,判斷了它們的長度是不是相同,如果長度不相同,那麼它們必然不是同一個字串。mov $0x1,%edx
和 mov %edx,%eax
返回了 1。
0x40135c ~ 0x401361 這幾行,判斷了所輸入的字串的第一個字元是不是