Files
Anthropic-Cybersecurity-Skills/skills/analyzing-android-malware-with-apktool/scripts/agent.py
T
mukul975 915ea611e5 Add 10 new cybersecurity skills with full folder anatomy
Skills added:
- implementing-privileged-access-workstation (IAM, PAW hardening)
- detecting-suspicious-oauth-application-consent (cloud security, Graph API)
- performing-hardware-security-module-integration (cryptography, PKCS#11)
- analyzing-android-malware-with-apktool (malware analysis, androguard)
- hunting-for-unusual-service-installations (threat hunting, T1543.003)
- detecting-shadow-it-cloud-usage (cloud security, proxy/DNS log analysis)
- performing-active-directory-forest-trust-attack (red team, impacket)
- implementing-deception-based-detection-with-canarytoken (deception, Canary API)
- analyzing-office365-audit-logs-for-compromise (cloud security, BEC detection)
- hunting-for-startup-folder-persistence (threat hunting, T1547.001)

Each skill includes SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
2026-03-11 00:47:03 +01:00

229 lines
8.7 KiB
Python

#!/usr/bin/env python3
"""Agent for static analysis of Android APK malware using androguard."""
import json
import re
import argparse
from datetime import datetime
try:
from androguard.core.apk import APK
from androguard.core.dex import DEX
from androguard.misc import AnalyzeAPK
except ImportError:
APK = None
AnalyzeAPK = None
DANGEROUS_PERMISSIONS = [
"android.permission.SEND_SMS", "android.permission.READ_SMS",
"android.permission.RECEIVE_SMS", "android.permission.READ_CONTACTS",
"android.permission.READ_CALL_LOG", "android.permission.RECORD_AUDIO",
"android.permission.CAMERA", "android.permission.ACCESS_FINE_LOCATION",
"android.permission.READ_PHONE_STATE", "android.permission.CALL_PHONE",
"android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_EXTERNAL_STORAGE",
"android.permission.INSTALL_PACKAGES", "android.permission.REQUEST_INSTALL_PACKAGES",
"android.permission.SYSTEM_ALERT_WINDOW", "android.permission.BIND_ACCESSIBILITY_SERVICE",
"android.permission.BIND_DEVICE_ADMIN", "android.permission.RECEIVE_BOOT_COMPLETED",
"android.permission.WRITE_SETTINGS", "android.permission.CHANGE_WIFI_STATE",
]
SUSPICIOUS_API_PATTERNS = [
r"Ljava/lang/Runtime;->exec",
r"Ljava/lang/ProcessBuilder;->start",
r"Ldalvik/system/DexClassLoader;->loadClass",
r"Ljava/lang/reflect/Method;->invoke",
r"Ljava/lang/Class;->forName",
r"Ljavax/crypto/Cipher;->getInstance",
r"Landroid/telephony/SmsManager;->sendTextMessage",
r"Landroid/app/admin/DevicePolicyManager;->lockNow",
r"Landroid/content/pm/PackageManager;->setComponentEnabledSetting",
r"Ljava/net/HttpURLConnection;->connect",
r"Lokhttp3/OkHttpClient;->newCall",
r"Landroid/webkit/WebView;->loadUrl",
r"Landroid/os/Build;->SERIAL",
r"Landroid/provider/Settings\$Secure;->getString",
]
def analyze_permissions(apk):
"""Analyze requested permissions and flag dangerous ones."""
permissions = apk.get_permissions()
dangerous = [p for p in permissions if p in DANGEROUS_PERMISSIONS]
return {
"total_permissions": len(permissions),
"permissions": permissions,
"dangerous_permissions": dangerous,
"dangerous_count": len(dangerous),
"permission_risk": "CRITICAL" if len(dangerous) >= 8 else "HIGH" if len(dangerous) >= 5 else "MEDIUM" if len(dangerous) >= 2 else "LOW",
}
def analyze_manifest(apk):
"""Extract manifest components: activities, services, receivers, providers."""
activities = apk.get_activities()
services = apk.get_services()
receivers = apk.get_receivers()
providers = apk.get_providers()
return {
"package_name": apk.get_package(),
"app_name": apk.get_app_name(),
"version_name": apk.get_androidversion_name(),
"version_code": apk.get_androidversion_code(),
"min_sdk": apk.get_min_sdk_version(),
"target_sdk": apk.get_target_sdk_version(),
"activities": list(activities),
"services": list(services),
"receivers": list(receivers),
"providers": list(providers),
"activity_count": len(activities),
"service_count": len(services),
"receiver_count": len(receivers),
"provider_count": len(providers),
}
def scan_suspicious_apis(dx):
"""Scan DEX analysis for suspicious API calls."""
findings = []
if not dx:
return findings
for pattern in SUSPICIOUS_API_PATTERNS:
class_name = pattern.split(";->")[0] + ";"
method_name = pattern.split(";->")[1] if ";->" in pattern else None
for method in dx.find_methods(classname=class_name, methodname=method_name):
xrefs = list(method.get_xref_from())
if xrefs:
findings.append({
"api": pattern,
"callers": len(xrefs),
"first_caller_class": str(xrefs[0][0].name) if xrefs else None,
})
return findings
def extract_strings(dx, apk):
"""Extract suspicious strings: URLs, IPs, base64 patterns."""
url_pattern = re.compile(r'https?://[\w\-._~:/?#\[\]@!$&\'()*+,;=]+', re.IGNORECASE)
ip_pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
b64_pattern = re.compile(r'[A-Za-z0-9+/]{30,}={0,2}')
urls = set()
ips = set()
b64_strings = []
if dx:
for s in dx.get_strings():
val = str(s)
urls.update(url_pattern.findall(val))
ips.update(ip_pattern.findall(val))
b64_matches = b64_pattern.findall(val)
b64_strings.extend(b64_matches[:5])
private_ips = {"10.", "192.168.", "172.16.", "127.0."}
external_ips = [ip for ip in ips if not any(ip.startswith(p) for p in private_ips)]
return {
"urls": sorted(urls)[:30],
"external_ips": sorted(external_ips)[:20],
"suspicious_base64": b64_strings[:10],
"url_count": len(urls),
"external_ip_count": len(external_ips),
}
def detect_obfuscation(apk, dx):
"""Detect code obfuscation indicators."""
indicators = []
if dx:
short_class_names = 0
for cls in dx.get_classes():
name = str(cls.name)
parts = name.replace("/", ".").split(".")
if any(len(p) == 1 and p.isalpha() for p in parts):
short_class_names += 1
if short_class_names > 10:
indicators.append({"type": "single_letter_classes", "count": short_class_names})
dex_files = [f for f in apk.get_files() if f.endswith(".dex")]
if len(dex_files) > 1:
indicators.append({"type": "multi_dex", "dex_count": len(dex_files)})
native_libs = [f for f in apk.get_files() if f.endswith(".so")]
if native_libs:
indicators.append({"type": "native_libraries", "libs": native_libs[:10]})
return {
"obfuscation_indicators": indicators,
"likely_obfuscated": len(indicators) > 0,
}
def full_analysis(apk_path):
"""Run comprehensive APK malware analysis."""
if not APK or not AnalyzeAPK:
return {"error": "androguard not installed: pip install androguard"}
a, d, dx = AnalyzeAPK(apk_path)
perm_analysis = analyze_permissions(a)
manifest = analyze_manifest(a)
suspicious_apis = scan_suspicious_apis(dx)
strings = extract_strings(dx, a)
obfuscation = detect_obfuscation(a, dx)
risk_score = 0
risk_score += min(perm_analysis["dangerous_count"] * 8, 40)
risk_score += min(len(suspicious_apis) * 10, 30)
risk_score += min(strings["external_ip_count"] * 5, 15)
risk_score += 15 if obfuscation["likely_obfuscated"] else 0
risk_score = min(risk_score, 100)
return {
"analysis_type": "Android APK Static Analysis",
"timestamp": datetime.utcnow().isoformat(),
"file": apk_path,
"manifest": manifest,
"permissions": perm_analysis,
"suspicious_apis": suspicious_apis[:20],
"strings": strings,
"obfuscation": obfuscation,
"risk_score": risk_score,
"risk_level": "CRITICAL" if risk_score >= 70 else "HIGH" if risk_score >= 50 else "MEDIUM" if risk_score >= 25 else "LOW",
"mitre_techniques": [
{"id": "T1418", "name": "Software Discovery"} if manifest["service_count"] > 5 else None,
{"id": "T1417", "name": "Input Capture"} if "android.permission.BIND_ACCESSIBILITY_SERVICE" in perm_analysis["permissions"] else None,
{"id": "T1582", "name": "SMS Control"} if "android.permission.SEND_SMS" in perm_analysis["permissions"] else None,
{"id": "T1404", "name": "Exploitation for Privilege Escalation"} if any("DevicePolicyManager" in a.get("api", "") for a in suspicious_apis) else None,
],
}
def main():
parser = argparse.ArgumentParser(description="Android APK Malware Analysis Agent")
parser.add_argument("apk", help="Path to APK file")
sub = parser.add_subparsers(dest="command")
sub.add_parser("permissions", help="Analyze permissions")
sub.add_parser("manifest", help="Extract manifest components")
sub.add_parser("apis", help="Scan for suspicious API calls")
sub.add_parser("strings", help="Extract URLs, IPs, and encoded strings")
sub.add_parser("full", help="Full malware analysis")
args = parser.parse_args()
if args.command == "full" or args.command is None:
result = full_analysis(args.apk)
else:
a, d, dx = AnalyzeAPK(args.apk)
if args.command == "permissions":
result = analyze_permissions(a)
elif args.command == "manifest":
result = analyze_manifest(a)
elif args.command == "apis":
result = scan_suspicious_apis(dx)
elif args.command == "strings":
result = extract_strings(dx, a)
print(json.dumps(result, indent=2, default=str))
if __name__ == "__main__":
main()