# Flutter Ssl Bypass

> Bypass SSL/TLS pinning in Flutter apps to intercept HTTPS traffic with Burp or mitmproxy. Use this skill whenever you need to intercept Flutter app traffic, bypass certificate pinning on Android/iOS, or analyze Flutter network requests. Flutter apps use BoringSSL inside libflutter.so which ignores standard Android SSL pinning bypasses - this skill covers Frida hooking, binary patching, and offset-based techniques to force certificate acceptance.

- Skill: `abelrguezr/flutter-ssl-bypass` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/flutter-ssl-bypass`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/flutter-ssl-bypass/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/flutter-ssl-bypass

---


# Flutter SSL/TLS Bypass

Flutter apps run networking code inside `libflutter.so` (Android) or `Flutter.framework` (iOS), which bundles BoringSSL. This means:

- **Java/Kotlin SSL pinning bypasses don't work** - verification happens in native code
- **System CA store is ignored** - BoringSSL uses its own CA store
- **Symbols are stripped** - you can't hook by function name

This skill covers three approaches to bypass Flutter TLS verification:

## Quick Decision Tree

| Situation | Recommended Approach |
|-----------|---------------------|
| Rooted device, need fast bypass | Frida Codeshare + system CA |
| Can't use Codeshare, have Ghidra | Offset-based hooking |
| Can rebuild the app | Binary patching with reFlutter |
| Multiple Flutter versions | Pattern-based Frida hooking |

---

## Method 1: Frida Codeshare (Fastest)

When you have a rooted device or writable AVD, this is the quickest path:

### Step 1: Install Proxy CA in System Store

```bash
# Get Burp CA certificate (DER format)
# Hash it and push to system store
adb push burp.der /system/etc/security/cacerts/
adb shell "chmod 644 /system/etc/security/cacerts/burp.der"
```

See `install-burp-certificate.md` for full instructions on hashing and renaming.

### Step 2: Deploy Frida Server

```bash
adb push frida-server-17.0.5-android-x86_64 /data/local/tmp/frida-server
adb shell "su -c 'chmod 755 /data/local/tmp/frida-server && /data/local/tmp/frida-server &'"
```

### Step 3: Spawn App with TLS Bypass

```bash
frida -U -f com.example.target --codeshare TheDauntless/disable-flutter-tls-v1 --no-pause
```

This Codeshare script overrides the Flutter TLS verifier to accept all certificates.

### Step 4: Route Traffic Through Proxy

```bash
# Emulator
adb shell settings put global http_proxy 10.0.2.2:8080

# Or use reverse tunnel
adb reverse tcp:8080 tcp:8080
```

### Step 5: Force Socket Redirection (if needed)

If the app ignores proxy settings:

```bash
frida -U -f com.example.target --no-pause \
  --codeshare TheDauntless/disable-flutter-tls-v1 \
  -l scripts/frida4burp.js
```

---

## Method 2: Offset-Based Hooking (Architecture-Agnostic)

When pattern scanning fails across architectures, hook by absolute offset:

### Step 1: Extract libflutter.so

```bash
unzip -j app.apk "lib/*/libflutter.so" -d libs/
# Pick the one matching your device architecture
# e.g., libs/lib/x86_64/libflutter.so or libs/lib/arm64-v8a/libflutter.so
```

### Step 2: Analyze in Ghidra

1. Open `libflutter.so` in Ghidra
2. **Search → For Strings → `ssl_client`**
3. Go to XREFs and examine each `FUN_...` reference
4. Find the function with:
   - 3 pointer-like arguments
   - Boolean return type
   - Located near BoringSSL code

This is `ssl_crypto_x509_session_verify_cert_chain()` from `ssl_x509.cc`.

### Step 3: Calculate Runtime Offset

```bash
# Example: Ghidra shows 0x02184644, image base is 0x00100000
# Offset = 0x02184644 - 0x00100000 = 0x02084644
```

### Step 4: Hook at Runtime

Use `scripts/offset-hook.js`:

```bash
# Edit the script with your calculated offset
# Then run:
frida -U -f com.target.app -l scripts/offset-hook.js --no-pause
```

---

## Method 3: Pattern-Based Hooking

For known Flutter versions, use opcode pattern matching:

### Step 1: Get the Pattern

For x86-64, the first 16 bytes of `ssl_crypto_x509_session_verify_cert_chain`:

```
55 41 57 41 56 41 55 41 54 53 48 83 EC 38 C6 02
```

For ARM64/ARMv7, extract from Ghidra:
1. Open `libflutter.so` in Ghidra
2. Navigate to the verifier function
3. Copy first ~32 bytes as space-separated hex

### Step 2: Run Pattern Hook

Use `scripts/pattern-hook.js`:

```bash
# Edit with your architecture's pattern
frida -U -f com.example.app -l scripts/pattern-hook.js
```

---

## Method 4: Binary Patching with reFlutter

For permanent bypass without runtime hooking:

### Step 1: Identify Flutter Version

```bash
# Extract libapp.so from APK
unzip app.apk lib/x86_64/libapp.so

# Get snapshot hash
python3 scripts/get_snapshot_hash.py libapp.so
# Output: adb4292f3ec25...
```

### Step 2: Map to Engine Version

1. Search the hash in [reFlutter enginehash list](https://github.com/Impact-I/reFlutter)
2. Note the Flutter version and engine commit
3. Pull DEPS file to find BoringSSL revision

### Step 3: Patch and Rebuild

```bash
git clone https://github.com/Impact-I/reFlutter
cd reFlutter
# Follow build instructions for your Flutter version
# Patch ssl_x509.cc to force return 1
# Rebuild libflutter.so
```

### Step 4: Replace in APK

```bash
# Extract APK
apktool d app.apk -o app-decompiled

# Replace libflutter.so in appropriate arch folder
# Rebuild and sign
apktool b app-decompiled -o app-patched.apk
apksigner sign --ks mykey.jks app-patched.apk
```

---

## Forcing Proxy Traffic

Flutter ignores device proxy settings. Options:

| Platform | Method |
|----------|--------|
| Android Emulator | Settings → Proxy → Manual |
| Physical Device | Evil Wi-Fi AP + DNS spoofing |
| Rooted Device | Magisk module editing `/etc/hosts` |
| Any | Frida socket redirection (see Method 1, Step 5) |

---

## Verification

After applying any bypass:

1. **Start Burp/mitmproxy** on port 8080
2. **Launch the app** with Frida attached
3. **Watch for traffic** in your proxy
4. **Test certificate acceptance** - Burp's dynamically generated certs should be accepted

If you see `SSL handshake failed` or no traffic:
- Verify CA is in system store (not user store)
- Check Frida is attached and hook is active
- Confirm proxy routing is working
- Try offset-based method if pattern scanning fails

---

## Troubleshooting

| Problem | Solution |
|---------|----------|
| Hook not triggering | Verify libflutter.so is loaded: `frida-ps -Ua` |
| Wrong architecture | Match Frida server and libflutter.so arch (x86_64 vs arm64) |
| Pattern not found | Use offset-based method instead |
| Traffic not routing | Use `frida4burp.js` for socket redirection |
| App crashes on hook | Ensure return type matches (bool = int in C) |

---

## References

- [Sensepost: Intercepting HTTPS in Flutter](https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/)
- [reFlutter GitHub](https://github.com/Impact-I/reFlutter)
- [BoringSSL ssl_x509.cc](https://github.com/google/boringssl/blob/main/ssl/ssl_x509.cc#L238)
- [Flutter SSL Bypass PoC](https://github.com/m4kr0x/flutter_ssl_bypass)

