./dr3dd

Securinets-CTF-2019, Matrix of Hell

by on under Reversing
8 minute read

Matrix of Hell, 992 pt

Welcome, fellow code adventurers, to the treacherous Matrix of Hell challenge! Brace yourselves as we navigate through the twisted paths of this binary labyrinth and unlock its secrets. Prepare for a journey filled with humor and code-cracking prowess!

As we confront the mighty binary, it challenges us with a password, a crackme-inspired puzzle. Undeterred, we open it in our trusty IDA to unravel its mysteries. But wait! Let’s give the variables some amusing aliases for our convenience.

Behold the three steps of the main function:

Step 1: The Binary’s Byte Symphony

The binary generates a symphony of bytes using a peculiar process and stores it in the “pass_cmp” variable.


v14 = 0;
  for ( i = 0; i <= 4; ++i )
  {
    for ( j = 0; j <= 4; ++j )
    {
      if ( v14 == 9 )
      {
        v14 = 10;
        --j;
      }
      else
      {
        a2 = (char **)j;
        a3 = (char **)(4 * (j + 6LL * i));
        *(_DWORD *)((char *)pass_cmp + (_QWORD)a3) = v14++ + 65;
      }
    }
  }

Here’s a snippet of the binary’s symphony in Python:


s = ['?']*100
v3=0
v4=0
for i in range(5):
   for j in range(5):
       if v14==9:
           v14=10
           j = j-1
       else:
           a3= (j+6*i)
           s[a3]=chr(v14+65)
       v14 += 1
print(''.join(s))

output--> ABCDE?FGHI??LMNOP?QRSTU?VWXYZ????           <-- pass_cmp 

The symphony echoes: ABCDE?FGHI??LMNOP?QRSTU?VWXYZ???? A cryptic melody indeed!

Step 2: Matrix Manipulations

In this step, the binary checks the length of the input, ensuring it’s 14 characters long. It then compares each byte of the password with a matrix (5x5) using a fascinating dance of loops. Here’s a glimpse of the code in IDA:


printf("PASSWORD:", a2, a3);
  gets(password);
  if ( strlen(password) != 14 || (sub_83A(), !v3) )   <-- check password length
  {
    printf("ACCESS DENIED");
    exit(0);
  }
  v16 = 0;
  for ( k = 0; k < strlen(password); ++k )            <-- iterate password byte by byte
  {
    for ( l = 0; l <= 4; ++l )
    {
      for ( m = 0; m <= 4; ++m )
      {
        if ( pass_cmp[m + 6LL * l] == password[k] )   <-- Compare password byte at k index
                                                          with above output. 
        {
          new_string[v16] = l + 65;                   <-- form new string
          v4 = v16 + 1;
          new_string[v4] = m + 49;                    <-- The length of new string is double
                                                          of password.
          v16 = v4 + 1;
        }
      }
    }
  }
  for ( n = 0; n < strlen(new_string); ++n )
    s2[n] = n % 4 ^ new_string[n];                    <-- doing some xor operation and form new 
                                                          string s2
  if ( strcmp(s1, s2) )                               <-- cmp s2 with s1 and s1 is in data 
                                                          section
  {												                            <-- s1 = 'B0C2A2C6A3A7C5@6B5F0A4G2B5A2'					
    printf("ACCESS DENIED", s2);
    exit(0);
  }

A new string, s2 is formed through a series of XOR operations and compared to another string, s1 But fear not, for we shall overcome this matrix madness!

s1 = "B0C2A2C6A3A7C5@6B5F0A4G2B5A2"                   <-- s1
new_string = ""
for i in range(28):                                                     
   new_string += chr(i%4^ord(s1[i]))
print(f)

output--> 'B1A1A3A5A2C4C4B5B4D3A5E1B4C1'              <-- new_string

Now we have to find out the co-ordinates of matrix (l,m) which is satisfied for this compare if ( pass_cmp[m + 6LL * l] == password[k] )

cord = []
for i in range(0,28,2):
    l,m=0,0
    l = ord(f[i])-ord('A')
    m = ord(f[i+1])-ord('1')
    cord.append((l,m))
print(cord),

output--> [(1, 0), (0, 0), (0, 2), (0, 4), (0, 1), (2, 3), (2, 3), (1, 4), (1, 3), (3, 2), (0, 4), (4, 0), (1, 3), (2, 0)]

We got the (l,m) value at which comparision is satisfied.Now we only have to recover the password.

cord = [(1, 0), (0, 0), (0, 2), (0, 4), (0, 1), (2, 3), (2, 3), (1, 4), (1, 3), (3, 2), (0, 4), (4, 0), (1, 3), (2, 0)]
pass_cmp = 'ABCDE?FGHI??LMNOP?QRSTU?VWXYZ????'
password = ""
for i in range(len(cord)):                    
     password += pass_cmp[cord[i][1]+6*cord[i][0]]

print(password)

output --> 'FACEBOO?ISEVIL'                    <-- one byte is missing '?' we know what it is :)
show password is --> 'FACEBOOKISEVIL'

Step 3: Unleashing the Flag

Once we conquer the second step and recover password the binary generates the flag with a flick of its own magic wand. It unveils the message:

flag : 1337_FD_DDLLLKMO_KUWRRRVL_HAHAHA

Reversing, Securinets-CTF-2019, Matrix of Hell
comments powered by Disqus