wuhp commited on
Commit
27aabbb
Β·
verified Β·
1 Parent(s): 39e1f35

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +191 -78
app.py CHANGED
@@ -1,150 +1,263 @@
1
  import gradio as gr
2
  import hashlib
3
- import bcrypt
4
- import base64
5
  import re
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- # -----------------------------
8
- # HASH DETECTION
9
- # -----------------------------
10
 
11
  def identify_hash(hash_value):
12
  possible = []
13
 
14
- if hash_value.startswith("$2a$") or hash_value.startswith("$2b$") or hash_value.startswith("$2y$"):
15
- possible.append("bcrypt")
16
-
17
- if hash_value.startswith("$argon2"):
18
- possible.append("Argon2")
19
-
20
- if hash_value.startswith("$6$"):
21
- possible.append("SHA512-Crypt")
22
-
23
- if hash_value.startswith("$5$"):
24
- possible.append("SHA256-Crypt")
25
 
 
26
  if re.fullmatch(r"[a-fA-F0-9]{32}", hash_value):
27
  possible.extend(["MD5", "NTLM"])
28
 
29
- if re.fullmatch(r"[a-fA-F0-9]{40}", hash_value):
30
  possible.append("SHA1")
31
 
32
- if re.fullmatch(r"[a-fA-F0-9]{64}", hash_value):
33
  possible.append("SHA256")
34
 
35
- if re.fullmatch(r"[a-fA-F0-9]{128}", hash_value):
36
  possible.append("SHA512")
37
 
 
 
 
 
 
 
 
38
  if not possible:
39
  possible.append("Unknown")
40
 
41
- return possible
42
 
43
 
44
- # -----------------------------
45
- # HASH VERIFICATION
46
- # -----------------------------
47
 
48
  def verify_hash(password, hash_value):
49
- results = []
50
-
51
  possible = identify_hash(hash_value)
52
 
53
  for alg in possible:
54
 
55
  try:
 
 
 
 
 
56
  if alg == "MD5":
57
- generated = hashlib.md5(password.encode()).hexdigest()
58
- if generated.lower() == hash_value.lower():
59
- results.append("βœ… MD5 match")
60
 
61
  elif alg == "SHA1":
62
- generated = hashlib.sha1(password.encode()).hexdigest()
63
- if generated.lower() == hash_value.lower():
64
- results.append("βœ… SHA1 match")
65
 
66
  elif alg == "SHA256":
67
- generated = hashlib.sha256(password.encode()).hexdigest()
68
- if generated.lower() == hash_value.lower():
69
- results.append("βœ… SHA256 match")
70
 
71
  elif alg == "SHA512":
72
- generated = hashlib.sha512(password.encode()).hexdigest()
73
- if generated.lower() == hash_value.lower():
74
- results.append("βœ… SHA512 match")
75
 
76
  elif alg == "NTLM":
77
- generated = hashlib.new(
78
- 'md4',
79
- password.encode('utf-16le')
80
  ).hexdigest()
81
 
82
- if generated.lower() == hash_value.lower():
83
- results.append("βœ… NTLM match")
 
 
 
 
84
 
85
  elif alg == "bcrypt":
86
  if bcrypt.checkpw(
87
  password.encode(),
88
  hash_value.encode()
89
  ):
90
- results.append("βœ… bcrypt match")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
- except Exception as e:
93
- results.append(f"Error testing {alg}: {str(e)}")
 
94
 
95
- return possible, "\n".join(results) if results else "No matches found."
 
96
 
 
97
 
98
- # -----------------------------
99
- # MAIN FUNCTION
100
- # -----------------------------
 
101
 
102
  def analyze(password, hash_value):
103
- possible, verification = verify_hash(password, hash_value)
104
 
105
- return (
106
- "\n".join(possible),
107
- verification
108
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
 
111
- # -----------------------------
112
- # GRADIO UI
113
- # -----------------------------
 
 
 
 
 
 
 
 
114
 
115
- with gr.Blocks(title="Hash Analyzer Lab") as demo:
116
- gr.Markdown("# Hash Analyzer / Verification Tool")
117
  gr.Markdown(
118
- "Educational hash identification and password verification utility."
 
 
 
 
 
 
 
 
119
  )
120
 
121
- password_input = gr.Textbox(
122
- label="Known Password",
123
- type="password",
124
- placeholder="Enter known plaintext password"
125
- )
126
 
127
- hash_input = gr.Textbox(
128
- label="Hash",
129
- lines=4,
130
- placeholder="Paste hash here"
131
- )
132
 
133
- analyze_btn = gr.Button("Analyze")
 
 
 
 
134
 
135
- possible_output = gr.Textbox(
136
- label="Possible Algorithms"
137
- )
 
 
 
 
 
 
 
 
 
 
138
 
139
- verification_output = gr.Textbox(
140
- label="Verification Results",
141
- lines=10
142
  )
143
 
144
  analyze_btn.click(
145
  fn=analyze,
146
  inputs=[password_input, hash_input],
147
- outputs=[possible_output, verification_output]
 
 
 
 
148
  )
149
 
150
  demo.launch()
 
1
  import gradio as gr
2
  import hashlib
 
 
3
  import re
4
+ import bcrypt
5
+
6
+ from passlib.hash import (
7
+ md5_crypt,
8
+ sha256_crypt,
9
+ sha512_crypt,
10
+ pbkdf2_sha256,
11
+ pbkdf2_sha512,
12
+ argon2,
13
+ bcrypt as passlib_bcrypt,
14
+ )
15
+
16
+ # -----------------------------------
17
+ # HASH IDENTIFICATION
18
+ # -----------------------------------
19
+
20
+ HASH_SIGNATURES = [
21
+ ("bcrypt", r"^\$2[aby]?\$"),
22
+ ("argon2", r"^\$argon2"),
23
+ ("sha512_crypt", r"^\$6\$"),
24
+ ("sha256_crypt", r"^\$5\$"),
25
+ ("md5_crypt", r"^\$1\$"),
26
+ ]
27
+
28
+ HASHCAT_MODES = {
29
+ "MD5": 0,
30
+ "SHA1": 100,
31
+ "SHA256": 1400,
32
+ "SHA512": 1700,
33
+ "NTLM": 1000,
34
+ "bcrypt": 3200,
35
+ "sha256_crypt": 7400,
36
+ "sha512_crypt": 1800,
37
+ "argon2": 22300,
38
+ "pbkdf2_sha256": 10900,
39
+ "pbkdf2_sha512": 12100,
40
+ }
41
 
 
 
 
42
 
43
  def identify_hash(hash_value):
44
  possible = []
45
 
46
+ # Prefix-based detection
47
+ for name, pattern in HASH_SIGNATURES:
48
+ if re.match(pattern, hash_value):
49
+ possible.append(name)
 
 
 
 
 
 
 
50
 
51
+ # Raw hex hashes
52
  if re.fullmatch(r"[a-fA-F0-9]{32}", hash_value):
53
  possible.extend(["MD5", "NTLM"])
54
 
55
+ elif re.fullmatch(r"[a-fA-F0-9]{40}", hash_value):
56
  possible.append("SHA1")
57
 
58
+ elif re.fullmatch(r"[a-fA-F0-9]{64}", hash_value):
59
  possible.append("SHA256")
60
 
61
+ elif re.fullmatch(r"[a-fA-F0-9]{128}", hash_value):
62
  possible.append("SHA512")
63
 
64
+ # PBKDF2 patterns
65
+ if "pbkdf2" in hash_value.lower():
66
+ if "sha256" in hash_value.lower():
67
+ possible.append("pbkdf2_sha256")
68
+ elif "sha512" in hash_value.lower():
69
+ possible.append("pbkdf2_sha512")
70
+
71
  if not possible:
72
  possible.append("Unknown")
73
 
74
+ return list(dict.fromkeys(possible))
75
 
76
 
77
+ # -----------------------------------
78
+ # VERIFY HASH
79
+ # -----------------------------------
80
 
81
  def verify_hash(password, hash_value):
82
+ matches = []
 
83
  possible = identify_hash(hash_value)
84
 
85
  for alg in possible:
86
 
87
  try:
88
+
89
+ # -----------------
90
+ # RAW HASHES
91
+ # -----------------
92
+
93
  if alg == "MD5":
94
+ h = hashlib.md5(password.encode()).hexdigest()
95
+ if h.lower() == hash_value.lower():
96
+ matches.append("βœ… MD5")
97
 
98
  elif alg == "SHA1":
99
+ h = hashlib.sha1(password.encode()).hexdigest()
100
+ if h.lower() == hash_value.lower():
101
+ matches.append("βœ… SHA1")
102
 
103
  elif alg == "SHA256":
104
+ h = hashlib.sha256(password.encode()).hexdigest()
105
+ if h.lower() == hash_value.lower():
106
+ matches.append("βœ… SHA256")
107
 
108
  elif alg == "SHA512":
109
+ h = hashlib.sha512(password.encode()).hexdigest()
110
+ if h.lower() == hash_value.lower():
111
+ matches.append("βœ… SHA512")
112
 
113
  elif alg == "NTLM":
114
+ h = hashlib.new(
115
+ "md4",
116
+ password.encode("utf-16le")
117
  ).hexdigest()
118
 
119
+ if h.lower() == hash_value.lower():
120
+ matches.append("βœ… NTLM")
121
+
122
+ # -----------------
123
+ # BCRYPT
124
+ # -----------------
125
 
126
  elif alg == "bcrypt":
127
  if bcrypt.checkpw(
128
  password.encode(),
129
  hash_value.encode()
130
  ):
131
+ matches.append("βœ… bcrypt")
132
+
133
+ # -----------------
134
+ # PASSLIB HASHES
135
+ # -----------------
136
+
137
+ elif alg == "sha256_crypt":
138
+ if sha256_crypt.verify(password, hash_value):
139
+ matches.append("βœ… sha256_crypt")
140
+
141
+ elif alg == "sha512_crypt":
142
+ if sha512_crypt.verify(password, hash_value):
143
+ matches.append("βœ… sha512_crypt")
144
+
145
+ elif alg == "md5_crypt":
146
+ if md5_crypt.verify(password, hash_value):
147
+ matches.append("βœ… md5_crypt")
148
+
149
+ elif alg == "argon2":
150
+ if argon2.verify(password, hash_value):
151
+ matches.append("βœ… argon2")
152
+
153
+ elif alg == "pbkdf2_sha256":
154
+ if pbkdf2_sha256.verify(password, hash_value):
155
+ matches.append("βœ… pbkdf2_sha256")
156
 
157
+ elif alg == "pbkdf2_sha512":
158
+ if pbkdf2_sha512.verify(password, hash_value):
159
+ matches.append("βœ… pbkdf2_sha512")
160
 
161
+ except Exception:
162
+ pass
163
 
164
+ return possible, matches
165
 
166
+
167
+ # -----------------------------------
168
+ # MAIN ANALYSIS
169
+ # -----------------------------------
170
 
171
  def analyze(password, hash_value):
 
172
 
173
+ possible, matches = verify_hash(password, hash_value)
174
+
175
+ alg_text = "\n".join(possible)
176
+
177
+ if matches:
178
+ verification = "\n".join(matches)
179
+ else:
180
+ verification = "❌ No verified match found."
181
+
182
+ # Hashcat suggestions
183
+ modes = []
184
+
185
+ for alg in possible:
186
+ if alg in HASHCAT_MODES:
187
+ modes.append(
188
+ f"{alg} β†’ Hashcat mode {HASHCAT_MODES[alg]}"
189
+ )
190
+
191
+ mode_text = "\n".join(modes) if modes else "No suggestions."
192
+
193
+ return alg_text, verification, mode_text
194
 
195
 
196
+ # -----------------------------------
197
+ # UI
198
+ # -----------------------------------
199
+
200
+ css = """
201
+ footer {
202
+ visibility: hidden;
203
+ }
204
+ """
205
+
206
+ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
207
 
 
 
208
  gr.Markdown(
209
+ """
210
+ # Pentest Hash Analyzer
211
+
212
+ Educational utility for:
213
+ - Hash identification
214
+ - Password verification
215
+ - Hashcat mode mapping
216
+ - CTF / TryHackMe workflows
217
+ """
218
  )
219
 
220
+ with gr.Row():
 
 
 
 
221
 
222
+ password_input = gr.Textbox(
223
+ label="Known Password",
224
+ type="password",
225
+ placeholder="Enter plaintext password"
226
+ )
227
 
228
+ hash_input = gr.Textbox(
229
+ label="Hash",
230
+ lines=6,
231
+ placeholder="Paste hash"
232
+ )
233
 
234
+ analyze_btn = gr.Button("Analyze Hash")
235
+
236
+ with gr.Row():
237
+
238
+ alg_output = gr.Textbox(
239
+ label="Possible Algorithms",
240
+ lines=8
241
+ )
242
+
243
+ verify_output = gr.Textbox(
244
+ label="Verification Results",
245
+ lines=8
246
+ )
247
 
248
+ hashcat_output = gr.Textbox(
249
+ label="Hashcat Modes",
250
+ lines=6
251
  )
252
 
253
  analyze_btn.click(
254
  fn=analyze,
255
  inputs=[password_input, hash_input],
256
+ outputs=[
257
+ alg_output,
258
+ verify_output,
259
+ hashcat_output
260
+ ]
261
  )
262
 
263
  demo.launch()