I try to play the Cybrics CTF yesterday😀…And the truth tell me that how suck i am… Btw…The challenges of Cybrics is very interesting and fresh.

Cybrics_Matreshka_Reverse

CyBRICS is a computer security competition (CTF) organized in a cross-university effort by BRICS countries academia.

The event is organized by CyBRICS coordinating universities: ITMO University (RU), SiChuan University (CN), NIT Warangal (IN), IIT Kharagpur (IN), Wits University (ZA), Tshwane University of Technology (ZA).

The competition is made and run by SPbCTF meetups crew (members of CTF teams LC↯BC, SiBears, PeterPEN, Yozik).

Challenge_Matreshka

Although it is easy for most individuals, i think it’s valuable.

appendix: Code2.class and data2.bin

Step1: Java analysis

You can get the source code from Code2.class by the jd-gui or other tools like it.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.PrintStream;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

class Code2
{
  public static byte[] decode(byte[] paramArrayOfByte, String paramString)
    throws Exception
  {
    SecretKeyFactory localSecretKeyFactory = SecretKeyFactory.getInstance("DES");
    byte[] arrayOfByte1 = paramString.getBytes();
    DESKeySpec localDESKeySpec = new DESKeySpec(arrayOfByte1);
    SecretKey localSecretKey = localSecretKeyFactory.generateSecret(localDESKeySpec);
    Cipher localCipher = Cipher.getInstance("DES");
    localCipher.init(2, localSecretKey);
    byte[] arrayOfByte2 = localCipher.doFinal(paramArrayOfByte);
    return arrayOfByte2;
  }
  public static byte[] encode(byte[] paramArrayOfByte, String paramString) throws Exception {
    SecretKeyFactory localSecretKeyFactory = SecretKeyFactory.getInstance("DES");
    byte[] arrayOfByte1 = paramString.getBytes();
    DESKeySpec localDESKeySpec = new DESKeySpec(arrayOfByte1);
    SecretKey localSecretKey = localSecretKeyFactory.generateSecret(localDESKeySpec);
    Cipher localCipher = Cipher.getInstance("DES");
    localCipher.init(1, localSecretKey);
    byte[] arrayOfByte2 = localCipher.doFinal(paramArrayOfByte);
    return arrayOfByte2;
  }

  public static void main(String[] paramArrayOfString) throws Exception {
    String str = "matreha!";
    byte[] arrayOfByte1 = encode(System.getProperty("user.name").getBytes(), str);
    byte[] arrayOfByte2 = { 76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18 };
    for (int i = 0; i < arrayOfByte2.length; i++) {
      if (arrayOfByte2[i] != arrayOfByte1[i]) {
        System.out.println("No");
        return;
      }
    }
    File localFile = new File("data.bin");
    FileInputStream localFileInputStream = new FileInputStream(localFile);
    byte[] arrayOfByte3 = new byte[(int)localFile.length()];
    localFileInputStream.read(arrayOfByte3);
    localFileInputStream.close();
    byte[] arrayOfByte4 = decode(arrayOfByte3, System.getProperty("user.name"));
    FileOutputStream localFileOutputStream = new FileOutputStream("stage2.bin");
    localFileOutputStream.write(arrayOfByte4, 0, arrayOfByte4.length);
    localFileOutputStream.flush();
    localFileOutputStream.close();
  }
}

Then you can know the data.bin is actually encoded… So how to decode it and get the stage2.bin?

Obviously, the value of “user.name” is the key…Make sure it is the property of challenge environment,not our computer’s “user.name”…

//...Ellipsis
  public static void main(String[] paramArrayOfString) throws Exception {
    String str = "matreha!";
    byte[] arrayOfByte1 = encode(System.getProperty("user.name").getBytes(), str);
    byte[] arrayOfByte2 = { 76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18 };
    String username = new String(decode(arrayOfByte2,"matreha!"));
    File localFile = new File("data.bin");
    FileInputStream localFileInputStream = new FileInputStream(localFile);
    byte[] arrayOfByte3 = new byte[(int)localFile.length()];
    localFileInputStream.read(arrayOfByte3);
    localFileInputStream.close();
    byte[] arrayOfByte4 = decode(arrayOfByte3, username);
    FileOutputStream localFileOutputStream = new FileOutputStream("stage2.bin");
    localFileOutputStream.write(arrayOfByte4, 0, arrayOfByte4.length);
    localFileOutputStream.flush();
    localFileOutputStream.close();
  }
//...

Then compile the program and run it…

Step2: Golang analysis

You have got the stage2.bin from step1.

According to the combination of static analysis and dynamic analysis, we can know the program logic as follows:

It should be noted that when XOR reaches the last byte, the loop produces some differences, and it is easy to ignore the key of the last byte, but this byte can be inferred……

Dynamically debugging:

The R8 stores the key byte that we should get…RSI stores our directory string…There is seventeen key bytes totally…After getting all the key bytes, just xor it with the Built-in ciphertext…

Built-in ciphertext(hex):0x53ddc587e46399144fa4142dc42404c0b0

Key(hex):0x38afaaf48c08f84b22c5605fa1576cabd1

In [58]: from libnum import n2s
In [59]: n2s(0x53ddc587e46399144fa4142dc42404c0b0^0x38afaaf48c08f84b22c5605fa1576cabd1)
Out[59]: 'kroshka_matreshka'

Then i mv the program in a directory named ‘kroshka_matreshka’ and run it…A result.pyc…well😎

Apparently,we arrived here:

Step3:Python analysis

Decompiling result.pyc, then you can see the logic from source code…This is an eight-byte key cycle XOR encryption algorithm.

You have known the flag is begin with cybrics{,so you can directly get the key:Kr0H4137,then you just get flag by decrypting the ciphertext…🆗

>>> from result import *
Enter key to get flag:
Kr0H4137
cybrics{M4TR35HK4_15_B35T}
>>>

Final

It’s a nice and full day!😄