After skimming lecture slides and skimming the textbook, I still felt hazy, so I decided to learn by doing and tackle CMU’s famous "bomb" lab. The goal is simple: supply the correct input strings to six successive phases before the program calls explode_bomb. All phases live in the same ELF-64 executable, so the first step is to dump its disassembly:
$ objdump -d bomb > bomb.asm
Each phase is a function named phase_X. We will walk through them one by one.
Phase 1 – A Plain String Comparison
The disassembly is tiny:
400e98: 48 83 ec 08 sub $0x8,%rsp
400e9c: be 00 24 40 00 mov $0x402400,%esi
400ea1: e8 6a 04 00 00 call 401310 <strings_not_equal>
strings_not_equal returns 0 when the user string equals the one pointed to by %esi. Dump that address:
(gdb) x/s 0x402400
0x402400: "Border relations with Canada have never been better."
Typing that sentence defuses phase 1.
Phase 2 – Six Doubling Integers
The function first calls read_six_numbers which expects six space-separated integers on stdin. A quick scan shows:
400f0a: 83 3c 24 01 cmpl $0x1,(%rsp)
400f0e: 74 20 je 400f30
The first number must be 1. A loop then ensures each subsequent number is twice the previous one:
400f17: 8b 43 fc mov -0x4(%rbx),%eax
400f1a: 01 c0 add %eax,%eax
400f1c: 39 03 cmp %eax,(%rbx)
The only valid sequence is 1 2 4 8 16 32.
Phase 3 – A Switch Statement in Disguise
sscanf is called with the format string "%d %d", so we need two integers. The first integer (let’s call it idx) must satisfy 0 ≤ idx ≤ 7. The code then uses idx to index a jump table:
400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)
Each jump target loads a specific constant into %eax and later compares it to the second integer. Picking idx = 0 lands on:
400f7c: b8 cf 00 00 00 mov $0xcf,%eax
Therefore 0 207 is one valid solution; other choices of idx give alternate answers.
Phase 4 – A Recursive Binary Search
Again we read two integers. The first integer n must be ≤ 14. The core logic is:
401048: e8 81 ff ff ff call 400fce <func4>
40104d: 85 c0 test %eax,%eax
40104f: 75 07 jne 401058 ; explode if != 0
401051: 83 7c 24 0c 00 cmpl $0x0,0xc(%rsp)
So func4(n, 0, 14) must return 0 and the second integer must be 0. func4 is a textbook binary search that returns 0 only when n == 7. Hence the required line is 7 0.
Phase 5 – A Tiny Alphabet Cipher
This phase reads a 6-character string. Each character’s low nibble (lowest 4 bits) is used as an index into a 16-byte array at 0x4024b0:
(gdb) x/16c 0x4024b0
0x4024b0: "maduiersnfotvbyl"
The resulting six characters must equal "flyers". Mapping indices:
f → 9, l → 15, y → 14, e → 5, r → 6, s → 7
Any ASCII characters whose low nibbles are 9 15 14 5 6 7 work, e.g. IONEFG.
Phace 6 – Linked-List Re-ordering
The last phase is longer, but the essence is:
- Read six distinct integers between 1 and 6.
- Use them to re-order a linked list of nodes whose values are
{0x3e9, 0x1f7, 0x2d5, 0x3d7, 0x1bb, 0x1dd}(1001, 503, 725, 983, 443, 477). - The re-ordered list must end up in strictly descending order.
Sorting the values descending gives 1001, 983, 725, 503, 477, 443, wich correspond to original indices 1 4 3 2 6 5. Therefore the correct input is:
1 4 3 2 6 5
With that, the bomb is fully defused.