-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathpybozocrack.py
108 lines (77 loc) · 3.23 KB
/
pybozocrack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python
import hashlib
import re
import urllib.request
from optparse import OptionParser
HASH_REGEX = re.compile("([a-fA-F0-9]{32})")
def dictionary_attack(h, wordlist):
for word in wordlist:
if hashlib.md5(word.encode('utf-8')).hexdigest() == h:
return word
def format_it(hash, plaintext):
return "{hash}:{plaintext}".format(hash=hash, plaintext=plaintext)
def crack_single_hash(h):
my_opener = urllib.request.build_opener()
my_opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows'
' NT 5.1; it; rv:1.8.1.11) '
' Gecko/20071127 Firefox/2.0.0.11')]
response = my_opener.open(
"http://www.google.com/search?q={hash}".format(hash=h))
wordlist = response.read().decode('utf-8').replace(
'.', ' ').replace(':', ' ').replace(
'?', '').replace("('", ' ').replace(
"'", ' ').split(' ')
plaintext = dictionary_attack(h, set(wordlist))
return plaintext
class BozoCrack(object):
def __init__(self, filename, *args, **kwargs):
self.hashes = []
with open(filename, 'r') as f:
hashes = [h.lower() for line in f if HASH_REGEX.match(line)
for h in HASH_REGEX.findall(line.replace('\n', ''))]
self.hashes = sorted(set(hashes))
print("Loaded {count} unique hashes".format(count=len(self.hashes)))
self.cache = self.load_cache()
def crack(self):
cracked_hashes = []
for h in self.hashes:
if h in self.cache:
print(format_it(h, self.cache[h]))
cracked_hashes.append((h, self.cache[h]))
continue
plaintext = crack_single_hash(h)
if plaintext:
print(format_it(h, plaintext))
self.cache[h] = plaintext
self.append_to_cache(h, plaintext)
cracked_hashes.append((h, plaintext))
return cracked_hashes
def load_cache(self, filename='cache'):
cache = {}
with open(filename, 'r') as c:
for line in c:
hash, plaintext = line.replace('\n', '').split(':', 1)
cache[hash] = plaintext
return cache
def append_to_cache(self, h, plaintext, filename='cache'):
with open(filename, 'a+') as c:
c.write(format_it(hash=h, plaintext=plaintext)+"\n")
def main(): # pragma: no cover
parser = OptionParser()
parser.add_option('-s', '--single', metavar='MD5HASH',
help='crack a single hash', dest='single', default=False)
parser.add_option('-f', '--file', metavar='HASHFILE',
help='crack multiple hashes on a file', dest='target',)
options, _ = parser.parse_args()
if not options.single and not options.target:
parser.error("please select -s or -f")
elif options.single:
plaintext = crack_single_hash(options.single)
if plaintext:
print(format_it(hash=options.single, plaintext=plaintext))
else:
cracked = BozoCrack(options.target).crack()
if not cracked:
print("No hashes were cracked.")
if __name__ == '__main__': # pragma: no cover
main()