Thursday 3 October 2013

Sharif CTF Quals 2013 - Reverse 300 - HelpMe

Task:
Download
We are provided with a Java archive (jar) that can be used to encrypt a file using an AES block cipher.

Firstly it will be very helpful to be able to execute this application. We will need to download Apache Commons Codec library to satisfy the dependencies. According to the Manifest file inside the jar we should put commons-codec-1.8.jar into the lib folder relative to our jar executable. Then let's decompile it using jd.
There are three classes: Crypto, Dandelion, HelpMe. The main function is located in the HelpMe class.


The logic of encryption is the following:

1) User provides filename to encrypt as CLI argument.
2) Crypto object is constructed using file name without extension as a password. Then it is initialized to encrypt: IV and salt are generated. Cipher is prepared to encrypt using AES-CBC with PKCS5 padding.
3) Dandelion object is created. It is used as a container for key, IV and salt.
4) Dandelion object which was created is serialized and saved with all cipher parameters into output file.
5) Input file is being encrypted and ciphertext is appended to the output file.

So in order to decrypt file "secret.enc" which is located in the jar file we will need to do the following:

1) Deserialize dandelion object from its beginning.
2) Bruteforce or calculate offset from where to start decoding
3) Create Crypto object and initialize it for decryption using deserialized dandelion fields.
4) Decrypt file.

We can do this because we have a key stored in the file and AES cipher is a symmetric cipher, which means it encrypt and decrypt with the same key.

The simplest way to calculate offset is to deserialize dandelion and serialize it once again. After that you can compare secret.enc with your serialization and see the offset or use function getOffset in HelpMe class. Also you can simply decrypt it about 50 times to get a valid plaintext after decrypting.

Java code that decrypts the flag:
import helpme.Crypto;
import helpme.Dandelion;

import java.io.File;

/**
 * @author Digital
 * 
 */
public class Decryptor
{
    public static void main(String[] args) throws Exception
    {
        Dandelion dandelion = helpme.Dandelion.ReadFromFile("path_to_secret.enc");
        System.out.println("Key :" + dandelion.getKey().substring(0, dandelion.getKey().lastIndexOf('.')));
        System.out.println("IV :" + dandelion.getIV());
        System.out.println("Salt :" + dandelion.getSalt());
        Crypto cr = new Crypto(dandelion.getKey().substring(0, dandelion.getKey().lastIndexOf('.')));
        cr.setupDecrypt(dandelion.getIV(), dandelion.getSalt());
        dandelion.WriteToFile("path_to_some_file_to_get_offset");

        File encrypted = new File("path_to_secret.enc");
        File output = new File("path_to_output.txt");
        cr.ReadEncryptedFile(encrypted, 174, output);
    }
}

And the result is:
Sweet Jesus! You did it!

Congratulations!!

The key is: J4v41sN0t4sB4d4stheyS4y1t1S


No comments:

Post a Comment