Tuesday, June 5, 2012

PATH - Password Analysis To HashCat

What is PATH: It is a script that integrates password analysis and Hashcat.

First and foremost let me say, I do not code on a regular basis. I created this script out of necessity and part laziness on my part(I always forgot which masks I already did). DigiNinja’s Password analysis tool Pipal is what got me thinking about creating this.Thanks to @digininja. I found myself analyzing list with Pipal and taking the Hashcat masks from the output one by one back into Hashcat. From time to time my box would sit idle because I didn’t know the exact moment the bruteforce had completed and sometimes it sat idle for hours. I grew tired of waiting and restarting Hashcat so I automated it and PATH was born. PATH is written in Python and is simple to use with a few command line options.
PATH can take a list of passwords then generate Hashcat masks and display them. However, the fun part comes in when you apply the cracking option. This takes your list, analyzes it, generates the masks and starts the brute-force attack, with each mask sequentially.

You can also start with just a list of hashes and a large dictionary and the cracking option. PATH can take this list start a dictionary attack, analyze the output, generate the masks and start the brute-force attack. You can even specify rules, if you do it will run the plain dictionary first then run it again with the rule applied.

Here is the help file:
Password Analysis To Hashcat (PATH): Generate Hashcat Masks From A Wordlist
Start a BruteForce Attack With The Results
optional arguments:
-h, –help show this help message and exit
-i INPUT, –input: Input File Name for Mask Analysis
-t TOP, –top:How Many Values Outputted Default 10
-o OUTPUT, –output: Output File Name
-c, –crackmode: Enables Brute ForceCrack Mode
-s SDICT, –sdict: Initial Dictionary
-p PHASH, –phash: Password Hash Type
-l HASHLIST, –hashlist: List of Hashes
-r RULES, –rules: Apply Rules to Inital Dictionary
-u, –usage How to Use This Tool
Example usage:
python PATH.py -s bigdict.txt -l hashes.txt -p 0 -o output.txt -c
python PATH.py -i plain.txt -c



This script requires a minimum of Python 2.7 and HashcatPlus. As long as the switches in Hashcat stay the same it should continue to work fine as versions progress. *This was tested only with MD5, LM and NTLM hashes. You must define the location of HashcatPlus in the script prior to running it.

****Thanks to the Linkedin hack I was able to confirm PATH works with SHA1.****
If you have trouble copy and pasting the code below. Here is just the text.
1:  #!/usr/bin/env python  
2:  #PATH created by F8lerror  
3:  #Follow me on Twitter @f8lerror  
4:    
5:  import subprocess  
6:  import string  
7:  import re  
8:  from collections import Counter  
9:  import argparse  
10:    
11:    
12:  hcpath = ''  
13:    
14:  if hcpath is '':  
15:       print "\nHEY! You need to put the path to hashcat in the script. In the hcpath parameter"  
16:    
17:    
18:    
19:  parser = argparse.ArgumentParser(description='Password Analysis To Hashcat (PATH):\nGenerate Hashcat Masks From A Wordlist Start a BruteForce Attack With The Results')  
20:  parser.add_argument('-i','--input', help='Input File Name for Mask Analysis', required=False)  
21:  parser.add_argument('-t','--top', help='How Many Values Outputed Default 10', required=False)  
22:  parser.add_argument('-o','--output', help='Output File Name', required=False)  
23:  parser.add_argument('-c','--crackmode', action='store_true', help='Enables Brute ForceCrack Mode', required=False)  
24:  parser.add_argument('-s','--sdict', help='Initial Dictionary', required=False)  
25:  parser.add_argument('-p','--phash', help='Password Hash Type', required=False)  
26:  parser.add_argument('-l','--hashlist', help='List of Hashes', required=False)  
27:  parser.add_argument('-r','--rules', help='Apply Rules to Inital Dictionary', required=False)  
28:  parser.add_argument('-u','--usage', action='store_true', help='How to Use This Tool', required=False)  
29:    
30:    
31:  args = parser.parse_args()  
32:    
33:  if args.usage is True:  
34:       print '-'*80+'\n'  
35:       print 'This was designed to help automate the process of cracking passwords. \nBy analyzing the output of cracked password PATH initiates brute force with the results\n\n'  
36:       print 'Example: Already have some passwords cracked: \n\t\"./toolname -i listofcrackedpasswords -l listofhashes -o outputfile -p hashtype -c\" \n\tThis will analyze the list and start a brute force against the top 10 most common hash masks'  
37:       print '\nExample: Fresh list of hashes: \n\t\"./toolname -l listofhashes -o outputfile -p hashtype -s bigdictonary -c\" \n\t This attack will do a dictonary attack first, then using what was cracked\n\t by the dictonary analyze the output and perform a brute force against the top 10 most common hash masks'  
38:       print '\n\nTo use rules add the -r flag to the dictonary attack\n'  
39:       print 'This has only been tested with the following hash types:\n\t0 = MD5\n\t1000 = NTLM\n\t3000 = LM\n'  
40:    
41:    
42:  def cracker():  
43:       flist = []  
44:       for line in ifile:  
45:                 line2 = re.sub(dhash, '', line)  
46:                 res = []  
47:                 for letter in line2.rstrip():  
48:                        
49:                      if re.search(ualpha, letter):  
50:                           res.append('?u')  
51:                      if re.search(lalpha, letter):  
52:                           res.append('?l')  
53:                      if re.search(ldigit, letter):  
54:                           res.append('?d')  
55:                      if re.search(splist, letter):  
56:                           res.append('?s')  
57:                 nlist = ''.join(res)   
58:                 flist.append(nlist)  
59:                   
60:         
61:       flist1 = '\n'.join(flist)  
62:       cnt = Counter()  
63:       for zlist in flist:  
64:            cnt[zlist] += 1  
65:    
66:    
67:       backtolist = cnt.items()  
68:    
69:       sortme = sorted(backtolist, key=lambda tup: tup[1], reverse=True)  
70:       if sortme:       
71:            print '\n'  
72:            print '-'*80  
73:            print 'Top '+str(num)+' Hashcat Masks with Frequency Count'   
74:            print '-'*80  
75:            print '\n'  
76:            for key, value in sortme[0:num]:  
77:                 print key +' ('+ str(value) +')'  
78:            usedmask = []  
79:    
80:    
81:                   
82:            if args.crackmode is True:  
83:                 if args.phash is None:  
84:                      print '\nOops! I need a hashtype. Hint: -p'  
85:                 elif args.output is None:  
86:                      print '\nOops! I need an output file. Hint: -o'  
87:                 elif args.hashlist is None:  
88:                      print '\nOops! I need something to crack. Hint: -l'  
89:                 else:  
90:                      for mask in sortme[0:num]:  
91:                           print '\n'  
92:                           print '-'*80  
93:                           print 'Now Brute Forcing With '+mask[0]  
94:                           print '-'*80  
95:                           print '\n'  
96:                           subprocess.call([hcpath, '--remove', '--hash-type', args.phash, '--attack-mode', '3', '--outfile', args.output, args.hashlist ,mask[0]])                 
97:                   
98:              
99:    
100:  if args.top is None:  
101:       num = 10  
102:  else:  
103:       num = int(args.top)  
104:    
105:  splist = r"[\W_]"  
106:  ualpha = r"[A-Z]"  
107:  lalpha = r"[a-z]"  
108:  ldigit = r"[0-9]"  
109:  dhash = r"^[a-f0-9]*:"  
110:    
111:    
112:    
113:  if args.sdict:  
114:       if args.rules:  
115:            print '\n'+'-'*80  
116:            print 'Starting Dictionary Attack'  
117:            print '-'*80+'\n'  
118:            if args.phash is None:  
119:                 print 'Oops! I need a hashtype. Hint: -p'  
120:            elif args.output is None:  
121:                 print 'Oops! We need an output file. Hint: -o'  
122:            elif args.hashlist is None:  
123:                 print 'Oops! I need something to crack. Hint: -l'  
124:            else:  
125:                 subprocess.call([hcpath, '--remove', '--hash-type', args.phash, '--outfile', args.output, args.hashlist ,args.sdict])  
126:                 print '\n'+'-'*80  
127:                 print 'Starting Dictionary with Rule Attack'  
128:                 print '-'*80+'\n'  
129:                 subprocess.call([hcpath, '--remove', '--hash-type', args.phash, '-r', args.rules, '--outfile', args.output, args.hashlist ,args.sdict])  
130:                 try:  
131:                      ifile = open(args.output, 'r')  
132:                      cracker()  
133:                 except IOError, err:  
134:                      print '\n'+'-'*80+'\n'+'The file doesn\'t exsist.\n'+'-'*80+'\n'  
135:       else:  
136:            print '\n'+'-'*80  
137:            print 'Starting Dictionary Attack'  
138:            print '-'*80+'\n'  
139:            if args.phash is None:  
140:                 print 'Oops! I need a hashtype. Hint: -p'  
141:            elif args.output is None:  
142:                 print 'Oops! We need an output file. Hint: -o'  
143:            elif args.hashlist is None:  
144:                 print 'Oops! I need something to crack. Hint: -l'  
145:            else:  
146:                 subprocess.call([hcpath, '--remove', '--hash-type', args.phash, '--outfile', args.output, args.hashlist ,args.sdict])  
147:                 try:  
148:                      ifile = open(args.output, 'r')  
149:                      cracker()  
150:                      ifile.close()  
151:                 except IOError, err:  
152:                      print '\n'+'-'*80+'\n'+'The file doesn\'t exsist.\n'+'-'*80+'\n'  
153:    
154:  if args.input:  
155:       try:  
156:            ifile = open(args.input, 'r')  
157:            cracker()  
158:       except IOError, err:  
159:            print '\n'+'-'*80+'\n'+'The file doesn\'t exsist.\n'+'-'*80+'\n'  
160:    
161:    

No comments:

Post a Comment