#!/usr/bin/env python3
"""Agent for malware eradication from infected systems — process kill, file removal, persistence cleanup."""

import argparse
import json
import os
import subprocess
import sys
from datetime import datetime, timezone


PERSISTENCE_LOCATIONS_WINDOWS = [
    r"HKCU\Software\Microsoft\Windows\CurrentVersion\Run",
    r"HKLM\Software\Microsoft\Windows\CurrentVersion\Run",
    r"HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce",
    r"HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce",
    r"HKLM\SYSTEM\CurrentControlSet\Services",
]

PERSISTENCE_LOCATIONS_LINUX = [
    "/etc/cron.d", "/var/spool/cron", "/etc/crontab",
    "/etc/init.d", "/etc/systemd/system", "/usr/lib/systemd/system",
    "/etc/rc.local", "~/.bashrc", "~/.bash_profile",
]


def kill_malicious_process(pid):
    """Terminate a malicious process by PID."""
    if sys.platform == "win32":
        cmd = ["taskkill", "/F", "/PID", str(pid)]
    else:
        cmd = ["kill", "-9", str(pid)]
    try:
        subprocess.check_output(cmd, text=True, errors="replace", timeout=10)
        return {"pid": pid, "status": "killed"}
    except subprocess.SubprocessError as e:
        return {"pid": pid, "status": "failed", "error": str(e)}


def quarantine_file(file_path, quarantine_dir):
    """Move malicious file to quarantine directory with metadata."""
    os.makedirs(quarantine_dir, exist_ok=True)
    if not os.path.isfile(file_path):
        return {"file": file_path, "status": "not_found"}
    import hashlib
    with open(file_path, "rb") as f:
        sha256 = hashlib.sha256(f.read()).hexdigest()
    dest = os.path.join(quarantine_dir, f"{sha256}_{os.path.basename(file_path)}.quarantine")
    try:
        os.rename(file_path, dest)
        meta = {
            "original_path": file_path,
            "sha256": sha256,
            "quarantined_at": datetime.now(timezone.utc).isoformat(),
            "quarantine_path": dest,
        }
        with open(dest + ".json", "w") as f:
            json.dump(meta, f, indent=2)
        return {"file": file_path, "status": "quarantined", "sha256": sha256}
    except OSError as e:
        return {"file": file_path, "status": "failed", "error": str(e)}


def scan_persistence_windows():
    """Scan Windows persistence locations for suspicious entries."""
    findings = []
    for key in PERSISTENCE_LOCATIONS_WINDOWS:
        try:
            result = subprocess.check_output(
                ["reg", "query", key], text=True, errors="replace", timeout=5
            )
            for line in result.splitlines():
                line = line.strip()
                if "REG_SZ" in line or "REG_EXPAND_SZ" in line:
                    parts = line.split(None, 2)
                    if len(parts) >= 3:
                        value = parts[2]
                        if any(d in value.lower() for d in ["temp", "appdata\\local\\temp", "public"]):
                            findings.append({
                                "key": key,
                                "name": parts[0],
                                "value": value,
                                "suspicious": True,
                            })
        except subprocess.SubprocessError:
            pass
    return findings


def scan_persistence_linux():
    """Scan Linux persistence locations for suspicious entries."""
    findings = []
    for loc in PERSISTENCE_LOCATIONS_LINUX:
        expanded = os.path.expanduser(loc)
        if os.path.isdir(expanded):
            for f in os.listdir(expanded):
                fpath = os.path.join(expanded, f)
                if os.path.isfile(fpath):
                    try:
                        stat = os.stat(fpath)
                        if stat.st_mtime > (datetime.now().timestamp() - 86400 * 7):
                            findings.append({
                                "path": fpath,
                                "modified": datetime.fromtimestamp(stat.st_mtime).isoformat(),
                                "note": "Recently modified persistence file",
                            })
                    except OSError:
                        pass
        elif os.path.isfile(expanded):
            try:
                with open(expanded, "r", errors="replace") as fh:
                    content = fh.read()
                for line in content.splitlines():
                    if any(s in line.lower() for s in ["curl", "wget", "nc ", "ncat", "bash -i"]):
                        findings.append({
                            "file": expanded,
                            "line": line.strip()[:200],
                            "note": "Suspicious command in startup file",
                        })
            except PermissionError:
                pass
    return findings


def clean_scheduled_tasks():
    """List suspicious scheduled tasks."""
    findings = []
    if sys.platform == "win32":
        try:
            result = subprocess.check_output(
                ["schtasks", "/Query", "/FO", "CSV", "/NH", "/V"],
                text=True, errors="replace", timeout=15
            )
            for line in result.splitlines():
                parts = line.strip('"').split('","')
                if len(parts) >= 9:
                    action = parts[8] if len(parts) > 8 else ""
                    if any(s in action.lower() for s in ["powershell", "cmd", "temp", "appdata"]):
                        findings.append({
                            "task_name": parts[1] if len(parts) > 1 else "",
                            "action": action[:200],
                        })
        except subprocess.SubprocessError:
            pass
    return findings


def main():
    parser = argparse.ArgumentParser(
        description="Eradicate malware from infected systems"
    )
    parser.add_argument("--scan-persistence", action="store_true")
    parser.add_argument("--kill-pid", type=int, nargs="*", help="PIDs to terminate")
    parser.add_argument("--quarantine-file", nargs="*", help="Files to quarantine")
    parser.add_argument("--quarantine-dir", default=os.environ.get("QUARANTINE_DIR", "/tmp/quarantine"))
    parser.add_argument("--output", "-o", help="Output JSON report")
    args = parser.parse_args()

    print("[*] Malware Eradication Agent")
    report = {"timestamp": datetime.now(timezone.utc).isoformat(), "actions": []}

    if args.kill_pid:
        for pid in args.kill_pid:
            result = kill_malicious_process(pid)
            report["actions"].append({"action": "kill", **result})
            print(f"[*] Kill PID {pid}: {result['status']}")

    if args.quarantine_file:
        for fpath in args.quarantine_file:
            result = quarantine_file(fpath, args.quarantine_dir)
            report["actions"].append({"action": "quarantine", **result})
            print(f"[*] Quarantine {fpath}: {result['status']}")

    if args.scan_persistence:
        if sys.platform == "win32":
            pers = scan_persistence_windows()
            tasks = clean_scheduled_tasks()
        else:
            pers = scan_persistence_linux()
            tasks = []
        report["persistence"] = pers
        report["scheduled_tasks"] = tasks
        print(f"[*] Persistence entries: {len(pers)}, Suspicious tasks: {len(tasks)}")

    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2)
        print(f"[*] Report saved to {args.output}")
    else:
        print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()
