mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +03:00
236 lines
8.8 KiB
Python
236 lines
8.8 KiB
Python
#!/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()
|