Files
T
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands
- Fix 49 verify=False in defensive skills (env-var override)
- Add timeout to 231 HTTP/subprocess/socket calls
- Fix 6 SQL injection patterns with whitelist validation
- Replace 8 __import__() with standard imports
- Remove 701 unused imports across 442 files
- Add authorized-testing disclaimers to all offensive skills
- Complete 11 incomplete skill directories
- Expand 10 stub SKILL.md files with full content
- Fix 2 YAML parse errors in frontmatter
- Fix 5 pre-existing syntax errors
- Convert 22 hardcoded paths/ports to environment variables
- Back up 21 redundant skill pairs to .bak
- Fix 2 global declaration errors
- 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE)
- 0 compile errors across all 724 agent.py files
2026-03-19 13:26:49 +01:00

154 lines
6.2 KiB
Python

#!/usr/bin/env python3
"""Agent for performing dynamic analysis of Android applications using Frida."""
import json
import argparse
import subprocess
try:
import frida
HAS_FRIDA = True
except ImportError:
HAS_FRIDA = False
def list_packages(device_id=None):
"""List installed packages on Android device/emulator."""
cmd = ["adb"] + (["-s", device_id] if device_id else []) + ["shell", "pm", "list", "packages", "-3"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
packages = [l.replace("package:", "").strip() for l in result.stdout.strip().split("\n") if l.strip()]
return {"total": len(packages), "packages": packages}
def capture_network_traffic(device_id=None, duration=30, output="capture.pcap"):
"""Capture network traffic from Android device using tcpdump."""
adb = ["adb"] + (["-s", device_id] if device_id else [])
subprocess.run(adb + ["shell", "tcpdump", "-i", "any", "-w", f"/sdcard/{output}", "-G", str(duration), "-W", "1"],
timeout=duration + 10, capture_output=True)
subprocess.run(adb + ["pull", f"/sdcard/{output}", output], capture_output=True, timeout=15)
return {"output": output, "duration": duration}
def check_ssl_pinning(package_name, device_id=None):
"""Check if app implements SSL/TLS certificate pinning using Frida."""
if not HAS_FRIDA:
return {"error": "frida not installed"}
device = frida.get_usb_device() if not device_id else frida.get_device(device_id)
pid = device.spawn([package_name])
session = device.attach(pid)
script = session.create_script("""
Java.perform(function() {
var results = {pinning_detected: false, methods: []};
try {
var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
TrustManagerImpl.verifyChain.implementation = function() {
results.pinning_detected = true;
results.methods.push('TrustManagerImpl.verifyChain');
return arguments[0];
};
} catch(e) {}
try {
var OkHostnameVerifier = Java.use('okhttp3.internal.tls.OkHostnameVerifier');
OkHostnameVerifier.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function() {
results.pinning_detected = true;
results.methods.push('OkHostnameVerifier.verify');
return true;
};
} catch(e) {}
setTimeout(function() { send(results); }, 5000);
});
""")
results = {}
def on_message(msg, data):
nonlocal results
if msg["type"] == "send":
results = msg["payload"]
script.on("message", on_message)
script.load()
device.resume(pid)
import time
time.sleep(8)
session.detach()
return {"package": package_name, "ssl_pinning": results}
def analyze_exported_components(package_name, device_id=None):
"""List exported activities, services, receivers, and providers."""
adb = ["adb"] + (["-s", device_id] if device_id else [])
result = subprocess.run(
adb + ["shell", "dumpsys", "package", package_name],
capture_output=True, text=True, timeout=15
)
output = result.stdout
components = {"activities": [], "services": [], "receivers": [], "providers": []}
section = None
for line in output.split("\n"):
line = line.strip()
if "Activity Resolver Table:" in line:
section = "activities"
elif "Service Resolver Table:" in line:
section = "services"
elif "Receiver Resolver Table:" in line:
section = "receivers"
elif "Provider Resolver Table:" in line:
section = "providers"
elif section and package_name in line:
components[section].append(line[:200])
return {"package": package_name, "components": components}
def check_data_storage(package_name, device_id=None):
"""Check for insecure data storage patterns."""
adb = ["adb"] + (["-s", device_id] if device_id else [])
findings = []
# Check shared preferences for sensitive data
sp_result = subprocess.run(
adb + ["shell", "run-as", package_name, "ls", "shared_prefs/"],
capture_output=True, text=True, timeout=10
)
if sp_result.returncode == 0:
prefs = [f.strip() for f in sp_result.stdout.split("\n") if f.strip()]
findings.append({"type": "shared_prefs", "files": prefs})
# Check for world-readable files
wr_result = subprocess.run(
adb + ["shell", "run-as", package_name, "find", ".", "-perm", "-o+r", "-type", "f"],
capture_output=True, text=True, timeout=10
)
if wr_result.stdout.strip():
findings.append({"type": "world_readable", "files": wr_result.stdout.strip().split("\n")[:20]})
return {"package": package_name, "findings": findings}
def main():
parser = argparse.ArgumentParser(description="Android Dynamic Analysis Agent")
parser.add_argument("--device", help="ADB device ID")
sub = parser.add_subparsers(dest="command")
sub.add_parser("packages", help="List third-party packages")
s = sub.add_parser("ssl", help="Check SSL pinning")
s.add_argument("--package", required=True)
c = sub.add_parser("components", help="Analyze exported components")
c.add_argument("--package", required=True)
d = sub.add_parser("storage", help="Check data storage security")
d.add_argument("--package", required=True)
n = sub.add_parser("network", help="Capture network traffic")
n.add_argument("--duration", type=int, default=30)
args = parser.parse_args()
if args.command == "packages":
result = list_packages(args.device)
elif args.command == "ssl":
result = check_ssl_pinning(args.package, args.device)
elif args.command == "components":
result = analyze_exported_components(args.package, args.device)
elif args.command == "storage":
result = check_data_storage(args.package, args.device)
elif args.command == "network":
result = capture_network_traffic(args.device, args.duration)
else:
parser.print_help()
return
print(json.dumps(result, indent=2, default=str))
if __name__ == "__main__":
main()