Phase_5

Previous: Phase_4

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

next: phase_6

Views: 115

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.