wuhp commited on
Commit
fde4d6e
Β·
verified Β·
1 Parent(s): 4202aa1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +240 -183
app.py CHANGED
@@ -1,5 +1,7 @@
1
  import gradio as gr
2
  import hashlib
 
 
3
  import re
4
  import bcrypt
5
 
@@ -7,257 +9,312 @@ 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()
 
1
  import gradio as gr
2
  import hashlib
3
+ import zlib
4
+ import base64
5
  import re
6
  import bcrypt
7
 
 
9
  md5_crypt,
10
  sha256_crypt,
11
  sha512_crypt,
 
 
12
  argon2,
 
13
  )
14
 
15
  # -----------------------------------
16
+ # JAVA HASHCODE
17
  # -----------------------------------
18
 
19
+ def java_string_hashcode(s):
20
+ h = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ for ch in s:
23
+ h = (31 * h + ord(ch)) & 0xFFFFFFFF
24
 
25
+ # convert to signed int32
26
+ if h >= 0x80000000:
27
+ h -= 0x100000000
 
 
 
 
 
 
 
 
28
 
29
+ return str(h)
 
30
 
 
 
31
 
32
+ # -----------------------------------
33
+ # DJB2
34
+ # -----------------------------------
35
 
36
+ def djb2(s):
37
+ h = 5381
 
 
 
 
38
 
39
+ for c in s:
40
+ h = ((h << 5) + h) + ord(c)
41
 
42
+ return str(h & 0xFFFFFFFF)
43
 
44
 
45
  # -----------------------------------
46
+ # FNV1A 32
47
  # -----------------------------------
48
 
49
+ def fnv1a_32(s):
50
+ h = 0x811c9dc5
 
 
 
51
 
52
+ for c in s:
53
+ h ^= ord(c)
54
+ h *= 0x01000193
55
+ h &= 0xFFFFFFFF
56
 
57
+ return str(h)
 
 
58
 
 
 
 
 
59
 
60
+ # -----------------------------------
61
+ # BASE64 CHECK
62
+ # -----------------------------------
 
63
 
64
+ def is_base64(value):
65
+ try:
66
+ decoded = base64.b64decode(value).decode()
67
+ return decoded
68
+ except:
69
+ return None
70
 
 
 
 
 
71
 
72
+ # -----------------------------------
73
+ # IDENTIFY HASH
74
+ # -----------------------------------
 
 
75
 
76
+ def identify_hash(hash_value):
 
77
 
78
+ possible = []
 
 
79
 
80
+ if hash_value.startswith("$2"):
81
+ possible.append("bcrypt")
 
 
 
 
82
 
83
+ if hash_value.startswith("$argon2"):
84
+ possible.append("argon2")
 
85
 
86
+ if hash_value.startswith("$6$"):
87
+ possible.append("sha512_crypt")
 
88
 
89
+ if hash_value.startswith("$5$"):
90
+ possible.append("sha256_crypt")
 
91
 
92
+ if re.fullmatch(r"[a-fA-F0-9]{32}", hash_value):
93
+ possible.extend(["MD5", "NTLM"])
 
94
 
95
+ elif re.fullmatch(r"[a-fA-F0-9]{40}", hash_value):
96
+ possible.append("SHA1")
 
97
 
98
+ elif re.fullmatch(r"[a-fA-F0-9]{64}", hash_value):
99
+ possible.append("SHA256")
 
100
 
101
+ elif re.fullmatch(r"[a-fA-F0-9]{128}", hash_value):
102
+ possible.append("SHA512")
 
103
 
104
+ # Integer hashes
105
+ if re.fullmatch(r"-?\d+", hash_value):
106
+ possible.extend([
107
+ "Java String.hashCode()",
108
+ "CRC32",
109
+ "Adler32",
110
+ "DJB2",
111
+ "FNV1a-32"
112
+ ])
113
 
114
+ return list(dict.fromkeys(possible))
115
 
116
 
117
  # -----------------------------------
118
+ # VERIFY
119
  # -----------------------------------
120
 
121
+ def verify(password, hash_value):
122
+
123
+ results = []
124
+
125
+ # -------------------------
126
+ # STANDARD HASHES
127
+ # -------------------------
128
+
129
+ try:
130
+ if hashlib.md5(password.encode()).hexdigest().lower() == hash_value.lower():
131
+ results.append("βœ… MD5")
132
+ except:
133
+ pass
134
+
135
+ try:
136
+ if hashlib.sha1(password.encode()).hexdigest().lower() == hash_value.lower():
137
+ results.append("βœ… SHA1")
138
+ except:
139
+ pass
140
+
141
+ try:
142
+ if hashlib.sha256(password.encode()).hexdigest().lower() == hash_value.lower():
143
+ results.append("βœ… SHA256")
144
+ except:
145
+ pass
146
+
147
+ try:
148
+ if hashlib.sha512(password.encode()).hexdigest().lower() == hash_value.lower():
149
+ results.append("βœ… SHA512")
150
+ except:
151
+ pass
152
+
153
+ # -------------------------
154
+ # JAVA HASHCODE
155
+ # -------------------------
156
+
157
+ try:
158
+ if java_string_hashcode(password) == hash_value:
159
+ results.append("βœ… Java String.hashCode()")
160
+ except:
161
+ pass
162
+
163
+ # -------------------------
164
+ # CRC32
165
+ # -------------------------
166
+
167
+ try:
168
+ crc = zlib.crc32(password.encode())
169
+
170
+ signed_crc = crc
171
+ if crc >= 0x80000000:
172
+ signed_crc -= 0x100000000
173
+
174
+ if str(crc) == hash_value or str(signed_crc) == hash_value:
175
+ results.append("βœ… CRC32")
176
+ except:
177
+ pass
178
+
179
+ # -------------------------
180
+ # ADLER32
181
+ # -------------------------
182
+
183
+ try:
184
+ adler = zlib.adler32(password.encode())
185
+
186
+ signed_adler = adler
187
+ if adler >= 0x80000000:
188
+ signed_adler -= 0x100000000
189
+
190
+ if str(adler) == hash_value or str(signed_adler) == hash_value:
191
+ results.append("βœ… Adler32")
192
+ except:
193
+ pass
194
+
195
+ # -------------------------
196
+ # DJB2
197
+ # -------------------------
198
+
199
+ try:
200
+ if djb2(password) == hash_value:
201
+ results.append("βœ… DJB2")
202
+ except:
203
+ pass
204
+
205
+ # -------------------------
206
+ # FNV1A
207
+ # -------------------------
208
+
209
+ try:
210
+ if fnv1a_32(password) == hash_value:
211
+ results.append("βœ… FNV1a-32")
212
+ except:
213
+ pass
214
+
215
+ # -------------------------
216
+ # BCRYPT
217
+ # -------------------------
218
+
219
+ try:
220
+ if hash_value.startswith("$2"):
221
+ if bcrypt.checkpw(
222
+ password.encode(),
223
+ hash_value.encode()
224
+ ):
225
+ results.append("βœ… bcrypt")
226
+ except:
227
+ pass
228
+
229
+ # -------------------------
230
+ # PASSLIB
231
+ # -------------------------
232
+
233
+ try:
234
+ if hash_value.startswith("$6$"):
235
+ if sha512_crypt.verify(password, hash_value):
236
+ results.append("βœ… sha512_crypt")
237
+ except:
238
+ pass
239
+
240
+ try:
241
+ if hash_value.startswith("$5$"):
242
+ if sha256_crypt.verify(password, hash_value):
243
+ results.append("βœ… sha256_crypt")
244
+ except:
245
+ pass
246
+
247
+ try:
248
+ if hash_value.startswith("$argon2"):
249
+ if argon2.verify(password, hash_value):
250
+ results.append("βœ… argon2")
251
+ except:
252
+ pass
253
+
254
+ # -------------------------
255
+ # BASE64
256
+ # -------------------------
257
+
258
+ decoded = is_base64(hash_value)
259
+
260
+ if decoded is not None:
261
+ if decoded == password:
262
+ results.append("βœ… Base64 encoded string")
263
+
264
+ return results
265
 
 
266
 
267
+ # -----------------------------------
268
+ # MAIN
269
+ # -----------------------------------
 
270
 
271
+ def analyze(password, hash_value):
 
272
 
273
+ possible = identify_hash(hash_value)
 
 
 
 
274
 
275
+ results = verify(password, hash_value)
276
 
277
+ return (
278
+ "\n".join(possible) if possible else "Unknown",
279
+ "\n".join(results) if results else "No matches found."
280
+ )
281
 
282
 
283
  # -----------------------------------
284
  # UI
285
  # -----------------------------------
286
 
287
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
 
 
 
 
288
 
289
+ gr.Markdown("# Advanced Hash / Encoding Analyzer")
 
 
 
 
 
 
 
 
 
 
 
 
290
 
291
  with gr.Row():
292
 
293
+ password = gr.Textbox(
294
  label="Known Password",
295
+ type="password"
 
296
  )
297
 
298
+ hash_value = gr.Textbox(
299
+ label="Hash / Encoded Value",
300
+ lines=5
 
301
  )
302
 
303
+ button = gr.Button("Analyze")
304
 
305
+ alg_output = gr.Textbox(
306
+ label="Possible Algorithms"
307
+ )
 
 
 
 
 
 
 
 
308
 
309
+ result_output = gr.Textbox(
310
+ label="Verification Results",
311
+ lines=10
312
  )
313
 
314
+ button.click(
315
+ analyze,
316
+ inputs=[password, hash_value],
317
+ outputs=[alg_output, result_output]
 
 
 
 
318
  )
319
 
320
  demo.launch()