analyzing-ios-binaries について
iOSアプリのバイナリを調べるセキュリティ分析スキルです。暗号化の解除を最初に行い、静的解析とランタイムでの列挙を組み合わせます。
主な機能
- 01解析前にFairPlay暗号化を確認
- 02復号済みアプリバイナリのダンプ
- 03Mach-O構造とエンタイトルメントの確認
- 04Objective-CとSwiftのメタデータ復元
- 05ランタイムでクラスとメソッドを列挙
活用シーン
- 01静的ツールで読めないIPAの調査
- 02アプリ拡張機能と組み込みフレームワークの確認
- 03過剰な権限やハードコードされた秘密情報の特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trilwu/ secskills --skill analyzing-ios-binariesインストール後、Claude Code で/analyzing-ios-binariesを入力して読み込まれたか確認します。
詳細
iOS バイナリの分析
App Store のバイナリは保存時に暗号化されており、読み込み時にカーネルによって復号されます。そのため、メモリから復号済みイメージをダンプするまでは、ダウンロードした IPA に対して静的ツールはすべて機能しません。この手順がほかのすべての作業の前提となるため、多くの iOS 分析は着手前に行き詰まります。
使用する場面
- IPA または
.appバンドルがあり、バイナリを読み取る必要がある class-dumpが何も返さない、または意味不明な結果を返すotoolにcryptid 1と表示される- Objective-C クラス、Swift 型、またはエクスポートされたシンボルを列挙する必要がある
- 埋め込みフレームワーク、アプリ拡張機能、または動的ライブラリを分析する
使用しない場面
- Android の対象 —
testing-mobile-applicationsまたは該当するreversing-*スキルを使用してください - iOS 評価全般(ストレージ、キーチェーン、IPC) —
testing-mobile-applicationsを使用してください - TLS の傍受 —
bypassing-mobile-pinningを使用してください - 脱獄検出によってツールが妨げられる場合 —
まず
bypassing-root-jailbreak-detectionを使用してください - クロスプラットフォームフレームワーク — Flutter、Unity、Xamarin にはそれぞれ専用のスキルがあります。マネージド層にはそれらを使用し、ネイティブシェルにはこのスキルを使用してください
まず暗号化を確認する
otool -l TargetApp | grep -A5 LC_ENCRYPTION_INFO
# cryptid 1 → FairPlay-encrypted, decrypt before anything else
# cryptid 0 → already decrypted (dev build, or you already dumped it)
暗号化されたバイナリに対して、それ以降の作業を行っても意味がありません。class-dump が何も返さない場合、難読化ではなく、ほとんどの場合これが原因です。
# Decrypt on a jailbroken device by dumping the loaded image
frida-ios-dump -l # list installed apps
frida-ios-dump com.target.app # produces a decrypted IPA
bagbak com.target.app # alternative, handles extensions/frameworks well
# Rootless jailbreaks and TrollStore installs work with the same tools
# Older devices: Clutch, flexdecrypt
メインバイナリだけでなく、フレームワークと拡張機能もダンプしてください。PlugIns/
(共有シート、ウィジェット、キーボード)と Frameworks/ には、それぞれ独自の暗号化された Mach-O が含まれています。また、アプリ拡張機能には興味深いエンタイトルメントが含まれていることが多く、メインアプリよりセキュリティ態勢が弱い場合もあります。
Mach-O の構造と保護機能
file TargetApp # thin or fat/universal
lipo -info TargetApp # architectures present
lipo -thin arm64 TargetApp -o app64 # extract one before analysis
otool -hv app64 # header flags: PIE
otool -l app64 | rg 'LC_LOAD_DYLIB|LC_RPATH|LC_CODE_SIGNATURE|LC_ENCRYPTION'
otool -Iv app64 | head # indirect symbols
nm -m app64 | rg -v ' U ' | head # defined symbols
# Protections at a glance
otool -hv app64 | rg PIE # ASLR
otool -Iv app64 | rg stack_chk # stack canaries
otool -Iv app64 | rg objc_release # ARC in use
エンタイトルメントを抽出してください。エンタイトルメントはアプリに許可されている操作を定義し、興味深い攻撃対象領域を明らかにすることもよくあります。
codesign -d --entitlements :- TargetApp.app
# Look for: keychain-access-groups, App Groups, associated-domains,
# get-task-allow (debuggable!), custom URL scheme claims
本番ビルドで get-task-allow が true に設定されている場合、アプリをデバッグできる状態であり、それ自体が指摘事項となります。
Objective-C
Objective-C はバイナリ内に完全なクラスメタデータを保持するため、メソッド名、セレクター、クラス階層、インスタンス変数を非常によく復元できます。
class-dump -H app64 -o ./headers # classic
class-dump-dyld # for dyld shared cache resident classes
dsdump --objc --color app64 # modern alternative, handles Swift too
# Then read the type map
rg -l 'Manager|Service|API|Auth|Crypto|Keychain|Payment' ./headers | head -20
逆アセンブラーでは、Objective-C の呼び出しは objc_msgSend を経由するため、呼び出し先は直接分岐ではなく、レジスター内のセレクター文字列になります。IDA と Ghidra にはこれを解決するプラグインがあります。プラグインがなければ、呼び出しグラフはほとんど役に立ちません。
Swift
Swift の分析はより困難です。名前はマングルされており、メソッドのディスパッチは objc_msgSend ではなく、静的に行われるか、ウィットネステーブルを介して行われることがよくあります。
# Demangle what you find
nm app64 | swift demangle
xcrun swift-demangle '$s10TargetApp11AuthManagerC5loginyyF'
# Swift type metadata lives in dedicated sections
otool -l app64 | rg '__swift5_types|__swift5_proto|__swift5_reflstr'
dsdump --swift app64
Swift を多用するアプリでの実践的なアプローチとして、@objc と @objcMembers のメンバーは引き続き Objective-C メタデータに現れるため、class-dump から部分的なマップを取得できます。それ以外は、完全なクラス一覧の復元を試みるのではなく、文字列参照とリフレクションセクションを起点に調べてください。Frida による実行時の列挙は、通常、静的な復元よりも迅速です。
frida -U -f com.target.app -l enumerate-swift-classes.js
実行時分析
# Enumerate everything the runtime knows
objection -g com.target.app explore
# ios hooking list classes
# ios hooking search methods <keyword>
# ios hooking watch method "-[AuthManager login:]" --dump-args --dump-return
# Direct Frida for anything objection does not cover
frida -U -f com.target.app -l hooks.js
iOS では、ほかのプラットフォームよりも実行時分析が静的分析に勝ることがよくあります。Objective-C ランタイムはイントロスペクション可能なため、クラスの一覧表示やメソッドの監視を行えば、objc_msgSend のディスパッチを逆アセンブルして読むよりも速くロジックを把握できます。
注目する点
- 過剰なエンタイトルメント — 信頼性の低い拡張機能と共有される App Groups、広範に共有されるキーチェーングループ、本番環境での
get-task-allow __cstringとバンドル内の plist ファイルにあるハードコードされたシークレット- 弱いキーチェーンのアクセシビリティ —
ThisDeviceOnlyクラスではなくkSecAttrAccessibleAlwaysで項目が保存されている - CryptoKit/CommonCrypto ではなく、バイナリ内にある独自の暗号処理
- リリースビルドに残されたデバッグコードとログ出力
- 安全でない
WKWebViewの設定 —allowFileAccessFromFileURLs、JS ブリッジを備えたビューへのリモートコンテンツの読み込み - 独自のネットワークスタックとピンニング動作を持つサードパーティ SDK。
Frameworks/を列挙して、それぞれを確認してください
退けるべき合理化
- 「class-dump が何も返さなかった。アプリは難読化されている。」 まず
cryptidを確認してください。ほとんどの場合、暗号化されています。 - 「メインのバイナリをダンプした。これがアプリだ。」 エクステンションとフレームワークは、それぞれ別の Mach-O と個別のエンタイトルメントを持ち、セキュリティが弱いこともよくあります。
- 「Swift だから何も復元できない。」 リフレクションセクション、
@objcメンバー、文字列参照から多くの情報を復元できます。実行時に列挙してください。 - 「静的解析で十分だ。」 iOS では実行時の内部情報を調査できます。これを省くと、節約できる手間よりも代償のほうが大きくなります。
- 「バイナリに PIE とスタックカナリアがあるから、セキュリティ対策済みだ。」 これらはコンパイラーのデフォルト設定であり、セキュリティレビューの証拠ではありません。
- 「ジェイルブレイクできないから、解析できない。」 それでもバンドル、plist、エンタイトルメント、アセットを確認し、Frida ガジェットを組み込んで再パッケージし、サイドローディングできます。レポートでは、その制約によって何ができなかったかを明記してください。
参考資料
testing-mobile-applications— ストレージ、キーチェーン、IPC、および iOS テスト全般bypassing-root-jailbreak-detection— 検出機能によってツールの使用が妨げられる場合bypassing-mobile-pinning— iOS スタックでの TLS インターセプトanalyzing-binaries— 同じ Mach-O を対象とした、より詳細なネイティブ RE- frida-ios-dump、bagbak、class-dump、dsdump、objection、Hopper/IDA/Ghidra