hacktricks/src/mobile-pentesting/android-app-pentesting/reversing-native-libraries.md

148 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ネイティブライブラリのリバース
{{#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`ファイルのリバースを容易にする、*実践的な*ワークフローと*最近の*ツール改善20232025に焦点を当てています。
---
### 新たに取得した `libfoo.so` のクイックトリアージワークフロー
1. **ライブラリを抽出する**
```bash
# From an installed application
adb shell "run-as <pkg> 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 デバッグに有用です。
---
### 参照: inmemory 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}}