Skip to content

Commit b949c10

Browse files
committed
feat: update phase 5 note in bomb-lab article
1 parent 4b822da commit b949c10

1 file changed

Lines changed: 152 additions & 0 deletions

File tree

docs/notes/CSAPP/bomb-lab.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,5 +654,157 @@ finish # 執行完當前函數返回上一層
654654
- 如何通過返回值編碼不同的路徑
655655
- 為什麼某些看似合理的輸入會失敗(不在二分搜尋的「自然路徑」上)
656656
657+
## :whale: Phase 5
658+
659+
```bash
660+
(gdb) break phase_5
661+
Breakpoint 1 at 0x401062
662+
(gdb) run solution.txt
663+
Starting program: /home/nvidia/Desktop/bomb/bomb solution.txt
664+
Welcome to my fiendish little bomb. You have 6 phases with
665+
which to blow yourself up. Have a nice day!
666+
Phase 1 defused. How about the next one?
667+
That's number 2. Keep going!
668+
Halfway there!
669+
So you got that one. Try this one.
670+
671+
Breakpoint 1, 0x0000000000401062 in phase_5 ()
672+
(gdb) disassemble
673+
Dump of assembler code for function phase_5:
674+
=> 0x0000000000401062 <+0>: push %rbx
675+
0x0000000000401063 <+1>: sub $0x20,%rsp
676+
0x0000000000401067 <+5>: mov %rdi,%rbx
677+
0x000000000040106a <+8>: mov %fs:0x28,%rax
678+
0x0000000000401073 <+17>: mov %rax,0x18(%rsp)
679+
0x0000000000401078 <+22>: xor %eax,%eax
680+
0x000000000040107a <+24>: callq 0x40131b <string_length>
681+
0x000000000040107f <+29>: cmp $0x6,%eax
682+
0x0000000000401082 <+32>: je 0x4010d2 <phase_5+112>
683+
0x0000000000401084 <+34>: callq 0x40143a <explode_bomb>
684+
0x0000000000401089 <+39>: jmp 0x4010d2 <phase_5+112>
685+
0x000000000040108b <+41>: movzbl (%rbx,%rax,1),%ecx
686+
0x000000000040108f <+45>: mov %cl,(%rsp)
687+
0x0000000000401092 <+48>: mov (%rsp),%rdx
688+
0x0000000000401096 <+52>: and $0xf,%edx
689+
0x0000000000401099 <+55>: movzbl 0x4024b0(%rdx),%edx
690+
0x00000000004010a0 <+62>: mov %dl,0x10(%rsp,%rax,1)
691+
0x00000000004010a4 <+66>: add $0x1,%rax
692+
0x00000000004010a8 <+70>: cmp $0x6,%rax
693+
0x00000000004010ac <+74>: jne 0x40108b <phase_5+41>
694+
0x00000000004010ae <+76>: movb $0x0,0x16(%rsp)
695+
0x00000000004010b3 <+81>: mov $0x40245e,%esi
696+
0x00000000004010b8 <+86>: lea 0x10(%rsp),%rdi
697+
0x00000000004010bd <+91>: callq 0x401338 <strings_not_equal>
698+
0x00000000004010c2 <+96>: test %eax,%eax
699+
0x00000000004010c4 <+98>: je 0x4010d9 <phase_5+119>
700+
0x00000000004010c6 <+100>: callq 0x40143a <explode_bomb>
701+
0x00000000004010cb <+105>: nopl 0x0(%rax,%rax,1)
702+
0x00000000004010d0 <+110>: jmp 0x4010d9 <phase_5+119>
703+
0x00000000004010d2 <+112>: mov $0x0,%eax
704+
0x00000000004010d7 <+117>: jmp 0x40108b <phase_5+41>
705+
0x00000000004010d9 <+119>: mov 0x18(%rsp),%rax
706+
0x00000000004010de <+124>: xor %fs:0x28,%rax
707+
0x00000000004010e7 <+133>: je 0x4010ee <phase_5+140>
708+
0x00000000004010e9 <+135>: callq 0x400b30 <__stack_chk_fail@plt>
709+
0x00000000004010ee <+140>: add $0x20,%rsp
710+
0x00000000004010f2 <+144>: pop %rbx
711+
0x00000000004010f3 <+145>: retq
712+
End of assembler dump.
713+
```
714+
715+
### :crab: 解題邏輯
716+
輸入 6 個字元 → 每個字元取低 4 bits 當索引 → 查表轉換 → 必須變成 "flyers"
717+
718+
### :crab: 關鍵指令解析
719+
720+
**1. 長度檢查 (+24 ~ +34)**
721+
```asm
722+
callq 0x40131b <string_length>
723+
cmp $0x6,%eax
724+
je 0x4010d2 <phase_5+112>
725+
callq 0x40143a <explode_bomb>
726+
```
727+
- 輸入必須是 6 個字元
728+
729+
**2. 初始化 loop counter (+112)**
730+
```asm
731+
mov $0x0,%eax
732+
jmp 0x40108b <phase_5+41>
733+
```
734+
- `%eax` = 0(迴圈計數器)
735+
736+
**3. 核心轉換迴圈 (+41 ~ +74)**
737+
```asm
738+
movzbl (%rbx,%rax,1),%ecx # 讀取輸入字串第 i 個字元
739+
mov %cl,(%rsp) # 暫存到 stack
740+
mov (%rsp),%rdx # 讀回到 %rdx
741+
and $0xf,%edx # 取低 4 bits (0-15)
742+
movzbl 0x4024b0(%rdx),%edx # 查表!key instruction
743+
mov %dl,0x10(%rsp,%rax,1) # 存結果到 stack offset 0x10
744+
add $0x1,%rax # i++
745+
cmp $0x6,%rax # 迴圈 6 次
746+
jne 0x40108b <phase_5+41>
747+
```
748+
749+
**關鍵概念:**
750+
- `and $0xf, %edx`:只保留字元的低 4 bits
751+
- `0x4024b0(%rdx)`:base + index 定址,從查表陣列取字元
752+
- 轉換後的字串存在 `%rsp + 0x10`
753+
754+
**4. 字串比較 (+76 ~ +100)**
755+
```asm
756+
movb $0x0,0x16(%rsp) # 加 null terminator
757+
mov $0x40245e,%esi # "flyers" 字串位址
758+
lea 0x10(%rsp),%rdi # 轉換後的字串
759+
callq 0x401338 <strings_not_equal>
760+
test %eax,%eax
761+
je 0x4010d9 <phase_5+119> # 相等就通過
762+
callq 0x40143a <explode_bomb>
763+
```
764+
765+
### :crab: 解題步驟
766+
767+
**1. 查看查表陣列**
768+
```gdb
769+
(gdb) x/s 0x4024b0
770+
```
771+
找出索引 0-15 對應的字元
772+
773+
**2. 反推輸入**
774+
- 目標:'f', 'l', 'y', 'e', 'r', 's'
775+
- 找出查表陣列中這些字母的索引位置
776+
- 找任意 ASCII 字元,其低 4 bits 等於這些索引
777+
778+
**3. 驗證**
779+
```gdb
780+
(gdb) break *0x4010bd
781+
(gdb) x/s $rdi # 檢查轉換結果
782+
(gdb) x/s 0x40245e # 確認目標是 "flyers"
783+
```
784+
785+
### :crab: 新學到的指令
786+
787+
- **`movzbl src, dst`**:move zero-extend byte to long
788+
- 讀 1 byte,放進 32-bit 暫存器,高位補 0
789+
790+
- **`and $0xf, %reg`**:bit masking
791+
- 取最低 4 bits(範圍 0-15)
792+
793+
- **`addr(%base, %index, scale)`**:陣列定址
794+
- 計算:base + index × scale
795+
- 例:`0x4024b0(%rdx)` = 0x4024b0 + %rdx
796+
797+
### :crab: Stack Canary (+8, +119 ~ +135)
798+
```asm
799+
mov %fs:0x28,%rax # 讀 canary
800+
mov %rax,0x18(%rsp) # 存到 stack
801+
...
802+
xor %fs:0x28,%rax # 檢查是否被改
803+
je 0x4010ee # 沒變就 OK
804+
callq 0x400b30 <__stack_chk_fail@plt>
805+
```
806+
- 防止 buffer overflow 的保護機制
807+
- 解題時可忽略
808+
657809
## :whale: x86-64 assembly cheat sheet
658810
- https://web.stanford.edu/class/cs107/resources/x86-64-reference.pdf

0 commit comments

Comments
 (0)