Cryptonik - BreizhCtf 2018
This write up is about the third APK that was given to us at the BreizhCTF : Cryptonik
Decompilation
To reverse Android application, I usually start by reversing the source code . For that i use 2 tools : Jadx and APKTool when Jadx is not sufficient.
For this chall, I only used Jadx with the command
jadx Cryptonik.apk
Once this command executed desassembled file of this applications are located in the folder Cryptonik.
Here I also unzipped the apk to get the file enc.bin from the assets folder.
Finding the vulnerability
Once extracted we get this file :
Cryptonik.java
package fr.breizhctf.saxx.jetepromets;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Random;
public class Cryptonik {
static class Data implements Serializable {
private final byte[] data1;
private final byte[] data2;
public Data(byte[] data1, byte[] data2) {
this.data1 = data1;
this.data2 = data2;
}
public byte[] getData1() {
return this.data1;
}
public byte[] getData2() {
return this.data2;
}
}
public static byte[] cryptonik_gen() {
byte[] nbyte = new byte[30];
new Random().nextBytes(nbyte);
return nbyte;
}
public static byte[] encrypt(byte[] data, byte[] key) {
byte[] enc = new byte[data.length];
for (int i = 0; i < data.length; i++) {
enc[i] = (byte) (data[i] ^ key[i % key.length]);
}
return enc;
}
public static void main(String[] args) throws Exception {
byte[] crypt = cryptonik_gen();
String flag = "BZHCTF{TEUTEUTEU_TEUTEUTEU_TEUTEUTEU_TEUTEUTEU_}";
String text = "Je te promets mes bras pour porter tes angoisses";
int lengthOfInput = text.length();
if (flag.length() != lengthOfInput) {
System.out.println("len(text) must be " + lengthOfInput + "!");
return;
}
Data data = new Data(encrypt(text.getBytes(), crypt), encrypt(flag.getBytes(), crypt));
ObjectOutputStream file = new ObjectOutputStream(new FileOutputStream("enc.bin"));
file.writeObject(data);
file.close();
}
}
And we where also given enc.bin in the assets which contained data that look like serialized data.
Here the vulnerability is that a plaintext that we know is xored with the same key that our flag to make sme encryptio.n So following this rules :
"plain" ^ "key" = "enc"
and "plain" ^ "enc" = "key"
We can get back the key and recover flag by xoring it with the key.
Getting the password
Here is my Java code that do the opposite :
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Random;
public class Cryptonik {
static class Data implements Serializable {
private final byte[] data1;
private final byte[] data2;
public Data(byte[] data1, byte[] data2) {
this.data1 = data1;
this.data2 = data2;
}
public byte[] getData1() {
return this.data1;
}
public byte[] getData2() {
return this.data2;
}
}
public static byte[] cryptonik_gen() {
byte[] nbyte = new byte[30];
new Random().nextBytes(nbyte);
return nbyte;
}
public static byte[] encrypt(byte[] data, byte[] key) {
byte[] enc = new byte[data.length];
for (int i = 0; i < data.length; i++) {
enc[i] = (byte) (data[i] ^ key[i % key.length]);
}
return enc;
}
public static void main(String[] args) throws Exception {
String text = "Je te promets mes bras pour porter tes angoisses";
ObjectInputStream file = new ObjectInputStream(new FileInputStream("enc.bin"));
Data e = (Data) file.readObject();
byte[] key = encrypt(e.getData1(),text.getBytes());
System.out.println(new String(key, "UTF-8"));
System.out.println(new String(encrypt(e.getData2(),key), "UTF-8"));
file.close();
}
}
And the flag is :
BZHCTF{Wat_do_u_dont_understand_in_0n3_71m3_p4d}