fork download
  1. #!/usr/bin/env python
  2. """
  3. AndroidLockCracker - Cracking and generating Android lock hashes
  4. Copyright (C) 2022 George Nicolaou (george({at})silensec({dot})com) and Dovine Owuor
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://w...content-available-to-author-only...u.org/licenses/>.
  15. """
  16. from itertools import product
  17. import string, getopt, sys, hashlib, struct, time
  18.  
  19. SHA1_LEN = 40
  20. MD5_LEN = 32
  21.  
  22. class PasswordGestureGenerate(object):
  23. def __init__(self, sizeX=3, sizeY=3, gesture=None):
  24. self.sizeX = sizeX
  25. self.sizeY = sizeY
  26. self.gesture = gesture
  27. return
  28.  
  29. def point_to_coords(self, point, sizeX=3, sizeY=3):
  30. column = (point % sizeY) - 1
  31. row = ( point - column * sizeX ) - 1
  32. yield ( column, row )
  33.  
  34. def generate_gesture_string(self, gesture ):
  35. string = ""
  36. for point in gesture:
  37. string += chr(point)
  38. return string
  39.  
  40. def generate_self_hash(self):
  41. if self.gesture == None:
  42. print("Bad gesture string")
  43. return False
  44. return self.generate_hash(self.generate_gesture_string(self.gesture))
  45.  
  46. def generate_hash(self, gesture_string):
  47. return hashlib.sha1(gesture_string).hexdigest().upper()
  48.  
  49. class PasswordPinGenerate(object):
  50. def __init__(self, passwd=None, salt=None):
  51. self.passwd = passwd
  52. self.salt = salt
  53. if self.passwd != None and self.salt != None:
  54. self.salted = self.passwd + self.salt
  55. else:
  56. self.salted = None
  57. return
  58.  
  59. def set_salt(self, salt=None):
  60. if salt == None:
  61. print("Bad salt")
  62. return False
  63. self.salt = salt
  64. return True
  65.  
  66. def generate_self_hash_sha1(self):
  67. if self.salted == None:
  68. self.salted = self.passwd + self.salt
  69. return hashlib.sha1(self.salted).hexdigest()
  70.  
  71. def generate_hash_sha1(self, passwd):
  72. salted = passwd + self.salt
  73. return hashlib.sha1(salted).hexdigest()
  74.  
  75. def generate_self_hash(self):
  76. salted = self.passwd + self.salt
  77. return (hashlib.sha1(salted).hexdigest() +
  78. hashlib.md5(salted).hexdigest()).upper()
  79.  
  80. def generate_hash(self, passwd):
  81. salted = passwd + self.salt
  82. return (hashlib.sha1(salted).hexdigest() +
  83. hashlib.md5(salted).hexdigest()).upper()
  84.  
  85. class PasswordPinCracker(object):
  86. def __init__(self, phash, salt, plengthbegin=4, plengthend=4, numeric=True,
  87. alpha=False, symbols=False):
  88. self.phash = phash.upper()
  89. self.phash_sha1 = phash[:SHA1_LEN]
  90. self.phash_md5 = phash[SHA1_LEN:]
  91. self.salt = salt
  92. self.plengthbegin = plengthbegin
  93. self.plengthend = plengthend
  94. self.numeric = numeric
  95. self.alpha = alpha
  96. self.symbols = symbols
  97. return
  98.  
  99. def _gen_charlist(self):
  100. charlist = ""
  101. if self.numeric == True:
  102. charlist += string.digits
  103. if self.alpha == True:
  104. charlist += string.ascii_letters
  105. if self.symbols == True:
  106. charlist += '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '
  107. return [_ for _ in charlist]
  108.  
  109. def begin_wordlist_crack(self, wordlist):
  110. try:
  111. wordlist = [l.strip() for l in open(wordlist)]
  112. except:
  113. print ("Bad wordlist file")
  114. return False
  115.  
  116. generator = PasswordPinGenerate()
  117. generator.set_salt(self.salt)
  118. for passwd in wordlist:
  119. phash_sha1 = generator.generate_hash_sha1(passwd)
  120. if self.phash_sha1 == phash_sha1:
  121. phash = generator.generate_hash(passwd)
  122. if self.phash == phash:
  123. return passwd
  124. return False
  125.  
  126. def begin_brute_crack(self):
  127. generator = PasswordPinGenerate()
  128. generator.set_salt(self.salt)
  129. charlist = self._gen_charlist()
  130. for length in xrange(self.plengthbegin, self.plengthend+1):
  131. for passwd in product(charlist, repeat=length):
  132. passwd = ''.join(passwd)
  133. phash = generator.generate_hash(passwd)
  134. if self.phash == phash:
  135. return passwd
  136. return False
  137.  
  138. class PasswordGestureCracker(object):
  139. def __init__(self, phash, sizeX=3, sizeY=3, lengthbegin=4, lengthend=4):
  140. self.phash = phash.upper()
  141. self.sizeX = sizeX
  142. self.sizeY = sizeY
  143. self.lengthbegin = lengthbegin
  144. self.lengthend = lengthend
  145. return
  146.  
  147. def _gen_points(self):
  148. return [ _ for _ in range(self.sizeX*self.sizeY)]
  149.  
  150. def begin_brute_crack(self):
  151. generator = PasswordGestureGenerate(self.sizeX, self.sizeY)
  152. gridpoints = self._gen_points()
  153. for length in xrange( self.lengthbegin, self.lengthend+1):
  154. #XXX Replace product() with something that doesn't generate
  155. #repetitions (eg 1,1,...)
  156. for passwd in product(gridpoints, repeat=length):
  157. phash = generator.generate_hash(generator.generate_gesture_string(passwd))
  158. if phash == self.phash:
  159. return passwd
  160. return False
  161.  
  162. def usage():
  163. options = [
  164. {"title": "Global Options:"},
  165. {"short": "-h", "long": "--help", "descr": "This help text"},
  166. {"short": "-s", "long": "--salt=", "descr": "The password salt (in decimal)"},
  167. {"title": "Cracking options:"},
  168. {"short": "-l", "long": "--length=", "descr": "The password fixed length"},
  169. {"short": "-B", "long": "--lengthbegin=", "descr": "The password begin length"},
  170. {"short": "-E", "long": "--lengthend=", "descr": "The password end length"},
  171. {"title": "PIN Cracking/Generation:"},
  172. {"short": "-w", "long": "--wordlist", "descr": "Use password wordlist"},
  173. {"short": "-a", "long": "--alpha", "descr": "Include letters in password generation/cracking"},
  174. {"short": "-n", "long": "--numeric", "descr": "Include numbers in password generation/cracking"},
  175. {"short": "-b", "long": "--symbols", "descr": "Include symbols in password generation/cracking"},
  176. {"title": "Gesture Cracking/Generation:"},
  177. {"short": "-g", "long": "--gridsize", "descr": "Grid square size eg: -g 3 (for 3x3)"},
  178. ]
  179. print ("%s %s %s" % ( sys.argv[0], "[OPTION(S)]", "TYPE LOCK PASSWORD/HASH [SALT]" ))
  180. print ("Author: George Nicolaou, Silensec and Dovine Owuor")
  181. print( "TYPE - The type of processing to do:\n\tcrack - For cracking\n\tgenerate - For generating hashes")
  182. print( "LOCK - The device lock type:\n\tpin - For PIN/Password locks (requires salt)\n\tgesture - For Gesture locks")
  183. print ("PASSWORD/HASH - The password to generate hash for or the hash to crack password for.\n\t\t(Note: dump gesture hash using `hashdump -C gesture.key`)")
  184. print ("SALT - The password salt to generate password with or the salt to crack password with (in decimal)\n")
  185. for opt in options:
  186. if "title" in opt:
  187. print( opt["title"])
  188. else:
  189. print( "\t%s %s\t%s" % (opt["short"], opt["long"], opt["descr"]))
  190. print ("Note: Default settings include only numeric PIN cracking")
  191. sys.exit()
  192.  
  193. class Options(object):
  194. PIN = 1
  195. GESTURE = 2
  196. salt = None
  197. passwd = None
  198. lock = None
  199. passwd_length = None
  200. passwd_length_begin = 4
  201. passwd_length_end = 16
  202. wordlist = None
  203. alpha = False
  204. numeric = True
  205. symbols = False
  206. gridX = 3
  207. gridY = 3
  208.  
  209. def handle_generate(opts):
  210. if opts.lock == opts.PIN:
  211. generator = PasswordPinGenerate(opts.passwd, opts.salt)
  212. phash = generator.generate_self_hash()
  213. print( "Password Hash: %s\nPassword Salt: %s" % (phash, opts.strsalt))
  214. sys.exit()
  215. elif opts.lock == opts.GESTURE:
  216. gesture = [int(n)-1 for n in opts.passwd.split(",")]
  217. generator = PasswordGestureGenerate( opts.gridX, opts.gridY, gesture )
  218. print ("Gesture Hash: %s\nGesture: %s" % (generator.generate_self_hash()),
  219. opts.passwd)
  220. return
  221.  
  222. def handle_crack(opts):
  223. if opts.lock == opts.PIN:
  224. if opts.passwd_length != None:
  225. opts.passwd_length_begin = opts.passwd_length
  226. opts.passwd_length_end = opts.passwd_length
  227. if opts.salt == None:
  228. print ("No salt specified")
  229. return
  230. cracker = PasswordPinCracker( opts.passwd, opts.salt,
  231. opts.passwd_length_begin,
  232. opts.passwd_length_end, opts.numeric,
  233. opts.alpha, opts.symbols )
  234. print ("Cracking... (this might take a while)")
  235. if opts.wordlist != None:
  236. start = time.time()
  237. passwd = cracker.begin_wordlist_crack(opts.wordlist)
  238. took = time.time() - start
  239. else:
  240. start = time.time()
  241. passwd = cracker.begin_brute_crack()
  242. took = time.time() - start
  243. elif opts.lock == opts.GESTURE:
  244. if opts.passwd_length != None:
  245. opts.passwd_length_begin = opts.passwd_length
  246. opts.passwd_length_end = opts.passwd_length
  247. cracker = PasswordGestureCracker( opts.passwd, opts.gridX, opts.gridY,
  248. opts.passwd_length_begin,
  249. opts.passwd_length_end )
  250.  
  251. print ("Cracking... (this might take a while)")
  252. start = time.time()
  253. passwd = cracker.begin_brute_crack()
  254. took = time.time() - start
  255. if passwd != False:
  256. passwd = ','.join([str(x+1) for x in passwd])
  257. if passwd == False:
  258. print ("Not found - Processing time: %.4f seconds" % took)
  259. else:
  260. print ("Processing time: %.4f seconds\nPassword: %s" % ( took, passwd ))
  261. return
  262.  
  263. def main():
  264. if len(sys.argv) < 2:
  265. usage()
  266. try:
  267. opts, args = getopt.getopt(sys.argv[1:], "hs:l:B:E:w:anbg:",
  268. ["help","salt=","length=", "lengthbegin=", "lengthend=",
  269. "wordlist=", "alpha", "numeric","symbols","gridsize="])
  270. except:
  271. usage()
  272.  
  273. if len(args) < 3:
  274. usage()
  275. options = Options()
  276.  
  277. for opt, arg in opts:
  278. if opt in ('-h', '--help'):
  279. usage()
  280. elif opt in ('-s', '--salt'):
  281. options.salt = struct.pack('>q', long(arg)).encode("hex")
  282. options.strsalt = arg
  283. elif opt in ('-l', '--length'):
  284. options.passwd_length = int(arg)
  285. elif opt in ('-B', '--lengthbegin'):
  286. options.passwd_length_begin = int(arg)
  287. elif opt in ('-E', '--lengthend'):
  288. options.passwd_length_end = int(arg)
  289. elif opt in ('-w', '--wordlist'):
  290. options.wordlist = arg
  291. elif opt in ('-a', '--alpha'):
  292. options.alpha = True
  293. elif opt in ('-n', '--numeric'):
  294. options.numeric = True
  295. elif opt in ('-b', '--symbols'):
  296. options.symbols = True
  297. elif opt in ('-g', '--gridsize'):
  298. options.gridX = int(arg)
  299. options.gridY = int(arg)
  300.  
  301. if args[1] in ("pin", "PIN"):
  302. options.lock = options.PIN
  303. elif args[1] in ("gesture", "GESTURE"):
  304. options.lock = options.GESTURE
  305. else:
  306. usage()
  307.  
  308. options.passwd = args[2]
  309. if len(args) == 4:
  310. options.salt = struct.pack('>q', long(args[3])).encode("hex")
  311. options.strsalt = args[3]
  312. if args[0] in ("crack", "CRACK"):
  313. handle_crack(options)
  314. elif args[0] in ("generate", "GENERATE"):
  315. handle_generate(options)
  316. else:
  317. usage()
  318.  
  319. if __name__ == "__main__":
  320. main()
  321.  
Success #stdin #stdout 0.02s 9540KB
stdin
Standard input is empty
stdout
prog [OPTION(S)] TYPE LOCK PASSWORD/HASH [SALT]
Author: George Nicolaou, Silensec and Dovine Owuor
TYPE - The type of processing to do:
	crack - For cracking
	generate - For generating hashes
LOCK - The device lock type:
	pin - For PIN/Password locks (requires salt)
	gesture - For Gesture locks
PASSWORD/HASH - The password to generate hash for or the hash to crack password for.
		(Note: dump gesture hash using `hashdump -C gesture.key`)
SALT - The password salt to generate password with or the salt to crack password with (in decimal)

Global Options:
	-h --help	This help text
	-s --salt=	The password salt (in decimal)
Cracking options:
	-l --length=	The password fixed length
	-B --lengthbegin=	The password begin length
	-E --lengthend=	The password end length
PIN Cracking/Generation:
	-w --wordlist	Use password wordlist
	-a --alpha	Include letters in password generation/cracking
	-n --numeric	Include numbers in password generation/cracking
	-b --symbols	Include symbols in password generation/cracking
Gesture Cracking/Generation:
	-g --gridsize	Grid square size eg: -g 3 (for 3x3)
Note: Default settings include only numeric PIN cracking