Skip to content

Add python3 support #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 28 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
# Android Pattern Lock Decoder

Pattern unlock on Android is entered by joining at least four points on a 3x3 matrix. Each
point can only be used once and the maximum number of points is nine. Android, internally
stores the pattern as a byte sequence. Each point is mapped to its index, where 0 represents
the top left point and 8 the bottom right one on the matrix. Thus the pattern is similar
to a PIN Lock with a minimum of four and and a maximum of nine digits but which only use
nine distinctive digits (0 to 8). Because points cannot be repeated in the pattern and
certain combinations are not possible (e.g. directly connecting 1 to 9), the number of
variations in an unlock pattern is considerably lower compared to those of a nine-digit PIN.
Pattern unlock on Android is entered by joining at least four points on a 3x3 matrix. Each point can only be used once and the maximum number of points is nine. Android, internally stores the pattern as a byte sequence.

Each point is mapped to its index, where 0 represents the top left point and 8 the bottom right one on the matrix. Thus the pattern is similar to a PIN Lock with a minimum of four and and a maximum of nine digits but which only use nine distinctive digits (0 to 8). Because points cannot be repeated in the pattern and certain combinations are not possible (e.g. directly connecting 1 to 9), the number of variations in an unlock pattern is considerably lower compared to those of a nine-digit PIN.

The Sha-1 hash of a pattern lock is stored in
```
Expand All @@ -17,23 +12,34 @@ The Sha-1 hash of a pattern lock is stored in
```
as an **unsalted** SHA-1 value.

Each pattern is always hashed to the same value because a random salt value isn't used
when calculating the hash. This makes it relatively easy to generate a precomputed table
of all possible patterns and their respective hashes. This allows for **instant** recovery
of the pattern once the `gesture.key` file is retrieved from the device. However the file,
is owned by the system user and its default permissions are set to `0600` so on production
devices recovery is not possible without rooting the device.
Each pattern is always hashed to the same value because a random salt value isn't used when calculating the hash. This makes it relatively easy to generate a precomputed table of all possible patterns and their respective hashes. This allows for **instant** recovery of the pattern once the `gesture.key` file is retrieved from the device. However the file,
is owned by the system user and its default permissions are set to `0600` so on production devices recovery is not possible without rooting the device.

## Usage

```bash
Usage: python3 androidpatterndecode.py -g <gesture.key> -d <dictionary file containing sha1 hashs>.

This program is used to recover android's pattern password.

Options:
-h, --help show this help message and exit
-g GESTURE_FILE, --gesture=GESTURE_FILE
Path to your gesture.key file in your local system
-d DICTIONARY_FILE, --dictionary=DICTIONARY_FILE
Path to your dictionary file containing sha1 hashes in
your local system
```

## Example

Example below uses the following pattern lock:

![Pattern-Lock](https://github.com/cvarta/droid-pattern-decoder/blob/master/res/img/device-2015-02-18-234613.png)
![Pattern-Lock](./res/img/pattern.png)

Copy the gesture.key file from `/data/system/gesture.key` to `/sdcard/` and pull the file
from the device using `adb pull /sdcard/gesture.key .`
Copy the gesture.key file from `/data/system/gesture.key` to `/sdcard/` and pull the file from the device using `adb pull /sdcard/gesture.key .`

To view the content use the od dump tool (Example file in [res/gesture.key](../master/res/gesture.key))
To view the content use the `od` dump tool or any hex editor like `ghex or HxD or xxd` (Example file in [res/gesture.key](./res/gesture.key))

```
$ od -t x1 < res/gesture.key
Expand All @@ -42,10 +48,9 @@ $ od -t x1 < res/gesture.key
0000024
```

To lookup the pattern use the supplied python script with the provided hash table:

```
$ ./src/androidpatterndecode.py -g ./res/gesture.key -d ./res/androidpatternsha1.txt
To retrieve the pattern from the `gesture.key` file, use the [androidpatterndecode.py](./androidpatterndecode.py) a python script by providing a hash table:

3214789
```bash
$ python3 androidpatterndecode.py -g res/gesture.key -d res/androidpatternsha1.txt
[+] Pattern retrieved from gesture.key file is: 3214789
```
59 changes: 41 additions & 18 deletions src/androidpatterndecode.py → androidpatterndecode.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,57 +1,80 @@
#!/usr/bin/python
#!/usr/bin/env python3

__author__ = 'Chris Yereaztian'

"""
This script recovers the pattern combination from Android's pattern lock.
To acquire the gesture.key file you need a rooted device.
"""

from optparse import OptionParser
import binascii

def b2s(a):
"""
Converts bytes to str
"""
return "".join(list(map(chr, a)))

def read_gesture(gesture_file_loc=""):
"""Reads gesture.key file and converts bytes to string"""
"""
Reads gesture.key file and converts bytes to string
"""
try:
gesture_file = open(gesture_file_loc, "rb")
sha1bytes = []
for i in range(0, 20):
sha1hash = gesture_file.read(1)
sha1bytes.append(sha1hash.encode('hex'))
i += 1
sha1bytes.append(binascii.hexlify(sha1hash))
# i += 1
sha1hash = ""
for i in range(0, 20):
sha1hash += sha1bytes[i]
return sha1hash
sha1hash += b2s(sha1bytes[i])
return(sha1hash)
except IOError:
print "[-] Gesture file cannot be opened. File not present or permission denied"
print("[-] Gesture file cannot be opened. File not present or permission denied")
exit(1)

def match_pattern(dictionary="", sha1hash=""):
"""Looks up hash in provided dictionary"""
"""
Looks up hash in provided dictionary
"""

sha1hash = str.upper(sha1hash)
dictionary_file = open(dictionary, "r")
lines = dictionary_file.readlines()

for line in lines:
if line.__contains__(sha1hash):
index = line.index(";", 0, 10)
pattern = line[0:index]
print ""
print pattern.center(80)
print("[+] Pattern retrieved from gesture.key file is: " + pattern)
# print(pattern.center(80))


def parse_opt():
#Create a option parser
parser = OptionParser("%prog [options].\n\rThis program is used to recover android's pattern passowrd.")
#Add options
# Create a option parser

parser = OptionParser("python3 %prog -g <gesture.key> -d <dictionary file containing sha1 hashs>.\n\rThis program is used to recover android's pattern password.")

# Add options

parser.add_option("-g", "--gesture", type="string", dest="gesture_file", help="Path to your gesture.key file in your local system")
parser.add_option("-d", "--dictionary", type="string", dest="dictionary_file", help="Path to your dictionary file in your local system")
#Parse options
parser.add_option("-d", "--dictionary", type="string", dest="dictionary_file", help="Path to your dictionary file containing sha1 hashes in your local system")

# Parse options

options, arguments = parser.parse_args()
#Verify all options are used

# Verify all options are used

if options.gesture_file and options.dictionary_file:
#Recover the pattern from the hash
# Recover the pattern from the hash
sha1hash = read_gesture(options.gesture_file)
match_pattern(options.dictionary_file, sha1hash)

else:
#Show help screen in case of missing arguments
# Show help screen in case of missing arguments
parser.print_help()
exit(1)

Expand Down
Binary file removed res/img/device-2015-02-18-234613.png
Binary file not shown.
Binary file added res/img/pattern.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.