Cryptonik

BreizhCTF 2018 - Mobile.

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}

@Areizen