BSides San Francisco CTF 2017 – pinlock

Description: It’s the developer’s first mobile application. They are trying their hand at storing secrets securely. Could one of them be the flag?
Note: For this challenge, we need install some things into our Android 5.1 device with Genymotion.
For example, an ARM Translator.
https://github.com/m9rco/Genymotion_ARM_Translation

Pinlock

Install the apk with adb

				
					adb install -r pinstore.apk
				
			

Then, decompile with apktool

				
					apktool d pinstore.apk
				
			

Notice that we have a simple pin code check. Just integers.
Let’s analyze the source code with jadx.

I notice in the AndroidManifest.xml file we have two activities

				
					<activity android:name="pinlock.ctf.pinlock.com.pinstore.MainActivity">  
    <intent-filter>  
        <action android:name="android.intent.action.MAIN"/>  
    <category android:name="android.intent.category.LAUNCHER"/>  
    </intent-filter>  
</activity>  
<activity android:name="pinlock.ctf.pinlock.com.pinstore.SecretDisplay"/>
				
			

The activity are exported as True by default, then, we can access it with adb

				
					adb shell am start -n pinlock.ctf.pinlock.com.pinstore/.SecretDisplay
				
			

It’s look like a database
Then, we can check that is a database inside of the app if we inspect the log with logcat when we try insert a incorrect pin.

				
					adb logcat -c && adb logcat

--------- beginning of main
E/AudioTrack(  660): did not receive expected priority boost on time
W/SQLiteConnectionPool( 2114): A SQLiteConnection object for database '/data/data/pinlock.ctf.pinlock.com.pinstore/databases/pinlock.db' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
				
			

So, going inside of our emulator file system. And it’s correct, there are a database.
We can download to our host machine with adb

				
					adb pull /data/data/pinlock.ctf.pinlock.com.pinstore/databases/pinlock.db
				
			

Then, with sqlite we can see the content of the database

				
					sqlite3 pinlock.db

SQLite version 3.46.1 2024-08-13 09:16:08
Enter ".help" for usage hints.
sqlite> .tables
android_metadata  pinDB             secretsDBv1       secretsDBv2
sqlite> select * from pinDB;
1|d8531a519b3d4dfebece0259f90b466a23efc57b
sqlite> select * from secretsDBv1;
1|hcsvUnln5jMdw3GeI4o/txB5vaEf1PFAnKQ3kPsRW2o5rR0a1JE54d0BLkzXPtqB
sqlite> select * from secretsDBv2;
1|Bi528nDlNBcX9BcCC+ZqGQo1Oz01+GOWSmvxRj7jg1g=
sqlite>
				
			

We will use just the first hash
d8531a519b3d4dfebece0259f90b466a23efc57b
Let’s crack it with hashcat

				
					hashcat -m 100 hash.txt /usr/share/seclists/rockyou.txt
				
			

And we got the pin

				
					d8531a519b3d4dfebece0259f90b466a23efc57b:7498
				
			

When the SecretActivity is started, we can see the logs

				
					--------- beginning of main
D/Version ( 2114): v1
D/secret  ( 2114): hcsvUnln5jMdw3GeI4o/txB5vaEf1PFAnKQ3kPsRW2o5rR0a1JE54d0BLkzXPtqB
D/Status  ( 2114): [B@128b6e8b
				
			

Looking in the folder that apktool drop, in the assets folder we have an README

				
					v1.0:
- Pin database with hashed pins

v1.1:
- Added AES support for secret

v1.2:
- Derive key from pin
[To-do: switch to the new database]
				
			

Now is time to read the source code of SecretActivity and CryptoUtilies
After read, we have the string t0ps3kr3tk3y and this is using an algorithm to decrypt it.

We have two secrets
hcsvUnln5jMdw3GeI4o/txB5vaEf1PFAnKQ3kPsRW2o5rR0a1JE54d0BLkzXPtqB
And
Bi528nDlNBcX9BcCC+ZqGQo1Oz01+GOWSmvxRj7jg1g=
We need modify the smali file for switch to the second one.

Because we have in the DatabaseUtilities class

				
					public String fetchSecret() throws IOException {  
        openDB();  
        Cursor cursor = this.db.rawQuery("SELECT entry FROM secretsDBv1", null);  
        String secret = "";  
        if (cursor.moveToFirst()) {  
            secret = cursor.getString(0);  
        }  
        Log.d("secret", secret);  
        cursor.close();  
        return secret;  
    }
				
			

That the rawQuery is using secretsDBv1 and we just change the 1 by 2
And in the try if the SecretDisplay class, we have the v1 string. So we need switch to v2

				
					try {  
            DatabaseUtilities dbUtils = new DatabaseUtilities(getApplicationContext());  
            CryptoUtilities cryptoUtils = new CryptoUtilities("v1", pin);  
            tv.setText(cryptoUtils.decrypt(dbUtils.fetchSecret()));  
        }
				
			

Let’s find the smali code corresponding to this two classes.

				
					cat DatabaseUtilities.smali | grep secretsDBv1 -n

315:    const-string v1, "SELECT entry FROM secretsDBv1"
				
			

In the 315 line of the code, just change secretsDBv1 to secretsDBv2.
Then, save the file.

And

				
					cat SecretDisplay.smali | grep v1 -n

74:    const-string v7, "v1"
				
			

In the 74 line, we have the last change that we must do. v1 to v2
Save the file

And now, we just need rebuild the app with apktool

				
					apktool b pinstore
				
			

Then, generate a key

				
					keytool -genkey -v -keystore name.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias alias
				
			

Sign the apk

				
					jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore name.keystore pinstore/dist/pinstore.apk alias
				
			

Delete the original app installed and reinstall with adb

				
					adb install -r pinstore/dist/pinstore.apk
				
			

Insert the correct code that is 7498
And we got the flag

I hope you found it useful (:

Leave a Reply

Your email address will not be published. Required fields are marked *