Flutter
Reading time: 5 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
Flutter
FlutterはGoogleのクロスプラットフォームUIツールキットで、開発者が単一のDartコードベースを書き、Engine(ネイティブC/C++)がAndroidおよびiOS用のプラットフォーム固有の機械コードに変換します。エンジンはDart VM、BoringSSL、Skiaなどをバンドルし、共有ライブラリlibflutter.so(Android)またはFlutter.framework(iOS)として出荷されます。すべての実際のネットワーキング(DNS、ソケット、TLS)はこのライブラリ内で行われ、通常のJava/Kotlin Swift/Obj-Cレイヤーではありません。この分離された設計が、通常のJavaレベルのFridaフックがFlutterアプリで失敗する理由です。
FlutterでのHTTPSトラフィックの傍受
これはこのブログ投稿の要約です。
FlutterでのHTTPS傍受が難しい理由
- SSL/TLS検証はBoringSSLの2層下に存在するため、JavaのSSLピンニングバイパスでは触れません。
- BoringSSLはlibflutter.so内に独自の CAストアを使用しているため、Burp/ZAP CAをAndroidのシステムストアにインポートしても何も変わりません。
- libflutter.so内のシンボルはストリップされており、マングルされています。これにより、動的ツールから証明書検証関数が隠されます。
正確なFlutterスタックのフィンガープリンティング
バージョンを知ることで、正しいバイナリを再構築またはパターンマッチできます。
Step | Command / File | Outcome |
---|---|---|
スナップショットハッシュを取得 | bash\npython3 get_snapshot_hash.py libapp.so\n | adb4292f3ec25… |
ハッシュを→エンジンにマップ | enginehashリストをreFlutterで | Flutter 3 · 7 · 12 + engine commit 1a65d409… |
依存コミットをプル | そのエンジンコミットのDEPSファイル | • dart_revision → Dart v2 · 19 · 6• dart_boringssl_rev → BoringSSL 87f316d7… |
ターゲット: ssl_crypto_x509_session_verify_cert_chain()
- BoringSSL内の
ssl_x509.cc
にあります。 bool
を返します – 単一のtrue
で全体の証明書チェーンチェックをバイパスできます。- 同じ関数はすべてのCPUアーキテクチャに存在し、オペコードのみが異なります。
オプションA – reFlutterを使用したバイナリパッチ
- アプリのFlutterバージョンに対して正確なエンジンとDartソースをクローンします。
- 2つのホットスポットを正規表現パッチします:
ssl_x509.cc
で、return 1;
を強制します。- (オプション)
socket_android.cc
で、プロキシをハードコーディングします("10.0.2.2:8080"
)。
- libflutter.soを再コンパイルし、APK/IPAに戻し、署名してインストールします。
- 一般的なバージョンのための事前パッチビルドがreFlutterのGitHubリリースに出荷され、ビルド時間を数時間節約します。
オプションB – Fridaを使用したライブフック(「ハードコア」パス)
シンボルがストリップされているため、読み込まれたモジュールの最初のバイトをパターンスキャンし、動的に戻り値を変更します。
javascript
// attach & locate libflutter.so
var flutter = Process.getModuleByName("libflutter.so");
// x86-64 pattern of the first 16 bytes of ssl_crypto_x509_session_verify_cert_chain
var sig = "55 41 57 41 56 41 55 41 54 53 48 83 EC 38 C6 02";
Memory.scan(flutter.base, flutter.size, sig, {
onMatch: function (addr) {
console.log("[+] found verifier at " + addr);
Interceptor.attach(addr, {
onLeave: function (retval) { retval.replace(0x1); } // always 'true'
});
},
onComplete: function () { console.log("scan done"); }
});
実行する:
bash
frida -U -f com.example.app -l bypass.js
ポーティングのヒント
- arm64-v8a または armv7 の場合、Ghidraから関数の最初の約32バイトを取得し、スペース区切りの16進数文字列に変換して
sig
を置き換えます。 - Flutterのリリースごとに1つのパターンを保持し、迅速な再利用のためにチートシートに保存します。
プロキシを通じてトラフィックを強制する
Flutter自体は デバイスのプロキシ設定を無視します。最も簡単なオプション:
- Android Studioエミュレーター: 設定 ▶ プロキシ → 手動。
- 物理デバイス: 悪意のあるWi-Fi AP + DNSスプーフィング、またはMagiskモジュールで
/etc/hosts
を編集。