-
-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathweakpass.py
More file actions
146 lines (118 loc) · 3.7 KB
/
weakpass.py
File metadata and controls
146 lines (118 loc) · 3.7 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python
import sys
import argparse
import os
import re
import time
import json
import socket
from urllib.request import urlopen, Request
from urllib.error import HTTPError
from dataclasses import dataclass
SEARCH_API = "https://weakpass.com/api/v1/search/{}.json"
@dataclass
class HashResponse:
type: str
hash: str
value: str
def __str__(self):
return f"{self.type}:{self.hash}:{self.value}"
def parse_args():
parser = argparse.ArgumentParser(description="Universal script for hash search/lookup")
parser.add_argument("value", nargs="?", help="Hash or string if file is not provided")
return parser.parse_args()
def fetch_search(input, retries=3, timeout=10):
url = SEARCH_API.format(input)
attempt = 0
while attempt < retries:
attempt += 1
try:
req = Request(url)
with urlopen(req, timeout=timeout) as resp:
raw = resp.read().decode()
data = json.loads(raw)
return HashResponse(
type=data.get("type", ""),
hash=data.get("hash", ""),
value=data.get("pass")
)
except HTTPError as e:
return None
except (socket.timeout, socket.error) as net_err:
if attempt >= retries:
return None
time.sleep(1)
continue
except Exception:
print("Exception")
if attempt >= retries:
return None
time.sleep(1)
continue
return None
def append_to_pot(hashrspn:HashResponse, filename: str = "weakpass.pot"):
try:
with open(filename, "a", encoding="utf-8") as f:
f.write(str(hashrspn) + "\n")
f.flush()
os.fsync(f.fileno())
return True
except Exception as e:
print(f"Write error: {e}")
return False
def detect_hash_type(hashstring):
if not re.match(r'^[0-9A-Fa-f]+$', hashstring):
return None
length = len(hashstring)
if length == 32:
return "NTLMD5"
elif length == 40:
return "SHA1"
elif length == 64:
return "SHA256"
elif length == 128:
return "SHA512"
else:
return None
def process_string(hashstring):
hashstring = hashstring.strip().lower()
if detect_hash_type(hashstring) == None:
sys.exit(1)
result=fetch_search(hashstring)
if result is not None:
print(result)
append_to_pot(result)
def process_file(filename):
with open(filename, "r", encoding="utf-8") as f:
total = sum(1 for _ in f)
bar_length = 30
processed = 0
with open(filename, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
processed += 1
if not line:
continue
else:
if detect_hash_type(line.lower()) is not None:
result=fetch_search(line.lower())
if result is not None:
print(result)
append_to_pot(result)
filled = int(bar_length * processed / total)
bar = "█" * filled + "-" * (bar_length - filled)
percent = (processed / total) * 100
sys.stdout.write(f"\r[{bar}] {percent:5.1f}% ({processed}/{total})")
sys.stdout.flush()
print("Done!")
def main():
args = parse_args()
if not args.value:
print("Error: requires file with hashes or hashstring")
sys.exit(1)
if not os.path.exists(args.value):
process_string(args.value)
else:
process_file(args.value)
if __name__ == "__main__":
main()