ej

ej from wolvctf in English

ej

Firstly, the program outputs
puts("solve my puzzle for a flag ;) (use u, d, l, r) \nwait i forgot to implement the display functionality :/");.I suppose u means up, d is down, l is left and r is right. (If you didn’t find it, that doesn’t matter)
It’s clearly that the program only checks our input after strlen, in the if statement.

1
2
3
4
5
6
7
8
if ( maze((__int64)input, s_len) )
{
puts("correct! :)");
sub_5563294E878E((__int64)input, s_len, v4);
sub_5563294E899C((__int64)v4, (__int64)&byte_5563294EB0C0, 0x21uLL);
puts(&byte_5563294EB0C0);
return 0LL;
}

so all we need to do is to solve maze. Let’s begin !!

maze

At the beginning of puzzle, the function iterates our input line.v2 stands for the bytes we input. From the variable v4 and v5 we can know that the puzzle is a 64*4+8 byte puzzle, which is 6*6*4. That means it’s a 6*6 puzzle.
And the logic is like this. Suppose we have a pointer starting at position 0.(Like a person trapped in the puzzle, the variable name is v7)

1. if `v2` is `u` 

It first check if we are at the first line(v7<=5), and then writes 3 to the position, and decreases pointer v7 by 6(going up a line)

2. if `v2` is `r` 

It first check if we are at the right bound((v7 + 1) % 6==0), and then writes 6 to the position, and adds pointer v7 by 1(going right)

3. if `v2` is `l` </br>

It first check if we are at the left bound((v7 - 1) % 6 == 5), and then writes 4 to the position, and minus pointer v7 by 1(going left)

4. if `v2` is `d`</br>

It first check if we are at the last line(v7 > 29), and then writes 5 to the position, and adds pointer v7 by 6(going down a line)

this procedure, literally, remembers all the choices of the direction changing of the pointer inside the maze at every block. At the last of maze function, there are three confinements we should meet.

1
return !v7 && (unsigned int)circle((__int64)v4) && (unsigned int)trinagle((__int64)v4);

the first !v7 means we should go back to the starting point. And the next 2 functions are some checkings for the former choices you have made.I named them after circle and trinagle

circle

To be explict, the circle function checks ** whether the pointer at some certain position forms the same direction from the former block**. And there is a rule block, which looks like this.

1
2
3
4
5
6
7
    0   1   2   3   4   5
0 ___ ___ ___ ___ ___ ___
1 ___ ___ _1*_ _1_ ___ ___
2 ___ ___ _1_ ___ ___ ___
3 ___ ___ _1_ ___ ___ _1_
4 ___ ___ ___ _1_ _2_ ___
5 _2_ ___ ___ ___ ___ _2_

Let me explain my former words. for ciecle, it means that when we run into the 1 in (2,1)(the one with star) from the left, for example, we did from (1,1) to (2,1), we should only turn left in (2,1), so we have no choice but go to (3,1). All the points with 1 acts the same thing.
(The reason is that in circle, it reverses the direction when meets ‘1’, left to right, down to up, and checks whether the number stored are the same. and to sum up. it did the direction checking)

trinagle

To be explict, the trinagle function checks whether the next block of some certain position acts the same thing like I do for example:

1
2
3
4
5
6
7
    0   1   2   3   4   5
0 ___ ___ ___ ___ ___ ___
1 ___ ___ _1_ _1_ ___ ___
2 ___ ___ _1_ ___ ___ ___
3 ___ ___ _1_ ___ ___ _1_
4 ___ ___ ___ _1_ _2_ ___
5 _2*_ ___ ___ ___ ___ _2_

when we reach(0,5), if we want to turn right to (1,5), this rule checks that when in (1,5), we should turn right again, that means we have to go like this (0,5)--->(1,5)--->(2,5)
What’s more, It alse checks that when we reach blocks with 2, we should go from two blocks with the same direction.For example, if we want to go to (4,4), we can only have the following choices: (2,4)—>(3,4)—>(4,4) and (4,2)—>(4,3)—>(4,4).The code is shown below

1
2
3
4
5
6
7
8
9
10
if ( v2 == 3 || v2 == 5 )
{
if ( (*(_BYTE *)(6 * i + j + 1LL + a1) != 4 || *(_BYTE *)(6 * i + j + 2LL + a1) != 4)
&& (*(_BYTE *)(6 * i + j - 1LL + a1) != 6 || *(_BYTE *)(6 * i + j - 2LL + a1) != 6) )
{
return 0LL;
}
}
else if ( (*(_BYTE *)(6 * (i + 1) + j + a1) != 3 || *(_BYTE *)(6 * (i + 2) + j + a1) != 3)
&& (*(_BYTE *)(6 * (i - 1) + j + a1) != 5 || *(_BYTE *)(6 * (i - 2) + j + a1) != 5) )

And that’s it ! the maze game.

solution

While my solution is shown below. the program gives the output correct but didn’t give the flag :) It may because there are various solutions for that

1
2
3
4
5
6
7
    0   1   2   3   4   5
0 _5_ _4_ _4_ _4_ _4_ _4_
1 _5_ _6_ _6_ _6_ _6_ _3_
2 _5_ _3_ _4_ _4_ _5_ _4_
3 _5_ _6_ _6_ _3_ _5_ _3_
4 _5_ _3_ _4_ _4_ _4_ _3_
5 _6_ _6_ _6_ _6_ _6_ _3_

the string input is dddddrrrrruuulddlllurrullurrrrulllll
The output is

1
2
3
4
5
6
7
➜  ej ./ej       
solve my puzzle for a flag ;) (use u, d, l, r)
wait i forgot to implement the display functionality :/
dddddrrrrruuulddlllurrullurrrrulllll
correct! :)
I[�X𴱍>:G��F�㿛�1Q���
%��

But anyway, the task is fun !!! :p

文章目录
  1. 1. ej
    1. 1.1. maze
      1. 1.1.1. circle
      2. 1.1.2. trinagle
    2. 1.2. solution
|