Android Anti-Instrumentation & SSL Pinning Bypass (Frida/Objection)

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

Ta strona przedstawia praktyczny workflow do odzyskania analizy dynamicznej aplikacji Android, które wykrywają/blokują instrumentację lub wymuszają pinning TLS. Skupia się na szybkim triage, powszechnych wykryciach oraz skryptach/taktykach do kopiowania, aby je obejść bez repakowania, gdy to możliwe.

Detection Surface (co sprawdzają aplikacje)

  • Kontrole root: su binary, ścieżki Magisk, wartości getprop, powszechne pakiety root
  • Kontrole Frida/debuggera (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), skanowanie /proc, classpath, załadowane biblioteki
  • Native anti‑debug: ptrace(), syscalls, anti‑attach, punkty przerwania, inline hooks
  • Kontrole wczesnej inicjalizacji: Application.onCreate() lub haki startowe procesu, które powodują awarię, jeśli instrumentacja jest obecna
  • TLS pinning: niestandardowy TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins

Step 1 — Szybkie zwycięstwo: ukryj root za pomocą Magisk DenyList

  • Włącz Zygisk w Magisk
  • Włącz DenyList, dodaj docelowy pakiet
  • Uruchom ponownie i przetestuj

Wiele aplikacji szuka tylko oczywistych wskaźników (su/ścieżki Magisk/getprop). DenyList często neutralizuje naiwne kontrole.

References:

  • Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk

Step 2 — Testy Frida Codeshare w 30 sekund

Wypróbuj powszechne skrypty drop-in przed głębszym zanurzeniem:

  • anti-root-bypass.js
  • anti-frida-detection.js
  • hide_frida_gum.js

Example:

bash
frida -U -f com.example.app -l anti-frida-detection.js

Te zazwyczaj stają się stubami dla kontroli Java root/debug, skanów procesów/usług oraz natywnego ptrace(). Przydatne w słabo chronionych aplikacjach; wzmocnione cele mogą wymagać dostosowanych haków.

  • Codeshare: https://codeshare.frida.re/

Krok 3 — Obejście detektorów w czasie inicjalizacji przez późniejsze podłączenie

Wiele detekcji działa tylko podczas uruchamiania procesu/onCreate(). Wstrzyknięcia w czasie uruchamiania (-f) lub gadżety są wykrywane; podłączenie po załadowaniu UI może przejść niezauważone.

bash
# Launch the app normally (launcher/adb), wait for UI, then attach
frida -U -n com.example.app
# Or with Objection to attach to running process
aobjection --gadget com.example.app explore  # if using gadget

Jeśli to działa, utrzymaj sesję stabilną i przejdź do mapowania oraz sprawdzania stubów.

Krok 4 — Mapowanie logiki detekcji za pomocą Jadx i poszukiwania ciągów

Słowa kluczowe do triage statycznego w Jadx:

  • "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"

Typowe wzorce Java:

java
public boolean isFridaDetected() {
return getRunningServices().contains("frida");
}

Common APIs do przeglądu/hookowania:

  • android.os.Debug.isDebuggerConnected
  • android.app.ActivityManager.getRunningAppProcesses / getRunningServices
  • java.lang.System.loadLibrary / System.load (native bridge)
  • java.lang.Runtime.exec / ProcessBuilder (probing commands)
  • android.os.SystemProperties.get (root/emulator heuristics)

Krok 5 — Stubbing w czasie rzeczywistym z Frida (Java)

Zastąp niestandardowe zabezpieczenia, aby zwracały bezpieczne wartości bez ponownego pakowania:

js
Java.perform(() => {
const Checks = Java.use('com.example.security.Checks');
Checks.isFridaDetected.implementation = function () { return false; };

// Neutralize debugger checks
const Debug = Java.use('android.os.Debug');
Debug.isDebuggerConnected.implementation = function () { return false; };

// Example: kill ActivityManager scans
const AM = Java.use('android.app.ActivityManager');
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
});

Triaging wczesnych awarii? Zrzucaj klasy tuż przed tym, jak umiera, aby zidentyfikować prawdopodobne przestrzenie nazw wykrywania:

js
Java.perform(() => {
Java.enumerateLoadedClasses({
onMatch: n => console.log(n),
onComplete: () => console.log('Done')
});
});

Zaloguj i zneutralizuj podejrzane metody, aby potwierdzić przepływ wykonania:

js
Java.perform(() => {
const Det = Java.use('com.example.security.DetectionManager');
Det.checkFrida.implementation = function () {
console.log('checkFrida() called');
return false;
};
});

Krok 6 — Śledź ścieżkę JNI/natywną, gdy haki Java zawodzą

Śledź punkty wejścia JNI, aby zlokalizować natywne ładowarki i inicjalizację detekcji:

bash
frida-trace -n com.example.app -i "JNI_OnLoad"

Szybka natywna triage pakietowanych plików .so:

bash
# List exported symbols & JNI
nm -D libfoo.so | head
objdump -T libfoo.so | grep Java_
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'

Interaktywne/natywne odwracanie:

  • Ghidra: https://ghidra-sre.org/
  • r2frida: https://github.com/nowsecure/r2frida

Przykład: neuter ptrace, aby pokonać prostą anty‑debug w libc:

js
const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) {
Interceptor.replace(ptrace, new NativeCallback(function () {
return -1; // pretend failure
}, 'int', ['int', 'int', 'pointer', 'pointer']));
}

Zobacz także: Reversing Native Libraries

Krok 7 — Patching Objection (wbudowany gadżet / podstawy stripowania)

Kiedy wolisz repakowanie od haków czasu wykonywania, spróbuj:

bash
objection patchapk --source app.apk

Notatki:

  • Wymaga apktool; upewnij się, że masz aktualną wersję z oficjalnego przewodnika, aby uniknąć problemów z budowaniem: https://apktool.org/docs/install
  • Wstrzykiwanie gadgetów umożliwia instrumentację bez roota, ale może być nadal wykrywane przez silniejsze kontrole w czasie inicjalizacji.

Odniesienia:

  • Objection: https://github.com/sensepost/objection

Krok 8 — Alternatywa: Łatka TLS pinning dla widoczności sieci

Jeśli instrumentacja jest zablokowana, nadal możesz analizować ruch, usuwając pinning statycznie:

bash
apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy

Przydatna ściągawka z poleceniami

bash
# List processes and attach
frida-ps -Uai
frida -U -n com.example.app

# Spawn with a script (may trigger detectors)
frida -U -f com.example.app -l anti-frida-detection.js

# Trace native init
frida-trace -n com.example.app -i "JNI_OnLoad"

# Objection runtime
objection --gadget com.example.app explore

# Static TLS pinning removal
apk-mitm app.apk

Wskazówki i uwagi

  • Preferuj dołączanie później niż uruchamianie, gdy aplikacje zawieszają się przy uruchamianiu
  • Niektóre detekcje są ponownie uruchamiane w krytycznych procesach (np. płatności, autoryzacja) — utrzymuj haki aktywne podczas nawigacji
  • Mieszaj statyczne i dynamiczne: przeszukuj ciągi w Jadx, aby skrócić listę klas; następnie hakuj metody, aby zweryfikować w czasie rzeczywistym
  • Wzmocnione aplikacje mogą używać pakietów i natywnego TLS pinning — spodziewaj się odwrotnego inżynierii kodu natywnego

Odniesienia

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