SHCTF23: SecureNotes3

Untitled


You are presented with an apk file: SecureNotes3.apk

The first thing to do is to decompile the apk to retrieve the java classes and resources.

Code Analysis

**MainActivity.java**

The layout has a prompt for a user to input a password. This password is then validated by a function validatePassword from a loaded SecureNotes3.so library. Upon validation, this password is used to decrypt an SQLite DB called notes.db that has a very fishy secrets table.

public void onClick(DialogInterface dialogInterface, int i) {
                String obj = editText.getText().toString();
                if (MainActivity.this.validatePassword(obj)) {
                    Toast.makeText(MainActivity.this, "Password Valid!", 0).show();
                    MainActivity.this.notes.clear();
                    ArrayList arrayList = new ArrayList();
                    MainActivity.this.InitializeSQLCipher(obj);
                    Cursor rawQuery = MainActivity.this.f171db.rawQuery("SELECT * FROM secrets;", new Object[0]);
                    if (rawQuery.getCount() > 0) {
                        rawQuery.moveToFirst();
                        do {
                            arrayList.add(new Note(rawQuery.getString(rawQuery.getColumnIndex("title")), rawQuery.getString(rawQuery.getColumnIndex("body"))));
                        } while (rawQuery.moveToNext());
                    } else {
                        Log.d(MainActivity.TAG, "onClick: fetchData in db: No data found in database");
                    }
}

Disassembly

You need to reverse engineer the native library file(implemented and compiled by NDK) to understand how the password validation happens.

Resources:

To prepare your Ghidra to begin the disassembly process, you need to load JNI types to resolve JNI symbols. Check out this repo.

Retype the first parameter of the validatePassword function to JNIEnv:

Untitled

Function Flow

Untitled

Regex: The user password should match the following regex string:

([a-z]{2}[0-9])((_[a-z0-9]{5}){2})(_[a-z][0-9])(_[a-z]{3}) → ab1_c2d3e_f4g5h_i6_jkl

This means the user password must be 22 bytes.

Untitled

The user’s input is split by _ .

The first check

Untitled

The second check

Untitled

The third check

Untitled

The fourth check

Untitled

The last check

Untitled

The final password, following the regex rules:

jn1_stuff_m4k3s_m3_cry

Database decryption

You found the database encryption key 🎉. Open sesame!

Untitled

Untitled

shctf{wh3r3v3r_y0u_4r3_1_w1ll_f1nd_y0u}

SHCTF23: Magic Trick

SHCTF23: Veiled Dimensions

comments powered by Disqus