# Reversing Native Libraries {{#include ../../banners/hacktricks-training.md}} **For further information check:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html) Android apps can use native libraries, typically written in C or C++, for performance-critical tasks. Malware creators also abuse these libraries because ELF shared objects are still harder to decompile than DEX/OAT byte-code. This page focuses on *practical* workflows and *recent* tooling improvements (2023-2025) that make reversing Android `.so` files easier. --- ### Quick triage-workflow for a freshly pulled `libfoo.so` 1. **Extract the library** ```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. **Identify architecture & protections** ```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. **List exported symbols & JNI bindings** ```bash readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI strings libfoo.so | grep -i "RegisterNatives" -n # static-registered JNI ``` 4. **Load in a decompiler** (Ghidra ≥ 11.0, IDA Pro, Binary Ninja, Hopper or Cutter/Rizin) and run auto-analysis. Newer Ghidra versions introduced an AArch64 decompiler that recognises PAC/BTI stubs and MTE tags, greatly improving analysis of libraries built with the Android 14 NDK. 5. **Decide on static vs dynamic reversing:** stripped, obfuscated code often needs *instrumentation* (Frida, ptrace/gdbserver, LLDB). --- ### Dynamic Instrumentation (Frida ≥ 16) Frida’s 16-series brought several Android-specific improvements that help when the target uses modern Clang/LLD optimisations: * `thumb-relocator` can now *hook tiny ARM/Thumb functions* generated by LLD’s aggressive alignment (`--icf=all`). * Enumerating and rebinding *ELF import slots* works on Android, enabling per-module `dlopen()`/`dlsym()` patching when inline hooks are rejected. * Java hooking was fixed for the new **ART quick-entrypoint** used when apps are compiled with `--enable-optimizations` on Android 14. 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. ### Process-local JNI telemetry via preloaded .so (SoTap) When full-featured instrumentation is overkill or blocked, you can still gain native-level visibility by preloading a small logger inside the target process. SoTap is a lightweight Android native (.so) library that logs the runtime behavior of other JNI (.so) libraries within the same app process (no root required). Key properties: - Initializes early and observes JNI/native interactions inside the process that loads it. - Persists logs using multiple writable paths with graceful fallback to Logcat when storage is restricted. - 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 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 | Year | CVE | Affected library | Notes | |------|-----|------------------|-------| |2023|CVE-2023-4863|`libwebp` ≤ 1.3.1|Heap buffer overflow reachable from native code that decodes WebP images. Several Android apps bundle vulnerable versions. When you see a `libwebp.so` inside an APK, check its version and attempt exploitation or patching.| | |2024|Multiple|OpenSSL 3.x series|Several memory-safety and padding-oracle issues. Many Flutter & ReactNative bundles ship their own `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 - **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) ### 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}}