In: Computer Science
I need the six numbers for phase_2 separated by space. This is called Bomblab Project.
Breakpoint 2, 0x0000000000400f49 in phase_2 ()
(gdb) disas
Dump of assembler code for function phase_2:
=> 0x0000000000400f49 <+0>: push %rbp
0x0000000000400f4a <+1>: push %rbx
0x0000000000400f4b <+2>: sub $0x28,%rsp
0x0000000000400f4f <+6>: mov %fs:0x28,%rax
0x0000000000400f58 <+15>: mov %rax,0x18(%rsp)
0x0000000000400f5d <+20>: xor %eax,%eax
0x0000000000400f5f <+22>: mov %rsp,%rsi
0x0000000000400f62 <+25>: callq 0x40173e
<read_six_numbers>
0x0000000000400f67 <+30>: cmpl $0x0,(%rsp)
0x0000000000400f6b <+34>: jns 0x400f72
<phase_2+41>
0x0000000000400f6d <+36>: callq 0x401708
<explode_bomb>
0x0000000000400f72 <+41>: mov %rsp,%rbp
0x0000000000400f75 <+44>: mov $0x1,%ebx
0x0000000000400f7a <+49>: mov %ebx,%eax
0x0000000000400f7c <+51>: add 0x0(%rbp),%eax
0x0000000000400f7f <+54>: cmp %eax,0x4(%rbp)
0x0000000000400f82 <+57>: je 0x400f89
<phase_2+64>
0x0000000000400f84 <+59>: callq 0x401708
<explode_bomb>
0x0000000000400f89 <+64>: add $0x1,%ebx
0x0000000000400f8c <+67>: add $0x4,%rbp
0x0000000000400f90 <+71>: cmp $0x6,%ebx
0x0000000000400f93 <+74>: jne 0x400f7a
<phase_2+49>
0x0000000000400f95 <+76>: mov 0x18(%rsp),%rax
0x0000000000400f9a <+81>: xor %fs:0x28,%rax
0x0000000000400fa3 <+90>: je 0x400faa
<phase_2+97>
0x0000000000400fa5 <+92>: callq 0x400b90
<__stack_chk_fail@plt>
0x0000000000400faa <+97>: add $0x28,%rsp
0x0000000000400fae <+101>: pop %rbx
0x0000000000400faf <+102>: pop %rbp
0x0000000000400fb0 <+103>: retq
End of assembler dump.
Answer:
First let's start by removing extra addresses that only add verbosity.
<+0>: push rbp ; save clobbered registers
<+1>: push rbx
<+2>: sub rsp,0x28 ; 40 bytes of locals
<+6>: mov rax,dword ptr fs:0x28 ; stuff referenced from fs are generally
; thread-local variables of some kind
<+15>: mov qword ptr[rsp+0x18],rax; at offset 0x18 there's a long long local
<+20>: xor eax,eax
<+22>: mov rsi,rsp ; rsi in System V ABI is the first parameter;
; it's passing straight the start of our locals as a
; pointer
<+25>: call <read_six_numbers> ; we can imagine that read_six_numbers takes
; an array of 6 int values, which are probably
; the locals between rsp and rsp+0x18 (0x18 =
; 24 = 6*sizeof(int))
<+30>: cmp dword ptr[rsp],0x1 ; this is the first read value
<+34>: je <phase_2+41> ; --\
<+36>: call <explode_bomb> ; | first bomb explosion
<+41>: mov rbx,rsp ; <-/ rbx points to the first number
<+44>: lea rbp,[rsp+0x14] ; 0x14 = 20 = 5th element of the numbers array
<+49>: mov eax,dword ptr[rbx]
<+51>: add eax,eax
<+53>: cmp dword ptr[rbx+4],eax ; rbx points to an integer, so +4 is
; really the integer that follows it
<+56>: je <phase_2+63>
<+58>: call <explode_bomb> ; second bomb explosion
<+63>: add rbx,0x4 ; again, this is a +1 in C pointer notation
<+67>: cmp rbx,rbp
<+70>: jne <phase_2+49>
<+72>: mov rax,qword ptr[rsp+0x18] ; again that long long
<+77>: xor rax,qword ptr fs:0x28 ; again that thread-local
<+86>: je <phase_2+93>
<+88>: call <__stack_chk_fail@plt> ; aaaah they have to do with stack smashing
; protection; we can ignore them, it's
; compiler-injected stuff
<+93>: add rsp,0x28 ; epilogue
<+97>: pop rbx
<+98>: pop rbp
<+99>: ret
Also, we can reasonably assume that the function takes no
parameters and returns no value, as it doesn't look at the initial
state of rsi
or to addresses above the initial value
of rsp
, and doesn't seem to leave rax
in
a particularly meaningful state.
Now, let's rewrite this in C
int numbers[6];
read_six_numbers(numbers);
if(numbers[0] == 1) goto l_41;
explode_bomb();
l_41:
int *rbx = &numbers[0];
int *rbp = &numbers[5];
l_49:
int eax = *rbx;
eax += eax;
if(eax == rbx[1]) goto l_63;
explode_bomb();
l_63:
rbx++;
if(rbx != rbp) goto l_49;
}
Finally, if that's of any help to understand the algorithm, we can move from pointers to indexes, which is probably closer to how a human would write it:
void phase_2() {
int numbers[6];
read_six_numbers(numbers);
if(numbers[0] != 1) explode_bomb();
for(int i = 0; i!=5; ++i) {
if(numbers[i]*2 != numbers[i+1]) explode_bomb();
}
}
Hence, the secret combination here must be 1, 2, 4, 8, 16, 32, as each number must be twice the previous one, and the first one must be 1.
*******************************************************************************************
# Feel free to ask questions in the comment section
# Hit the like if my answer if it is worth helping to you.
# you can payback and help me with a like.