Matreshka 50
Description:
Matreshka (Reverse, Easy, 50 pts) Author: Khanov Artur (awengar)
Matreshka hides flag. Open it
https://cybrics.net/files/matreshka.zip
Decompiling java
After unzipping the file we find 2 files one is a .class and an encrypted file. First thing that I did was to decompile the .class file I used this website to do it http://www.decompiler.com1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
class Code2 {
public static byte[] decode(byte[] var0, String var1) throws Exception {
SecretKeyFactory var2 = SecretKeyFactory.getInstance("DES");
byte[] var3 = var1.getBytes();
DESKeySpec var4 = new DESKeySpec(var3);
SecretKey var5 = var2.generateSecret(var4);
Cipher var6 = Cipher.getInstance("DES");
var6.init(2, var5);
byte[] var7 = var6.doFinal(var0);
return var7;
}
public static byte[] encode(byte[] var0, String var1) throws Exception {
SecretKeyFactory var2 = SecretKeyFactory.getInstance("DES");
byte[] var3 = var1.getBytes();
DESKeySpec var4 = new DESKeySpec(var3);
SecretKey var5 = var2.generateSecret(var4);
Cipher var6 = Cipher.getInstance("DES");
var6.init(1, var5);
byte[] var7 = var6.doFinal(var0);
return var7;
}
public static void main(String[] var0) throws Exception {
String var1 = "matreha!";
byte[] var2 = encode(System.getProperty("user.name").getBytes(), var1);
byte[] var3 = new byte[]{76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18};
for(int var4 = 0; var4 < var3.length; ++var4) {
if (var3[var4] != var2[var4]) {
System.out.println("No");
return;
}
}
File var9 = new File("data.bin");
FileInputStream var5 = new FileInputStream(var9);
byte[] var6 = new byte[(int)var9.length()];
var5.read(var6);
var5.close();
byte[] var7 = decode(var6, System.getProperty("user.name"));
FileOutputStream var8 = new FileOutputStream("stage2.bin");
var8.write(var7, 0, var7.length);
var8.flush();
var8.close();
}
}
Interpreting the java file
Now that we have some java code I started to analyse the decode and encode functions and we can easily see that the algorithm used for the encryption was DES, the encode function encrypts an array of bytes with a key string, the decode function obviously does the opposite.
1 | public static byte[] encode(byte[] var0, String var1) throws Exception { |
By looking at the main function we can see the key used to encrypt the file was an username from the machine of the creator of the challenge, we don’t know this username but we do know the result of the encryption of this username and the key used:
1 | String var1 = "matreha!"; |
We can easily reverse this since we have the key matreha! we can just use the decode function to decrypt the username and use it to decrypt the stage2.bin, I did small modifications to the java file and ended up with this:
1 | import java.io.File; |
Now compiling it with javac and running with java commands we get stage2:
1 | $ javac wtf.java |
Stage2 (golang binary)
Now we have a 64bit ELF, this a go binary , this one is very similar to the previous challenge but kind of harder to reverse since is go, this time instead of the system username the directory name is used to encrypt the file:
Once again after this, a verification of an encrypted folder is done before trying to decrypt the stage3 file:
After this I created a folder named abcdefghijklmnopq which has 0x11 (17 in decimal) of size, I inserted a break point at cmp dl, bl and dumped the encrypted string abcdefghijklmnopq and the original encrypted string folder name which is present in the binary.
First getting the encrypted bytes of the folder I created:
Second get the encrypted bytes of the original folder:
We have everything we need to recover the original folder name! Since is xor encryption we just need to get the bytes of the encrypted string abcdefghijklmnopq xor it with the plaintext abcdefghijklmnopq and finally xor with encrypted original name reversing the all thing, I used a python script to do this:
1 | a = [0x59,0xCD,0xC9,0x90,0xE9,0x6E,0x9F,0x23,0x4B,0xAF,0x0B,0x33,0xCC,0x39,0x03,0xDB,0xA0] |
Getting the original folder name
1 | $ python qwd.py |
To dump the final file just move the binary to a folder named kroshka_matreshka
Stage 3 (python pyc file)
This stage is the easiest one we just need to decompile the .pyc with https://pypi.org/project/uncompyle6/ and we end up with this:
1 | def decode(data, key): |
Once again xor encryption since we already know the first 8 bytes of the flag as “cybrics{“ if we xor this with the first bytes of the encrypted flag we will get the key it’s easy to write a python script for this:
1 | c = [40, 11, 82, 58, 93, 82, 64, 76, 6, 70, 100, 26, 7, 4, 123, 124, 127, 45, 1, 125, 107, 115, 0, 2, 31, 15] |
Getting the key
1 | python roflmao.py |
The key was Kr0H4137, using it to decrypt the flag:
1 | $ python3 result.py |
The flag was cybrics{M4TR35HK4_15_B35T}