| import gradio as gr |
| import spaces |
| import subprocess |
| import os |
|
|
| |
| def get_hashcat_binary(): |
| binary_path = "./hashcat-7.1.2/hashcat.bin" |
| |
| if not os.path.exists("hashcat-7.1.2"): |
| print("Installing dependencies...") |
| subprocess.run(["apt-get", "update"], check=True) |
| subprocess.run(["apt-get", "install", "-y", "p7zip-full", "wget"], check=True) |
| |
| print("Downloading hashcat 7.1.2...") |
| subprocess.run(["wget", "https://hashcat.net/files/hashcat-7.1.2.7z"], check=True) |
| subprocess.run(["7z", "x", "hashcat-7.1.2.7z"], check=True) |
| subprocess.run(["chmod", "+x", binary_path], check=True) |
| |
| return binary_path |
|
|
| |
| @spaces.GPU(duration=600) |
| def run_hashcat(hash_input, wordlist_input, allowed_symbols, attack_mode): |
| hc_bin = get_hashcat_binary() |
| |
| if os.path.exists("target.hash"): |
| os.remove("target.hash") |
| if os.path.exists("custom.dict"): |
| os.remove("custom.dict") |
| |
| with open("target.hash", "w") as f: |
| f.write(hash_input.strip() + "\n") |
| |
| with open("custom.dict", "w") as f: |
| f.write(wordlist_input.strip()) |
| |
| |
| if attack_mode == "Quick Check (NTLM)": |
| cmd = [hc_bin, "-m", "1000", "-a", "0", "target.hash", "custom.dict", "--force", "--backend-ignore-cuda"] |
| |
| elif attack_mode == "Hybrid (Words + 4 Custom Chars)": |
| cmd = [hc_bin, "-m", "1000", "-a", "6", "-1", allowed_symbols, "target.hash", "custom.dict", "?1?1?1?1", "--force", "--backend-ignore-cuda"] |
| |
| elif attack_mode == "Hybrid (Words + 6 Custom Chars)": |
| cmd = [hc_bin, "-m", "1000", "-a", "6", "-1", allowed_symbols, "target.hash", "custom.dict", "?1?1?1?1?1?1", "--force", "--backend-ignore-cuda"] |
| |
| elif attack_mode == "Rules-Based Mutations": |
| rules_dir = "/usr/share/hashcat/rules" |
| rule_path = os.path.join(rules_dir, "best64.rule") |
| |
| if not os.path.exists(rule_path): |
| return f"Error: Rule file not found at {rule_path}" |
| |
| cmd = [hc_bin, "-m", "1000", "-a", "0", "target.hash", "custom.dict", "-r", rule_path, "--force", "-O", "--backend-ignore-opencl"] |
| |
| else: |
| return "Error: Invalid mode selected" |
| |
| print(f"Exec: {' '.join(cmd)}") |
| try: |
| result = subprocess.run(cmd, capture_output=True, text=True, timeout=600) |
| return result.stdout + "\n--- STDERR ---\n" + result.stderr |
| except Exception as e: |
| return f"Error: {str(e)}" |
|
|
| |
| with gr.Blocks() as demo: |
| gr.Markdown("# ⚡ DPAPI Password Recovery Tool") |
| |
| with gr.Row(): |
| txt_hash = gr.Textbox(label="1. NT Hash", value="3232d48683d6ffc3e7ff9e9052c9a0f3") |
| txt_words = gr.Textbox(label="2. Password Wordlist (one per line)", lines=8, placeholder="Edward9945\nLove060516\nRed1red") |
| |
| with gr.Row(): |
| txt_symbols = gr.Textbox( |
| label="3. Allowed Characters", |
| value="acdegilmnorstuvwxz0123456789!@#$&*.", |
| info="Only these chars will be tested" |
| ) |
| mode_select = gr.Dropdown( |
| [ |
| "Quick Check (NTLM)", |
| "Hybrid (Words + 4 Custom Chars)", |
| "Hybrid (Words + 6 Custom Chars)", |
| "Rules-Based Mutations" |
| ], |
| label="4. Attack Mode", |
| value="Hybrid (Words + 6 Custom Chars)" |
| ) |
| |
| btn_run = gr.Button("🔓 Crack Password", variant="primary") |
| output_log = gr.Code(label="Hashcat Output", language="shell") |
| |
| btn_run.click( |
| fn=run_hashcat, |
| inputs=[txt_hash, txt_words, txt_symbols, mode_select], |
| outputs=output_log |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|