九宫格密码
密文存储于:/data/system/gesture.key 。使用sha1加密,对应位置表示的数字如下:
注意是十六进制。
比如最左侧最下侧划一竖一横就是“0003060708”,对应密文是“c8c0b24a15dc8bbfd411427973574695230458f0”
python代码:
import hashlib
a = '\x00\x03\x06\x07\x08'
print 'sha1 = %s' % (hashlib.sha1(a).hexdigest(),)
样本容量很小,可以暴力破解,也可以生成个字典查询。
感谢三只小潴,已经做好了字典和查询代码。
我上传到服务器了,大家可以上传gesture.key破解测试。
PIN和复杂密码
关键代码如下:
从代码来看password.key使用sha1和MD5加密,添加了salt,这个salt的强度很高,存储于
/data/data/com.android.providers.settings/databases/databasessettings.db(Android 4.0及以前)
/data/system/locksettings.db(Android4.1及以后)
secure表的lockscreen.password_salt这一项。
密文则存储在/data/system/password.key。
这种情况下比九宫格密码复杂很多,带了salt,无法做字典了。具体分为三种情况测试。
1、已经进入系统。
测试手机:三星 S3
这种情况,例如开了调试模式也root过,能够成功连接电脑,或者某些特定机型可以通过COM口访问存储内容等等。
实际测试:
设置PIN密码为“1234”,password.key密文为“CA0DC9C8E828442DD1D446376A0FA470EF812088”,只有40位,不对啊,不是应该72位么?难道三星只用了sha1?
salt为“6545741435738626456”,要用这个salt先得转换为十六进制,然后英文全部转换为小写。
_id | name | value |
---|---|---|
132 | lockscreen.password_salt | 6545741435738626456 |
python代码:returnedsalt = binascii.hexlify(struct.pack('>q', int(salt) ))
转换后为“5ad72527acc19998”。
sha1(12345ad72527acc19998)=549c3f339fc3ec8da7b5112ae6cec23cca2d0cdf
奇怪,怎么不是“CA0DC9C8E828442DD1D446376A0FA470EF812088”。
因为三星这个大贱货做了修改,没用原生的程序……做了1024次sha1运算,具体可以看附录的加密流程。
不过拿到hash和salt,直接可以用hashcat跑了,专门提供了针对三星的破解。
命令:cudaHashcat64.exe -m 5800 CA0DC9C8E828442DD1D446376A0FA470EF812088:5ad72527acc19998 -a 3 ?d?d?d?d
2、未进入系统。
测试手机:中兴 ZTE V970。
这种情况类似于,JTAG取镜像,读芯片,Recovery模式读存储分区。
这时password.key是72字节,正常的,其中前40字节是sha1,32字节是md5。
密文“36E8759BA3346F604DC15A6A184D79C64035F0879AE702616BEEEC1ADEACF1ABC9A1263A”
SHA1 hash "36E8759BA3346F604DC15A6A184D79C64035F087"
MD5 hash “9AE702616BEEEC1ADEACF1ABC9A1263A”
salt "2312160962934435513",转换后为“201672253b3b6eb9”
拿到salt和密文后可以用 hashcat 暴力破解,MD5速度快,就用MD5跑:
cudaHashcat64.exe -m 10 9AE702616BEEEC1ADEACF1ABC9A1263A:201672253b3b6eb9 -a 3 ?d?d?d?d
3、Android 4.1以后
支持多用户,每个用户的salt不一样,需要select value from locksettings where name='lockscreen.password_salt' and user=number,其他破解方法相同。
BTW:不得不感慨,老外分析得的确透彻!受益良多!
附录:
高手逆向的三星的加密流程
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;
}
password.py
import os, sys, subprocess, binascii, struct
import sqlite3 as lite
salt='2312160962934435513'
returnedsalt = binascii.hexlify(struct.pack('>q', int(salt) ))
print returnedsalt
sha1hash = 'CA0DC9C8E828442DD1D446376A0FA470EF812088'
参考资料:
http://bbs.pediy.com/showthread.php?t=166933
http://www.freebuf.com/articles/terminal/31176.html
http://forensics.spreitzenbarth.de/2012/02/28/cracking-pin-and-password-locks-on-android/
https://www.pentestpartners.com/blog/cracking-android-passwords-a-how-to/
https://hashcat.net/forum/thread-2202.html
http://khorchanov.blogspot.hk/2013/07/cracking-android-devices-pin-lock.html
发表评论