Bomb Lab Notes
- This lab does not feel especially friendly at the beginning, so I started by getting comfortable with
gdb. - These are just my own notes and solutions. Solving it once by yourself really does deepen your understanding.
- Start with the first phase if you want to see how the process begins.
- Good luck.
Bomb Lab Notes
First, disassemble the bomb binary:
1 | objdump -d bomb > bomb.asm |
Then you can search inside bomb.asm for things like <phase_1>, <phase_2>, and so on.
After that, open the binary with gdb:
1 | gdb bomb |
Phase 1
The first phase is the easiest one to read. The function loads a string address into a register, calls a helper that compares two strings, and explodes if the return value is not zero.
So the most direct way to solve it is to break near the comparison call and inspect the registers:
1 | (gdb) b *0x400ee9 |
Then run the bomb and type anything for the first input:
1 | Welcome to my fiendish little bomb. You have 6 phases with |
Now inspect the string argument:
1 | (gdb) x/s $rsi |
That is the answer to phase 1.
You can also check your own input:
1 | (gdb) x/s $rdi |
Phase 2
This phase calls read_six_numbers, so the first obvious guess is that it expects six integers.
Reading the assembly shows:
- the first number must be
1 - each following number must be double the previous one
So the required sequence is:
1 | 1 2 4 8 16 32 |
And the bomb responds with:
1 | That's number 2. Keep going! |
Phase 3
This phase uses sscanf with a format that reads two integers. The first number is checked to make sure it is at most 7, and then the code jumps through a small jump table. Each case loads a different constant into %eax, and the second input must match that constant.
So the structure is:
1 | index value |
One valid answer is:
1 | 0 207 |
That is enough to pass phase 3.
Phase 4
This phase also reads two integers, and then calls a recursive helper func4.
From the assembly, you can see:
- the first input must be at most
14 - the return value of
func4(first, 0, 14)must be0 - the second input must also be
0
The midpoint logic inside func4 reveals that the only valid first input is 7, so the answer is:
1 | 7 0 |
The bomb replies:
1 | So you got that one. Try this one. |
Phase 5
This one expects a string of length 6.
The core loop takes each input character, keeps only its low four bits with andl $0x0f, and uses that value as an index into a 16-character lookup table:
1 | maduiersnfotvbyl |
The transformed result must become:
1 | flyers |
So what matters is choosing six characters whose low four bits map to:
1 | 9 15 14 5 6 7 |
One working example is:
1 | 9?.567 |
After that, the bomb says:
1 | Good work! On to the next... |
Phase 6
This is the most annoying normal phase.
It starts by reading six integers, then checks:
- each number must be between
1and6 - no two numbers can be the same
After that, it transforms each input x into 7 - x. Then it uses those transformed positions to walk through a linked list stored in memory and rebuild a new list in that order.
The list in memory looks like this:
1 | (gdb) x/24qd 0x6032d0 |
The reordered list must be in descending order by node value:
1 | 924, 691, 477, 443, 332, 168 |
That corresponds to node indices:
1 | 3 4 5 6 1 2 |
But remember that the program internally uses 7 - x, so the actual input must be:
1 | 4 3 2 1 6 5 |
And then you get:
1 | Congratulations! You've defused the bomb! |
- Done.
