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 here1. 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=1mWeb UI: http://127.0.0.1:8081 (password above). Flow List = live requests.
Verify it's up:
lsof -nP -iTCP:8080 -sTCP:LISTENFor reliable self-inspection add
-w /tmp/flows.mitm, then read later withmitmdump -nr /tmp/flows.mitm. (mitmweb's stdout is block-buffered and lags — the web UI /-wfile are the source of truth, not the background task output.)
2. iPhone setup (user does this, same Wi-Fi)
Settings → Wi-Fi → ⓘ → Configure Proxy → Manual → Server = Mac IP, Port =
8080.Install cert ON the phone (a downloaded
.pemon the Mac is useless): Safari → http://mitm.it → tap the Apple icon → Allow → install the profile in Settings → General → VPN & Device Management.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 |
|---|---|---|
| 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, |
Only | 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) orapk-mitmis 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-Originor aBearertoken. 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 JWTexp), 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 fastCloud 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-Paddingheader 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.comhosts: third-party analytics, usually pinned and irrelevant to the target.
9. Cleanup (always offer at the end)
Stop proxy:
pkill -f mitmwebRemind 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.