#!/usr/bin/env python3
"""
Mobile Malware Behavior Analyzer

Performs static indicator analysis on Android APK files to detect malware behaviors.
Checks permissions, code patterns, and VirusTotal reputation.

Usage:
    python process.py --apk suspicious.apk [--vt-key API_KEY] [--output report.json]
"""

import argparse
import hashlib
import json
import subprocess
import sys
import zipfile
import re
from datetime import datetime
from pathlib import Path

try:
    import requests
except ImportError:
    requests = None

DANGEROUS_PERMISSIONS = {
    "android.permission.READ_SMS": "SMS access - banking trojan indicator",
    "android.permission.RECEIVE_SMS": "SMS interception - banking trojan indicator",
    "android.permission.SEND_SMS": "SMS sending - premium SMS fraud indicator",
    "android.permission.CAMERA": "Camera access - spyware indicator",
    "android.permission.RECORD_AUDIO": "Microphone access - spyware indicator",
    "android.permission.READ_CONTACTS": "Contact harvesting - worm/spyware indicator",
    "android.permission.READ_CALL_LOG": "Call log access - spyware indicator",
    "android.permission.ACCESS_FINE_LOCATION": "Location tracking - stalkerware indicator",
    "android.permission.SYSTEM_ALERT_WINDOW": "Overlay capability - credential stealer indicator",
    "android.permission.BIND_DEVICE_ADMIN": "Device admin - ransomware indicator",
    "android.permission.BIND_ACCESSIBILITY_SERVICE": "Accessibility abuse - overlay attacks",
    "android.permission.REQUEST_INSTALL_PACKAGES": "Silent app installation capability",
    "android.permission.WRITE_EXTERNAL_STORAGE": "External storage write - data staging",
}

MALWARE_CODE_PATTERNS = {
    "dynamic_dex_loading": r"DexClassLoader|InMemoryDexClassLoader|PathClassLoader",
    "reflection": r"java\.lang\.reflect|Method\.invoke|Class\.forName",
    "native_code_loading": r"System\.loadLibrary|System\.load\(",
    "command_execution": r"Runtime\.getRuntime\(\)\.exec|ProcessBuilder",
    "crypto_operations": r"javax\.crypto\.Cipher|javax\.crypto\.spec",
    "base64_encoding": r"android\.util\.Base64|java\.util\.Base64",
    "root_detection": r"\/system\/xbin\/su|\/system\/app\/Superuser|isRooted|RootBeer",
    "emulator_detection": r"Build\.FINGERPRINT.*generic|goldfish|ranchu|sdk_gphone",
    "keylogger": r"AccessibilityService|onAccessibilityEvent|TYPE_VIEW_TEXT_CHANGED",
    "screen_capture": r"MediaProjection|createVirtualDisplay|CAPTURE_SECURE",
}


def compute_hashes(file_path: str) -> dict:
    """Compute file hashes."""
    with open(file_path, "rb") as f:
        data = f.read()
    return {
        "md5": hashlib.md5(data).hexdigest(),
        "sha1": hashlib.sha1(data).hexdigest(),
        "sha256": hashlib.sha256(data).hexdigest(),
        "size": len(data),
    }


def extract_permissions(apk_path: str) -> list:
    """Extract permissions from APK using aapt."""
    try:
        result = subprocess.run(
            ["aapt", "dump", "permissions", apk_path],
            capture_output=True, text=True, timeout=30
        )
        perms = []
        for line in result.stdout.split("\n"):
            if "uses-permission:" in line:
                perm = line.split("name='")[1].split("'")[0] if "name='" in line else line.strip()
                perms.append(perm)
        return perms
    except (subprocess.TimeoutExpired, FileNotFoundError, IndexError):
        return []


def scan_code_patterns(apk_path: str) -> dict:
    """Scan DEX code for malware patterns."""
    findings = {}
    try:
        with zipfile.ZipFile(apk_path, "r") as z:
            for name in z.namelist():
                if name.endswith(".dex"):
                    dex_data = z.read(name).decode("utf-8", errors="replace")
                    for pattern_name, pattern in MALWARE_CODE_PATTERNS.items():
                        matches = re.findall(pattern, dex_data)
                        if matches:
                            findings[pattern_name] = {
                                "count": len(matches),
                                "samples": list(set(matches))[:3],
                            }
    except zipfile.BadZipFile:
        findings["error"] = "Invalid ZIP/APK file"
    return findings


def check_virustotal(sha256: str, api_key: str) -> dict:
    """Query VirusTotal for file reputation."""
    if not requests or not api_key:
        return {"skipped": True}
    try:
        resp = requests.get(
            f"https://www.virustotal.com/api/v3/files/{sha256}",
            headers={"x-apikey": api_key},
            timeout=15
        )
        if resp.status_code == 200:
            data = resp.json().get("data", {}).get("attributes", {})
            stats = data.get("last_analysis_stats", {})
            return {
                "malicious": stats.get("malicious", 0),
                "suspicious": stats.get("suspicious", 0),
                "undetected": stats.get("undetected", 0),
                "total_engines": sum(stats.values()),
                "detection_names": [
                    f"{engine}: {result.get('result')}"
                    for engine, result in data.get("last_analysis_results", {}).items()
                    if result.get("category") == "malicious"
                ][:10],
            }
        return {"status_code": resp.status_code}
    except Exception as e:
        return {"error": str(e)}


def assess_risk(permissions: list, code_patterns: dict, vt_result: dict) -> dict:
    """Calculate overall malware risk assessment."""
    risk_score = 0
    indicators = []

    # Permission-based risk
    dangerous_found = [p for p in permissions if p in DANGEROUS_PERMISSIONS]
    risk_score += len(dangerous_found) * 10

    # High-risk combinations
    perm_set = set(permissions)
    if {"android.permission.READ_SMS", "android.permission.INTERNET"} <= perm_set:
        indicators.append("SMS stealer pattern (READ_SMS + INTERNET)")
        risk_score += 30
    if {"android.permission.CAMERA", "android.permission.RECORD_AUDIO", "android.permission.INTERNET"} <= perm_set:
        indicators.append("Spyware pattern (CAMERA + AUDIO + INTERNET)")
        risk_score += 40
    if "android.permission.BIND_DEVICE_ADMIN" in perm_set:
        indicators.append("Device admin capability (ransomware indicator)")
        risk_score += 25

    # Code pattern risk
    if "dynamic_dex_loading" in code_patterns:
        indicators.append("Dynamic DEX loading detected")
        risk_score += 20
    if "command_execution" in code_patterns:
        indicators.append("Command execution capability")
        risk_score += 15
    if "emulator_detection" in code_patterns:
        indicators.append("Anti-emulator checks (sandbox evasion)")
        risk_score += 15
    if "keylogger" in code_patterns:
        indicators.append("Accessibility service abuse (keylogger)")
        risk_score += 30

    # VirusTotal
    if vt_result.get("malicious", 0) > 0:
        risk_score += min(vt_result["malicious"] * 5, 50)
        indicators.append(f"VirusTotal: {vt_result['malicious']} engines detected as malicious")

    risk_level = "CRITICAL" if risk_score >= 80 else "HIGH" if risk_score >= 50 else "MEDIUM" if risk_score >= 25 else "LOW"

    return {
        "risk_score": min(risk_score, 100),
        "risk_level": risk_level,
        "indicators": indicators,
    }


def main():
    parser = argparse.ArgumentParser(description="Mobile Malware Behavior Analyzer")
    parser.add_argument("--apk", required=True, help="Path to APK file")
    parser.add_argument("--vt-key", help="VirusTotal API key")
    parser.add_argument("--output", default="malware_report.json", help="Output report")
    args = parser.parse_args()

    if not Path(args.apk).exists():
        print(f"[-] File not found: {args.apk}")
        sys.exit(1)

    print("[*] Computing hashes...")
    hashes = compute_hashes(args.apk)

    print("[*] Extracting permissions...")
    permissions = extract_permissions(args.apk)

    print("[*] Scanning code patterns...")
    code_patterns = scan_code_patterns(args.apk)

    print("[*] Checking VirusTotal...")
    vt_result = check_virustotal(hashes["sha256"], args.vt_key)

    print("[*] Assessing risk...")
    risk = assess_risk(permissions, code_patterns, vt_result)

    report = {
        "analysis": {
            "file": args.apk,
            "date": datetime.now().isoformat(),
            "hashes": hashes,
        },
        "permissions": {
            "total": len(permissions),
            "dangerous": {p: DANGEROUS_PERMISSIONS[p] for p in permissions if p in DANGEROUS_PERMISSIONS},
        },
        "code_patterns": code_patterns,
        "virustotal": vt_result,
        "risk_assessment": risk,
    }

    with open(args.output, "w") as f:
        json.dump(report, f, indent=2)

    print(f"\n[+] Report saved: {args.output}")
    print(f"[!] Risk Level: {risk['risk_level']} (Score: {risk['risk_score']}/100)")
    for ind in risk["indicators"]:
        print(f"    - {ind}")


if __name__ == "__main__":
    main()
