01. Introduction
In this exercise we'll try to decrypt the the password of the CrackMeSimple Challenge, by analysing the ProgramCode.
APK File:
02. Code analysis
Open the package with jadx-gui. The following AES Util Part looks interessting:
Copy package org.bfe.crackmesimple.util;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESUtil {
private static final String ENCRYPTION_IV = "SHCUOkfd89ut7777";
private static final String ENCRYPTION_KEY = "Simpleji4todnkfL";
public static byte[] encrypt(byte[] bArr) {
try {
Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
instance.init(1, makeKey(), makeIv());
return instance.doFinal(bArr);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] decrypt(byte[] bArr) {
try {
Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
instance.init(2, makeKey(), makeIv());
return instance.doFinal(bArr);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static AlgorithmParameterSpec makeIv() {
try {
return new IvParameterSpec(ENCRYPTION_IV.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
static Key makeKey() {
try {
return new SecretKeySpec(MessageDigest.getInstance("SHA-256").digest(ENCRYPTION_KEY.getBytes("UTF-8")), "AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (UnsupportedEncodingException e2) {
e2.printStackTrace();
return null;
}
}
}
We can see the AES encryption key
and the initialization vector
:
Copy public class AESUtil { private static final String ENCRYPTION_IV = "SHCUOkfd89ut7777";
private static final String ENCRYPTION_KEY = "Simpleji4todnkfL";
I also took notice about the cipher instance: AES/CBC /PKCS5Padding
From the encryption key a SHA-256 cryptographic hash(!) will be generated:
Copy static Key makeKey()
{ try
{ return new SecretKeySpec(MessageDigest.getInstance("SHA-256").digest(ENCRYPTION_KEY.getBytes("UTF-8")), "AES");
The second interessting part is the LoginView Model class:
Copy public class LoginViewModel extends ViewModel {
private static byte[] exs = {-28, 73, 79, 78, 113, 73, 101, 98, 115, 6, 27, -35, 111, -55, -114, -11, -29, 0, -73, 91, 115, -24, -4, -94, -59, 43, -57, 112, 11, -54, -115, 2};
protected DexClassLoader dexClassLoader = null;
private MutableLiveData<LoginFormState> loginFormState = new MutableLiveData<>();
private MutableLiveData<LoginResult> loginResult = new MutableLiveData<>();
03. Decode with Cyberchef
First I generate a SHA-256 hash from the encryption key:
Output:
Now we have all pieces together. The final Cyberchef Recipe looks like this:
Input value:
Copy -28, 73, 79, 78, 113, 73, 101, 98, 115, 6, 27, -35, 111, -55, -114, -11, -29, 0, -73, 91, 115, -24, -4, -94, -59, 43, -57, 112, 11, -54, -115, 2
Copy From_Decimal('Comma',true)
AES_Decrypt({'option':'Hex','string':'d6eadb48382e79d35f25cbca4fb55ef69d842ee79ad843b4bae757fa99344d1a'},
{'option':'UTF8','string':'SHCUOkfd89ut7777'},'CBC','Raw','Raw',{'option':'Hex','string':''},{'option':'Hex','string':''})
Output: HL{R3v3rsing.FUN}