Reverse Engineering(リバースエンジニアリング)は、ソースコードにアクセスせずにモバイルアプリケーションのロジックと構造を復元することです。AndroidおよびiOSのコンテキストでは、アルゴリズム、暗号化キー、APIエンドポイント、ビジネスロジックを抽出するために、DEX/APKおよびMach-O/IPAバイナリファイルを逆コンパイルすることを意味します。Veracode Security Research(2025)によると、トップ200のモバイルアプリケーションの60%以上に、リバースエンジニアリングを容易にする指標が少なくとも1つ含まれています。Reverse Engineeringは攻撃だけでなく、セキュリティ監査、特許分析、ペネトレーションテストにも使用されます。
重要ポイント
Reverse Engineering(リバースエンジニアリング)は、アプリケーションのバイナリ表現からその特性、ロジック、構造を復元することを目的としたソフトウェア解析の分野です。モバイルアプリケーションの場合、分析対象はAPKファイル(Android)とIPAファイル(iOS)であり、コンパイルされたコード、リソース、マニフェスト、証明書が含まれています。リバースエンジニアリングの結果は、アルゴリズム、プロトコル、暗号化キー、APIスキーマ、ビジネスロジックの抽出です。
リバースエンジニアリングの目的は、合法的なものと非合法的なものに分けられます。合法的なもの:セキュリティツールを作成するためのマルウェア分析、脆弱性調査のための自社アプリケーションの監査、クローズドプロトコルとの互換性の確保、特許分析、教育。非合法的なもの:知的財産の盗難、ライセンス制限の回避、海賊版の作成、ユーザーデータを盗むためのアプリケーションの改変。Google Play Protect(2025)によると、銀行アプリケーションの悪意のある改変の78%は、リバースエンジニアリングによって処理された元のAPKに基づいて作成されています。
リバースエンジニアリングの方法論には、静的解析(アプリケーションを実行しない)と動的解析(実行中)の2つの主要な方向性が含まれます。各アプローチは異なるレベルの情報を提供します。静的解析はコードの全体像を提供しますが、ランタイムデータはありません。動的解析は実際の動作、データフロー、ネットワーク呼び出しを明らかにしますが、特定の実行シナリオ内に限られます。プロフェッショナルなリバースエンジニアリングは常に両方のアプローチを組み合わせます。
静的解析はリバースエンジニアリングの最初の段階です。元のAPKまたはIPAがアンパックされ、各コンポーネントが個別に分析されます。主な対象:DEXバイトコード、リソース、マニフェスト、ネイティブライブラリ(.so、.dylib)、メタデータ。
jadxはAndroidアプリケーションの静的解析のための主要ツールです。DEXバイトコードを最小限の損失で読み取り可能なJavaコードに変換します。jadxは、マルチデックス逆コンパイル、ラムダ式とインラインKotlinクラスの認識、Gradleプロジェクトへのエクスポートをサポートしています。難読化されたコード(ProGuard)の場合、jadxはa、b、cという名前のコードを表示しますが、クラス構造と呼び出しシーケンスは保持されます。独立したテストによると、jadxは難読化があっても85~92%のコードを正確に逆コンパイルします。
apktoolはAPKをsmaliコード(DEXアセンブラ)にデコードし、リソースを読み取り可能な形式で復元します。AndroidManifest.xmlはAXMLから読み取り可能なXMLに変換され、レイアウトはXMLマークアップに、strings.xmlはプレーンテキストになります。apktoolを使用すると、リソースを変更してAPKを再構築できます。apktoolでアンパックしてリソースを置き換えた後、変更されたコンテンツでアプリケーションをインストールできます。
Ghidra(NSA)は、Androidの.soライブラリとiOSの.dylibを分析するために不可欠なリバースエンジニアリングフレームワークです。GhidraはARM64コードを逆アセンブルし、C擬似コードを再構築し、コールグラフを構築します。モバイルリバースエンジニアリングでは、Ghidraは暗号化とDRMメカニズムのネイティブ実装を分析するために使用されます。Ghidraは分析を自動化するためのPythonとJavaのスクリプティングをサポートしています。
# APKのアンパックと逆コンパイル
$ jadx -d output_dir app.apk
# apktoolによるリソースのアンパック
$ apktool d app.apk -o app_unpacked
# Ghidraによるネイティブライブラリ分析
$ ghidra app.apk/lib/arm64-v8a/libnative.so
# DEX内の文字列定数の検索
$ strings classes.dex | grep -i api_key
動的解析は実行中のアプリケーションに対して実行されます。アナライザーはプロセスに接続し、リアルタイムで関数呼び出し、引数、戻り値をインターセプトします。
Fridaはモバイルアプリケーションの動的解析のための主要ツールです。Fridaはアプリケーションプロセス(Android ARTまたはiOSアプリ)にJavaScriptエンジンを注入し、Java/Objective-CとC/C++の両方の関数呼び出しをインターセプトできます。Fridaを使用すると、リバースエンジニアは以下を実行できます:パラメータ付きのAES.decrypt()メソッドのすべての呼び出しをログ記録、戻り値を任意に置換、Universal Android SSL Unpinを介したSSLピンニングの無効化、Stalkerを介したネイティブ呼び出しのトレース。FridaはAPK/IPAを変更せずに動作するため、ペネトレーションテストに不可欠です。
ObjectionはJavaScriptスクリプトを記述せずに一般的なリバースエンジニアリングタスクのための既製コマンドを提供します:disable-pinning(SSLピンニングの無効化)、dump-keychain(iOS)、explore(クラス階層の閲覧)、memory search(メモリ内の文字列検索)。Objectionはコードを1行も書かずに完全な動的解析を実行できます。iOSアプリケーションの場合、Objectionは自動的にNSURLSession、CFNetwork、NSKeyedArchiverへの呼び出しを検出してログ記録します。
XposedはAndroid用のフレームワークで、Zygote内のapp_processファイルを置き換えることで動作します。Fridaとは異なり、Xposedはインストール後にrootアクセスを必要としません。Xposedモジュールは任意のアプリケーションでメソッド呼び出しをインターセプトできます。リバースエンジニアリングでは、Xposedは長期的な分析に便利です:モジュールがインストールされて継続的に実行され、さまざまなシナリオでのアプリケーションの動作をログ記録します。XposedはAndroid 8.1までをサポートしています。Android 9+では、SandHookベースのEdXposedが使用されます。
// Frida:アプリケーション内のdecrypt()メソッドのインターセプト
let aesClass = Java.use("javax.crypto.Cipher");
aesClass.doFinal.overload(
"[B", "int", "int"
).implementation = function(
input, offset, len
) {
console("[AES] decrypt called, len=" + len);
return this.doFinal(input, offset, len);
};
標準的なリバースエンジニアリングのワークフローは、順次的なステップで構成され、各ステップが特定のレベルの情報を提供します。
アナリストはメタデータレベルでAPKを調査します:targetSdk、uses-permission(要求される権限)、intent-filter、エクスポートされたコンポーネント。権限から使用されているAPIを特定できます(android.permission.CAMERA → カメラ、android.permission.RECORD_AUDIO → オーディオ)。エクスポートされたアクティビティは、認証なしのエントリポイントを特定します。この段階はaaptまたはApkAnalyzerを介して実行され、1~2分かかります。
APKがアンパックされ、classes.dex(またはマルチデックス)がjadxに入力されます。出力はパッケージに整理されたJava/Kotlinコードです。アナリストは主要なクラス(CryptoUtils、ApiClient、AuthManager、DatabaseHelper)を探し、どのアルゴリズムが使用されているかを確認します。コードにAES/CBC/PKCS5Paddingなどの文字列が含まれている場合、アプリケーションは暗号化を使用しており、キーを見つける必要があります。この段階で、ハードコードされたキー、API URL、OAuthトークン、シークレットが特定されます。難読化なしの場合、アプリケーションコード全体が通常のJavaプロジェクトのように読み取れます。
SSLピンニングを無効にするためにFridaまたはObjectionを設定した後、アナリストはアプリケーションを起動し、Burp Suiteまたはmitmproxyを介してネットワークトラフィックをインターセプトします。トラフィックデータはAPIスキーマを明らかにします:どのエンドポイント、どのパラメータ、どの形式か。可能であれば、アナリストはリクエストを変更し、不正または悪意のあるデータに対するサーバーの応答を確認します。サーバーサイドの検証の欠如は、このステップで発見される直接的な脆弱性です。
分析結果は構造化された形式で記録されます。発見された脆弱性ポイントごとに、クラスとメソッド、脆弱性の説明、悪用ベクトル、修正推奨事項が示されます。このデータセットは開発チームに渡されるか、ペネトレーションテストレポートの作成に使用されます。自動化環境(MobSF)では、静的および動的分析の結果に基づいてレポートが自動生成されます。
iOSアプリケーションのリバースエンジニアリングは、Appleの厳格なセキュリティアーキテクチャと標準デバイスでのファイルシステムへの直接アクセスの欠如により、Androidよりも困難です。iOSの分析にはジェイルブレイクが必要です。
IPAアーカイブにはMach-Oバイナリ(Appleのユニバーサル実行可能ファイル形式)が含まれています。逆コンパイルにはHopper DisassemblerまたはIDA Proが使用されます。最小限の損失でJavaに逆コンパイルされるAndroid DEXとは異なり、Mach-OにはネイティブのARM64コードが含まれており、C疑似コードへの再構築の精度は低くなります。Hopperは60~70%の再構築を達成します。残りはアセンブリレベルで分析する必要があります。
iOS上のFridaにはジェイルブレイクとfrida-serverのインストールが必要です。接続後、FridaはAPIメッセージルーティングを介してObjective-Cメソッドをインターセプトします。iOSアプリケーションの場合、典型的なシナリオには以下が含まれます:HTTPリクエストをログ記録するためのNSURLSession.dataTaskWithRequestのインターセプト、シリアル化されたデータ分析のためのNSKeyedUnarchiverのインターセプト、frida-traceを介したCoreDataクエリのトレース。FridaはiOS 15~17でDopamineジェイルブレイクのリリースとともに利用可能になりました。
リバースエンジニアリングには、IPAの改変とそれに続く再パッケージ化およびデバイスへのインストールが含まれる場合があります。ツールには、アンパックのためのipatool、セクション表示のためのMachOView、コードインジェクションのためのoptoolが含まれます。改変後、IPAはジェイルブレイクされたデバイスにインストールするために、ldidまたはfastlane sighを介して署名されます。iOS 16+では、コード署名はSecure Enclaveレベルで検証され、改変されたIPAはジェイルブレイクされていないデバイスでは実行されません。
// Frida:iOSアプリケーション内のHTTPリクエストのインターセプト
if (ObjC.available) {
let NSURLSession = ObjC.classes.NSURLSession;
let dataTaskWithRequest = ObjC.protocol("NSURLSessionDelegate")
.method("- URLSession:dataTask:didReceiveData:");
Interceptor.attach(dataTaskWithRequest.implementation, {
onEnter(args) {
let data = ObjC.Object(args[3]);
console("[HTTP Response]", data.toString());
}
});
}
リバースエンジニアリングからの保護は、多層防御の原則に従います。単一の方法では100%の保護は提供できませんが、組み合わせることでリバースエンジニアリングを経済的に非現実的にします。
基本レベルはAndroid用のProGuardで、クラス名とメソッド名を1文字の名前に置き換えます。強化された保護のために、DexGuardはオーバーロード誘導(異なるシグネチャを持つ同じ名前の複数のメソッド)とAES-256文字列暗号化を追加します。難読化により、コード分析時間はレベルに応じて5分から5~20時間に増加します。DexGuardはさらに制御フローを難読化し、jadxでコードを読み取り不能にします。
すべての文字列定数(URL、キー、トークン、SQLクエリ)はビルド時に暗号化され、ランタイムで復号化されます。これにより、DEXファイル内の文字列の静的解析から保護されます。app.apkでstringsコマンドを実行した攻撃者は、APIエンドポイントを1つも見ることができません。逆コンパイル後も、すべての文字列はバイナリデータとして表示されます。各文字列に個別のキーを使用できるため、難読化解除が複雑になります。
アプリケーション内のRASPエージェントは、ランタイムでFridaとデバッグを検出します。APKのSHA-256ハッシュによる整合性チェックは、改変されたバージョンのアプリケーションの実行を防止します。APKハッシュが参照ハッシュ(ネイティブ層に保存)と一致しない場合、アプリケーションは終了します。これにより、APKの改変に基づく攻撃(再パッケージ化を含む)をブロックします。
重要なビジネスロジックはクライアントではなくサーバーで実行されるべきです。攻撃者がアプリケーションを完全に逆コンパイルしても、サーバーコードはアクセス不可能なままです。すべてのリクエストとパラメータのサーバーサイド検証は、リバースエンジニアリング中に発見された脆弱性の悪用を防ぎます。サーバーアテステーション(Play Integrity APIまたはApp Attest経由)は、リクエストが正当で改変されていないアプリケーションからのものであることを確認します。
よくある質問
米国では、リバースエンジニアリングはDMCAによって規制されています。相互運用性、セキュリティテスト、アーカイブ目的で許可されています。技術的保護手段(DRM)の回避は禁止されています。欧州では、EUCD第6条がDMCAと同様です。ロシアでは、著作権所有者の同意なしのリバースエンジニアリングは著作権侵害と見なされる可能性があります。商用のリバースエンジニアリングの前には法的相談が必須です。
いいえ。攻撃者のデバイスで実行されるコードはすべて分析可能です。これはクライアントサイドセキュリティモデルの根本的な制限です。保護の目的は、リバースエンジニアリングを経済的に魅力的でなくすることです。時間とリソースのコストが得られる結果の価値を上回るべきです。難読化、RASP、サーバーサイドロジックの組み合わせが現在の保護基準です。
リパッケージングとは、リバースエンジニアリングによるアプリケーションの改変とその後のAPKの再構築です。攻撃者はapktoolでAPKをアンパックし、悪意のあるコードを追加するかAPIキーを置き換え、再構築して自身の証明書で署名します。リパッケージングは、Kaspersky Threat Report(2025)によると、Android上の全攻撃の86%を占めています。対策:ランタイムでデジタル署名を確認します。
FridaスクリプトUniversal Android SSL Unpinは、iOS上のTrustManager.checkServerTrustedとServerTrustManagerの呼び出しをインターセプトし、実装を許可-allに置き換えます。OkHttpおよびURLConnectionでのX509TrustManagerメソッドのインターセプトも使用されます。SSLピンニングは、Fridaを使用して既製のスクリプトで10秒で回避できます。より堅牢な保護は、サーバーサイドの証明書検証による証明書の透明性です。
.so/.dylibライブラリ内のネイティブC/C++コードは、DEX内のJavaよりもはるかにリバースが困難です。PGOとOsizeコンパイルを使用したSwiftは、Objective-Cよりも難読化されたバイナリを生成します。RustはランタイムメタデータやObjective-Cの標準ラッパーなしでネイティブコードにコンパイルされるため、現代のモバイル開発言語の中でリバースエンジニアリングが最も困難です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。