# ネイティブライブラリのリバース {{#include ../../banners/hacktricks-training.md}} **詳細は次を参照してください:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html) Androidアプリは、通常CやC++で書かれたネイティブライブラリをパフォーマンスが重要な処理に使います。マルウェア作成者もこれらのライブラリを悪用します。なぜなら、ELF shared objectsはDEX/OATバイトコードよりもまだデコンパイルが難しいからです。 本ページは、Androidの`.so`ファイルのリバースを容易にする、*実践的な*ワークフローと*最近の*ツール改善(2023–2025)に焦点を当てています。 --- ### 新たに取得した `libfoo.so` のクイックトリアージワークフロー 1. **ライブラリを抽出する** ```bash # From an installed application adb shell "run-as cat lib/arm64-v8a/libfoo.so" > libfoo.so # Or from the APK (zip) unzip -j target.apk "lib/*/libfoo.so" -d extracted_libs/ ``` 2. **アーキテクチャと保護を特定する** ```bash file libfoo.so # arm64 or arm32 / x86 readelf -h libfoo.so # OS ABI, PIE, NX, RELRO, etc. checksec --file libfoo.so # (peda/pwntools) ``` 3. **エクスポートされたシンボルとJNIバインディングを列挙する** ```bash readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI strings libfoo.so | grep -i "RegisterNatives" -n # static-registered JNI ``` 4. **デコンパイラにロードする** (Ghidra ≥ 11.0, IDA Pro, Binary Ninja, Hopper or Cutter/Rizin) そして自動解析を実行する。 新しいGhidraはAArch64のデコンパイラを導入し、PAC/BTIスタブやMTEタグを認識するようになったため、Android 14 NDKでビルドされたライブラリの解析が大幅に改善されました。 5. **静的解析か動的解析かを決める:** ストリップ済みや難読化されたコードはしばしば*instrumentation*(Frida、ptrace/gdbserver、LLDB)が必要になります。 --- ### Dynamic Instrumentation (Frida ≥ 16) Fridaの16シリーズは、ターゲットが最新のClang/LLD最適化を使っている場合に役立ついくつかのAndroid固有の改善をもたらしました: * `thumb-relocator`は、LLDの積極的なアラインメント(`--icf=all`)で生成される小さなARM/Thumb関数に対して*フック*できるようになりました。 * ELFのimportスロットを列挙してリバインドする機能がAndroid上で動作するようになり、inline hooksが拒否された場合でもモジュール単位での`dlopen()`/`dlsym()`パッチが可能になりました。 * Javaフッキングは、Android 14で`--enable-optimizations`付きでコンパイルされたアプリが使う新しい**ART quick-entrypoint**に対して修正されました。 Example: enumerating all functions registered through `RegisterNatives` and dumping their addresses at runtime: ```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 will work out of the box on PAC/BTI-enabled devices (Pixel 8/Android 14+) as long as you use frida-server 16.2 or later – earlier versions failed to locate padding for inline hooks. ### プロセスローカルなJNIテレメトリ via preloaded .so (SoTap) フル機能のインストゥルメンテーションが過剰だったりブロックされている場合でも、ターゲットプロセス内に小さなロガーを事前ロードすることでネイティブレベルの可視性を得られます。SoTapは、同じアプリプロセス内の他のJNI (.so)ライブラリの実行時挙動をログする軽量のAndroidネイティブ(.so)ライブラリです(root不要)。 Key properties: - 早期に初期化され、それをロードしたプロセス内のJNI/nativeのやり取りを監視します。 - 複数の書き込み可能パスにログを保存し、ストレージが制限されている場合はLogcatにフォールバックします。 - Source-customizable: edit sotap.c to extend/adjust what gets logged and rebuild per ABI. Setup (repack the APK): 1) Drop the proper ABI build into the APK so the loader can resolve libsotap.so: - lib/arm64-v8a/libsotap.so (for arm64) - lib/armeabi-v7a/libsotap.so (for arm32) 2) Ensure SoTap loads before other JNI libs. Inject a call early (e.g., Application subclass static initializer or onCreate) so the logger is initialized first. Smali snippet example: ```smali const-string v0, "sotap" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V ``` 3) Rebuild/sign/install, run the app, then collect logs. Log paths (checked in order): ``` /data/user/0/%s/files/sotap.log /data/data/%s/files/sotap.log /sdcard/Android/data/%s/files/sotap.log /sdcard/Download/sotap-%s.log # If all fail: fallback to Logcat only ``` Notes and troubleshooting: - ABI の整合は必須です。不一致があると UnsatisfiedLinkError が発生し、ロガーはロードされません。 - ストレージ制約は近年の Android では一般的です。ファイル書き込みが失敗しても SoTap は Logcat 経由で出力します。 - 動作や冗長度はカスタマイズを意図しています。sotap.c を編集したらソースから再ビルドしてください。 この手法は、プロセス開始時からのネイティブ呼び出しフローを観察することが重要で、root やシステム全体のフックが使えない場合のマルウェアトリアージや JNI デバッグに有用です。 --- ### 参照: in‑memory native code execution via JNI 一般的な攻撃パターンとして、ランタイムで生の shellcode blob をダウンロードし、JNI ブリッジ経由でメモリから直接実行する(ディスク上に ELF を置かない)という手法があります。詳細と使える JNI スニペットはこちら: {{#ref}} in-memory-jni-shellcode-execution.md {{#endref}} --- ### APK 内で探すべき最近の脆弱性 | 年 | CVE | 影響ライブラリ | 備考 | |------|-----|------------------|-------| |2023|CVE-2023-4863|`libwebp` ≤ 1.3.1|WebP 画像をデコードするネイティブコードから到達可能な heap buffer overflow。複数の Android アプリが脆弱なバージョンをバンドルしています。APK 内に `libwebp.so` を見つけたら、そのバージョンを確認し、エクスプロイトやパッチ適用を試みてください.| | |2024|Multiple|OpenSSL 3.x series|複数のメモリ安全性やパディングオラクルの問題。多くの Flutter & ReactNative バンドルは独自の `libcrypto.so` を同梱しています。| APK 内で *third-party* の `.so` ファイルを見つけたら、常に upstream のアドバイザリとハッシュを突き合わせてください。SCA (Software Composition Analysis) はモバイルではあまり行われていないため、古い脆弱なビルドが横行しています。 --- ### Anti-Reversing & Hardening trends (Android 13-15) * **Pointer Authentication (PAC) & Branch Target Identification (BTI):** Android 14 はサポートされる ARMv8.3+ シリコン上でシステムライブラリに PAC/BTI を有効にします。Decompiler は PAC 関連の疑似命令を表示するようになりました。動的解析では Frida が PAC を剥がした後にトランポリンを注入しますが、カスタムトランポリンは必要に応じて `pacda`/`autibsp` を呼ぶべきです。 * **MTE & Scudo hardened allocator:** memory-tagging はオプトインですが、多くの Play-Integrity 対応アプリは `-fsanitize=memtag` でビルドしています。タグフォールトをキャプチャするには `setprop arm64.memtag.dump 1` と `adb shell am start ...` を併用してください。 * **LLVM Obfuscator (opaque predicates, control-flow flattening):** 商用パッカー(例:Bangcle、SecNeo)は Java のみならず *native* コードを保護することが増えています。`.rodata` 内に偽の制御フローや暗号化された文字列ブロブが存在することを想定してください。 --- ### リソース - **Learning ARM Assembly:** [Azeria Labs – ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/) - **JNI & NDK Documentation:** [Oracle JNI Spec](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html) · [Android JNI Tips](https://developer.android.com/training/articles/perf-jni) · [NDK Guides](https://developer.android.com/ndk/guides/) - **Debugging Native Libraries:** [Debug Android Native Libraries Using JEB Decompiler](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3) ### 参考 - Frida 16.x change-log (Android hooking, tiny-function relocation) – [frida.re/news](https://frida.re/news/) - NVD advisory for `libwebp` overflow CVE-2023-4863 – [nvd.nist.gov](https://nvd.nist.gov/vuln/detail/CVE-2023-4863) - SoTap: Lightweight in-app JNI (.so) behavior logger – [github.com/RezaArbabBot/SoTap](https://github.com/RezaArbabBot/SoTap) - SoTap Releases – [github.com/RezaArbabBot/SoTap/releases](https://github.com/RezaArbabBot/SoTap/releases) - How to work with SoTap? – [t.me/ForYouTillEnd/13](https://t.me/ForYouTillEnd/13) - [CoRPhone — JNI memory-only execution pattern and packaging](https://github.com/0xdevil/corphone) {{#include ../../banners/hacktricks-training.md}}