Defusing CMU's Binary Bomb: A Walk-through of All Six Phases

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:

  1. Read six distinct integers between 1 and 6.
  2. 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).
  3. 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.

Tags: binary-bomb reverse-engineering x86-64 objdump gdb

Posted on Fri, 25 Sep 2026 16:23:35 +0000 by XeRoZeN