diff --git a/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md b/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md index a2d8317ca..0fec01ae9 100644 --- a/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md +++ b/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md @@ -1,31 +1,31 @@ -# Android アンチインストゥルメンテーション & SSL ピンニングバイパス (Frida/Objection) +# Android アンチインストルメンテーション & SSL ピニングバイパス (Frida/Objection) {{#include ../../banners/hacktricks-training.md}} -このページは、インストゥルメンテーションを検知/rootでブロックする Android アプリや TLS ピンニングを強制するアプリに対して、動的解析を再確立するための実践的なワークフローを示します。高速なトリアージ、一般的な検知方法、再パッケージ不要で回避可能なコピペ可能なフック/戦術に焦点を当てています。 +このページは、Instrumentation を検出/ルートブロックする、または TLS ピニングを強制する Android アプリに対して動的解析を取り戻すための実践的なワークフローを提供します。迅速なトリアージ、一般的な検出方法、repacking を行わずに回避するためのコピペ可能なフック/戦術に焦点を当てています。 -## 検知サーフェス(アプリがチェックする項目) +## Detection Surface (what apps check) -- Root チェック: su バイナリ、Magisk パス、getprop の値、一般的な root パッケージ -- Frida/デバッガ検知(Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), /proc のスキャン、classpath、読み込まれたライブラリ -- ネイティブのアンチデバッグ: ptrace(), syscalls、anti‑attach、ブレークポイント、インラインフック -- 早期初期化チェック: Application.onCreate() やプロセス起動時のフックで、インストゥルメンテーションがあるとクラッシュさせるもの -- TLS ピンニング: カスタム TrustManager/HostnameVerifier、OkHttp CertificatePinner、Conscrypt ピンニング、ネイティブピン +- Root checks: su binary, Magisk paths, getprop values, common root packages +- Frida/debugger checks (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scanning /proc, classpath, loaded libs +- Native anti‑debug: ptrace(), syscalls, anti‑attach, breakpoints, inline hooks +- Early init checks: Application.onCreate() or process start hooks that crash if instrumentation is present +- TLS pinning: custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins -## Step 1 — 即効の対処: Magisk DenyList で root を隠す +## Step 1 — Quick win: hide root with Magisk DenyList -- Magisk で Zygisk を有効化 -- DenyList を有効にして対象パッケージを追加 -- 再起動して再テスト +- Enable Zygisk in Magisk +- Enable DenyList, add the target package +- Reboot and retest -多くのアプリは明白な指標(su/Magisk パス/getprop)しか見ていません。DenyList はナイーブなチェックを無効化することが多いです。 +多くのアプリは明白な指標(su/Magisk パス/getprop)しか見ていません。DenyList は単純なチェックを無効化することがよくあります。 References: - Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk -## Step 2 — 30秒フリダ Codeshare テスト +## Step 2 — 30‑second Frida Codeshare tests -深掘りする前に一般的な drop‑in スクリプトを試してください: +深掘りする前に一般的なドロップインスクリプトを試してください: - anti-root-bypass.js - anti-frida-detection.js @@ -35,13 +35,13 @@ Example: ```bash frida -U -f com.example.app -l anti-frida-detection.js ``` -これらは通常、Javaのroot/debugチェック、プロセス/サービスのスキャン、およびネイティブのptrace()をスタブ化します。保護の弱いアプリには有用ですが、堅牢に保護されたターゲットではカスタムフックが必要になる場合があります。 +これらは通常、Java root/debug checks、process/service scans、およびネイティブ ptrace() をスタブ化します。軽度に保護されたアプリには有用ですが、強固に保護されたターゲットではカスタムフックが必要になる場合があります。 - Codeshare: https://codeshare.frida.re/ ## Medusa (Frida framework)で自動化 -Medusaは、SSL unpinning、root/emulator detection bypass、HTTP comms logging、crypto key interceptionなどのための90以上の既成モジュールを提供します。 +Medusaは、SSL unpinning、root/emulator detection bypass、HTTP comms logging、crypto key interception などのための90以上の既成モジュールを提供します。 ```bash git clone https://github.com/Ch0pin/medusa cd medusa @@ -54,22 +54,22 @@ use http_communications/multiple_unpinner use root_detection/universal_root_detection_bypass run com.target.app ``` -ヒント: Medusa は custom hooks を書く前に迅速な成果を出すのに最適です。modules を個別に選んで自分の scripts と組み合わせることもできます。 +ヒント:Medusaはカスタムhooksを書く前の短期的な成果を得るのに最適です。モジュールを選んで自分のscriptsと組み合わせることもできます。 -## Step 3 — attaching late で init-time detectors を Bypass する +## ステップ 3 — 初期化時の検出を回避するために遅れてアタッチする -多くの検出は process spawn/onCreate() の実行時のみ走ります。Spawn‑time injection (-f) や gadgets は検出されやすいですが、UI が読み込まれた後に attaching すると回避できることがあります。 +多くの検出は process spawn/onCreate() の間にのみ実行されます。Spawn‑time injection (-f) や gadgets は検出されやすく、UI がロードされた後にアタッチすると回避できることがあります。 ```bash # Launch the app normally (launcher/adb), wait for UI, then attach frida -U -n com.example.app # Or with Objection to attach to running process aobjection --gadget com.example.app explore # if using gadget ``` -もしこれが機能するなら、セッションを安定させたまま map と stub checks に進んでください。 +If this works, keep the session stable and proceed to map and stub checks. -## Step 4 — Jadx と文字列探索による検出ロジックのマッピング +## ステップ4 — Jadx と文字列検索による検出ロジックのマッピング -Static triage keywords in Jadx: +静的トリアージ用キーワード(Jadx): - "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger" 典型的な Java パターン: @@ -78,16 +78,16 @@ public boolean isFridaDetected() { return getRunningServices().contains("frida"); } ``` -Common APIs を確認・hook すべき一般的な API: +確認/フックすべき一般的なAPI: - android.os.Debug.isDebuggerConnected - android.app.ActivityManager.getRunningAppProcesses / getRunningServices -- java.lang.System.loadLibrary / System.load (native bridge) -- java.lang.Runtime.exec / ProcessBuilder (probing commands) -- android.os.SystemProperties.get (root/emulator heuristics) +- java.lang.System.loadLibrary / System.load (ネイティブブリッジ) +- java.lang.Runtime.exec / ProcessBuilder (プロービングコマンド) +- android.os.SystemProperties.get (root/エミュレータのヒューリスティック) -## Step 5 — Runtime stubbing with Frida (Java) +## ステップ5 — Fridaによるランタイムのスタブ化(Java) -カスタムガードを上書きして、安全な値を返す(repacking を行わずに): +パッキングし直さずに安全な値を返すようカスタムガードをオーバーライド: ```js Java.perform(() => { const Checks = Java.use('com.example.security.Checks'); @@ -102,7 +102,7 @@ const AM = Java.use('android.app.ActivityManager'); AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); }; }); ``` -早期クラッシュをトリアージしていますか?クラッシュ直前にクラスをダンプして、検出に使われそうな名前空間を特定します: +早期クラッシュをトリアージしていますか?クラッシュ直前にクラスをダンプして、検出されそうな名前空間を特定しましょう: ```js Java.perform(() => { Java.enumerateLoadedClasses({ @@ -119,7 +119,7 @@ RootChecker.isDeviceRooted.implementation = function () { return false; }; } catch (e) {} }); -疑わしいメソッドをログに記録して無効化し、実行フローを確認する: +実行フローを確認するために、疑わしいメソッドをログに記録して無効化する: ```js Java.perform(() => { const Det = Java.use('com.example.security.DetectionManager'); @@ -131,9 +131,9 @@ return false; ``` ## Bypass emulator/VM detection (Java stubs) -一般的なヒューリスティック: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE containing generic/goldfish/ranchu/sdk; QEMU artifacts like /dev/qemu_pipe, /dev/socket/qemud; default MAC 02:00:00:00:00:00; 10.0.2.x NAT; missing telephony/sensors. +一般的なヒューリスティック: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE に generic/goldfish/ranchu/sdk が含まれる; QEMU のアーティファクト(例: /dev/qemu_pipe, /dev/socket/qemud); デフォルト MAC 02:00:00:00:00:00; 10.0.2.x の NAT; telephony/sensors が欠如している。 -Build フィールドの簡易偽装: +Quick spoof of Build fields: ```js Java.perform(function(){ var Build = Java.use('android.os.Build'); @@ -143,11 +143,11 @@ Build.BRAND.value = 'google'; Build.FINGERPRINT.value = 'google/panther/panther:14/UP1A.231105.003/1234567:user/release-keys'; }); ``` -ファイルの存在チェックと識別子(TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList)に対するスタブを追加して、現実的な値を返すようにしてください。 +ファイル存在チェックや識別子(TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList)に対するスタブを追加して、現実的な値を返すようにしてください。 ## SSL pinning bypass quick hook (Java) -カスタム TrustManagers を無効化し、許容的な SSL contexts を強制します: +カスタム TrustManagers を無効化し、寛容な SSL コンテキストを強制します: ```js Java.perform(function(){ var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); @@ -166,27 +166,27 @@ return SSLContextInit.call(this, km, TrustManagers, sr); }); ``` 注意 -- OkHttp 向けに拡張: 必要に応じて okhttp3.CertificatePinner と HostnameVerifier を hook するか、CodeShare のユニバーサル unpinning スクリプトを使用する。 +- OkHttp向けに拡張する: hook okhttp3.CertificatePinner and HostnameVerifier as needed, or use a universal unpinning script from CodeShare. - 実行例: `frida -U -f com.target.app -l ssl-bypass.js --no-pause` -## ステップ6 — Java hooks が失敗したときは JNI/native のトレイルを辿る +## ステップ6 — Java hooks が失敗したときは JNI/native の痕跡を追う -JNI のエントリポイントをトレースして native loaders と detection init を特定する: +JNI entry points をトレースして native loaders と detection init を特定する: ```bash frida-trace -n com.example.app -i "JNI_OnLoad" ``` -バンドルされた .so ファイルの簡易ネイティブトリアージ: +バンドルされた .so ファイルの簡易ネイティブトリアージ: ```bash # List exported symbols & JNI nm -D libfoo.so | head objdump -T libfoo.so | grep Java_ strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root' ``` -インタラクティブ/ネイティブ逆解析: +インタラクティブ/ネイティブのリバースエンジニアリング: - Ghidra: https://ghidra-sre.org/ - r2frida: https://github.com/nowsecure/r2frida -例: ptrace を無効化して libc の単純な anti‑debug を回避する: +例: ptrace を無効化して libc の簡易な anti‑debug を回避する: ```js const ptrace = Module.findExportByName(null, 'ptrace'); if (ptrace) { @@ -202,28 +202,28 @@ reversing-native-libraries.md ## ステップ7 — Objection patching (embed gadget / strip basics) -runtime hooks より repacking を好む場合は、次を試してください: +repackingをruntime hooksより好む場合は、次を試してください: ```bash objection patchapk --source app.apk ``` -注記: -- apktool が必要;ビルド問題を避けるため、公式ガイドから最新バージョンを取得してください: https://apktool.org/docs/install -- Gadget injection は root を必要としない instrumentation を可能にするが、より強力な初期化時チェックによって検出される可能性がある。 +注意: +- apktool が必要です。ビルドの問題を避けるため、公式ガイドから最新バージョンを入手してください: https://apktool.org/docs/install +- Gadget injection は root を必要とせずに instrumentation を可能にしますが、より厳しい init‑time チェックで検出されることがあります。 -任意で、Zygisk 環境でのより強力な root 隠蔽のために LSPosed モジュールと Shamiko を追加し、DenyList を調整して子プロセスもカバーしてください。 +オプションとして、Zygisk 環境での root 隠蔽を強化するために LSPosed モジュールと Shamiko を追加し、子プロセスをカバーするよう DenyList を整備してください。 参考: - Objection: https://github.com/sensepost/objection -## Step 8 — Fallback: TLS pinning をパッチしてネットワークの可視性を確保する +## Step 8 — フォールバック: TLS pinning をパッチしてネットワーク可視性を確保 -If instrumentation is blocked, you can still inspect traffic by removing pinning statically: +instrumentation がブロックされている場合、pinning を静的に除去してトラフィックを解析できます: ```bash apk-mitm app.apk # Then install the patched APK and proxy via Burp/mitmproxy ``` - ツール: https://github.com/shroudedcode/apk-mitm -- ネットワーク設定の CA‑trust トリック(および Android 7+ の user CA trust)については、次を参照: +- ネットワーク設定の CA‑trust トリック(および Android 7+ の user CA trust)については、次を参照: {{#ref}} make-apk-accept-ca-certificate.md @@ -251,14 +251,32 @@ objection --gadget com.example.app explore # Static TLS pinning removal apk-mitm app.apk ``` -## ヒントと注意点 +## Universal proxy forcing + TLS unpinning (HTTP Toolkit Frida hooks) -- アプリが起動時にクラッシュする場合は、spawnするよりも遅めにattachすることを優先する -- 一部の検出は重要なフロー(例:payment、auth)で再実行される — navigation中はhooksを有効にしておく -- 静的解析と動的解析を組み合わせる: Jadxでstring huntして候補クラスを絞り込み、hook methodsでruntime時に検証する -- ハード化されたアプリはpackersやnative TLS pinningを使用することがある — native codeをreverseすることを想定する +最近のアプリはしばしばシステムプロキシを無視し、複数層のピンニング(Java + native)を強制するため、ユーザー/システムCAをインストールしていてもトラフィックのキャプチャが困難になる。実用的なアプローチとしては、汎用のTLS unpinningとプロキシ強制を既製のFridaフックで組み合わせ、すべてをmitmproxy/Burp経由へルーティングする方法がある。 -## 参考 +Workflow +- ホストで mitmproxy(または Burp)を起動する。デバイスがホストのIP/ポートに到達できることを確認する。 +- HTTP Toolkitの統合済みFridaフックを読み込み、OkHttp/OkHttp3、HttpsURLConnection、Conscrypt、WebViewなどの一般的なスタックでTLSのunpinningとプロキシ使用の強制を行う。これによりCertificatePinner/TrustManagerのチェックをバイパスし、プロキシセレクタを上書きするため、アプリが明示的にプロキシを無効化していてもトラフィックは常にあなたのプロキシ経由で送信される。 +- Fridaとフックスクリプトを使ってターゲットアプリを起動し、mitmproxyでリクエストをキャプチャする。 + +例 +```bash +# Device connected via ADB or over network (-U) +# See the repo for the exact script names & options +frida -U -f com.vendor.app \ +-l ./android-unpinning-with-proxy.js \ +--no-pause + +# mitmproxy listening locally +mitmproxy -p 8080 +``` +ノート +- Combine with a system-wide proxy via `adb shell settings put global http_proxy :` when possible. Frida フックはアプリがグローバル設定を回避してもプロキシの使用を強制します。 +- この手法は、pinning や proxy 回避が一般的な、モバイルから IoT へのオンボーディングフローを MITM する必要がある場合に最適です。 +- Hooks: https://github.com/httptoolkit/frida-interception-and-unpinning + +## 参考資料 - [Reversing Android Apps: Bypassing Detection Like a Pro](https://www.kayssel.com/newsletter/issue-12/) - [Frida Codeshare](https://codeshare.frida.re/)