# Bomb lab
###### tags: `ryanpatiency`
[原 CMU 課程網站資料 - IA32 Assembly](http://csapp.cs.cmu.edu/2e/labs.html)
[成大資工 Wiki 資料 - ARM Assembly](http://wiki.csie.ncku.edu.tw/embedded/Lab34)
* 目的
* 複習 ARM 處理器和指令集,並深入 stack 和執行時期的行為
* 熟悉 objdump、gdb 等工具,並利用上述工具分析執行檔
* 環境安裝
* [Download bomb lab (NCKU)](http://wiki.csie.ncku.edu.tw/embedded/Lab34/bomb.tar.gz)
* Download tools:
```
$ sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
$ sudo apt-get install qemu-user qemu-system-arm qemu
```
* [Download Arm gdb](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm)
* 加入 Path
* `$ vim ~/.bashrc`
* 加入 `export PATH=$PATH:(你的資料路徑)/gcc-arm-none-eabi-7-2017-q4-major/bin`
* `$ source ~/.bashrc`
如果以上有多餘或缺少的,請幫我更正,謝謝
## 第1題模擬和練習
* 到 bomb 資料夾
* 請先觀察 bomb.c `$ gedit ./bomb.c`
```clike=
read_line(input);
phase_1(input);
printf("Phase 1 defused.\n");
...
read_line(input);
phase_4(input);
printf("Phase 4 defused.\n");
printf("Congratulations! You've defused the bomb!\n");
```
可以發現 read_line(input) 後,下一個 function 是 phase_1, 這個 function 會檢查你的 input ,如果和預設值不同,就會爆炸
* 實際執行看看
```
$ qemu-arm -L /usr/arm-linux-gnueabihf/ ./bomb
Example phase 0, please type in help
```
這時游標會停在新的一行空白行,意思是叫你輸入密碼。我們隨便輸入看看:
* 測試 abc
```
$ qemu-arm -L /usr/arm-linux-gnueabihf/ ./bomb
Example phase 0, please type in help
abc
Bomb explode!
```
所以現在要做的就是讓炸彈不爆炸,我們輸入正確答案 "help"
```
$ qemu-arm -L /usr/arm-linux-gnueabihf/ ./bomb
Example phase 0, please type in help
help
Phase 0 defused. It's your turn now, cheer up =)
```
但這時游標會停在新的一行空白行,意思是叫你輸入phase 1 的密碼。我們如果亂輸入的話:
```
$ qemu-arm -L /usr/arm-linux-gnueabihf/ ./bomb
Example phase 0, please type in help
help
Phase 0 defused. It's your turn now, cheer up =)
abc
Bomb explode!
```
炸彈又爆炸了
再看看 bomb.c ,我們會發現共有 5 個 phase, 全都過關後,才會輸出:
```clike=
printf("Congratulations! You've defused the bomb!\\n");
```
由於我們不知道 phase_1 到 phase_4 的密碼,我們需要 gdb 的幫助
* 先背景執行程式在 port 1234:
```
$ qemu-arm -g 1234 -L /usr/arm-linux-gnueabihf/ ./bomb
```
* 開啟 gdb: (需要另外開一個終端機)
```
$ arm-none-eabi-gdb ./bomb
```
* 產生 `(gdb) ` 等你輸入指令
* 在 gdb 中,連上 port 1234
```
(gdb) target remote :1234
```
* 成功訊息
```
Remote debugging using :1234
warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB. Attempting to continue with the default arm settings.
0xf67d6a40 in ?? ()
(gdb)
```
現在可以開始學習 gdb 的常用指令了[link](https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf)
看過一遍後,你知道可以使用 gdb 來跑程式,於是你可以在 gdb 輸入
`(gdb) continue`
你會發現 gdb 不再出現 (gdb) 的符號,因為程式會一直執行到結束,回到原本的 terminal, 會發現他和原本的程式行為一樣。你可以隨便輸入,直到爆炸。
爆炸後 gdb 顯示
```
[Inferior 1 (Remote target) exited with code 010]
(gdb)
```
程式結束錯誤,你再重開就好,先再執行程式的終端機輸入
```
$ qemu-arm -g 1234 -L /usr/arm-linux-gnueabihf/ ./bomb
```
然後在 gdb 輸入
```
(gdb) target remote :1234
```
於是你知道用 continue 前,應該用 break
* 在 gdb 輸入
```
(gdb) break phase_0
```
* 再輸入
```
(gdb) continue
```
* 再另外一個 terminal 輸入
```
$ qemu-arm -g 1234 -L /usr/arm-linux-gnueabihf/ ./bomb
Example phase 0, please type in help
abc
```
按下 enter 後,你會發現,雖然我亂輸入 abc, 他還沒有爆炸。因為進入斷點,你成功進去 phase_0 的函式裏面了,為了觀察 assembly:
```
(gdb) disassemble
```
可看到
```
Dump of assembler code for function phase_0:
0x000087d8 <+0>: push {r7, lr}
0x000087da <+2>: sub sp, #16
0x000087dc <+4>: add r7, sp, #0
0x000087de <+6>: str r0, [r7, #4]
0x000087e0 <+8>: movw r3, #35628 ; 0x8b2c
=> 0x000087e4 <+12>: movt r3, #0
0x000087e8 <+16>: str r3, [r7, #12]
0x000087ea <+18>: ldr r0, [r7, #4]
0x000087ec <+20>: ldr r1, [r7, #12]
0x000087ee <+22>: blx 0x84c8 <strcmp@plt>
0x000087f2 <+26>: mov r3, r0
0x000087f4 <+28>: cmp r3, #0
0x000087f6 <+30>: beq.n 0x87fc <phase_0+36>
0x000087f8 <+32>: bl 0x87c0 <explode_bomb>
0x000087fc <+36>: adds r7, #16
0x000087fe <+38>: mov sp, r7
0x00008800 <+40>: pop {r7, pc}
End of assembler dump.
```
這時候你就應該要去學 arm-assembly 了
reference:
* gnu arm assembler: http://www.ic.unicamp.br/~celio/mc404-2014/docs/gnu-arm-directives.pdf
* official document https://www.scss.tcd.ie/~waldroj/3d1/arm_arm.pdf
如果你看懂 assembly 後,你會發現重點是這三行
```
0x000087ea <+18>: ldr r0, [r7, #4]
0x000087ec <+20>: ldr r1, [r7, #12]
0x000087ee <+22>: blx 0x84c8 <strcmp@plt>
```
不斷執行 **(執行 4 次)**
```
(gdb) stepi
```
直到做字串比較前
```
=> 0x000087ee <+22>: blx 0x84c8 <strcmp@plt>
```
輸入
```
(gdb) set $r1 = $r0
```
然後
```
(gdb) continue
```
你應該能成功通過 phase_0 ,雖然你沒有輸入 help
如果你成功到達這一步驟,剩下的主要就是學習 arm assembly 而已,祝你成功拆除炸彈
[解題嘗試](https://hackmd.io/s/r1pQi7JTf)