odexus commited on
Commit
34fb3e8
ยท
verified ยท
1 Parent(s): a0fb0ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +243 -57
app.py CHANGED
@@ -2,78 +2,264 @@ import gradio as gr
2
  import spaces
3
  import subprocess
4
  import os
 
5
 
6
- # --- 1. THE INSTALLER (Restored) ---
7
  def get_hashcat_binary():
8
- # If the file exists from your previous run, use it.
9
- if os.path.exists("hashcat-6.2.6/hashcat"):
10
- return "./hashcat-6.2.6/hashcat"
11
-
12
- # If missing, quick compile
13
- print("โšก Downloading & Compiling Hashcat...")
14
- subprocess.run("wget https://github.com/hashcat/hashcat/archive/refs/tags/v6.2.6.tar.gz", shell=True)
15
- subprocess.run("tar -xzf v6.2.6.tar.gz", shell=True)
16
- subprocess.run("make -C hashcat-6.2.6 -j8", shell=True)
17
- return "./hashcat-6.2.6/hashcat"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  # --- 2. THE ATTACK LOGIC ---
20
  @spaces.GPU(duration=300)
21
  def run_hashcat(hash_input, wordlist_input, allowed_symbols, attack_mode):
22
- # A. Get Binary & Fix Permissions
23
- hc_bin = get_hashcat_binary()
24
- subprocess.run(f"chmod +x {hc_bin}", shell=True)
25
-
26
- # B. Sanity Check (Logs the version to prove it's alive)
27
- check = subprocess.run(f"{hc_bin} --version", shell=True, capture_output=True, text=True)
28
- logs = [f"--- DEBUG START ---", f"Binary: {hc_bin}", f"Version Check: {check.stdout.strip()}"]
29
-
30
- # C. Prepare Files
31
- with open("target.hash", "w") as f: f.write(hash_input.strip())
32
- with open("custom.dict", "w") as f: f.write(wordlist_input.strip())
33
-
34
- # D. Build Command
35
- # 2>&1 merges errors into output so you can see crashes
36
- base_cmd = f"{hc_bin} -m 1000 --force -O"
37
- charset = f"-1 {allowed_symbols}"
38
-
39
- if attack_mode == "Quick Check (NTLM)":
40
- cmd = f"{base_cmd} -a 0 target.hash custom.dict"
41
- elif attack_mode == "Hybrid (Words + 4 Custom Chars)":
42
- cmd = f"{base_cmd} -a 6 {charset} target.hash custom.dict ?1?1?1?1"
43
- elif attack_mode == "Hybrid (Words + 6 Custom Chars)":
44
- cmd = f"{base_cmd} -a 6 {charset} target.hash custom.dict ?1?1?1?1?1?1"
45
- elif attack_mode == "Rules-Based Mutations":
46
- cmd = f"{base_cmd} -a 0 target.hash custom.dict -r ./hashcat-6.2.6/rules/best66.rule"
47
- else:
48
- return "Error: Invalid Mode"
49
-
50
- logs.append(f"Command: {cmd}")
51
- logs.append("--- RUNNING... ---")
52
-
53
- # E. Run & Capture Everything
54
- process = subprocess.run(f"{cmd} 2>&1", shell=True, capture_output=True, text=True)
55
- logs.append(process.stdout)
56
 
57
- return "\n".join(logs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  # --- 3. THE INTERFACE ---
60
- with gr.Blocks() as demo:
61
- gr.Markdown("# โšก Direct Hashcat Runner (Complete)")
 
62
 
63
  with gr.Row():
64
- txt_hash = gr.Textbox(label="1. Hash", placeholder="Paste NTLM hash")
65
- txt_words = gr.Textbox(label="2. Wordlist", lines=5, placeholder="Word1\nWord2")
 
 
 
 
 
 
 
 
 
66
 
67
  with gr.Row():
68
- txt_symbols = gr.Textbox(label="3. Allowed Chars", value="acdegilmnorstuvwxz0123456789!@#$&*?.")
 
 
 
 
69
  mode_select = gr.Dropdown(
70
- ["Quick Check (NTLM)", "Hybrid (Words + 4 Custom Chars)", "Hybrid (Words + 6 Custom Chars)", "Rules-Based Mutations"],
71
- label="4. Mode", value="Hybrid (Words + 6 Custom Chars)"
 
 
 
 
 
 
 
72
  )
73
 
74
- btn_run = gr.Button("๐Ÿ”“ CRACK NOW", variant="primary")
75
- output_log = gr.Code(label="Hashcat Raw Output", language="shell")
 
 
 
 
 
 
 
 
 
 
76
 
77
- btn_run.click(fn=run_hashcat, inputs=[txt_hash, txt_words, txt_symbols, mode_select], outputs=output_log)
 
 
 
 
78
 
79
- demo.launch()
 
 
2
  import spaces
3
  import subprocess
4
  import os
5
+ import sys
6
 
7
+ # --- 1. THE INSTALLER ---
8
  def get_hashcat_binary():
9
+ """Returns path to hashcat binary, compiling if needed."""
10
+ binary_path = "./hashcat-6.2.6/hashcat.bin" # Changed to .bin
11
+
12
+ if os.path.exists(binary_path):
13
+ print(f"โœ“ Found existing binary: {binary_path}")
14
+ return binary_path
15
+
16
+ try:
17
+ print("โšก Downloading & Compiling Hashcat...")
18
+
19
+ # Download
20
+ result = subprocess.run(
21
+ "wget -q https://github.com/hashcat/hashcat/archive/refs/tags/v6.2.6.tar.gz",
22
+ shell=True, capture_output=True, text=True
23
+ )
24
+ if result.returncode != 0:
25
+ raise RuntimeError(f"Download failed: {result.stderr}")
26
+
27
+ # Extract
28
+ result = subprocess.run(
29
+ "tar -xzf v6.2.6.tar.gz",
30
+ shell=True, capture_output=True, text=True
31
+ )
32
+ if result.returncode != 0:
33
+ raise RuntimeError(f"Extract failed: {result.stderr}")
34
+
35
+ # Compile
36
+ print("Compiling (this takes 2-3 minutes)...")
37
+ result = subprocess.run(
38
+ "make -C hashcat-6.2.6 -j$(nproc)",
39
+ shell=True, capture_output=True, text=True, timeout=300
40
+ )
41
+
42
+ print("Make stdout:", result.stdout[-500:]) # Last 500 chars
43
+ print("Make stderr:", result.stderr[-500:])
44
+ print("Make return code:", result.returncode)
45
+
46
+ # Check what was actually built
47
+ print("\nFiles in hashcat-6.2.6:")
48
+ for f in os.listdir("hashcat-6.2.6"):
49
+ if "hashcat" in f.lower():
50
+ full_path = os.path.join("hashcat-6.2.6", f)
51
+ print(f" {f} - exists: {os.path.exists(full_path)}, "
52
+ f"size: {os.path.getsize(full_path) if os.path.exists(full_path) else 0}")
53
+
54
+ # Try multiple possible binary names
55
+ possible_binaries = [
56
+ "./hashcat-6.2.6/hashcat.bin",
57
+ "./hashcat-6.2.6/hashcat",
58
+ "./hashcat-6.2.6/hashcat.exe"
59
+ ]
60
+
61
+ for binary in possible_binaries:
62
+ if os.path.exists(binary):
63
+ print(f"โœ“ Found binary: {binary}")
64
+ os.chmod(binary, 0o755)
65
+ return binary
66
+
67
+ raise FileNotFoundError(
68
+ f"Compilation completed but no binary found. Checked: {possible_binaries}"
69
+ )
70
+
71
+ except subprocess.CalledProcessError as e:
72
+ raise RuntimeError(f"Failed to install hashcat: {e.stderr}")
73
+ except subprocess.TimeoutExpired:
74
+ raise RuntimeError("Compilation timed out after 5 minutes")
75
 
76
  # --- 2. THE ATTACK LOGIC ---
77
  @spaces.GPU(duration=300)
78
  def run_hashcat(hash_input, wordlist_input, allowed_symbols, attack_mode):
79
+ """Run hashcat with specified parameters."""
80
+ logs = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
+ try:
83
+ # A. Validate inputs
84
+ if not hash_input or not hash_input.strip():
85
+ return "โŒ Error: Hash input is required"
86
+ if not wordlist_input or not wordlist_input.strip():
87
+ return "โŒ Error: Wordlist input is required"
88
+
89
+ logs.append("=== HASHCAT GPU CRACKER ===\n")
90
+
91
+ # B. Get Binary
92
+ logs.append("๐Ÿ“ฆ Locating hashcat binary...")
93
+ hc_bin = get_hashcat_binary()
94
+ logs.append(f"โœ“ Binary: {hc_bin}\n")
95
+
96
+ # C. Version Check
97
+ logs.append("๐Ÿ” Checking version...")
98
+ version_check = subprocess.run(
99
+ [hc_bin, "--version"],
100
+ capture_output=True,
101
+ text=True,
102
+ timeout=10
103
+ )
104
+ logs.append(version_check.stdout.strip())
105
+ logs.append("")
106
+
107
+ # D. Device Info
108
+ logs.append("๐ŸŽฎ Checking GPU...")
109
+ device_check = subprocess.run(
110
+ [hc_bin, "-I"],
111
+ capture_output=True,
112
+ text=True,
113
+ timeout=10
114
+ )
115
+ logs.append(device_check.stdout.strip())
116
+ logs.append("")
117
+
118
+ # E. Prepare Files
119
+ logs.append("๐Ÿ“ Preparing attack files...")
120
+ with open("target.hash", "w") as f:
121
+ f.write(hash_input.strip() + "\n")
122
+
123
+ word_count = len(wordlist_input.strip().split('\n'))
124
+ with open("custom.dict", "w") as f:
125
+ f.write(wordlist_input.strip())
126
+ logs.append(f"โœ“ Hash file created")
127
+ logs.append(f"โœ“ Wordlist created ({word_count} words)\n")
128
+
129
+ # F. Build Command
130
+ base_cmd = [hc_bin, "-m", "1000", "--force", "-O", "--potfile-path", "hashcat.potfile"]
131
+
132
+ if attack_mode == "Quick Check (NTLM)":
133
+ cmd = base_cmd + ["-a", "0", "target.hash", "custom.dict"]
134
+ logs.append(f"โš”๏ธ Attack: Dictionary ({word_count} words)")
135
+
136
+ elif attack_mode == "Hybrid (Words + 4 Custom Chars)":
137
+ cmd = base_cmd + ["-a", "6", "-1", allowed_symbols,
138
+ "target.hash", "custom.dict", "?1?1?1?1"]
139
+ keyspace = word_count * (len(allowed_symbols) ** 4)
140
+ logs.append(f"โš”๏ธ Attack: Hybrid (words + 4 chars)")
141
+ logs.append(f" Keyspace: ~{keyspace:,} combinations")
142
+
143
+ elif attack_mode == "Hybrid (Words + 6 Custom Chars)":
144
+ cmd = base_cmd + ["-a", "6", "-1", allowed_symbols,
145
+ "target.hash", "custom.dict", "?1?1?1?1?1?1"]
146
+ keyspace = word_count * (len(allowed_symbols) ** 6)
147
+ logs.append(f"โš”๏ธ Attack: Hybrid (words + 6 chars)")
148
+ logs.append(f" Keyspace: ~{keyspace:,} combinations")
149
+
150
+ elif attack_mode == "Rules-Based Mutations":
151
+ rules_path = "./hashcat-6.2.6/rules/best66.rule"
152
+ if not os.path.exists(rules_path):
153
+ return "โŒ Error: Rules file not found"
154
+ cmd = base_cmd + ["-a", "0", "target.hash", "custom.dict", "-r", rules_path]
155
+ logs.append(f"โš”๏ธ Attack: Rules-based (best66)")
156
+ else:
157
+ return f"โŒ Error: Invalid attack mode"
158
+
159
+ logs.append(f" Charset: {allowed_symbols}\n")
160
+ logs.append("๐Ÿš€ Starting attack...\n")
161
+ logs.append("=" * 60)
162
+
163
+ # G. Execute
164
+ process = subprocess.run(
165
+ cmd,
166
+ capture_output=True,
167
+ text=True,
168
+ timeout=270
169
+ )
170
+
171
+ logs.append(process.stdout)
172
+
173
+ if process.stderr:
174
+ logs.append("\n--- STDERR ---")
175
+ logs.append(process.stderr)
176
+
177
+ # H. Check Results
178
+ logs.append("\n" + "=" * 60)
179
+ if os.path.exists("hashcat.potfile"):
180
+ with open("hashcat.potfile", "r") as f:
181
+ potfile_content = f.read().strip()
182
+ if potfile_content:
183
+ logs.append("\n๐ŸŽ‰ PASSWORD CRACKED!")
184
+ logs.append("=" * 60)
185
+ for line in potfile_content.split('\n'):
186
+ if ':' in line:
187
+ hash_part, password = line.split(':', 1)
188
+ logs.append(f"Password: {password}")
189
+ else:
190
+ logs.append("\nโŒ Password not found")
191
+ else:
192
+ logs.append("\nโŒ Password not found")
193
+
194
+ return "\n".join(logs)
195
+
196
+ except subprocess.TimeoutExpired:
197
+ return "\n".join(logs) + "\n\nโฑ๏ธ TIMEOUT: Attack exceeded time limit"
198
+ except Exception as e:
199
+ return "\n".join(logs) + f"\n\nโŒ ERROR: {str(e)}\n{type(e).__name__}"
200
+ finally:
201
+ # Cleanup
202
+ for tmp_file in ["target.hash", "custom.dict"]:
203
+ try:
204
+ if os.path.exists(tmp_file):
205
+ os.remove(tmp_file)
206
+ except:
207
+ pass
208
 
209
  # --- 3. THE INTERFACE ---
210
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
211
+ gr.Markdown("# โšก Hashcat GPU Cracker")
212
+ gr.Markdown("*Educational/Research Use Only*")
213
 
214
  with gr.Row():
215
+ txt_hash = gr.Textbox(
216
+ label="๐ŸŽฏ NTLM Hash",
217
+ placeholder="8846F7EAEE8FB117AD06BDD830B7586C",
218
+ info="32-character hex hash"
219
+ )
220
+ txt_words = gr.Textbox(
221
+ label="๐Ÿ“š Wordlist",
222
+ lines=6,
223
+ placeholder="password\nadmin\nwelcome\n123456",
224
+ info="One word per line"
225
+ )
226
 
227
  with gr.Row():
228
+ txt_symbols = gr.Textbox(
229
+ label="๐Ÿ”ค Character Set",
230
+ value="abcdefghijklmnopqrstuvwxyz0123456789!@#$",
231
+ info="Characters for hybrid attacks"
232
+ )
233
  mode_select = gr.Dropdown(
234
+ choices=[
235
+ "Quick Check (NTLM)",
236
+ "Hybrid (Words + 4 Custom Chars)",
237
+ "Hybrid (Words + 6 Custom Chars)",
238
+ "Rules-Based Mutations"
239
+ ],
240
+ label="โš”๏ธ Attack Mode",
241
+ value="Quick Check (NTLM)",
242
+ info="Start with Quick Check"
243
  )
244
 
245
+ with gr.Row():
246
+ btn_run = gr.Button("๐Ÿš€ Start Attack", variant="primary", size="lg")
247
+
248
+ output_log = gr.Code(label="๐Ÿ“Š Attack Log", language="shell", lines=25)
249
+
250
+ gr.Markdown("""
251
+ ### ๐Ÿ’ก Tips:
252
+ - **Quick Check**: Tests wordlist directly
253
+ - **Hybrid**: Appends random characters to each word
254
+ - **Rules**: Applies mutations (l33t speak, caps, etc.)
255
+ - Start simple, escalate if needed
256
+ """)
257
 
258
+ btn_run.click(
259
+ fn=run_hashcat,
260
+ inputs=[txt_hash, txt_words, txt_symbols, mode_select],
261
+ outputs=output_log
262
+ )
263
 
264
+ if __name__ == "__main__":
265
+ demo.launch()