Analiza bibliotek natywnych

Reading time: 7 minutes

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Więcej informacji: https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html

Aplikacje Android mogą używać bibliotek natywnych, zwykle napisanych w C lub C++, do zadań krytycznych pod względem wydajności. Twórcy malware także nadużywają tych bibliotek, ponieważ ELF shared objects wciąż są trudniejsze do dekompilacji niż DEX/OAT byte-code. Ta strona koncentruje się na praktycznych workflowach i najnowszych udoskonaleniach narzędzi (2023–2025), które ułatwiają reversing Androidowych plików .so.


Szybki proces wstępnej analizy dla świeżo pozyskanego libfoo.so

  1. Extract the library
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/
  1. 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)
  1. 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
  1. 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.
  2. Decide on static vs dynamic reversing: stripped, obfuscated code often needs instrumentation (Frida, ptrace/gdbserver, LLDB).

Instrumentacja dynamiczna (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.

Przykład: 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 będzie działać od razu na urządzeniach z PAC/BTI (Pixel 8/Android 14+), o ile użyjesz frida-server 16.2 lub nowszej – wcześniejsze wersje nie potrafiły zlokalizować paddingu dla inline hooks.

Process-local JNI telemetry via preloaded .so (SoTap)

Gdy pełna instrumentacja jest przesadą lub zablokowana, nadal możesz uzyskać widoczność na poziomie native, preładowując mały logger wewnątrz docelowego procesu. SoTap to lekka natywna biblioteka Android (.so), która loguje zachowanie w czasie wykonywania innych bibliotek JNI (.so) w tym samym procesie aplikacji (nie wymaga root).

Key properties:

  • Inicjalizuje się wcześnie i obserwuje JNI/native interactions wewnątrz procesu, który ją ładuje.
  • Przechowuje logi, używając wielu zapisywalnych ścieżek z awaryjnym przełączeniem na Logcat, gdy dostęp do pamięci jest ograniczony.
  • Source-customizable: edytuj sotap.c, aby rozszerzyć/dostosować co jest logowane i przebuduj per ABI.

Setup (repack the APK):

  1. Umieść właściwy build ABI w APK, aby loader mógł rozwiązać libsotap.so:
  • lib/arm64-v8a/libsotap.so (dla arm64)
  • lib/armeabi-v7a/libsotap.so (dla arm32)
  1. Upewnij się, że SoTap ładuje się przed innymi bibliotekami JNI. Wstrzyknij wywołanie wcześnie (np. statyczny initializer podklasy Application lub onCreate), aby logger był zainicjalizowany jako pierwszy. Przykład fragmentu Smali:
smali
const-string v0, "sotap"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
  1. Przebuduj/podpisz/zainstaluj, uruchom aplikację, a następnie zbierz logi.

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:

  • Wyrównanie ABI jest obowiązkowe. Brak dopasowania spowoduje UnsatisfiedLinkError i logger nie załaduje się.
  • Ograniczenia przestrzeni dyskowej są powszechne w nowoczesnym Androidzie; jeśli zapisy plików zawiodą, SoTap będzie nadal wysyłać przez Logcat.
  • Zachowanie/poziom szczegółowości jest przeznaczony do dostosowania; po edycji pliku sotap.c odbuduj z źródeł.

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.


Najnowsze podatności, które warto wyszukiwać w APK

RokCVEBibliotekaUwagi
2023CVE-2023-4863libwebp ≤ 1.3.1Przepełnienie bufora sterty dostępne z poziomu natywnego kodu dekodującego obrazy WebP. Wiele aplikacji Android dołącza podatne wersje. Gdy zobaczysz libwebp.so w APK, sprawdź jej wersję i spróbuj exploitowania lub załatania.
2024MultipleOpenSSL 3.x seriesKilka problemów związanych z bezpieczeństwem pamięci oraz padding-oracle. Wiele bundli Flutter & ReactNative dostarcza własne libcrypto.so.

Gdy zauważysz third-party .so pliki w APK, zawsze porównaj ich hash z upstream advisories. SCA (Software Composition Analysis) jest rzadko stosowane na urządzeniach mobilnych, więc przestarzałe, podatne buildy są powszechne.


Trendy Anti-Reversing i Hardening (Android 13-15)

  • Pointer Authentication (PAC) & Branch Target Identification (BTI): Android 14 włącza PAC/BTI w bibliotekach systemowych na obsługiwanym sprzęcie ARMv8.3+. Dekompilery teraz pokazują pseudo-instrukcje związane z PAC; dla analizy dynamicznej Frida wstrzykuje trampoliny po usunięciu PAC, ale twoje niestandardowe trampoliny powinny wywoływać pacda/autibsp tam, gdzie to konieczne.
  • MTE & Scudo hardened allocator: memory-tagging jest opcjonalne, ale wiele aplikacji świadomych Play-Integrity buduje się z -fsanitize=memtag; użyj setprop arm64.memtag.dump 1 oraz adb shell am start ... aby przechwycić błędy tagów.
  • LLVM Obfuscator (opaque predicates, control-flow flattening): komercyjne packery (np. Bangcle, SecNeo) coraz częściej chronią kod natywny, nie tylko Java; spodziewaj się fałszywych ścieżek sterowania i zaszyfrowanych blobów stringów w .rodata.

Zasoby

Referencje

tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks