Cracking Android passwords, a how-to
I’ve been sort of meaning to write this for a while, but it wasn’t until I was asked for further information on how it works that I actually though that it may be worthwhile describing this in depth.
If you search around the Interwebs you can find some forensics sites
explaining the basics, but not in enough detail to actually crack it.
The point of this post is to give some background on how the screen lock, known as Keyguard, works, what it protects and how to perform password guessing on the hash.
Why Crack the Password?
To be honest I’ve not really seen much use in cracking that password before, to gain access to the hash and salt you need to have root level access to the device, by which point you can already assume that you have all the files.
You can also delete the password so you don’t need it to connect to the phone; which enables you to abuse open sessions (e.g. apps like Facebook, Google Play or Twitter) were replaying the authentication token would be hard.
But, there are some reasons why it may be advantageous to gain the password:
- We may find the hash in a backup file on a local machine; which could allow us to compromise the phone from a backup.
- Password reuse: most people will use the same PIN for all their devices (or even other things like their bankcards). This could allow a device which is easily JTAGed or a cheap tablet which already allows root access to be abused to compromise somebody’s phone.
- The password is used as the key for Android’s encryption (if enabled) of the partition, allowing us to potentially decrypt it.
- The Android keystore is encrypted with a master key (its KEK) which is based off the screen lock password.
- Because we can.
How is it stored?
Just a couple of caveats first, there is some change between Android pre 4.2 and there may be changes after Android 4.4 that affect this. The password is stored differently if there is more than one user on the device. Also, when I say “password” I include the PIN – this is stored in exactly the same way; other mechanisms, such as patterns or facial recognition are subjects for later posts.
The password is stored as a hex representation of a hash in the file /data/system/password.key, an example can be seen below:
All of you familiar with hash lengths are probably looking confused now. The string is 72 characters long, which is a strange number and not valid for most hash functions. There is a really simple explanation here: it’s actually two hashes, one SHA1 and one MD5 concatenated together. This doesn’t make much sense until you figure in the performance of the early Android smart phones – allowing low powered devices to choose to only use the MD5 hash and speed up the processing of the lock guard.
So this splits the above hash into:
This file isn’t everything you need; you also need the salt, which can be found in a SQLite database; where the location depends on the version of Android you’re running:
|Android Version||Location /strong>|
|Cupcake, Donut, Éclair, Froyo, Gingerbread, Ice Cream Sandwich||/data/data/com.android.providers.settings/databases/settings.db|
|Jelly Bean, Kit Kat, Lollipop||/data/system/locksettings.db|
Whichever version you’re using; the salt can be found in the locksettings table, with the following SQL:
This will return a 64 bit (or long integer), for example:
To use this, we need to convert it to hex and then lower case it. You can use Windows calculator to do this and then manually convert the characters (or use something like Notepad++), so in hex:
And lower cased:
I’m going to use Hashcat, as I have a separate graphics card in my laptop, which allows me to do other things whilst I’m cracking passwords.
Sadly Hashcat does not have support for stock Android hashes. It has 5800 (Samsung Android Password/PIN) which is a Samsung specific variant and 8800 (Android FDE <= 4.3) which is for cracking Android disk encryption.
But, as Android uses a standard algorithm we can just use one of hashcat’s standard algorithms.
We can look at the AOSP source code to see how the algorithm is encoded (in /core/java/com/android/internal/widget/LockPatternUtils.java):
byte sha1 = MessageDigest.getInstance(algo = “SHA-1”).digest(saltedPassword);
byte md5 = MessageDigest.getInstance(algo = “MD5”).digest(saltedPassword);
hashed = (toHex(sha1) + toHex(md5)).getBytes();
So, the password key file can be seen as the following:
If we look at Hashcat’s list of hash types we can see both of these. I’ve included benchmarks for the GeForce GT 740M on my laptop as a speed comparison:
|Hash Type||Algorithm||Benchmark (on my laptop)|
|10||MD5($pass . $salt)||1077.8 MH/.s|
|110||SHA1($pass . $salt)||261.4 MH/s|
As using MD5 is 5 times faster than SHA1, I can choose to just crack this, so, lets crack the above password, brute forcing all 4 digit PINs:
cudaHashcat v1.31 starting…Device #1: GeForce GT 740M, 2048MB, 1032Mhz, 2MCU
Hashes: 1 hashes; 1 unique digests, 1 unique salts
Bitmaps: 8 bits, 256 entries, 0x000000ff mask, 1024 bytesINFO: approaching final keyspace, workload adjusted
Input.Mode…..: Mask (?d?d?d?d) 
Time.Started…: 0 secs
Speed.GPU.#1…: 2022.9 kH/s
Recovered……: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress…….: 10000/10000 (100.00%)
Skipped……..: 0/10000 (0.00%)
Rejected…….: 0/10000 (0.00%)
HWMon.GPU.#1…: 0% Util, 49c Temp, N/A Fan
Started: Thu Jan 29 11:26:48 2015
Stopped: Thu Jan 29 11:26:49 2015
Cracked in “0 seconds”!
A special note about users
Android Jelly Bean added support for multiple users. Each user has separate apps and data storage, which includes the keyguard password. User 0 is a special user, being the device owner.
We can still use the above techniques to crack all hashed passwords on devices with multiple users, but we need to modify the gathering techniques slightly.
Users are identified by a user number, with 0 being the device owner and then incrementing by 10 for each new users (i.e. 0, 10, 20) this information is stored in /data/system/users/user.xml
For multiple users, password.key will be stored in /data/system/users/number in a directory with the user number.
We will have to modify the query for the locksettings database as well: