Home APKrypt writeup
Post
Cancel
Preview Image

APKrypt writeup

Description

Can you get the ticket without the VIP code?

Writeup

We receive an apk file, which we can then decompile via codium and the APKLab extension. The MainActivity.java file is seen below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package com.example.apkrypt;

import android.app.Activity;
import android.os.Bundle;
import android.util.Base64;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
/* loaded from: classes.dex */
public class MainActivity extends Activity {
    Button b1;
    EditText ed1;

    @Override // android.app.Activity
    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 instance = MessageDigest.getInstance("MD5");
            instance.update(str.getBytes());
            byte[] digest = instance.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 instance = Cipher.getInstance("AES");
        instance.init(1, generateKey);
        return Base64.encodeToString(instance.doFinal(str.getBytes("utf-8")), 0);
    }

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

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

This file hashes our input, checks that the hash matches a hardcoded hash, and then decrypts the flag. to get around this check we can patch the apk

To patch the apk we can go into the smali files, which include the lines

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    const-string v0, "5d41402abc4b2a76b9719d911017c592"

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

    move-result p1

    if-eqz p1, :cond_0

    .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;

The strings included in the smali file is what the apk is going to check against when it is running. We can therefore simply change the md5 hash into something that we know is hashed into that value, for example:

1
2
3
┌──(bitis㉿workstation)-[~/Coding/BitisG.github.io]
└─$ echo -n "hello" | md5sum
5d41402abc4b2a76b9719d911017c592  -

We can then use APKLab in VScodium to recompile the apk, and when we enter the string hello as our vip code we get the flag as a Toast!

This post is licensed under CC BY 4.0 by the author.