mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 05:34:55 +03:00
c47eed6a64
- 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
161 lines
5.9 KiB
Python
161 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for iOS app reverse engineering with Frida.
|
|
|
|
Uses frida-tools to attach to iOS processes, hook Objective-C
|
|
methods, bypass SSL pinning, dump keychain entries, and trace
|
|
API calls for security assessment.
|
|
"""
|
|
|
|
import subprocess
|
|
import json
|
|
import sys
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
|
|
class FridaIOSAgent:
|
|
"""Reverse engineers iOS applications using Frida."""
|
|
|
|
def __init__(self, target_app, device_id=None, output_dir="./frida_ios"):
|
|
self.target_app = target_app
|
|
self.device_id = device_id
|
|
self.output_dir = Path(output_dir)
|
|
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
self.findings = []
|
|
|
|
def _frida_cmd(self, script_code, timeout=60):
|
|
cmd = ["frida", "-U"]
|
|
if self.device_id:
|
|
cmd.extend(["-D", self.device_id])
|
|
cmd.extend(["-n", self.target_app, "-q", "-e", script_code])
|
|
try:
|
|
result = subprocess.run(cmd, capture_output=True, text=True,
|
|
timeout=timeout)
|
|
return {"stdout": result.stdout, "stderr": result.stderr,
|
|
"returncode": result.returncode}
|
|
except (FileNotFoundError, subprocess.TimeoutExpired) as exc:
|
|
return {"error": str(exc)}
|
|
|
|
def list_running_apps(self):
|
|
"""List running applications on the connected iOS device."""
|
|
cmd = ["frida-ps", "-Ua"]
|
|
if self.device_id:
|
|
cmd.extend(["-D", self.device_id])
|
|
try:
|
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
|
|
return {"apps": result.stdout}
|
|
except (FileNotFoundError, subprocess.TimeoutExpired) as exc:
|
|
return {"error": str(exc)}
|
|
|
|
def bypass_ssl_pinning(self):
|
|
"""Inject Frida script to bypass SSL certificate pinning."""
|
|
script = """
|
|
var m = ObjC.classes.NSURLSessionConfiguration;
|
|
Interceptor.attach(m['- setTLSMinimumSupportedProtocol:'].implementation, {
|
|
onEnter: function(args) { console.log('[*] TLS config intercepted'); }
|
|
});
|
|
try {
|
|
var SSLSetPeerDomainName = Module.findExportByName(null, 'SSLSetPeerDomainName');
|
|
if (SSLSetPeerDomainName) {
|
|
Interceptor.attach(SSLSetPeerDomainName, {
|
|
onEnter: function(args) { },
|
|
onLeave: function(retval) { retval.replace(0); }
|
|
});
|
|
console.log('[+] SSL pinning bypassed');
|
|
}
|
|
} catch(e) { console.log('[-] ' + e); }
|
|
"""
|
|
result = self._frida_cmd(script)
|
|
if "SSL pinning bypassed" in result.get("stdout", ""):
|
|
self.findings.append({"type": "SSL Pinning Bypass",
|
|
"severity": "Medium",
|
|
"details": "SSL pinning can be bypassed with Frida"})
|
|
return result
|
|
|
|
def dump_keychain(self):
|
|
"""Dump iOS Keychain entries accessible by the app."""
|
|
script = """
|
|
var kSecClass = ObjC.classes.NSString.stringWithString_('kSecClass');
|
|
var query = ObjC.classes.NSMutableDictionary.dictionary();
|
|
query.setObject_forKey_(ObjC.classes.NSString.stringWithString_('kSecClassGenericPassword'), kSecClass);
|
|
query.setObject_forKey_(ObjC.classes.NSNumber.numberWithBool_(true), ObjC.classes.NSString.stringWithString_('kSecReturnAttributes'));
|
|
query.setObject_forKey_(ObjC.classes.NSString.stringWithString_('kSecMatchLimitAll'), ObjC.classes.NSString.stringWithString_('kSecMatchLimit'));
|
|
var result = new ObjC.Object(ptr(0));
|
|
var status = ObjC.classes.NSDictionary.alloc();
|
|
console.log('[*] Keychain query executed');
|
|
"""
|
|
result = self._frida_cmd(script)
|
|
return result
|
|
|
|
def trace_objc_methods(self, class_name):
|
|
"""Trace all method calls on a specific Objective-C class."""
|
|
script = f"""
|
|
var target = ObjC.classes.{class_name};
|
|
if (target) {{
|
|
var methods = target.$ownMethods;
|
|
console.log('[*] Tracing ' + methods.length + ' methods on {class_name}');
|
|
methods.forEach(function(method) {{
|
|
try {{
|
|
Interceptor.attach(target[method].implementation, {{
|
|
onEnter: function(args) {{
|
|
console.log('[CALL] {class_name} ' + method);
|
|
}}
|
|
}});
|
|
}} catch(e) {{}}
|
|
}});
|
|
}} else {{
|
|
console.log('[-] Class {class_name} not found');
|
|
}}
|
|
"""
|
|
return self._frida_cmd(script, timeout=30)
|
|
|
|
def check_jailbreak_detection(self):
|
|
"""Test if app has jailbreak detection and attempt bypass."""
|
|
script = """
|
|
var paths = ['/Applications/Cydia.app', '/usr/sbin/sshd',
|
|
'/bin/bash', '/usr/bin/ssh', '/etc/apt'];
|
|
var NSFileManager = ObjC.classes.NSFileManager;
|
|
Interceptor.attach(NSFileManager['- fileExistsAtPath:'].implementation, {
|
|
onEnter: function(args) {
|
|
var path = ObjC.Object(args[2]).toString();
|
|
for (var i = 0; i < paths.length; i++) {
|
|
if (path.indexOf(paths[i]) !== -1) {
|
|
console.log('[*] Jailbreak check: ' + path);
|
|
}
|
|
}
|
|
},
|
|
onLeave: function(retval) {}
|
|
});
|
|
console.log('[+] Jailbreak detection hooks installed');
|
|
"""
|
|
result = self._frida_cmd(script, timeout=15)
|
|
if "Jailbreak check" in result.get("stdout", ""):
|
|
self.findings.append({"type": "Jailbreak Detection Present",
|
|
"severity": "Info"})
|
|
return result
|
|
|
|
def generate_report(self):
|
|
report = {
|
|
"target_app": self.target_app,
|
|
"report_date": datetime.utcnow().isoformat(),
|
|
"findings": self.findings,
|
|
}
|
|
report_path = self.output_dir / "frida_ios_report.json"
|
|
with open(report_path, "w") as f:
|
|
json.dump(report, f, indent=2)
|
|
print(json.dumps(report, indent=2))
|
|
return report
|
|
|
|
|
|
def main():
|
|
app = sys.argv[1] if len(sys.argv) > 1 else "TargetApp"
|
|
agent = FridaIOSAgent(app)
|
|
agent.list_running_apps()
|
|
agent.bypass_ssl_pinning()
|
|
agent.check_jailbreak_detection()
|
|
agent.generate_report()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|