Reversing Native Libraries

Reading time: 7 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

For further information check: https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html

Android apps podem usar native libraries, tipicamente escritas em C ou C++, para tarefas que exigem desempenho. Criadores de malware também abusam dessas bibliotecas porque ELF shared objects ainda são mais difíceis de decompilar que byte-code DEX/OAT. Esta página foca em workflows práticos e melhorias de tooling recentes (2023-2025) que tornam o reversing de arquivos .so do Android mais fácil.


Quick triage-workflow for a freshly pulled 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).

Dynamic Instrumentation (Frida ≥ 16)

Frida’s 16-series trouxe várias melhorias específicas para Android que ajudam quando o alvo usa otimizações modernas do Clang/LLD:

  • thumb-relocator agora pode hook tiny ARM/Thumb functions geradas pelo alinhamento agressivo do LLD (--icf=all).
  • A enumeração e rebind de ELF import slots funciona no Android, permitindo patching por módulo com dlopen()/dlsym() quando hooks inline são rejeitados.
  • Java hooking foi corrigido para o novo ART quick-entrypoint usado quando apps são compilados com --enable-optimizations no 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 o preenchimento para inline hooks.

Telemetria JNI local ao processo via .so pré-carregado (SoTap)

Quando uma instrumentação completa é overkill ou bloqueada, você ainda pode obter visibilidade em nível nativo pré-carregando um pequeno logger dentro do processo alvo. SoTap é uma biblioteca nativa Android leve (.so) que registra o comportamento em tempo de execução de outras bibliotecas JNI (.so) dentro do mesmo processo do app (não é necessário root).

Principais propriedades:

  • Inicializa cedo e observa interações JNI/native dentro do processo que a carrega.
  • Persiste logs usando múltiplos caminhos graváveis com fallback gracioso para Logcat quando o armazenamento está restrito.
  • Personalizável no código-fonte: edite sotap.c para estender/ajustar o que é registrado e recompile por ABI.

Configuração (reempacotar o APK):

  1. Coloque o build ABI apropriado dentro do APK para que o loader possa resolver libsotap.so:
  • lib/arm64-v8a/libsotap.so (for arm64)
  • lib/armeabi-v7a/libsotap.so (for arm32)
  1. Garanta que o SoTap seja carregado antes de outras libs JNI. Injete uma chamada cedo (por exemplo, inicializador estático da subclasse Application ou onCreate) para que o logger seja inicializado primeiro. Exemplo de trecho Smali:
smali
const-string v0, "sotap"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
  1. Recompile/assine/instale, execute o app e então colete os logs.

Caminhos de log (verificados em ordem):

/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

Notas e solução de problemas:

  • O alinhamento de ABI é obrigatório. Uma incompatibilidade causará UnsatisfiedLinkError e o logger não será carregado.
  • Restrições de armazenamento são comuns no Android moderno; se gravações de arquivo falharem, SoTap ainda emitirá via Logcat.
  • Comportamento/verbosidade deve ser personalizado; reconstrua a partir do código-fonte após editar sotap.c.

Essa abordagem é útil para triagem de malware e depuração JNI, onde observar fluxos de chamadas nativas desde o início do processo é crítico, mas root/ganchos em todo o sistema não estão disponíveis.


Vulnerabilidades recentes que valem a pena procurar em APKs

YearCVEAffected libraryNotes
2023CVE-2023-4863libwebp ≤ 1.3.1Heap buffer overflow alcançável a partir de código nativo que decodifica imagens WebP. Vários apps Android empacotam versões vulneráveis. Quando você encontrar um libwebp.so dentro de um APK, verifique sua versão e tente exploração ou correção.
2024MultipleOpenSSL 3.x seriesVárias questões de segurança de memória e padding-oracle. Muitos bundles Flutter & ReactNative incluem seu próprio libcrypto.so.

Quando você identificar arquivos .so de third-party dentro de um APK, sempre confira seu hash contra advisories upstream. SCA (Software Composition Analysis) é incomum em mobile, então builds vulneráveis e desatualizados são comuns.


Tendências de Anti-Reversing & Hardening (Android 13-15)

  • Pointer Authentication (PAC) & Branch Target Identification (BTI): Android 14 habilita PAC/BTI em system libraries em silicon ARMv8.3+ suportado. Decompiladores agora mostram pseudo-instruções relacionadas a PAC; para análise dinâmica o Frida injeta trampolines após remover o PAC, mas seus trampolines customizados devem chamar pacda/autibsp quando necessário.
  • MTE & Scudo hardened allocator: a marcação de memória (memory-tagging) é opt-in, mas muitos apps compatíveis com Play-Integrity são buildados com -fsanitize=memtag; use setprop arm64.memtag.dump 1 mais adb shell am start ... para capturar tag faults.
  • LLVM Obfuscator (opaque predicates, control-flow flattening): packers comerciais (ex.: Bangcle, SecNeo) protegem cada vez mais código native, não apenas Java; espere fluxo de controle falso e blobs de strings criptografadas em .rodata.

Resources

References

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks