# Reversing 네이티브 라이브러리 {{#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 decompiler를 도입했으며, PAC/BTI stubs와 MTE tags를 인식하여 Android 14 NDK로 빌드된 라이브러리의 분석을 크게 개선한다. 5. **정적 vs 동적 reversing 결정:** 스트립되거나 난독화된 코드는 종종 *instrumentation* (Frida, ptrace/gdbserver, LLDB)이 필요하다. --- ### Dynamic Instrumentation (Frida ≥ 16) Frida의 16 시리즈는 대상이 최신 Clang/LLD 최적화를 사용할 때 도움이 되는 여러 Android 특정 개선을 가져왔다: * `thumb-relocator`는 이제 LLD의 공격적 정렬(`--icf=all`)로 생성된 작은 ARM/Thumb 함수를 *hook*할 수 있다. * *ELF import slots*를 열거하고 재바인딩하는 기능이 Android에서 동작하여, 인라인 훅이 거부될 때 모듈별 `dlopen()`/`dlsym()` 패칭을 가능하게 한다. * Android 14에서 `--enable-optimizations`로 컴파일된 앱에서 사용되는 새로운 **ART quick-entrypoint**에 대한 Java hooking이 수정되었다. 예시: `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-enabled 기기(Pixel 8/Android 14+)에서 frida-server 16.2 이상을 사용하면 별도 설정 없이 동작합니다 — 이전 버전은 inline hooks의 패딩을 찾지 못했습니다. ### Process-local JNI telemetry via preloaded .so (SoTap) 전체 기능의 계측(instrumentation)이 과하거나 차단된 경우, 대상 프로세스에 작은 로거를 사전 로드해 네이티브 수준의 가시성을 확보할 수 있습니다. SoTap는 동일 앱 프로세스 내의 다른 JNI(.so) 라이브러리들의 런타임 동작을 로깅하는 경량 Android 네이티브(.so) 라이브러리입니다 (루트 불필요). Key properties: - 초기에 초기화되며, 그것을 로드한 프로세스 내에서의 JNI/native 상호작용을 관찰합니다. - 여러 쓰기 가능한 경로에 로그를 지속적으로 저장하며, 저장소 제약이 있을 때는 Logcat으로 우아하게 fallback합니다. - Source-customizable: sotap.c를 편집해 로깅 대상을 확장/조정하고 ABI별로 재빌드하세요. Setup (repack the APK): 1) 로더가 libsotap.so를 해석할 수 있도록 APK에 적절한 ABI 빌드를 넣습니다: - lib/arm64-v8a/libsotap.so (for arm64) - lib/armeabi-v7a/libsotap.so (for arm32) 2) SoTap가 다른 JNI 라이브러리보다 먼저 로드되도록 하세요. 로거가 먼저 초기화되도록 초기에 호출을 삽입합니다(예: Application subclass static initializer 또는 onCreate). Smali snippet example: ```smali const-string v0, "sotap" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V ``` 3) 재빌드/서명/설치 후 앱을 실행하고 로그를 수집하세요. 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 alignment is mandatory. A mismatch will raise UnsatisfiedLinkError and the logger won’t load. - Storage constraints are common on modern Android; if file writes fail, SoTap will still emit via Logcat. - Behavior/verbosity is intended to be customized; rebuild from source after editing sotap.c. This approach is useful for malware triage and JNI debugging where observing native call flows from process start is critical but root/system-wide hooks aren’t available. --- ### See also: in‑memory native code execution via JNI A common attack pattern is to download a raw shellcode blob at runtime and execute it directly from memory through a JNI bridge (no on‑disk ELF). Details and ready‑to‑use JNI snippet here: {{#ref}} in-memory-jni-shellcode-execution.md {{#endref}} --- ### Recent vulnerabilities worth hunting for in APKs | 연도 | CVE | 영향받는 라이브러리 | 설명 | |------|-----|------------------|-------| |2023|CVE-2023-4863|`libwebp` ≤ 1.3.1|WebP 이미지를 디코딩하는 네이티브 코드에서 도달 가능한 힙 버퍼 오버플로우. 여러 Android 앱이 취약한 버전을 번들합니다. APK 내부에 `libwebp.so`가 보이면 버전을 확인하고 exploitation 또는 패치를 시도하세요.| | |2024|Multiple|OpenSSL 3.x series|여러 메모리 안전성 및 padding-oracle 문제. 많은 Flutter & ReactNative 번들들이 자체 `libcrypto.so`를 탑재합니다.| When you spot *third-party* `.so` files inside an APK, always cross-check their hash against upstream advisories. SCA (Software Composition Analysis) is uncommon on mobile, so outdated vulnerable builds are rampant. --- ### Anti-Reversing & Hardening trends (Android 13-15) * **Pointer Authentication (PAC) & Branch Target Identification (BTI):** Android 14 enables PAC/BTI in system libraries on supported ARMv8.3+ silicon. Decompilers now display PAC‐related pseudo-instructions; for dynamic analysis Frida injects trampolines *after* stripping PAC, but your custom trampolines should call `pacda`/`autibsp` where necessary. * **MTE & Scudo hardened allocator:** memory-tagging is opt-in but many Play-Integrity aware apps build with `-fsanitize=memtag`; use `setprop arm64.memtag.dump 1` plus `adb shell am start ...` to capture tag faults. * **LLVM Obfuscator (opaque predicates, control-flow flattening):** commercial packers (e.g., Bangcle, SecNeo) increasingly protect *native* code, not only Java; expect bogus control-flow and encrypted string blobs in `.rodata`. --- ### Resources - **ARM 어셈블리 학습:** [Azeria Labs – ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/) - **JNI & NDK 문서:** [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/) - **네이티브 라이브러리 디버깅:** [Debug Android Native Libraries Using JEB Decompiler](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3) ### References - 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}}