Reversing Native Libraries
Reading time: 5 minutes
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
For further information check: 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
- Extract the library
# 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/
- Identify architecture & protections
file libfoo.so # arm64 or arm32 / x86 readelf -h libfoo.so # OS ABI, PIE, NX, RELRO, etc. checksec --file libfoo.so # (peda/pwntools)
- List exported symbols & JNI bindings
readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI strings libfoo.so | grep -i "RegisterNatives" -n # static-registered JNI
- 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. - 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:
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.
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
; usesetprop arm64.memtag.dump 1
plusadb 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
- JNI & NDK Documentation: Oracle JNI Spec · Android JNI Tips · NDK Guides
- Debugging Native Libraries: Debug Android Native Libraries Using JEB Decompiler
References
- Frida 16.x change-log (Android hooking, tiny-function relocation) – frida.re/news
- NVD advisory for
libwebp
overflow CVE-2023-4863 – nvd.nist.gov
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.