most android apps trust the client way too much. hidden endpoints, hardcoded keys, debug flags left in production. all you need is the right toolchain to find them.
the approach is simple: jadx for static analysis, frida for runtime hooking. one shows you the code, the other lets you mess with it while it runs.
start by pulling the apk and throwing it into jadx:
$ adb shell pm path com.target.app # package:/data/app/com.target.app/base.apk $ adb pull /data/app/com.target.app/base.apk $ jadx --decompile base.apk -d output/
look for api endpoints, auth logic, anything interesting. grep is your friend here. search for strings like /api/, Authorization, Bearer, secret.
$ grep -rni "api" output/sources/ | head -20 $ grep -rni "secret\|key\|token" output/sources/
once you find something interesting, hook it with frida to see what's happening at runtime. say you found an isAdmin() check:
// bypass.js Java.perform(function() { var auth = Java.use("com.target.app.AuthManager"); auth.isAdmin.implementation = function() { console.log("[+] isAdmin() called, returning true"); return true; }; });
$ frida -U -f com.target.app -l bypass.js
certificate pinning? most apps use okhttp or a custom trust manager. the idea is simple — the app validates the server's certificate against a pinned hash. if it doesn't match, the connection drops. but since we control the runtime, we just hook the check and make it always pass.
for okhttp-based pinning, the target is usually CertificatePinner.check():
// ssl_bypass.js Java.perform(function() { var CertPinner = Java.use("okhttp3.CertificatePinner"); CertPinner.check.overload( "java.lang.String", "java.util.List" ).implementation = function(hostname, peerCerts) { console.log("[+] bypassing pin for: " + hostname); return; }; });
for apps using a custom TrustManager, you need to find the class that implements X509TrustManager and hook checkServerTrusted():
// trustmanager_bypass.js Java.perform(function() { var tm = Java.use("com.target.app.CustomTrustManager"); tm.checkServerTrusted.implementation = function(chain, authType) { console.log("[+] trusting all certs"); return; }; });
run it the same way:
$ frida -U -f com.target.app -l ssl_bypass.js
now all traffic flows through your proxy. point the device to burp, and you're intercepting every request the app makes — auth tokens, api calls, everything.
one thing to watch out for: some apps stack multiple pinning layers. you might bypass okhttp but still get blocked by a native check. in that case, look for libssl hooks or use something like objection which covers most common cases out of the box.
the real value isn't in any single trick. it's in chaining static findings with dynamic confirmation. jadx tells you what the code could do. frida tells you what it actually does.