hacktricks/src/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md

276 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Android Anti-Instrumentation & SSL Pinning Bypass (Frida/Objection)
{{#include ../../banners/hacktricks-training.md}}
Diese Seite bietet einen praktischen Workflow, um die dynamische Analyse gegen Android-Apps wiederherzustellen, die Instrumentation erkennen/rootblockieren oder TLS pinning erzwingen. Der Fokus liegt auf schneller Triage, häufigen Erkennungen und kopierbaren Hooks/Taktiken, um diese nach Möglichkeit ohne Repacking zu umgehen.
## Detection Surface (what apps check)
- Root-Checks: su binary, Magisk paths, getprop values, common root packages
- Frida/debugger checks (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scanning /proc, classpath, loaded libs
- Native antidebug: ptrace(), syscalls, antiattach, breakpoints, inline hooks
- Early init checks: Application.onCreate() or process start hooks that crash if instrumentation is present
- TLS pinning: custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins
## Step 1 — Quick win: hide root with Magisk DenyList
- Enable Zygisk in Magisk
- Enable DenyList, add the target package
- Reboot and retest
Viele Apps suchen nur nach offensichtlichen Indikatoren (su/Magisk paths/getprop). DenyList neutralisiert oft naive Checks.
References:
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
## Step 2 — 30second Frida Codeshare tests
Try common dropin scripts before deep diving:
- 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
```
Diese ersetzen typischerweise Java root/debug-Prüfungen, Prozess-/Service-Scans und native ptrace()-Aufrufe durch Stubs. Nützlich bei leicht geschützten Apps; gehärtete Ziele benötigen möglicherweise maßgeschneiderte Hooks.
- Codeshare: https://codeshare.frida.re/
## Automatisieren mit Medusa (Frida framework)
Medusa bietet 90+ fertige Module für SSL unpinning, root/emulator detection bypass, HTTP comms logging, crypto key interception und mehr.
```bash
git clone https://github.com/Ch0pin/medusa
cd medusa
pip install -r requirements.txt
python medusa.py
# Example interactive workflow
show categories
use http_communications/multiple_unpinner
use root_detection/universal_root_detection_bypass
run com.target.app
```
Tipp: Medusa ist großartig für schnelle Erfolge, bevor du eigene hooks schreibst. Du kannst auch modules gezielt auswählen und mit deinen eigenen scripts kombinieren.
## Schritt 3 — Detektoren zur Initialisierungszeit umgehen durch spätes Anhängen
Viele Erkennungen laufen nur während des ProzessSpawns/onCreate(). Spawntime injection (-f) oder gadgets werden erwischt; spätes Anhängen, nachdem die UI geladen ist, kann unbemerkt vorbeischlüpfen.
```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
```
Wenn das funktioniert, halte die Sitzung stabil und fahre mit map- und stub-Checks fort.
## Schritt 4 — Erkennungslogik mit Jadx und string hunting kartieren
Statische Triage-Schlüsselwörter in Jadx:
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
Typische Java-Muster:
```java
public boolean isFridaDetected() {
return getRunningServices().contains("frida");
}
```
Häufige APIs zur Überprüfung/Hook:
- android.os.Debug.isDebuggerConnected
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
- java.lang.System.loadLibrary / System.load (Native-Bridge)
- java.lang.Runtime.exec / ProcessBuilder (Prüf-/Erkennungsbefehle)
- android.os.SystemProperties.get (Root-/Emulator-Heuristiken)
## Schritt 5 — Runtime stubbing mit Frida (Java)
Überschreibe benutzerdefinierte Guards, damit sie sichere Werte zurückgeben, ohne repacking:
```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(); };
});
```
Frühzeitige Abstürze triagieren? Dump die Klassen kurz bevor die App abstürzt, um wahrscheinliche Detection-Namespaces zu erkennen:
```js
Java.perform(() => {
Java.enumerateLoadedClasses({
onMatch: n => console.log(n),
onComplete: () => console.log('Done')
});
});
```
// Quick root detection stub example (adapt to target package/class names)
Java.perform(() => {
try {
const RootChecker = Java.use('com.target.security.RootCheck');
RootChecker.isDeviceRooted.implementation = function () { return false; };
} catch (e) {}
});
Protokolliere und deaktiviere verdächtige Methoden, um den Ausführungsfluss zu bestätigen:
```js
Java.perform(() => {
const Det = Java.use('com.example.security.DetectionManager');
Det.checkFrida.implementation = function () {
console.log('checkFrida() called');
return false;
};
});
```
## Bypass emulator/VM detection (Java stubs)
Gängige Heuristiken: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE, die generic/goldfish/ranchu/sdk enthalten; QEMU-Artefakte wie /dev/qemu_pipe, /dev/socket/qemud; Standard-MAC 02:00:00:00:00:00; 10.0.2.x NAT; fehlende telephony/sensors.
Schnelles Spoofing der Build-Felder:
```js
Java.perform(function(){
var Build = Java.use('android.os.Build');
Build.MODEL.value = 'Pixel 7 Pro';
Build.MANUFACTURER.value = 'Google';
Build.BRAND.value = 'google';
Build.FINGERPRINT.value = 'google/panther/panther:14/UP1A.231105.003/1234567:user/release-keys';
});
```
Ergänze Stub-Implementierungen für Datei-Existenzprüfungen und Identifikatoren (TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList), damit realistische Werte zurückgegeben werden.
## SSL pinning bypass quick hook (Java)
Neutralisiere benutzerdefinierte TrustManagers und erzwinge permissive SSL contexts:
```js
Java.perform(function(){
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
// No-op validations
X509TrustManager.checkClientTrusted.implementation = function(){ };
X509TrustManager.checkServerTrusted.implementation = function(){ };
// Force permissive TrustManagers
var TrustManagers = [ X509TrustManager.$new() ];
var SSLContextInit = SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;','[Ljavax.net.ssl.TrustManager;','java.security.SecureRandom');
SSLContextInit.implementation = function(km, tm, sr){
return SSLContextInit.call(this, km, TrustManagers, sr);
};
});
```
Hinweise
- Für OkHttp erweitern: hook okhttp3.CertificatePinner und HostnameVerifier bei Bedarf, oder verwende ein universelles unpinning script von CodeShare.
- Beispiel ausführen: `frida -U -f com.target.app -l ssl-bypass.js --no-pause`
## Schritt 6 — Der JNI/native-Spur folgen, wenn Java hooks fehlschlagen
Verfolge JNI-Einstiegspunkte, um native Loader und Detection-Init zu lokalisieren:
```bash
frida-trace -n com.example.app -i "JNI_OnLoad"
```
Schnelle native Triage der gebündelten .so-Dateien:
```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'
```
Interaktives/native reversing:
- Ghidra: https://ghidra-sre.org/
- r2frida: https://github.com/nowsecure/r2frida
Beispiel: ptrace neutralisieren, um einfaches antidebug in libc zu umgehen:
```js
const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) {
Interceptor.replace(ptrace, new NativeCallback(function () {
return -1; // pretend failure
}, 'int', ['int', 'int', 'pointer', 'pointer']));
}
```
Siehe auch:
{{#ref}}
reversing-native-libraries.md
{{#endref}}
## Schritt 7 — Objection patching (embed gadget / strip basics)
Wenn du repacking gegenüber runtime hooks bevorzugst, versuche:
```bash
objection patchapk --source app.apk
```
Hinweise:
- Erfordert apktool; stelle sicher, dass du eine aktuelle Version gemäß der offiziellen Anleitung verwendest, um Build-Probleme zu vermeiden: https://apktool.org/docs/install
- Gadget injection ermöglicht instrumentation ohne Root, kann aber dennoch von stärkeren inittime checks erkannt werden.
Optional kannst du LSPosed-Module und Shamiko hinzufügen, um stärkeres root hiding in Zygisk-Umgebungen zu erreichen, und die DenyList pflegen, um Child-Prozesse abzudecken.
Referenzen:
- Objection: https://github.com/sensepost/objection
## Schritt 8 — Fallback: TLS pinning patchen für Netzwerksichtbarkeit
Wenn instrumentation blockiert ist, kannst du den Traffic trotzdem untersuchen, indem du das Pinning statisch entfernst:
```bash
apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy
```
- Tool: https://github.com/shroudedcode/apk-mitm
- Für Tricks zur NetzwerkKonfiguration/CATrust (und BenutzerCATrust ab Android 7), siehe:
{{#ref}}
make-apk-accept-ca-certificate.md
{{#endref}}
{{#ref}}
install-burp-certificate.md
{{#endref}}
## Praktische Befehlsübersicht
```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
```
## Tipps & Hinweise
- Bevorzuge late attaching gegenüber spawning, wenn Apps beim Launch abstürzen
- Einige Detections laufen in kritischen Flows (z. B. payment, auth) erneut — halte hooks während der Navigation aktiv
- Kombiniere static und dynamic: string hunt in Jadx, um Klassen vorzuselektieren; hook dann Methoden, um sie zur runtime zu verifizieren
- Hardened apps können packers und native TLS pinning verwenden — erwarte, nativen Code zu reverse-engineeren
## Referenzen
- [Reversing Android Apps: Bypassing Detection Like a Pro](https://www.kayssel.com/newsletter/issue-12/)
- [Frida Codeshare](https://codeshare.frida.re/)
- [Objection](https://github.com/sensepost/objection)
- [apk-mitm](https://github.com/shroudedcode/apk-mitm)
- [Jadx](https://github.com/skylot/jadx)
- [Ghidra](https://ghidra-sre.org/)
- [r2frida](https://github.com/nowsecure/r2frida)
- [Apktool install guide](https://apktool.org/docs/install)
- [Magisk](https://github.com/topjohnwu/Magisk)
- [Medusa (Android Frida framework)](https://github.com/Ch0pin/medusa)
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
{{#include ../../banners/hacktricks-training.md}}