#!/usr/bin/env python3
"""PowerShell obfuscated malware deobfuscation agent."""

import json
import argparse
import re
import base64
from datetime import datetime


def decode_base64_commands(script_content):
    """Find and decode Base64 encoded PowerShell commands."""
    decoded = []
    b64_pattern = re.compile(r'-[eE](?:nc(?:odedcommand)?)\s+([A-Za-z0-9+/=]{20,})')
    for match in b64_pattern.finditer(script_content):
        encoded = match.group(1)
        try:
            raw = base64.b64decode(encoded)
            text = raw.decode("utf-16-le", errors="replace")
            decoded.append({"encoded": encoded[:60] + "...", "decoded": text[:500]})
        except Exception:
            pass
    standalone_b64 = re.compile(r'["\']([A-Za-z0-9+/]{40,}={0,2})["\']')
    for match in standalone_b64.finditer(script_content):
        try:
            raw = base64.b64decode(match.group(1))
            text = raw.decode("utf-8", errors="replace")
            if text.isprintable() or "http" in text.lower():
                decoded.append({"encoded": match.group(1)[:60] + "...", "decoded": text[:500]})
        except Exception:
            pass
    return decoded


def deobfuscate_string_concatenation(script_content):
    """Resolve string concatenation obfuscation."""
    concat_pattern = re.compile(r"(?:'[^']*'\s*\+\s*){2,}'[^']*'")
    resolved = []
    for match in concat_pattern.finditer(script_content):
        original = match.group(0)
        parts = re.findall(r"'([^']*)'", original)
        result = "".join(parts)
        resolved.append({"obfuscated": original[:80], "resolved": result[:500]})
    return resolved


def detect_obfuscation_techniques(script_content):
    """Identify obfuscation techniques used in the script."""
    techniques = []
    checks = [
        (r'-[eE](?:nc(?:odedcommand)?)', "Base64 encoded command", "HIGH"),
        (r'\[(?:char|int)\]\s*\d+', "Character code conversion", "MEDIUM"),
        (r'(?:iex|invoke-expression)', "Invoke-Expression (IEX) execution", "HIGH"),
        (r'\$\{[^}]+\}', "Variable name obfuscation with braces", "LOW"),
        (r'\.(?:replace|split|reverse)\(', "String manipulation methods", "MEDIUM"),
        (r'-(?:join|split)\s', "Array join/split obfuscation", "MEDIUM"),
        (r'(?:Net\.WebClient|DownloadString|DownloadFile)', "Web download cradle", "CRITICAL"),
        (r'(?:Start-Process|Invoke-Item|cmd\s*/c)', "Process execution", "HIGH"),
        (r'\[System\.Convert\]::FromBase64String', ".NET Base64 decode", "HIGH"),
        (r'(?:gci|ls|dir)\s+env:', "Environment variable access", "LOW"),
    ]
    for pattern, name, severity in checks:
        if re.search(pattern, script_content, re.IGNORECASE):
            techniques.append({"technique": name, "severity": severity})
    return techniques


def extract_iocs(script_content):
    """Extract indicators of compromise from deobfuscated content."""
    iocs = {"urls": [], "ips": [], "domains": [], "file_paths": []}
    url_pattern = re.compile(r'https?://[^\s"\'<>]+')
    ip_pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
    path_pattern = re.compile(r'[A-Z]:\\[\w\\]+\.\w{2,4}|/(?:tmp|var|etc)/[\w/]+')
    iocs["urls"] = list(set(url_pattern.findall(script_content)))
    iocs["ips"] = list(set(ip_pattern.findall(script_content)))
    iocs["file_paths"] = list(set(path_pattern.findall(script_content)))
    return iocs


def run_analysis(script_path):
    """Execute PowerShell deobfuscation analysis."""
    print(f"\n{'='*60}")
    print(f"  POWERSHELL MALWARE DEOBFUSCATION")
    print(f"  File: {script_path}")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    with open(script_path, "r", errors="replace") as f:
        content = f.read()

    techniques = detect_obfuscation_techniques(content)
    print(f"--- OBFUSCATION TECHNIQUES ({len(techniques)}) ---")
    for t in techniques:
        print(f"  [{t['severity']}] {t['technique']}")

    b64 = decode_base64_commands(content)
    print(f"\n--- BASE64 DECODED ({len(b64)}) ---")
    for d in b64[:5]:
        print(f"  {d['decoded'][:100]}")

    concat = deobfuscate_string_concatenation(content)
    print(f"\n--- STRING CONCAT RESOLVED ({len(concat)}) ---")
    for c in concat[:5]:
        print(f"  {c['resolved'][:100]}")

    all_decoded = content
    for d in b64:
        all_decoded += "\n" + d["decoded"]
    iocs = extract_iocs(all_decoded)
    print(f"\n--- IOCs ---")
    print(f"  URLs: {iocs['urls'][:5]}")
    print(f"  IPs: {iocs['ips'][:5]}")
    print(f"  Paths: {iocs['file_paths'][:5]}")

    return {"techniques": techniques, "decoded_b64": b64, "concat": concat, "iocs": iocs}


def main():
    parser = argparse.ArgumentParser(description="PowerShell Deobfuscation Agent")
    parser.add_argument("--script", required=True, help="Path to obfuscated PowerShell script")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    report = run_analysis(args.script)
    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2, default=str)
        print(f"\n[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
