SKILL: /eardop

name: eardrop description: Listen to an iPhone's HTTPS traffic from the Mac to find where an app fetches data/images. Sets up mitmproxy, walks the iPhone proxy+cert setup, then locates and extracts API endpoints. Trigger when the user wants to "sniff iphone traffic", "intercept app traffic", "see where an image/app loads from", "MITM my phone", or inspect an app's API calls.

eardrop — iPhone HTTPS traffic interception

Goal: see the decrypted HTTP(S) calls an iPhone app makes (from the Mac), find the endpoint/image a screen loads, and optionally replay it to download assets.

Legitimate use only: the user's own device + own network/account. Stop if it's not.

0. Preflight — is the tooling there?

command -v mitmweb mitmdump mitmproxy        # need mitmproxy (brew install mitmproxy)
ls ~/.mitmproxy/mitmproxy-ca-cert.pem        # CA cert (auto-created on first run)
ipconfig getifaddr en0 || ipconfig getifaddr en1   # Mac Wi-Fi IP — phone points here

1. Start the proxy (background, fixed password)

mitmweb's auto token is awkward over a background pipe — set a known password instead.

mitmweb --no-web-open-browser --web-host 127.0.0.1 --web-port 8081 \
        --listen-port 8080 --set web_password=iris --set stream_large_bodies=1m
  • Web UI: http://127.0.0.1:8081 (password above). Flow List = live requests.

  • Verify it's up: lsof -nP -iTCP:8080 -sTCP:LISTEN

  • For reliable self-inspection add -w /tmp/flows.mitm, then read later with mitmdump -nr /tmp/flows.mitm. (mitmweb's stdout is block-buffered and lags — the web UI / -w file are the source of truth, not the background task output.)

2. iPhone setup (user does this, same Wi-Fi)

  1. Settings → Wi-Fi → ⓘ → Configure Proxy → Manual → Server = Mac IP, Port = 8080.

  2. Install cert ON the phone (a downloaded .pem on the Mac is useless): Safari → http://mitm.it → tap the Apple icon → Allow → install the profile in Settings → General → VPN & Device Management.

  3. CRITICAL — enable full trust: Settings → General → About → Certificate Trust Settings → toggle mitmproxy ON. This is the step that's always skipped.

3. Verify trust before chasing the app

User opens https://example.com in Safari:

  • Loads fine + shows in Flow List → trust OK.

  • "This connection is not private" → cert NOT trusted (often the user trusted a different tool's cert, e.g. Proxyman — check the profile name is mitmproxy). Redo 2.3.

4. Capture the target

  • User fully closes + reopens the app, performs the action (open photo, etc.).

  • Cached assets won't re-fetch — use a new item or pull-to-refresh.

  • Filter in the web UI Search box: ~t image (image responses), ~m GET, or a hostname.

  • Click a flow → Request tab for URL + headers; Response tab for the body.

5. Diagnosing "nothing shows up"

Read the proxy log / flows. The signatures:

Symptom

Meaning

Fix

Client TLS handshake failed … client disconnected

App rejects our cert

Trust not enabled (§2.3) or the app pins certs (§6)

App shows "connection error", log frozen

Traffic not reaching Mac, or all conns fail

Re-check proxy IP (it can change), firewall, :8080 listening

Only mitm.it/analytics flows, app silent

Cert untrusted → only HTTP got through

§2.3

Safari "not private"

OS-level trust missing

§2.3

6. Certificate pinning (Instagram, Meta, banks, many SDKs)

If handshakes keep failing after trust is confirmed, the app pins its cert — it hardcodes the expected cert and rejects mitmproxy's regardless of OS trust. A plain proxy can't beat this. Options:

  • A8–A11 devices (iPhone 6s … 8/X) are jailbreakable via checkm8 (palera1n, unpatchable bootrom) on any iOS incl. 16/17 → install SSL Kill Switch 3 / A-Bypass in Sileo to disable pinning system-wide. (A11 + iOS15/16: remove the passcode first or it boot-loops; semi-tethered, re-run palera1n after each reboot.)

  • Android emulator + Frida (frida-multiple-unpinning) or apk-mitm is often easier.

  • Even when pinned, mitmproxy still logs the hostnames (server connect …) — useful for mapping which CDNs/APIs an app talks to without decrypting.

7. Extract & replay (download assets via the API)

Once you see the API:

  • Note required headers — many APIs reject calls missing a custom Origin/X-Origin or a Bearer token. Copy them from a captured Request → Headers.

  • Stash the token in a file (/tmp/<app>_token.txt) to keep commands clean; tokens expire (decode the JWT exp), so grab a fresh one if calls start returning 401.

  • Replay with curl, following redirects for signed asset URLs:

    T=$(cat /tmp/app_token.txt)
    curl -s -H "origin: <captured-origin>" -H "authorization: Bearer $T" \
         -H "accept: application/json" "https://api.example.com/v1/<resource>" | python3 -m json.tool
    curl -sL '<signed CDN/S3 url>' -o ~/Desktop/asset.jpg   # presigned URLs need no auth, expire fast
  • Cloud asset URLs (Rails ActiveStorage …/blobs/redirect/<signed-id>/<name>) 302 to a presigned S3/GCS link; the bucket name often reveals quality tiers (…-thumbnails, …-originals, …-preview). Check resolution: sips -g pixelWidth -g pixelHeight file.jpg.

8. Noise to ignore

  • X-Padding header full of junk JSON (often the famous Foursquare "Central Park" sample, quotes swapped for *): deliberate size-obfuscation filler to defeat traffic analysis. Not real data — ignore.

  • AppsFlyer / Sentry / PostHog / Firebase / Apple *.ess.apple.com hosts: third-party analytics, usually pinned and irrelevant to the target.

9. Cleanup (always offer at the end)

  • Stop proxy: pkill -f mitmweb

  • Remind the user to set iPhone Wi-Fi proxy back to Off (Settings → Wi-Fi → ⓘ → Configure Proxy → Off) — otherwise no internet once the Mac proxy stops.

  • Delete any stashed tokens (rm /tmp/*_token.txt) and temp flow files.

readers loved this