# AndroNotes
> Our Forensic experts dumped the mobile device of a criminal, can you identify what the thugs are up to...
We get a 3.5GB dump of a flash memory of an Android device with a task of retrieving an encrypted note. After a while oflooking at installed applications we take an even closer look at the "Safe Notes - Secure Ad-free notepad"(com.protectedtext.android) app and, especially, it's stored data at`/dump/data/data/com.protectedtext.android/`:```./databases./databases/notes_db_name-journal./databases/google_app_measurement_local.db-journal./databases/google_app_measurement_local.db./databases/notes_db_name./shared_prefs./shared_prefs/com.google.android.gms.appid.xml./shared_prefs/com.protectedtext.n2.xml./shared_prefs/com.google.android.gms.measurement.prefs.xml./shared_prefs/com.protectedtext.lon.xml./shared_prefs/com.crashlytics.sdk.android:answers:settings.xml./shared_prefs/remoteConfigPrefs.xml./shared_prefs/com.google.firebase.remoteconfig_legacy_settings.xml./shared_prefs/frc_1:169956459094:android:8d67c78e1c4facc6_firebase_settings.xml./shared_prefs/com.protectedtext.android_preferences.xml./shared_prefs/TwitterAdvertisingInfoPreferences.xml./shared_prefs/com.crashlytics.prefs.xml```
At first, we looked into the `./databases/notes_db_name` file, which is a sqlite database.
```$ sqlite3 ./databases/notes_db_nameSQLite version 3.31.1 2020-01-27 19:55:54Enter ".help" for usage hints.sqlite> .schemaCREATE TABLE android_metadata (locale TEXT);CREATE TABLE Notes (ID_COLUMN integer primary key autoincrement, NOTE_CONTENT_COLUMN text, LAST_TIME_MODIFIED_COLUMN integer, IS_ENCRYPTED_COLUMN integer, INIT_CONTENT_HASH_COLUMN text, EXPECTED_DB_VERSION_COLUMN integer, LAST_SELECTED_TAB_INDEX_COLUMN integer, PASSWORD_COLUMN text, URL_COLUMN text );CREATE TABLE sqlite_sequence(name,seq);```
It's schema was very promising, but...
```sqlite> select * from Notes;sqlite> ```
... the database was empty.
Then we looked at shared_prefs and especially the `./shared_prefs/com.protectedtext.n2.xml` file that turned outto have a base64-encoded high-entropy data, possibly an encrypted note.```$ cat shared_prefs/com.protectedtext.n2.xml 
<map>    <string name="a">U2FsdGVkX19c/zcgG/UScI+1bKvOvunZUy6Ck1FB/dxMD+BGQLAAkEVufV1+skdK5cyCFqnw2WTY546XgOGnD11WLjg1N0RbbeotynkRGGKFZ3XAMQQUk7v08mBs8IYVISRxSzktd9HgT4cCAjtvWgpYytz9y7Tb4hF1x8plEb114yaWfNspk4XmLqUyssVnyIhqBXDmmIEFVudV+EQsOkYcBW5S1GINEBLqV6lxLKHSTlwWej2Y+TpC1mOAScmIs6NAyquw7ow2oYpqDBC6SB5dslgHYeV9YoCv+evP+lQdmCTf+88VvT001MnUHtgTFnsRcZR1rCmZp2EXNQArCH/onRSAE2ehGPv2NIfsnljeSfg7jO12zkRqf1q22SLtFpHL8OLKjrfvpcY5yRIm1H1vkYRDewYlku6r/WoESpBfAvl8/VKmkrsPfp1JjKLuO3mDOuv5CmE7HBmT3etR5b1WEL78nizxtkj4wFKyY2I4SuHmsNFANZdxMsdpZImYpB6pG0i5ifMGiesjThvTQU8pblQ2XQSrNuqpTtjwXvk=</string></map>```
Now's the time to finally look into the application itself. We've downloaded an APK and decompiled its code.
We started with `com.protectedtext.android` package and quickly ran into the `a.c.b()` method with a string suggestingit might deal with the aforementioned shared prefs file:```javapublic JSONObject b(long j) {    Context applicationContext = PtApplication.b().getApplicationContext();    String string = applicationContext.getSharedPreferences("com.protectedtext.n" + j, 0).getString("a", (String) null);    if (string == null) {        f.a((Throwable) new IllegalStateException("Note xml file exists, but no keys inside!"));    }    try {        return new JSONObject(e.a(string, f3128b + j));    } catch (JSONException e) {        f.a((Throwable) e);        throw new RuntimeException(e);    }}```
The `e.a` method it invokes when creating the JSONObject looks like a decryption function:
```javapublic static String a(String str, String str2) {    try {        byte[] decode = Base64.decode(str, 0);        byte[] bArr = new byte[8];        byte[] bArr2 = new byte[(decode.length - 16)];        System.arraycopy(decode, 8, bArr, 0, 8);        System.arraycopy(decode, 16, bArr2, 0, bArr2.length);        MessageDigest instance = MessageDigest.getInstance("MD5");        byte[] a2 = a(str2.getBytes(), bArr);        byte[] digest = instance.digest(a2);        byte[] digest2 = instance.digest(a(digest, a2));        byte[] digest3 = instance.digest(a(digest2, a2));        SecretKeySpec secretKeySpec = new SecretKeySpec(a(digest, digest2), "AES");        IvParameterSpec ivParameterSpec = new IvParameterSpec(digest3);        Cipher instance2 = Cipher.getInstance("AES/CBC/PKCS5Padding");        instance2.init(2, secretKeySpec, ivParameterSpec);        return new String(instance2.doFinal(bArr2), "UTF-8");    } catch {        ... error handling ...    }}```
It takes base64-encoded data and a key. Conveniently it's just a static key constructed from a few strings:```javaStringBuilder sb = new StringBuilder();sb.append("7igb2h048io6fyv");sb.append(Math.random() > -1.0d ? "8h92q3ruag" : "98hasdfil");sb.append("09g8h");f3128b = sb.toString();```
Copying all that code into a new Java project and passing the base64-encoded data we've found in the shared prefsalong with the static key to the decryption function gives us the note contents and the flag:
```json{"id":2,"content":"Operation Secret:\nINS{P1n_L0c4l_AuTh3nT1c4t10N_1s_4asY}\nf47c13a09bfcad9eb1f81fbf12c04516e0d900e409a74c660f933e69cf93914e16bc9facc7d379a036fe71468bd4504f2a388a0a28a9b727a38ab7843203488c♻ Reload this website to hide mobile app metadata! ♻{\"version\":1,\"color\":-1118482}","ordering_time":1640170640052,"is_encrypted":false,"expected_db_ver":2,"selected_tab_index":0}```
The application description on Google Play also suggests that the app uses a user-provided PIN to protect user's data,but we guess it only blocks the UI.