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
:
Function Flow
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.
The user’s input is split by _ .
The first check
The second check
The third check
The fourth check
The last check
The final password, following the regex rules:
jn1_stuff_m4k3s_m3_cry
Database decryption
You found the database encryption key 🎉. Open sesame!
shctf{wh3r3v3r_y0u_4r3_1_w1ll_f1nd_y0u}