CSAPP: Bomb Lab(1)
阿新 • • 發佈:2019-02-02
實驗需要掌握的相關工具
一.gdb(除錯工具)
主要作用在於設定斷點除錯程式。
常用命令 | 舉例 |
---|---|
disassemble | disassemble phase_1(將函式phase_1反彙編顯示出來) |
print或p | p/s (char*)0x123456 列印記憶體地址中的內容 |
詳細見gdb教程
二. objdump(反編譯工具)
主要是兩個命令:
- objdump -d ./bomb>assemble.txt
反彙編bomb程式,並且輸出到assemble.txt。該命令將整個程式反彙編(與gdb中disassemble可以協助使用) - objdump -t ./bomb
輸出符號表
三. strings
列印程式中出現的所有的字串
實驗過程
實驗準備
實驗虛擬機器為:ubuntu 14.4 64位
運用objdump將程式反彙編到assemble.txt檔案中
main函式的有用的主要反彙編程式碼如下
0000000000400da0 <main>:
400da0: 53 push %rbx
.......
400e32: e8 67 06 00 00 callq 40149e <read_line>
400 e37: 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
400e49: e8 c2 fc ff ff callq 400b10 <puts@plt>
400 e4e: e8 4b 06 00 00 callq 40149e <read_line>
400e53: 48 89 c7 mov %rax,%rdi
400e56: e8 a1 00 00 00 callq 400efc <phase_2>
400e5b: e8 64 07 00 00 callq 4015c4 <phase_defused>
400e60: bf ed 22 40 00 mov $0x4022ed,%edi
400e65: e8 a6 fc ff ff callq 400b10 <puts@plt>
400e6a: e8 2f 06 00 00 callq 40149e <read_line>
400e6f: 48 89 c7 mov %rax,%rdi
400e72: e8 cc 00 00 00 callq 400f43 <phase_3>
400e77: e8 48 07 00 00 callq 4015c4 <phase_defused>
400e7c: bf 0b 23 40 00 mov $0x40230b,%edi
400e81: e8 8a fc ff ff callq 400b10 <puts@plt>
400e86: e8 13 06 00 00 callq 40149e <read_line>
400e8b: 48 89 c7 mov %rax,%rdi
400e8e: e8 79 01 00 00 callq 40100c <phase_4>
400e93: e8 2c 07 00 00 callq 4015c4 <phase_defused>
400e98: bf d8 23 40 00 mov $0x4023d8,%edi
400e9d: e8 6e fc ff ff callq 400b10 <puts@plt>
400ea2: e8 f7 05 00 00 callq 40149e <read_line>
400ea7: 48 89 c7 mov %rax,%rdi
400eaa: e8 b3 01 00 00 callq 401062 <phase_5>
400eaf: e8 10 07 00 00 callq 4015c4 <phase_defused>
400eb4: bf 1a 23 40 00 mov $0x40231a,%edi
400eb9: e8 52 fc ff ff callq 400b10 <puts@plt>
400ebe: e8 db 05 00 00 callq 40149e <read_line>
400ec3: 48 89 c7 mov %rax,%rdi
400ec6: e8 29 02 00 00 callq 4010f4 <phase_6>
400ecb: e8 f4 06 00 00 callq 4015c4 <phase_defused>
400ed0: b8 00 00 00 00 mov $0x0,%eax
Bomb 1
用於驗證輸入的phase_1()函式反彙編程式碼如下:
(gdb) disassemble phase_1 //反編譯phase_1函式
Dump of assembler code for function phase_1:
0x0000000000400ee0 <+0>: sub $0x8,%rsp
0x0000000000400ee4 <+4>: mov $0x402400,%esi
0x0000000000400ee9 <+9>: callq 0x401338 <strings_not_equal>
0x0000000000400eee <+14>: test %eax,%eax
0x0000000000400ef0 <+16>: je 0x400ef7 <phase_1+23>
0x0000000000400ef2 <+18>: callq 0x40143a <explode_bomb>
0x0000000000400ef7 <+23>: add $0x8,%rsp
0x0000000000400efb <+27>: retq
End of assembler dump.
其中我們可以看到mov $0x402400,%esi
,將記憶體地址指向的內容作為strings_not_equal()
的第二引數,而在main()的400e37行
已經將input變數地址放入rdi中作為第一個引數(相關程式碼段見下面程式碼段)。根據strings_not_equal()
函式名可以得到該函式是比較兩個引數所指向的內容是否相等。故我們在gdb中運用print方法獲取
(gdb) break phase_1 //為函式phase_1設定斷點,當進入phase_1時暫停
(gdb) si//單步除錯,且函式則進入函式內部
.........//多次單步除錯
(gdb) si
0x0000000000400ee9 in phase_1 ()
(gdb) info register //程式執行到400ee9之前的程式暫存器內容列表
rax 0x603780 6305664
rbx 0x0 0
rcx 0x3 3
rdx 0x1 1
rsi 0x402400 4203520 //引數2
rdi 0x603780 6305664 //引數1
rbp 0x0 0x0
rsp 0x7fffffffdd20 0x7fffffffdd20
r8 0x7ffff7ff6004 140737354096644
r9 0x0 0
r10 0x7fffffffdab0 140737488345776
r11 0x7ffff7a45110 140737348129040
r12 0x400c90 4197520
r13 0x7fffffffde10 140737488346640
r14 0x0 0
r15 0x0 0
rip 0x400ee9 0x400ee9 <phase_1+9>
eflags 0x202 [ IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) p/s (char*)0x402400 //根據分析列印記憶體地址內容,獲取以下字串
$1 = 0x402400 "Border relations with Canada have never been better."
根據得到的字串測試bomb確實為正確的結果,解除bomb 1。
Bomb 2
(gdb) disassemble phase_2
Dump of assembler code for function phase_2:
0x0000000000400efc <+0>: push %rbp
0x0000000000400efd <+1>: push %rbx
0x0000000000400efe <+2>: sub $0x28,%rsp
0x0000000000400f02 <+6>: mov %rsp,%rsi
0x0000000000400f05 <+9>: callq 0x40145c <read_six_numbers> //讀入,並且判斷是否讀入6個數字
0x0000000000400f0a <+14>: cmpl $0x1,(%rsp) //判斷第一個數字是否為1
0x0000000000400f0e <+18>: je 0x400f30 <phase_2+52> //相等則進入迴圈判斷
0x0000000000400f10 <+20>: callq 0x40143a <explode_bomb>//第一個不是1,則爆炸
0x0000000000400f15 <+25>: jmp 0x400f30 <phase_2+52>
0x0000000000400f17 <+27>: mov -0x4(%rbx),%eax
0x0000000000400f1a <+30>: add %eax,%eax
0x0000000000400f1c <+32>: cmp %eax,(%rbx) //後一個元素是不是前一個的兩倍,因為第一個是1,所以得到後面的元素一定是2、4、8、16、32
0x0000000000400f1e <+34>: je 0x400f25 <phase_2+41>
0x0000000000400f20 <+36>: callq 0x40143a <explode_bomb> //不是兩倍則炸彈爆炸
0x0000000000400f25 <+41>: add $0x4,%rbx
0x0000000000400f29 <+45>: cmp %rbp,%rbx
0x0000000000400f2c <+48>: jne 0x400f17 <phase_2+27>
0x0000000000400f2e <+50>: jmp 0x400f3c <phase_2+64>
0x0000000000400f30 <+52>: lea 0x4(%rsp),%rbx
0x0000000000400f35 <+57>: lea 0x18(%rsp),%rbp
0x0000000000400f3a <+62>: jmp 0x400f17 <phase_2+27>
0x0000000000400f3c <+64>: add $0x28,%rsp
0x0000000000400f40 <+68>: pop %rbx
0x0000000000400f41 <+69>: pop %rbp
0x0000000000400f42 <+70>: retq
End of assembler dump.
根據callq 0x40145c <read_six_numbers>
上下文可以得到這個字串是由6個數字組成,並且在該函式中有函式的401480: mov $0x4025c3,%esi
行程式碼中可以讀取輸入的記憶體地址中儲存的字串格式為“%d %d %d %d %d %d”。緊接著對於phase_2函式的彙編程式碼進行閱讀分析,先關重要程式碼註釋見上面程式碼段,可以推測得到第一個數字一定為1,並且後面的數字是第一個數字的兩倍。綜上所述可以得到拆除該炸彈的字串為“1 2 4 8 16 32”
根據驗證,確認為正確答案