#!/usr/bin/env python3 """Agent for performing mobile app certificate pinning bypass testing — authorized testing only.""" import json import argparse import subprocess from pathlib import Path FRIDA_SSL_BYPASS_SCRIPT = """ Java.perform(function() { // TrustManagerImpl bypass var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); TrustManagerImpl.verifyChain.implementation = function() { console.log('[*] Bypassed TrustManagerImpl.verifyChain'); return Java.use('java.util.ArrayList').$new(); }; // OkHttp CertificatePinner bypass try { var CertificatePinner = Java.use('okhttp3.CertificatePinner'); CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(hostname, peerCerts) { console.log('[*] Bypassed OkHttp CertificatePinner for: ' + hostname); }; } catch(e) { console.log('[!] OkHttp not found'); } // WebViewClient bypass try { var WebViewClient = Java.use('android.webkit.WebViewClient'); WebViewClient.onReceivedSslError.implementation = function(view, handler, error) { console.log('[*] Bypassed WebView SSL error'); handler.proceed(); }; } catch(e) {} }); """ def detect_pinning_implementation(apk_path): """Detect certificate pinning implementation in an APK.""" cmd = ["apktool", "d", apk_path, "-o", "/tmp/apk_decompile", "-f"] try: subprocess.run(cmd, capture_output=True, text=True, timeout=120) except FileNotFoundError: return {"error": "apktool not installed"} pinning_indicators = { "okhttp_pinner": "CertificatePinner", "trustmanager": "X509TrustManager", "network_security_config": "network_security_config", "ssl_pinning_webview": "onReceivedSslError", "conscrypt": "TrustManagerImpl", "certificate_transparency": "CertificateTransparency", } findings = {} smali_dir = Path("/tmp/apk_decompile") for smali_file in smali_dir.rglob("*.smali"): content = smali_file.read_text(encoding="utf-8", errors="replace") for indicator_name, pattern in pinning_indicators.items(): if pattern in content: findings.setdefault(indicator_name, []).append(str(smali_file.relative_to(smali_dir))) nsc_file = smali_dir / "res" / "xml" / "network_security_config.xml" nsc_content = None if nsc_file.exists(): nsc_content = nsc_file.read_text() return { "apk": apk_path, "pinning_detected": bool(findings), "implementations": {k: v[:5] for k, v in findings.items()}, "network_security_config": nsc_content[:500] if nsc_content else None, "pinning_strength": "STRONG" if len(findings) >= 3 else "MODERATE" if findings else "NONE", } def run_frida_bypass(package_name, device_id=None): """Launch Frida SSL pinning bypass against a running app.""" script_path = Path("/tmp/frida_ssl_bypass.js") script_path.write_text(FRIDA_SSL_BYPASS_SCRIPT) cmd = ["frida", "-U", "-l", str(script_path), "-f", package_name, "--no-pause"] if device_id: cmd = ["frida", "-D", device_id, "-l", str(script_path), "-f", package_name, "--no-pause"] try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) return { "package": package_name, "script": "ssl_pinning_bypass", "output": result.stdout[:1000], "errors": result.stderr[:500] if result.stderr else None, "success": result.returncode == 0, } except FileNotFoundError: return {"error": "frida not installed — pip install frida-tools"} except subprocess.TimeoutExpired: return {"package": package_name, "status": "RUNNING", "note": "Frida is attached — use Ctrl+C to detach"} def run_objection_bypass(package_name): """Use objection to disable SSL pinning on Android/iOS.""" cmd = ["objection", "-g", package_name, "explore", "-s", "android sslpinning disable"] try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) return { "package": package_name, "tool": "objection", "output": result.stdout[:1000], "success": "disabled" in result.stdout.lower(), } except FileNotFoundError: return {"error": "objection not installed — pip install objection"} except Exception as e: return {"error": str(e)} def check_proxy_setup(): """Verify proxy setup for traffic interception.""" checks = {} try: result = subprocess.run(["adb", "shell", "settings", "get", "global", "http_proxy"], capture_output=True, text=True, timeout=10) proxy = result.stdout.strip() checks["android_proxy"] = proxy if proxy and proxy != "null" else "NOT_SET" except Exception as e: checks["android_proxy_error"] = str(e) try: result = subprocess.run(["adb", "shell", "ls", "/system/etc/security/cacerts/"], capture_output=True, text=True, timeout=10) cert_count = len(result.stdout.strip().splitlines()) checks["system_ca_certs"] = cert_count except Exception as e: checks["ca_cert_error"] = str(e) try: result = subprocess.run(["adb", "shell", "su", "-c", "cat /data/misc/user/0/cacerts-added/ 2>/dev/null | wc -l"], capture_output=True, text=True, timeout=10) checks["user_ca_certs"] = result.stdout.strip() except Exception: checks["user_ca_certs"] = "unknown" return {"proxy_setup": checks} def main(): parser = argparse.ArgumentParser(description="Mobile App Certificate Pinning Bypass Agent (Authorized Only)") sub = parser.add_subparsers(dest="command") d = sub.add_parser("detect", help="Detect pinning in APK") d.add_argument("--apk", required=True) f = sub.add_parser("frida", help="Frida SSL bypass") f.add_argument("--package", required=True) f.add_argument("--device", help="Device ID") o = sub.add_parser("objection", help="Objection SSL bypass") o.add_argument("--package", required=True) sub.add_parser("proxy", help="Check proxy setup") args = parser.parse_args() if args.command == "detect": result = detect_pinning_implementation(args.apk) elif args.command == "frida": result = run_frida_bypass(args.package, args.device) elif args.command == "objection": result = run_objection_bypass(args.package) elif args.command == "proxy": result = check_proxy_setup() else: parser.print_help() return print(json.dumps(result, indent=2, default=str)) if __name__ == "__main__": main()