Skip to content

Instantly share code, notes, and snippets.

@danzek
Last active October 17, 2022 18:22
Show Gist options
  • Save danzek/f9416b1404570754b10f to your computer and use it in GitHub Desktop.
Save danzek/f9416b1404570754b10f to your computer and use it in GitHub Desktop.

Revisions

  1. danzek revised this gist Jan 2, 2018. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions bruteforcegesture.py
    Original file line number Diff line number Diff line change
    @@ -36,6 +36,11 @@
    Credit must be given to Michael Spreitzenbarth's helpful blog post:
    http://forensics.spreitzenbarth.de/2012/02/28/cracking-the-pattern-lock-on-android/
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    """

    import binascii
  2. @4n68r 4n68r revised this gist Sep 13, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion bruteforcegesture.py
    Original file line number Diff line number Diff line change
    @@ -48,7 +48,7 @@
    __credits__ = ["Michael Spreitzenbarth", "Chema Garcia", "Kieron Craggs"]
    __version__ = "0.1"
    __maintainer__ = "Dan O'Day"
    __email__ = "[email protected]"
    __email__ = "[email protected]"
    __status__ = "Prototype"


  3. @4n68r 4n68r renamed this gist Dec 22, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. @4n68r 4n68r created this gist Dec 22, 2014.
    96 changes: 96 additions & 0 deletions bruteforcegesture
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,96 @@
    #!/usr/bin/env python

    """Cracks a gesture.key file (Android pattern lock), reverse-engineers the Android method of creating an unsalted SHA1
    hash value from the 3-9 digit pattern code (each digit consisting of 9 possible values: 0-8).
    Note that Android > v2.33 requires minimum of four values, but three makes this work for old ones too.
    The original Android source code for pattern locks:
    /*
    * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
    * at least a second level of protection. First level is that the file
    * is in a location only readable by the system process.
    * @param pattern the gesture pattern.
    * @return the hash of the pattern in a byte array.
    */
    private static byte[] patternToHash(List pattern) {
    if (pattern == null) {
    return null;
    }
    final int patternSize = pattern.size();
    byte[] res = new byte[patternSize];
    for (int i = 0; i < patternSize; i++) {
    LockPatternView.Cell cell = pattern.get(i);
    res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
    }
    try {
    MessageDigest md = MessageDigest.getInstance("SHA-1");
    byte[] hash = md.digest(res);
    return hash;
    } catch (NoSuchAlgorithmException nsa) {
    return res;
    }
    }
    Credit must be given to Michael Spreitzenbarth's helpful blog post:
    http://forensics.spreitzenbarth.de/2012/02/28/cracking-the-pattern-lock-on-android/
    """

    import binascii
    import hashlib
    import itertools
    import os
    import sys

    __author__ = "Dan O'Day"
    __credits__ = ["Michael Spreitzenbarth", "Chema Garcia", "Kieron Craggs"]
    __version__ = "0.1"
    __maintainer__ = "Dan O'Day"
    __email__ = "[email protected]"
    __status__ = "Prototype"


    def brute_force_gesture_key_file(gestureSHA1):
    """
    Brute forces possible permutations of gesture.key file until one of them matches the supplied SHA1 hash sum.
    :param sha1sum: SHA1 hash sum value from gesture.key file
    :return: numeric permutation that matches the supplied SHA1 hash sum or null value (None) if not found
    """
    for i in range(3, 10): # pattern length between 3-9 digits
    print 'checking patterns with length %d...' % i
    perms = itertools.permutations([0, 1, 2, 3, 4, 5, 6, 7, 8], i)
    for combo in perms:
    pattern = ''.join(str(v) for v in combo)
    key = binascii.unhexlify(''.join('%02x' % int(c) for c in pattern))
    sha1 = hashlib.sha1(key).hexdigest()
    if sha1 == gestureSHA1: # eureka! we found it!
    return pattern
    return None # fail


    def main():
    fn = sys.argv[1]
    if not fn and not os.path.isfile(fn):
    print 'usage: bruteforcegesture.py gesture.key [more gesture.key files]'
    sys.exit(1)

    with open(fn, 'rb') as f:
    gestureSHA1 = f.read(hashlib.sha1().digest_size).encode('hex')

    if len(gestureSHA1) / 2 != hashlib.sha1().digest_size:
    print 'invalid gesture.key file'
    sys.exit(1)

    cracked_pattern = brute_force_gesture_key_file(gestureSHA1)

    if cracked_pattern:
    print 'pattern found:', cracked_pattern
    else:
    print 'pattern not found'


    if __name__ == '__main__':
    main()