Bomb Lab

phase_1

We can see the memory with x/s

x/s 0x402400

So the first phase we input is:

Border relations with Canada have never been better.

phase_2

Read_six_numbers function description

In the phase_2, we will input 6 numbers first. The first number will be stored in rdx , second will be stored in rcx,third will be stored r8, the fourth will be stored in r9 ,the fifth will be stored in rsp, the sixth will be stored in rsp+0x8. When the program run to 0x40148f, it will compare the eax with 5, which means whether we have inputed the 6 numbers, if not it will jump to explode_bomb.

phase_2 function description

First of all, the program will check the first number whether is 1 which means the first number we input must be 1 or it will trigger the explode_bomb. After the comparsion, we get into the loop, the process of checking the right number.

The loop asm code description:

add rbx,0x4 # the cur will be the next
cmp rbx,rbp # determine the end of the loop

mov eax, DWORD PTR [rbx-0x4] # the before value moves to eax
add eax, eax # double eax
cmp DWORD PTR [rbx],eax # the next number must be twice previous number

So the answer is

1 2 4 8 16 32

phase_3

When we get into the phase_3, the code of swich function in asm which make me stuck for a while.

The first number must be lower than 7, or it will trigger the explode_bomb. The second number is variable because of the switch statement. The second number will be stored in rsp+0xc, when the program run to 0x400fc2, the eax will compare with your second input.

My answer is:

1 313

phase_4

func_4 description

edx = a
esi = b
eax = a, eax = a - b
ecx = a - b
ecx = ecx >> 31
eax = ecx + eax = (a-b) >> 31 + (a-b)
eax = ((a-b)>>31+(a-b))>>1

We don’t have to know the func_4 code meaning. The argument we can’t control, it always sets as 0xe automatically. Obviously, the function is recursive function. When ecx is bigger than edi, the function will return.

phase_4 descirption

Obviously, the first number will be stored in rsp+0x8, the second one will be stored in rsp+0xc.

If we the first number bigger than 0xe, it will jump to explode_bomb. So we have to choose the one which lower than 0xe.

Whatever the first number we input, it will be changed to 0xe finally and get into the func4 with 0xe

phase_5

To the better understanding, I divided the phase_5 into three parts.

First part, the length of string must be equal to six.

The second part, also is the most difficult and important.

mov rdx, QWORD PTR [rsp] # move the first character of the string to rsp from rdx
and edx,0xf
# get the lower 4 digits.
# For example 1100 1111 -> 1111, 1001 1101 -> 1101
# 1100 1111 & 0000 1111 -> 1111
movzx edx, BYTE PTR[rdx + 0x4024b0]
# 0x4024b0 is the array address, maduiersnfotvbyl
# we should take the index to get the character of string.
# for example
# 1111 -> 15+0x4024b0 -> l
# 1001 -> 9+0x4024b0 -> f
mov BYTE PTR [rsp+rax*1+0x10], dl # store the modified character in new address of stack
add rax, 0x1 # move the cur
cmp rax, 0x6 # the end of the loop

After we get the new string in rsp+0x10, we have to be equal to the value in 0x40245e which means the new stirng have to be equal to “flyers”

gdb-peda$ x/s 0x40245e
0x40245e:       "flyers"

The enumerate available character python script as follows:

flyers

f = 9 = 1001 , l = 15 = 1111, y = 14 = 1110 , e = 5 = 0100, r = 6 = 0101, s = 7 = 0110

# CSAPP Bomb Lab Phase5
# Enumerate available characters
# Author: Kelpie
# Date: 2023-2-27

char_list = [9,15,14,5,6,7]

cur1 = []
cur2 = []
cur3 = []
cur4 = []
cur5 = []
cur6 = []


# what is upper?
# 1 << 4 = 0001 0000
# 2 << 4 = 0010 0000

for i in range(1,8):
    upper = i << 4
    for j in char_list:
        char = upper | j
        str = chr(char)
        # The python switch statement is not available until 3.10 :-(
        if j == 9 :
            cur1.append(str)
        elif j == 15 :
            cur2.append(str)
        elif j == 14 :
            cur3.append(str)
        elif j == 5 :
            cur4.append(str)
        elif j == 6 :
            cur5.append(str)
        elif j == 7 :
            cur6.append(str)

print("cur1: " , cur1)
print("cur2: " , cur2)
print("cur3: " , cur3)
print("cur4: " , cur4)
print("cur5: " , cur5)
print("cur6: " , cur6)
cur1:  [')', '9', 'I', 'Y', 'i', 'y']
cur2:  ['/', '?', 'O', '_', 'o']
cur3:  ['.', '>', 'N', '^', 'n', '~']
cur4:  ['%', '5', 'E', 'U', 'e', 'u']
cur5:  ['&', '6', 'F', 'V', 'f', 'v']
cur6:  ["'", '7', 'G', 'W', 'g', 'w']

phase_6

The most challenging phase is undoubtedly at the end. But when you finish this part, when you review it. I will find this phase is not so difficult.
I sorted out the idea of doing the problem and write the comment in the asm code.
For the better understanding, I divided asm code into 6 part, each part is the different function in this phase.
The most puzzling part is Part 4. When you get what is ecx, 0x6032d0 meaning and know this part is the double loop, you will get clearer understanding.

0x00000000004010f4 <+0>:     push   r14
0x00000000004010f6 <+2>:     push   r13
0x00000000004010f8 <+4>:     push   r12
0x00000000004010fa <+6>:     push   rbp
0x00000000004010fb <+7>:     push   rbx
0x00000000004010fc <+8>:     sub    rsp,0x50
0x0000000000401100 <+12>:    mov    r13,rsp
0x0000000000401103 <+15>:    mov    rsi,rsp
0x0000000000401106 <+18>:    call   0x40145c <read_six_numbers>
0x000000000040110b <+23>:    mov    r14,rsp
0x000000000040110e <+26>:    mov    r12d,0x0
0x0000000000401114 <+32>:    mov    rbp,r13
0x0000000000401117 <+35>:    mov    eax,DWORD PTR [r13+0x0]
0x000000000040111b <+39>:    sub    eax,0x1
0x000000000040111e <+42>:    cmp    eax,0x5
0x0000000000401121 <+45>:    jbe    0x401128 <phase_6+52>
0x0000000000401123 <+47>:    call   0x40143a <explode_bomb>

# if the numbers of input is enough to 6, it will trigger the explode_bomb

------------ ------------ ---------- part 1 ---------- ------------ ------------

0x0000000000401128 <+52>:    add    r12d,0x1
0x000000000040112c <+56>:    cmp    r12d,0x6
0x0000000000401130 <+60>:    je     0x401153 <phase_6+95>
0x0000000000401132 <+62>:    mov    ebx,r12d
0x0000000000401135 <+65>:    movsxd rax,ebx
0x0000000000401138 <+68>:    mov    eax,DWORD PTR [rsp+rax*4]
# We input the number will be stored in RSP
# rsp+rax*4
0x000000000040113b <+71>:    cmp    DWORD PTR [rbp+0x0],eax
0x000000000040113e <+74>:    jne    0x401145 <phase_6+81>
0x0000000000401140 <+76>:    call   0x40143a <explode_bomb>

# check if exist the same number in we input or trigger the bomb

------------ ------------ ---------- part 2 ---------- ------------ ------------

0x0000000000401145 <+81>:    add    ebx,0x1
0x0000000000401148 <+84>:    cmp    ebx,0x5
0x000000000040114b <+87>:    jle    0x401135 <phase_6+65>
0x000000000040114d <+89>:    add    r13,0x4
0x0000000000401151 <+93>:    jmp    0x401114 <phase_6+32>
0x0000000000401153 <+95>:    lea    rsi,[rsp+0x18]
-----------
0x0000000000401158 <+100>:   mov    rax,r14
0x000000000040115b <+103>:   mov    ecx,0x7
0x0000000000401160 <+108>:   mov    edx,ecx
0x0000000000401162 <+110>:   sub    edx,DWORD PTR [rax]
0x0000000000401164 <+112>:   mov    DWORD PTR [rax],edx
0x0000000000401166 <+114>:   add    rax,0x4
0x000000000040116a <+118>:   cmp    rax,rsi
0x000000000040116d <+121>:   jne    0x401160 <phase_6+108>

# each number will be sub by 7
------------ ------------ ---------- part 3 ---------- ------------ ------------

----------------------------------------------------------------------------------------
# double loop in this section
# This section get the index from rsp+rsi*1 and stored the node[index] to rsp+rsi*2+0x20
----------------------------------------------------------------------------------------
0x000000000040116f <+123>:   mov    esi,0x0
0x000000000040116f <+123>:   mov    esi,0x0
0x0000000000401174 <+128>:   jmp    0x401197 <phase_6+163>
0x0000000000401176 <+130>:   mov    rdx,QWORD PTR [rdx+0x8]  # rdx = node.next
0x000000000040117a <+134>:   add    eax,0x1
0x000000000040117d <+137>:   cmp    eax,ecx
0x000000000040117f <+139>:   jne    0x401176 <phase_6+130>
0x0000000000401181 <+141>:   jmp    0x401188 <phase_6+148>
0x0000000000401183 <+143>:   mov    edx,0x6032d0
0x0000000000401188 <+148>:   mov    QWORD PTR [rsp+rsi*2+0x20],rdx
0x000000000040118d <+153>:   add    rsi,0x4
0x0000000000401191 <+157>:   cmp    rsi,0x18
0x0000000000401195 <+161>:   je     0x4011ab <phase_6+183>
0x0000000000401197 <+163>:   mov    ecx,DWORD PTR [rsp+rsi*1]
0x000000000040119a <+166>:   cmp    ecx,0x1
0x000000000040119d <+169>:   jle    0x401183 <phase_6+143>
0x000000000040119f <+171>:   mov    eax,0x1
0x00000000004011a4 <+176>:   mov    edx,0x6032d0
0x00000000004011a9 <+181>:   jmp    0x401176 <phase_6+130>

------------ ------------ ---------- part 4 ---------- ------------ ------------

0x00000000004011ab <+183>:   mov    rbx,QWORD PTR [rsp+0x20]
0x00000000004011b0 <+188>:   lea    rax,[rsp+0x28]
0x00000000004011b5 <+193>:   lea    rsi,[rsp+0x50]
0x00000000004011ba <+198>:   mov    rcx,rbx
0x00000000004011bd <+201>:   mov    rdx,QWORD PTR [rax]
0x00000000004011c0 <+204>:   mov    QWORD PTR [rcx+0x8],rdx
0x00000000004011c4 <+208>:   add    rax,0x8
0x00000000004011c8 <+212>:   cmp    rax,rsi
0x00000000004011cb <+215>:   je     0x4011d2 <phase_6+222>
0x00000000004011cd <+217>:   mov    rcx,rdx
0x00000000004011d0 <+220>:   jmp    0x4011bd <phase_6+201>
# connect the node
------------ ------------ ---------- part 5 ---------- ------------ ------------

0x00000000004011d2 <+222>:   mov    QWORD PTR [rdx+0x8],0x0
0x00000000004011da <+230>:   mov    ebp,0x5
0x00000000004011df <+235>:   mov    rax,QWORD PTR [rbx+0x8]
0x00000000004011e3 <+239>:   mov    eax,DWORD PTR [rax]
0x00000000004011e5 <+241>:   cmp    DWORD PTR [rbx],eax
# compare the node value
0x00000000004011e7 <+243>:   jge    0x4011ee <phase_6+250>
0x00000000004011e9 <+245>:   call   0x40143a <explode_bomb>
0x00000000004011ee <+250>:   mov    rbx,QWORD PTR [rbx+0x8]
0x00000000004011f2 <+254>:   sub    ebp,0x1
0x00000000004011f5 <+257>:   jne    0x4011df <phase_6+235>
0x00000000004011f7 <+259>:   add    rsp,0x50
0x00000000004011fb <+263>:   pop    rbx
0x00000000004011fc <+264>:   pop    rbp
0x00000000004011fd <+265>:   pop    r12
0x00000000004011ff <+267>:   pop    r13
0x0000000000401201 <+269>:   pop    r14
0x0000000000401203 <+271>:   ret
------------ ------------ ---------- part 6 ---------- ------------ ------------

The all modified input by Part 3 will be stored in $rsp.

The 0x6032d0 is the node.

struct node{
	int nodeVal; // 4 bytes
	int Weinput; // 4 bytes
	node* next;  // 8 bytes
}
sizeof(node) = 16 bytes

The answer is:

4 3 2 1 6 5

All phases had been finished :-)