ネイティブライブラリのリバースエンジニアリング

Reading time: 8 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をサポートする

詳細情報は次を確認してください: https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html

Androidアプリは、パフォーマンスが重要なタスクのために通常CまたはC++で書かれたネイティブライブラリを使用できます。マルウェア作成者もこれらのライブラリを悪用します。なぜなら、ELF共有オブジェクトはDEX/OATバイトコードよりもデコンパイルが難しいからです。このページは、Androidの.soファイルのリバースエンジニアリングを容易にする実用的なワークフローと最近のツール改善(2023-2025)に焦点を当てています。


新しく取得したlibfoo.soのための迅速なトリアージワークフロー

  1. ライブラリを抽出する
bash
# インストールされたアプリケーションから
adb shell "run-as <pkg> cat lib/arm64-v8a/libfoo.so" > libfoo.so
# またはAPK(zip)から
unzip -j target.apk "lib/*/libfoo.so" -d extracted_libs/
  1. アーキテクチャと保護を特定する
bash
file libfoo.so        # arm64またはarm32 / x86
readelf -h libfoo.so  # OS ABI, PIE, NX, RELROなど
checksec --file libfoo.so  # (peda/pwntools)
  1. エクスポートされたシンボルとJNIバインディングをリストする
bash
readelf -s libfoo.so | grep ' Java_'     # 動的リンクされたJNI
strings libfoo.so   | grep -i "RegisterNatives" -n   # 静的登録されたJNI
  1. デコンパイラに読み込む (Ghidra ≥ 11.0, IDA Pro, Binary Ninja, HopperまたはCutter/Rizin) し、自動分析を実行します。新しいGhidraバージョンは、PAC/BTIスタブとMTEタグを認識するAArch64デコンパイラを導入し、Android 14 NDKで構築されたライブラリの分析を大幅に改善しました。
  2. 静的リバースエンジニアリングと動的リバースエンジニアリングを決定する: ストリップされた、難読化されたコードはしばしばインスツルメンテーション(Frida、ptrace/gdbserver、LLDB)が必要です。

動的インスツルメンテーション (Frida ≥ 16)

Fridaの16シリーズは、ターゲットが最新のClang/LLD最適化を使用している場合に役立ついくつかのAndroid特有の改善をもたらしました:

  • thumb-relocatorは、LLDの攻撃的なアライメント(--icf=all)によって生成された小さなARM/Thumb関数フックできるようになりました。
  • ELFインポートスロットの列挙と再バインディングはAndroidで機能し、インラインフックが拒否された場合にモジュールごとのdlopen()/dlsym()パッチを可能にします。
  • Javaフックは、Android 14で--enable-optimizationsを使用してアプリがコンパイルされるときに使用される新しいARTクイックエントリポイントのために修正されました。

例:RegisterNativesを通じて登録されたすべての関数を列挙し、実行時にそのアドレスをダンプする:

javascript
Java.perform(function () {
var Runtime = Java.use('java.lang.Runtime');
var register = Module.findExportByName(null, 'RegisterNatives');
Interceptor.attach(register, {
onEnter(args) {
var envPtr  = args[0];
var clazz   = Java.cast(args[1], Java.use('java.lang.Class'));
var methods = args[2];
var count   = args[3].toInt32();
console.log('[+] RegisterNatives on ' + clazz.getName() + ' -> ' + count + ' methods');
// iterate & dump (JNI nativeMethod struct: name, sig, fnPtr)
}
});
});

Fridaは、PAC/BTI対応デバイス(Pixel 8/Android 14+)で、frida-server 16.2以降を使用すれば、すぐに動作します。以前のバージョンはインラインフックのためのパディングを見つけることができませんでした。 citeturn5search2turn5search0


APKで狙うべき最近の脆弱性

CVE影響を受けるライブラリノート
2023CVE-2023-4863libwebp ≤ 1.3.1WebP画像をデコードするネイティブコードから到達可能なヒープバッファオーバーフロー。いくつかのAndroidアプリが脆弱なバージョンをバンドルしています。APK内にlibwebp.soが見つかった場合、そのバージョンを確認し、エクスプロイトまたはパッチを試みてください。
2024複数OpenSSL 3.xシリーズいくつかのメモリ安全性およびパディングオラクルの問題。多くのFlutterおよびReactNativeバンドルは独自のlibcrypto.soを出荷しています。

APK内にサードパーティ.soファイルを見つけた場合は、常にそのハッシュを上流のアドバイザリーと照合してください。モバイルではSCA(ソフトウェア構成分析)が一般的ではないため、古い脆弱なビルドが蔓延しています。


逆アセンブル防止およびハードニングのトレンド(Android 13-15)

  • ポインタ認証(PAC)およびブランチターゲット識別(BTI): Android 14は、サポートされているARMv8.3+シリコンのシステムライブラリでPAC/BTIを有効にします。デコンパイラはPAC関連の擬似命令を表示します。動的分析のためにFridaはPACを除去した後にトランポリンを注入しますが、カスタムトランポリンは必要に応じてpacda/autibspを呼び出すべきです。
  • MTEおよびScudoハードニングアロケータ: メモリタグ付けはオプトインですが、多くのPlay-Integrity対応アプリは-fsanitize=memtagでビルドされています。タグフォルトをキャプチャするには、setprop arm64.memtag.dump 1adb shell am start ...を使用してください。
  • LLVMオブフスケータ(不透明な述語、制御フローのフラット化): 商業パッカー(例:Bangcle、SecNeo)は、Javaだけでなくネイティブコードを保護する傾向が高まっています。.rodata内に偽の制御フローや暗号化された文字列ブロブを期待してください。

リソース

参考文献

  • Frida 16.xの変更ログ(Androidフッキング、tiny-functionの再配置) – frida.re/news citeturn5search0
  • libwebpオーバーフローCVE-2023-4863に関するNVDアドバイザリー – nvd.nist.gov citeturn2search0

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をサポートする