├── DecodeAndroidGesture.jar ├── DecodeAndroidGesture.java ├── MANIFEST.MF └── README.md /DecodeAndroidGesture.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jzyra/DecodeAndroidGesture/2f67654254dd76ca97ce3f9daff4ad02d7c0437b/DecodeAndroidGesture.jar -------------------------------------------------------------------------------- /DecodeAndroidGesture.java: -------------------------------------------------------------------------------- 1 | import java.io.FileInputStream; 2 | import java.io.IOException; 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.util.Arrays; 6 | import java.util.Formatter; 7 | 8 | /** 9 | * Read sequence gesture for validate Android's pattern lock screen in gesture.key file. 10 | * @author Jeremy ZYRA 11 | * @version 1.0 12 | */ 13 | public final class DecodeAndroidGesture { 14 | /** 15 | * Constructor of the class. 16 | */ 17 | private DecodeAndroidGesture() { 18 | } 19 | 20 | /** 21 | * Convert byte array to hexadecimal string. 22 | * @param hash The byte array 23 | * @return hexadecimal representation of byte array 24 | */ 25 | private static String byteToHex(final byte[] hash) { 26 | Formatter formatter = new Formatter(); 27 | //Convert to hexadecimal for each byte in hash 28 | for (byte b : hash) { 29 | formatter.format("%02x", b); 30 | } 31 | String result = formatter.toString(); 32 | formatter.close(); 33 | return result; 34 | } 35 | 36 | /** 37 | * Hash to SHA-1 the gesture code. 38 | * @param code Code in byte array 39 | * @return SHA-1 String representation 40 | */ 41 | private static String hashCode(final int[] code) { 42 | byte[] byteArray = new byte[code.length]; 43 | //Convert int array to byte array 44 | for (int i = 0; i < code.length; ++i) { 45 | byteArray[i] = (byte) code[i]; 46 | } 47 | String result = new String(""); 48 | try { 49 | MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); 50 | //Hash code byte array 51 | sha1.update(byteArray); 52 | result = byteToHex(sha1.digest()); 53 | } catch (NoSuchAlgorithmException e) { 54 | System.out.println("[-] Error: " + e.getMessage()); 55 | System.exit(0); 56 | } 57 | return result; 58 | } 59 | 60 | /** 61 | * Concatenates all elements in array. 62 | * @param array It's array to concatenate. 63 | * @return String representation of all elements concatened 64 | */ 65 | private static String joinArray(final int[] array) { 66 | String result = new String(""); 67 | //For each byte in array, add byte in result String. 68 | for (int i = 0; i < array.length; ++i) { 69 | result += array[i]; 70 | } 71 | return result; 72 | } 73 | 74 | /** 75 | * Add element in array. 76 | * @param org It's array target. 77 | * @param added It's value to added at array. 78 | * @return Array with the new value 79 | */ 80 | private static int[] addElement(final int[] org, final int added) { 81 | int[] result = Arrays.copyOf(org, org.length + 1); 82 | result[org.length] = added; 83 | return result; 84 | } 85 | 86 | /** 87 | * Remove element in array. 88 | * @param arg It's array target. 89 | * @param value It's value to remove in array 90 | * @return Array without the value 91 | */ 92 | private static int[] deleteElement(final int[] arg, final int value) { 93 | int[] result = new int[arg.length - 1]; 94 | int count = 0; 95 | for (int element : arg) { 96 | if (element != value) { 97 | result[count] = element; 98 | count++; 99 | } 100 | } 101 | return result; 102 | } 103 | 104 | /** 105 | * Search the gesture code. 106 | * @param tab1 Array of int elements 107 | * @param tab2 Array of int elements 108 | * @param hash SHA-1 hash in gesture.key file 109 | * @return Code in string format or empty string ifi algorithme don't find code. 110 | */ 111 | private static String genHashs(final int[] tab1, final int[] tab2, final String hash) { 112 | int[] code = {}; 113 | int[] param = {}; 114 | String result = new String(""); 115 | //Browse all possible sequence. 116 | for (int i = 0; i < tab2.length; ++i) { 117 | code = tab1; 118 | code = addElement(code, tab2[i]); 119 | //If code size is more than 3. 120 | if (code.length > 3) { 121 | //If the hash code to sequence is equal to hash in gesture.key, the sequence is found. 122 | if (hashCode(code).equals(hash)) { 123 | return joinArray(code); 124 | } 125 | } 126 | param = tab2; 127 | param = deleteElement(param, tab2[i]); 128 | result = genHashs(code, param, hash); 129 | if (!result.equals("")) { 130 | return result; 131 | } 132 | } 133 | return ""; 134 | } 135 | 136 | /** 137 | * Read the hash in gesture.key file. 138 | * @param file The path to gesture.key file. 139 | * @return SHA-1 hash in file. 140 | */ 141 | private static String readGestureFile(final String file) { 142 | String sha1 = new String(""); 143 | try { 144 | int n = 0; 145 | //Open gesture.key file 146 | FileInputStream gesture = new FileInputStream(file); 147 | while ((n = gesture.read()) >= 0) { 148 | //If the byte is less than 16, add 0 in string for format byte with two digits in string. 149 | if (n < 0x10) { 150 | sha1 += "0" + Integer.toHexString(n); 151 | } else { 152 | sha1 += Integer.toHexString(n); 153 | } 154 | } 155 | gesture.close(); 156 | //Display error if gesture.key file can't be opened. 157 | } catch (IOException e) { 158 | System.out.println("[-] Error: " + e.getMessage()); 159 | System.exit(0); 160 | } 161 | return sha1; 162 | } 163 | 164 | /** 165 | * The function print the usage. 166 | */ 167 | private static void printHelp() { 168 | System.out.println("NAME"); 169 | System.out.println("\tDecodeAndroidGesture.jar\n"); 170 | System.out.println("SYNOPSIS"); 171 | System.out.println("\tDecodeAndroidGesture.jar FILE\n"); 172 | System.out.println("DESCRIPTION"); 173 | System.out.println("\tDecode gesture.key file in Android device."); 174 | System.out.println("\tThis file is at : /data/system/gesture.key\n"); 175 | System.out.println("\tFILE"); 176 | System.out.println("\t\tSet the path to gesture.key file.\n"); 177 | System.out.println("\tThe sequence returned by this application is the order of balls validation."); 178 | System.out.println("\tThe Android's screen can be represented by this pattern : (Each digit represent a ball)\n"); 179 | System.out.println("\t+---+---+---+"); 180 | System.out.println("\t| 0 | 1 | 2 |"); 181 | System.out.println("\t+---+---+---+"); 182 | System.out.println("\t| 3 | 4 | 5 |"); 183 | System.out.println("\t+---+---+---+"); 184 | System.out.println("\t| 6 | 7 | 8 |"); 185 | System.out.println("\t+---+---+---+\n"); 186 | System.out.println("AUTHOR"); 187 | System.out.println("\tJeremy ZYRA"); 188 | } 189 | 190 | /** 191 | * Entry point program. 192 | * @param args The path to gesture.key file. 193 | */ 194 | public static void main(final String[] args) { 195 | int[] tab1 = {}; 196 | int[] tab2 = {0, 1, 2, 3, 4, 5, 6, 7, 8}; 197 | String hash, sequence; 198 | //Check parameters. 199 | if (args.length == 1) { 200 | hash = readGestureFile(args[0]); 201 | System.out.println("[+] Searching..."); 202 | //Launch algorithm for search sequence. 203 | sequence = genHashs(tab1, tab2, hash); 204 | //If sequence not found. 205 | if (sequence.equals("")) { 206 | System.out.println("[-] Sequence not found. "); 207 | } else { 208 | System.out.println("[+] Sequence: " + sequence); 209 | } 210 | //Print usage command. 211 | } else { 212 | printHelp(); 213 | } 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: . 3 | Main-Class: DecodeAndroidGesture 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DecodeAndroidGesture 2 | 3 | This tool decode Android's pattern lock screen with gesture.key file in Android device. 4 | It just decode 3x3 dimensions schema. 5 | 6 | # Usage 7 | 8 | You can copy Android's file at /data/system/gesture.key in your computer. 9 | And run jar file : 10 | 11 | java -jar DecodeAndroidGesture.jar gesture.key 12 | 13 | After a few instant, the tool return digits sequence. 14 | Each digits represent a ball in your Android's pattern lock screen. 15 | 16 | Android's pattern lock screen can be represented by this schema : 17 | 18 | +---+---+---+ 19 | | 0 | 1 | 2 | 20 | +---+---+---+ 21 | | 3 | 4 | 5 | 22 | +---+---+---+ 23 | | 6 | 7 | 8 | 24 | +---+---+---+ 25 | 26 | 27 | In this schema, each digits represent a ball. 28 | 29 | --------------------------------------------------------------------------------