#!/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()