Initial commit: Flights iOS app
Flight search app built on FlightConnections.com API data. Features: airport search with autocomplete, browse by country/state/map, flight schedules by route and date, multi-airline support with per-airline schedule loading. Includes 4,561-airport GPS database for map browsing. Adaptive light/dark mode UI inspired by Flighty. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
132
frida/server.py
Normal file
132
frida/server.py
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Frida data receiver server.
|
||||
Receives captured HTTP responses from the Frida hook and saves them.
|
||||
Also provides a simple API to query captured data.
|
||||
"""
|
||||
|
||||
import json
|
||||
import frida
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
from pathlib import Path
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
import threading
|
||||
|
||||
CAPTURE_DIR = Path(__file__).parent / "captures"
|
||||
CAPTURE_DIR.mkdir(exist_ok=True)
|
||||
|
||||
captured_data = []
|
||||
|
||||
|
||||
def on_message(message, data):
|
||||
"""Handle messages from Frida hook."""
|
||||
if message["type"] == "send":
|
||||
payload = message["payload"]
|
||||
captured_data.append(payload)
|
||||
|
||||
url = payload.get("url", "unknown")
|
||||
status = payload.get("status", "?")
|
||||
method = payload.get("method", "?")
|
||||
body_len = len(payload.get("responseBody", "") or "")
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"[CAPTURED] {method} {url}")
|
||||
print(f" Status: {status} | Response: {body_len} chars")
|
||||
|
||||
# Save to file
|
||||
ts = time.strftime("%Y%m%d_%H%M%S")
|
||||
domain = url.split("/")[2] if "/" in url else "unknown"
|
||||
filename = f"{ts}_{domain}_{method}_{status}.json"
|
||||
filepath = CAPTURE_DIR / filename
|
||||
|
||||
with open(filepath, "w") as f:
|
||||
json.dump(payload, f, indent=2)
|
||||
|
||||
print(f" Saved: {filepath.name}")
|
||||
|
||||
# Print response body preview
|
||||
resp_body = payload.get("responseBody", "")
|
||||
if resp_body:
|
||||
try:
|
||||
parsed = json.loads(resp_body)
|
||||
print(f" Response preview: {json.dumps(parsed, indent=2)[:500]}")
|
||||
except:
|
||||
print(f" Response preview: {resp_body[:300]}")
|
||||
|
||||
elif message["type"] == "error":
|
||||
print(f"[ERROR] {message['stack']}")
|
||||
|
||||
|
||||
def attach_to_app(package_name, script_path):
|
||||
"""Attach Frida to a running app and load the hook script."""
|
||||
device = frida.get_usb_device()
|
||||
print(f"[*] Connected to: {device.name}")
|
||||
|
||||
# Try to attach to running process first
|
||||
try:
|
||||
session = device.attach(package_name)
|
||||
print(f"[*] Attached to running process: {package_name}")
|
||||
except frida.ProcessNotFoundError:
|
||||
# Spawn it
|
||||
print(f"[*] Spawning: {package_name}")
|
||||
pid = device.spawn([package_name])
|
||||
session = device.attach(pid)
|
||||
device.resume(pid)
|
||||
print(f"[*] Spawned and attached: PID {pid}")
|
||||
|
||||
with open(script_path) as f:
|
||||
script_code = f.read()
|
||||
|
||||
script = session.create_script(script_code)
|
||||
script.on("message", on_message)
|
||||
script.load()
|
||||
|
||||
print(f"[*] Script loaded. Intercepting traffic for {package_name}...")
|
||||
return session
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python server.py <package_name> [hook_script.js]")
|
||||
print("")
|
||||
print("Examples:")
|
||||
print(" python server.py com.spirit.customerapp")
|
||||
print(" python server.py com.delta.mobile.android")
|
||||
print(" python server.py com.united.mobile.android")
|
||||
print("")
|
||||
print("Default hook script: okhttp_hook.js")
|
||||
sys.exit(1)
|
||||
|
||||
package_name = sys.argv[1]
|
||||
script_path = sys.argv[2] if len(sys.argv) > 2 else str(Path(__file__).parent / "okhttp_hook.js")
|
||||
|
||||
print(f"[*] Target: {package_name}")
|
||||
print(f"[*] Script: {script_path}")
|
||||
print(f"[*] Captures: {CAPTURE_DIR}")
|
||||
print("")
|
||||
|
||||
session = attach_to_app(package_name, script_path)
|
||||
|
||||
print("")
|
||||
print("[*] Ready. Interact with the app to trigger API calls.")
|
||||
print("[*] Press Ctrl+C to stop.")
|
||||
print("")
|
||||
|
||||
try:
|
||||
sys.stdin.read()
|
||||
except KeyboardInterrupt:
|
||||
print("\n[*] Stopping...")
|
||||
session.detach()
|
||||
|
||||
# Save all captured data
|
||||
if captured_data:
|
||||
summary_path = CAPTURE_DIR / f"all_captures_{time.strftime('%Y%m%d_%H%M%S')}.json"
|
||||
with open(summary_path, "w") as f:
|
||||
json.dump(captured_data, f, indent=2)
|
||||
print(f"[*] Saved {len(captured_data)} captures to {summary_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user