This is the writeup for CSAPP bomblab
Tool: IDA/Ghidra, pwndbg
Phase 1 compare input with a string originally inside the program.
Border relations with Canada have never been better.
So input the same string can defuse the bomb
Phase 2 read in 6 numbers in sequence. There is a while loop checking that the number in the back should be twice the one in the front.
1 2 4 8 16 32
Phase 3 read in 2 numbers. The first number used as a variable in a switch statement of total 8 choices. From the disassembler, we can know different value that will be compared with our second number. So find the right case you want to choose and input them as pairs
Phase 4 also read in 2 numbers. The first number should be less than or equal to
0xE = 14. There is a function called
func4 that is a recursive function, the input number should make its return value equal to 0. After some test, input
0 can return
0, so just simply solved it.
Then the program just simply compare the second value with 0. If it is, you will pass the test, otherwise the bomb will explode.
Phase 6 read in string with length 6, encrypt/decrypt it in some way and compare the result of the encryption/decryption with
It take an
AND operation to the input string byte, which result only the half of the byte. Ex.
f = 0x66; 0x66 AND 0x0f = 0x06. The program use the last half byte as the index to get the characters in the array. If the output of those character become
flyers, you defuse the bomb.
The encryption/decryption array:
unsigned char array_3449 =
Phase 6 read in 6 numbers. First, there are two nested loop to make sure every input number is less or equal to 6, and there are no number that next to each other are equal. Ex:
1 3 4 6 9 2 (X) because 9 > 6
Then there is a second loop use 7 minus each input number and store the value in the same position as the original input.
The third loop initialize the “node” for the next loop. There are 6 nodes in total (also 6 input).
The fourth loop set up the pointer for each “node” by the sequence of the input. Similar to an object, the “node” here have 8 byte to store their own value and another 8 byte point to another node.
The last loop examine the “node chain” to make sure it is in decreasing or same order.
After debugging, the pointing direction should be:
node3 -> node4 -> node5 -> node6 -> node1 -> node2
The solution should be (remember, the second loop reverse the inputs if we choose not to have repeated number):
4 3 2 1 6 5
If we take a specific look at the
phase_defused function, we can see that if the
num_input_strings, which counting the number of inputs, equal to 6, another branch will open up.
After dynamic analysis, the new branch in the
phase_defused function redo the
sscanf function on the input of phase 4:
sscanf(PHASE_4_str, "%d %d %s", rdx, rcx, r8);
Then compare the contents of the last string with
DrEvil. If equal, the checks passed, successfully into the secrete phase. But as it said:
But finding it and solving it are quite different...
The secret phase read in string and convert it to long int. The value after convert should less than 1000. Then call the
fun7, another recursive function, with the parameter of
char *a1, input_val.
a1 is an array in the program
.data section, which we are able to access by disassembler. The return value of
fun7 should equal to 2, then we defuse the secret phase.
There are two recursive branches for
fun7. The whole
fun7 looks like this:
// error case
So in order to make the the return value to be 2, we may go in the first branch for first call, go in the second branch for second call, and terminate the recursion for third call.
After examine the array, we can easily find the solution for the secret phase follow the procedure above.