Phase_5
See the code first.
0000000000401062 <phase_5>: 401062: 53 push %rbx 401063: 48 83 ec 20 sub $0x20,%rsp 401067: 48 89 fb mov %rdi,%rbx 40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 401071: 00 00 401073: 48 89 44 24 18 mov %rax,0x18(%rsp) 401078: 31 c0 xor %eax,%eax 40107a: e8 9c 02 00 00 callq 40131b <string_length> 40107f: 83 f8 06 cmp $0x6,%eax 401082: 74 4e je 4010d2 <phase_5+0x70> 401084: e8 b1 03 00 00 callq 40143a <explode_bomb> 401089: eb 47 jmp 4010d2 <phase_5+0x70> 40108b: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx 40108f: 88 0c 24 mov %cl,(%rsp) 401092: 48 8b 14 24 mov (%rsp),%rdx 401096: 83 e2 0f and $0xf,%edx 401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx 4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1) 4010a4: 48 83 c0 01 add $0x1,%rax 4010a8: 48 83 f8 06 cmp $0x6,%rax 4010ac: 75 dd jne 40108b <phase_5+0x29> 4010ae: c6 44 24 16 00 movb $0x0,0x16(%rsp) 4010b3: be 5e 24 40 00 mov $0x40245e,%esi 4010b8: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi 4010bd: e8 76 02 00 00 callq 401338 <strings_not_equal> 4010c2: 85 c0 test %eax,%eax 4010c4: 74 13 je 4010d9 <phase_5+0x77> 4010c6: e8 6f 03 00 00 callq 40143a <explode_bomb> 4010cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 4010d0: eb 07 jmp 4010d9 <phase_5+0x77> 4010d2: b8 00 00 00 00 mov $0x0,%eax 4010d7: eb b2 jmp 40108b <phase_5+0x29> 4010d9: 48 8b 44 24 18 mov 0x18(%rsp),%rax 4010de: 64 48 33 04 25 28 00 xor %fs:0x28,%rax 4010e5: 00 00 4010e7: 74 05 je 4010ee <phase_5+0x8c> 4010e9: e8 42 fa ff ff callq 400b30 <__stack_chk_fail@plt> 4010ee: 48 83 c4 20 add $0x20,%rsp 4010f2: 5b pop %rbx 4010f3: c3 retq
We find it is related to these three functions: string_length, explode_bomb, and strings_not_equal.
Here is the string length.
000000000040131b <string_length>: 40131b: 80 3f 00 cmpb $0x0,(%rdi) 40131e: 74 12 je 401332 <string_length+0x17> 401320: 48 89 fa mov %rdi,%rdx 401323: 48 83 c2 01 add $0x1,%rdx 401327: 89 d0 mov %edx,%eax 401329: 29 f8 sub %edi,%eax 40132b: 80 3a 00 cmpb $0x0,(%rdx) 40132e: 75 f3 jne 401323 <string_length+0x8> 401330: f3 c3 repz retq 401332: b8 00 00 00 00 mov $0x0,%eax 401337: c3 retq
We rewrite it into C style.
int string_length(char a[])
{//ret eax, di a,dx ptr,
int ret;
if(a[0]==0)
return 0;
loop:
char *ptr=a;
ptr++;
ret=ptr;
ret=ret-(&a[0]);
if (*ptr!=0)
goto loop;
else
return ret;
}
This function calculates how many chars did you enter.
I found WSL is a better tool to access the Linux environment. So I use WSL rather than Ubuntu20.04.


Back to phase_5 function.
We can rewrite phase_5 in C-style.
int phase_5()
{
int rax=0;
rbx=rdi;
while(rax!=6)
{
ecx=*(rax+rbx);// rbx is edi, which is our input.
//The rax is our offset to read each char in the array we input
*(rsp)=cl(ecx lower);
rdx=*(rax+rbx);
edx=edx%16;// "and 16" is equal to mod 16, you can think it in binary form
edx=*(char)(4024b0+rdx);
*(rax+rsp+16)=dl (rdx lower);
rax++;
}
*(rsp+16+6)=0;
esi=0x40245e;
rdi=rsp+16;
test....
explode or return;
}
Maybe you still feel confused. We can list the variable (blocks) and compare them. Then substitute them into logic procedure.
We can find these
1.(rax+rbx)
2.(4024b0+rdx)
3.(rax+rsp+16)
4.(rsp+16+6)
5.rsp+16
Ok, because rax is always used to counting, then it must be the offset to access each member of the array we put in. Move to the second one, the address 4024b0 is quite queer. Rdx keeps changing and 4024b0 is constant. Yes, their combination is like the form of “base+offset”, there may some useful data(mostly a string array) stays in this address. The third one until the fifth one tells us the rsp +16 is an important base also.
It seems like this function reads our input char by char, and does something then wants to generate a new char array.
Then we see these two lines. They are two parameters of <strings_not_equal>. So we can infer rdi is the new array generated, and 0x40245e is the address of an array, too.
esi=0x40245e; rdi=rsp+16;
Then we set breakpoints of explode_bomb and try to print the contents of the address and registers.
Of cause, we try “123456” to fill it.

Then


Aha, our professor is humourous, you can not stop the bomb with ctrl-c really, but you can return to the gdb command line. I think it is a good operation cause it won’t explode the bomb, right?:)
So the program will compare “flyers” with the new array it generates. Do not enter flyers directly!!! What you should do now is to enter “kill” and think of the confusing loop.
I think the most confusing part is why it tries to find the remainder of one char. In fact, we can regard char type as int type but shorter. So you can change your mind, do not take dx as a char anymore, take it as an integer number instead.
After the operation of the remainder of edx, the rdx is the offset of “edx=*(char)(4024b0+rdx);”, the rdx means the rdx(th) character in char array 4024b0. Then write the edx to stack, which will be compared with “flyers”.
Then we find the number of each character in “flyers” from “maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?”. The m is 0, a is 1, d is 3… so on.
In the end, we create a new array [ 9, 15, 14, 5, 6, 7]. We are approaching the answer! Then we need to find the characters of these numbers because we can only type char rather than int.
We write c code to find them. But the result is annoying……
We cannot type them ok?!

But do not worry! The requirements come from remainders of 16, so we can add n times 16 to each number until all of the numbers can represent a char we can type by keyboard.

Then add 16 until they are in the range of 65 to 122.
We can add 64 or 80 or 96. We try 64 this time.

The answer is IONEFG.

Good work!
We finished phase_5!
Next time we will try to solve phase_6.
The key to phase 1: Border relations with Canada have never been better.
The key to phase 2: 1 2 4 8 16 32
The key to phase 3: 0 207
The key to phase 4: 0 0, 1 0, 3 0, 7 0
The key to phase 5: IONEFG , Y_^UVW , ionefg
Views: 115
