OWASP Uncrackable Level 1
1. Introduction
This app holds a secret inside. Can you find it?
Objective: A secret string is hidden somewhere in this app. Find a way to extract it.
Author: Bernhard Mueller
2. Analysis and Source Code
Emulator Setup: Nexus 5 with Android 9.0
adb install Uncrackable-Level1.apk
After starting the app there’s a message:
Root detected!
This is unacceptable. The app is now going to exit.
Note: We need to find a way to bypass the root detection. If this is done we need a way to find the secret string!

I’ll unpack the android package
apktool d -f -r Uncrackable-Level1.apk
I’ll also unpack the classes.dex from from the Uncrackable-Level1.apk file
unzip -j Unrackable-Level1.apk classes.dex
Next I’ll use strings against the classes.dex file

There are several things here that catch my attention:
5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=
looks like base64 string
8d127684cbc37c17616d806cf50473cc
looks like a HEX string
AES/ECB/PKCS7Padding
gives me a hint about the encryption algorithm being used
For the further analysis of the source code I’ll open the android package with jadx-gui
Let’s check the AndroidManifest.xml first:
Package name is:
owasp.mstg.uncrackable1

Entrypoint is:

The MainActivity contains the onCreate method, and immediately performs on evaluation to check for root:
public void onCreate(Bundle bundle) {
if (c.a() || c.b() || c.c()) {
a("Root detected!");
}
2.1 Root detection
If either c.a(), c.b(), or c.c() returns true, then the string “Root detected” is passed to the a() method, which looks like this:
private void a(String str) {
AlertDialog create = new AlertDialog.Builder(this).create();
create.setTitle(str);
create.setMessage("This is unacceptable. The app is now going to exit.");
create.setButton(-3, "OK", new DialogInterface.OnClickListener() { // from class: sg.vantagepoint.uncrackable1.MainActivity.1
@Override // android.content.DialogInterface.OnClickListener
public void onClick(DialogInterface dialogInterface, int i) {
System.exit(0);
}
We can try to patch the condition or hook it with frida.
2.2 Secret Key
The secret key is calculated somewhere around here:
public class a {
public static boolean a(String str) {
byte[] bArr;
byte[] bArr2 = new byte[0];
try {
bArr = sg.vantagepoint.a.a.a(b("8d127684cbc37c17616d806cf50473cc"), Base64.decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", 0));
} catch (Exception e) {
Log.d("CodeCheck", "AES error:" + e.getMessage());
bArr = bArr2;
}
return str.equals(new String(bArr));
}
public class a {
public static byte[] a(byte[] bArr, byte[] bArr2) {
SecretKeySpec secretKeySpec = new SecretKeySpec(bArr, "AES/ECB/PKCS7Padding");
Cipher instance = Cipher.getInstance("AES");
instance.init(2, secretKeySpec);
return instance.doFinal(bArr2);
}
}
4. Decrypt Secret
I’ll use an online AES tool that help me with decryption:
https://the-x.cn/en-us/cryptography/Aes.aspx
Input is the BASE64 string

Options:
ECB
PKCS7
128bits
HEX KEY: 8d127684cbc37c17616d806cf50473cc

Output:

Alternative solution with python:

5. Hooking the root protection with Frida
Let’s try to hook the root protection with frida
This code will overload the exit function and print a string out „Exit called instead of closing the application“
hook.js
setImmediate(function() {
console.log("[+] Starting hooker");
Java.perform(function () {
var system = Java.use("java.lang.System");
system.exit.overload("int").implementation = function(var0) {
console.log("[+] Exit called");
};
});
});
Let’s check the frida connection:
frida-ps -U
frida -U -f owasp.mstg.uncrackable1 -l hook1.js –no-pause

Let’s check the Secret from the decryption above:
I want to believe


