Android锁屏密码破解研究【九宫格和复杂密码】

九宫格密码

密文存储于:/data/system/gesture.key 。使用sha1加密,对应位置表示的数字如下:

13967864366300

注意是十六进制。

比如最左侧最下侧划一竖一横就是“0003060708”,对应密文是“c8c0b24a15dc8bbfd411427973574695230458f0”

gesture

python代码:

import hashlib
a = '\x00\x03\x06\x07\x08'
print 'sha1 = %s' % (hashlib.sha1(a).hexdigest(),)

样本容量很小,可以暴力破解,也可以生成个字典查询。

感谢,已经做好了字典和查询代码。

我上传到服务器了,大家可以上传gesture.key破解测试。

(imagettftext()函数在Linux上竟然不能使用simkai.ttf字体,浪费了好长时间调试环境……)

PIN和复杂密码

关键代码如下:

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;
}

从代码来看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这一项。

secure

密文则存储在/data/system/password.key。

这种情况下比九宫格密码复杂很多,带了salt,无法做字典了。具体分为三种情况测试。

 

1、已经进入系统。

测试手机:三星 S3

这种情况,例如开了调试模式也root过,能够成功连接电脑,或者某些特定机型可以通过COM口访问存储内容等等。

实际测试:

设置PIN密码为“1234”,password.key密文为“CA0DC9C8E828442DD1D446376A0FA470EF812088”,只有40位,不对啊,不是应该72位么?难道三星只用了sha1?

key

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

hashcatSamsung

 

2、未进入系统。

测试手机:中兴 ZTE V970。

这种情况类似于,JTAG取镜像,读芯片,Recovery模式读存储分区。

这时password.key是72字节,正常的,其中前40字节是sha1,32字节是md5。

ztehash

密文“36E8759BA3346F604DC15A6A184D79C64035F0879AE702616BEEEC1ADEACF1ABC9A1263A”

SHA1 hash "36E8759BA3346F604DC15A6A184D79C64035F087"

MD5 hash “9AE702616BEEEC1ADEACF1ABC9A1263A”

salt "2312160962934435513",转换后为“201672253b3b6eb9”

zte hash

 

拿到salt和密文后可以用 hashcat 暴力破解,MD5速度快,就用MD5跑:

cudaHashcat64.exe -m 10 9AE702616BEEEC1ADEACF1ABC9A1263A:201672253b3b6eb9 -a 3 ?d?d?d?d

hashcatmd5

 

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'