Skip to content

APKrypt – Hack The Box

Difficult: Easy Category: Mobile OS: Android

Description: Can you get the ticket without the VIP code?


Download the zip file and extract with the hackthebox password. There are a README.txt file that say 1. Install this application in an API Level 29 or earlier (i.e. Android 10.0 (Google APIs)).

Decompile the apk with apktool

apktool d APKrypt.apk

And install it with adb

adb install -r APKrypt.apk

Let’s check the source code with jadx We can see some interesting in the MainActivity

protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    setContentView(R.layout.activity_main);
    this.b1 = (Button) findViewById(R.id.button);
    this.ed1 = (EditText) findViewById(R.id.editTextVipCode);
    this.b1.setOnClickListener(new View.OnClickListener() { // from class: com.example.apkrypt.MainActivity.1
        @Override // android.view.View.OnClickListener
        public void onClick(View view) {
            try {
                if (MainActivity.md5(MainActivity.this.ed1.getText().toString()).equals("735c3628699822c4c1c09219f317a8e9")) {
                    Toast.makeText(MainActivity.this.getApplicationContext(), MainActivity.decrypt("k+RLD5J86JRYnluaZLF3Zs/yJrVdVfGo1CQy5k0+tCZDJZTozBWPn2lExQYDHH1l"), 1).show();
                } else {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "Wrong VIP code!", 0).show();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public static String md5(String str) {
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.update(str.getBytes());
        byte[] digest = messageDigest.digest();
        StringBuffer stringBuffer = new StringBuffer();
        for (byte b : digest) {
            stringBuffer.append(Integer.toHexString(b & 255));
        }
        return stringBuffer.toString();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return "";
    }
}

public static String encrypt(String str) throws Exception {
    Key generateKey = generateKey();
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(1, generateKey);
    return Base64.encodeToString(cipher.doFinal(str.getBytes("utf-8")), 0);
}

public static String decrypt(String str) throws Exception {
    Key generateKey = generateKey();
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(2, generateKey);
    return new String(cipher.doFinal(Base64.decode(str, 0)), "utf-8");
}

private static Key generateKey() throws Exception {
    return new SecretKeySpec("Dgu8Trf6Ge4Ki9Lb".getBytes(), "AES");
}

In the first block we have the onCreate method (when the app is executed, and then we have 4 functions: md5, encrypt, decrypt and generateKey.

But I’ll keep this piece of code

public void onClick(View view) {
                try {
                    if (MainActivity.md5(MainActivity.this.ed1.getText().toString()).equals("735c3628699822c4c1c09219f317a8e9")) {
                        Toast.makeText(MainActivity.this.getApplicationContext(), MainActivity.decrypt("k+RLD5J86JRYnluaZLF3Zs/yJrVdVfGo1CQy5k0+tCZDJZTozBWPn2lExQYDHH1l"), 1).show();
                    }

If we modify the smali code, we can get the flag without any data on the textbox Letme explain, The code onClick have a smali code that is represented as

.method public onClick(Landroid/view/View;)V
    .registers 4

    .line 36
    :try_start_0
    iget-object p1, p0, Lcom/example/apkrypt/MainActivity$1;->this$0:Lcom/example/apkrypt/MainActivity;

    iget-object p1, p1, Lcom/example/apkrypt/MainActivity;->ed1:Landroid/widget/EditText;

    invoke-virtual {p1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;

    move-result-object p1

    invoke-virtual {p1}, Ljava/lang/Object;->toString()Ljava/lang/String;

    move-result-object p1

    invoke-static {p1}, Lcom/example/apkrypt/MainActivity;->md5(Ljava/lang/String;)Ljava/lang/String;

    move-result-object p1

    const-string v0, "735c3628699822c4c1c09219f317a8e9"

    invoke-virtual {p1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result p1

    if-eqz p1, :cond_2d

    .line 37
    iget-object p1, p0, Lcom/example/apkrypt/MainActivity$1;->this$0:Lcom/example/apkrypt/MainActivity;

    invoke-virtual {p1}, Lcom/example/apkrypt/MainActivity;->getApplicationContext()Landroid/content/Context;

    move-result-object p1

    const-string v0, "k+RLD5J86JRYnluaZLF3Zs/yJrVdVfGo1CQy5k0+tCZDJZTozBWPn2lExQYDHH1l"

    invoke-static {v0}, Lcom/example/apkrypt/MainActivity;->decrypt(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0

    const/4 v1, 0x1

    invoke-static {p1, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object p1

    invoke-virtual {p1}, Landroid/widget/Toast;->show()V

    goto :goto_42

    .line 39
    :cond_2d
    iget-object p1, p0, Lcom/example/apkrypt/MainActivity$1;->this$0:Lcom/example/apkrypt/MainActivity;

    invoke-virtual {p1}, Lcom/example/apkrypt/MainActivity;->getApplicationContext()Landroid/content/Context;

    move-result-object p1

    const-string v0, "Wrong VIP code!"

    const/4 v1, 0x0

    invoke-static {p1, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object p1

    invoke-virtual {p1}, Landroid/widget/Toast;->show()V
    :try_end_3d
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_3d} :catch_3e

    goto :goto_42

    :catch_3e
    move-exception p1

    .line 42
    invoke-virtual {p1}, Ljava/lang/Exception;->printStackTrace()V

    :goto_42
    return-void
.end method

We need look at this line:

if-eqz p1, :cond_2d

That say “if “code” is p1 (encrypted code), then cond_2d that is the toast message with the flag” If-eqz is equal If-nez is not-equal

Then, we go to

/APKrypt/smali/com/example/apkrypt/

And with nano edit the file

nano MainActivity\$1.smali

Search the onClick method (line 65 probably) And change if-eqz to if-nez

Save the file and go to the start of the folder Build a new apk with apktool

apktool b APKrypt

And go to /APKrypt/dist/ Then generate a new key with keytool

keytool -genkey -keystore lautaro.keystore -validity 1000 -alias lautaro

Sign the new apk with jarsigner

jarsigner -keystore lautaro.keystore -verbose APKrypt.apk lautaro

Delete the previous apk installed And install the new apk with adb

adb install -r APKrypt.apk

Now run again the app and press the button

I hope you found it useful (: