Created
June 5, 2023 05:07
-
-
Save cyberheartmi9/12801c03e5794097baf1293909b07d30 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// $ frida -l antiroot.js -U -f com.example.app --no-pause | |
// CHANGELOG by Pichaya Morimoto (p.morimoto@sth.sh): | |
// - I added extra whitelisted items to deal with the latest versions | |
// of RootBeer/Cordova iRoot as of August 6, 2019 | |
// - The original one just fucked up (kill itself) if Magisk is installed lol | |
// Credit & Originally written by: https://codeshare.frida.re/@dzonerzy/fridantiroot/ | |
// If this isn't working in the future, check console logs, rootbeer src, or libtool-checker.so | |
Java.perform(function() { | |
var RootPackages = ["com.noshufou.android.su", "com.noshufou.android.su.elite", "eu.chainfire.supersu", | |
"com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.koushikdutta.rommanager", | |
"com.koushikdutta.rommanager.license", "com.dimonvideo.luckypatcher", "com.chelpus.lackypatch", | |
"com.ramdroid.appquarantine", "com.ramdroid.appquarantinepro", "com.devadvance.rootcloak", "com.devadvance.rootcloakplus", | |
"de.robv.android.xposed.installer", "com.saurik.substrate", "com.zachspong.temprootremovejb", "com.amphoras.hidemyroot", | |
"com.amphoras.hidemyrootadfree", "com.formyhm.hiderootPremium", "com.formyhm.hideroot", "me.phh.superuser", | |
"eu.chainfire.supersu.pro", "com.kingouser.com", "com.android.vending.billing.InAppBillingService.COIN","com.topjohnwu.magisk" | |
]; | |
var RootBinaries = ["su", "busybox", "supersu", "Superuser.apk", "KingoUser.apk", "SuperSu.apk","magisk"]; | |
var RootProperties = { | |
"ro.build.selinux": "1", | |
"ro.debuggable": "0", | |
"service.adb.root": "0", | |
"ro.secure": "1" | |
}; | |
var RootPropertiesKeys = []; | |
for (var k in RootProperties) RootPropertiesKeys.push(k); | |
var PackageManager = Java.use("android.app.ApplicationPackageManager"); | |
var Runtime = Java.use('java.lang.Runtime'); | |
var NativeFile = Java.use('java.io.File'); | |
var String = Java.use('java.lang.String'); | |
var SystemProperties = Java.use('android.os.SystemProperties'); | |
var BufferedReader = Java.use('java.io.BufferedReader'); | |
var ProcessBuilder = Java.use('java.lang.ProcessBuilder'); | |
var StringBuffer = Java.use('java.lang.StringBuffer'); | |
var loaded_classes = Java.enumerateLoadedClassesSync(); | |
send("Loaded " + loaded_classes.length + " classes!"); | |
var useKeyInfo = false; | |
var useProcessManager = false; | |
send("loaded: " + loaded_classes.indexOf('java.lang.ProcessManager')); | |
if (loaded_classes.indexOf('java.lang.ProcessManager') != -1) { | |
try { | |
//useProcessManager = true; | |
//var ProcessManager = Java.use('java.lang.ProcessManager'); | |
} catch (err) { | |
send("ProcessManager Hook failed: " + err); | |
} | |
} else { | |
send("ProcessManager hook not loaded"); | |
} | |
var KeyInfo = null; | |
if (loaded_classes.indexOf('android.security.keystore.KeyInfo') != -1) { | |
try { | |
//useKeyInfo = true; | |
//var KeyInfo = Java.use('android.security.keystore.KeyInfo'); | |
} catch (err) { | |
send("KeyInfo Hook failed: " + err); | |
} | |
} else { | |
send("KeyInfo hook not loaded"); | |
} | |
PackageManager.getPackageInfo.overload('java.lang.String', 'int').implementation = function(pname, flags) { | |
var shouldFakePackage = (RootPackages.indexOf(pname) > -1); | |
if (shouldFakePackage) { | |
send("Bypass root check for package: " + pname); | |
pname = "set.package.name.to.a.fake.one.so.we.can.bypass.it"; | |
} | |
return this.getPackageInfo.call(this, pname, flags); | |
}; | |
NativeFile.exists.implementation = function() { | |
var name = NativeFile.getName.call(this); | |
var shouldFakeReturn = (RootBinaries.indexOf(name) > -1); | |
if (shouldFakeReturn) { | |
send("Bypass return value for binary: " + name); | |
return false; | |
} else { | |
return this.exists.call(this); | |
} | |
}; | |
var exec = Runtime.exec.overload('[Ljava.lang.String;'); | |
var exec1 = Runtime.exec.overload('java.lang.String'); | |
var exec2 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;'); | |
var exec3 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;'); | |
var exec4 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File'); | |
var exec5 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;', 'java.io.File'); | |
exec5.implementation = function(cmd, env, dir) { | |
if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") { | |
var fakeCmd = "grep"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
if (cmd == "su") { | |
var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
if (cmd == "which") { | |
var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"; | |
send("Bypass which command"); | |
return exec1.call(this, fakeCmd); | |
} | |
return exec5.call(this, cmd, env, dir); | |
}; | |
exec4.implementation = function(cmdarr, env, file) { | |
for (var i = 0; i < cmdarr.length; i = i + 1) { | |
var tmp_cmd = cmdarr[i]; | |
if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") { | |
var fakeCmd = "grep"; | |
send("Bypass " + cmdarr + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
if (tmp_cmd == "su") { | |
var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"; | |
send("Bypass " + cmdarr + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
} | |
return exec4.call(this, cmdarr, env, file); | |
}; | |
exec3.implementation = function(cmdarr, envp) { | |
for (var i = 0; i < cmdarr.length; i = i + 1) { | |
var tmp_cmd = cmdarr[i]; | |
if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") { | |
var fakeCmd = "grep"; | |
send("Bypass " + cmdarr + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
if (tmp_cmd == "su") { | |
var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"; | |
send("Bypass " + cmdarr + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
} | |
return exec3.call(this, cmdarr, envp); | |
}; | |
exec2.implementation = function(cmd, env) { | |
if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") { | |
var fakeCmd = "grep"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
if (cmd == "su") { | |
var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
return exec2.call(this, cmd, env); | |
}; | |
exec.implementation = function(cmd) { | |
for (var i = 0; i < cmd.length; i = i + 1) { | |
var tmp_cmd = cmd[i]; | |
if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") { | |
var fakeCmd = "grep"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
if (tmp_cmd == "su") { | |
var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
} | |
return exec.call(this, cmd); | |
}; | |
exec1.implementation = function(cmd) { | |
if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") { | |
var fakeCmd = "grep"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
if (cmd == "su") { | |
var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"; | |
send("Bypass " + cmd + " command"); | |
return exec1.call(this, fakeCmd); | |
} | |
return exec1.call(this, cmd); | |
}; | |
String.contains.implementation = function(name) { | |
if (name == "test-keys") { | |
send("Bypass test-keys check"); | |
return false; | |
} | |
return this.contains.call(this, name); | |
}; | |
var get = SystemProperties.get.overload('java.lang.String'); | |
get.implementation = function(name) { | |
if (RootPropertiesKeys.indexOf(name) != -1) { | |
send("Bypass " + name); | |
return RootProperties[name]; | |
} | |
return this.get.call(this, name); | |
}; | |
Interceptor.attach(Module.findExportByName("libc.so", "fopen"), { | |
onEnter: function(args) { | |
var path1 = Memory.readCString(args[0]); | |
var path = path1.split("/"); | |
var executable = path[path.length - 1]; | |
var shouldFakeReturn = (RootBinaries.indexOf(executable) > -1) | |
if (shouldFakeReturn) { | |
Memory.writeUtf8String(args[0], "/ggezxxx"); | |
send("Bypass native fopen >> "+path1); | |
} | |
}, | |
onLeave: function(retval) { | |
} | |
}); | |
Interceptor.attach(Module.findExportByName("libc.so", "fopen"), { | |
onEnter: function(args) { | |
var path1 = Memory.readCString(args[0]); | |
var path = path1.split("/"); | |
var executable = path[path.length - 1]; | |
var shouldFakeReturn = (RootBinaries.indexOf(executable) > -1) | |
if (shouldFakeReturn) { | |
Memory.writeUtf8String(args[0], "/ggezxxx"); | |
send("Bypass native fopen >> "+path1); | |
} | |
}, | |
onLeave: function(retval) { | |
} | |
}); | |
Interceptor.attach(Module.findExportByName("libc.so", "system"), { | |
onEnter: function(args) { | |
var cmd = Memory.readCString(args[0]); | |
send("SYSTEM CMD: " + cmd); | |
if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id") { | |
send("Bypass native system: " + cmd); | |
Memory.writeUtf8String(args[0], "grep"); | |
} | |
if (cmd == "su") { | |
send("Bypass native system: " + cmd); | |
Memory.writeUtf8String(args[0], "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"); | |
} | |
}, | |
onLeave: function(retval) { | |
} | |
}); | |
/* | |
TO IMPLEMENT: | |
Exec Family | |
int execl(const char *path, const char *arg0, ..., const char *argn, (char *)0); | |
int execle(const char *path, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]); | |
int execlp(const char *file, const char *arg0, ..., const char *argn, (char *)0); | |
int execlpe(const char *file, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]); | |
int execv(const char *path, char *const argv[]); | |
int execve(const char *path, char *const argv[], char *const envp[]); | |
int execvp(const char *file, char *const argv[]); | |
int execvpe(const char *file, char *const argv[], char *const envp[]); | |
*/ | |
BufferedReader.readLine.overload().implementation = function() { | |
var text = this.readLine.call(this); | |
if (text === null) { | |
// just pass , i know it's ugly as hell but test != null won't work :( | |
} else { | |
var shouldFakeRead = (text.indexOf("ro.build.tags=test-keys") > -1); | |
if (shouldFakeRead) { | |
send("Bypass build.prop file read"); | |
text = text.replace("ro.build.tags=test-keys", "ro.build.tags=release-keys"); | |
} | |
} | |
return text; | |
}; | |
var executeCommand = ProcessBuilder.command.overload('java.util.List'); | |
ProcessBuilder.start.implementation = function() { | |
var cmd = this.command.call(this); | |
var shouldModifyCommand = false; | |
for (var i = 0; i < cmd.size(); i = i + 1) { | |
var tmp_cmd = cmd.get(i).toString(); | |
if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd.indexOf("mount") != -1 || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd.indexOf("id") != -1) { | |
shouldModifyCommand = true; | |
} | |
} | |
if (shouldModifyCommand) { | |
send("Bypass ProcessBuilder " + cmd); | |
this.command.call(this, ["grep"]); | |
return this.start.call(this); | |
} | |
if (cmd.indexOf("su") != -1) { | |
send("Bypass ProcessBuilder " + cmd); | |
this.command.call(this, ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"]); | |
return this.start.call(this); | |
} | |
return this.start.call(this); | |
}; | |
if (useProcessManager) { | |
var ProcManExec = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File', 'boolean'); | |
var ProcManExecVariant = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.lang.String', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'boolean'); | |
ProcManExec.implementation = function(cmd, env, workdir, redirectstderr) { | |
var fake_cmd = cmd; | |
for (var i = 0; i < cmd.length; i = i + 1) { | |
var tmp_cmd = cmd[i]; | |
if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") { | |
var fake_cmd = ["grep"]; | |
send("Bypass " + cmdarr + " command"); | |
} | |
if (tmp_cmd == "su") { | |
var fake_cmd = ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"]; | |
send("Bypass " + cmdarr + " command"); | |
} | |
} | |
return ProcManExec.call(this, fake_cmd, env, workdir, redirectstderr); | |
}; | |
ProcManExecVariant.implementation = function(cmd, env, directory, stdin, stdout, stderr, redirect) { | |
var fake_cmd = cmd; | |
for (var i = 0; i < cmd.length; i = i + 1) { | |
var tmp_cmd = cmd[i]; | |
if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") { | |
var fake_cmd = ["grep"]; | |
send("Bypass " + cmdarr + " command"); | |
} | |
if (tmp_cmd == "su") { | |
var fake_cmd = ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"]; | |
send("Bypass " + cmdarr + " command"); | |
} | |
} | |
return ProcManExecVariant.call(this, fake_cmd, env, directory, stdin, stdout, stderr, redirect); | |
}; | |
} | |
if (useKeyInfo) { | |
KeyInfo.isInsideSecureHardware.implementation = function() { | |
send("Bypass isInsideSecureHardware"); | |
return true; | |
} | |
} | |
}); | |
/* | |
* This script combines, fixes & extends a long list of other scripts, most notably including: | |
* | |
* - https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/ | |
* - https://codeshare.frida.re/@avltree9798/universal-android-ssl-pinning-bypass/ | |
* - https://pastebin.com/TVJD63uM | |
*/ | |
setTimeout(function () { | |
Java.perform(function () { | |
console.log("---"); | |
console.log("Unpinning Android app..."); | |
/// -- Generic hook to protect against SSLPeerUnverifiedException -- /// | |
// In some cases, with unusual cert pinning approaches, or heavy obfuscation, we can't | |
// match the real method & package names. This is a problem! Fortunately, we can still | |
// always match built-in types, so here we spot all failures that use the built-in cert | |
// error type (notably this includes OkHttp), and after the first failure, we dynamically | |
// generate & inject a patch to completely disable the method that threw the error. | |
try { | |
const UnverifiedCertError = Java.use('javax.net.ssl.SSLPeerUnverifiedException'); | |
UnverifiedCertError.$init.implementation = function (str) { | |
console.log(' --> Unexpected SSL verification failure, adding dynamic patch...'); | |
try { | |
const stackTrace = Java.use('java.lang.Thread').currentThread().getStackTrace(); | |
const exceptionStackIndex = stackTrace.findIndex(stack => | |
stack.getClassName() === "javax.net.ssl.SSLPeerUnverifiedException" | |
); | |
const callingFunctionStack = stackTrace[exceptionStackIndex + 1]; | |
const className = callingFunctionStack.getClassName(); | |
const methodName = callingFunctionStack.getMethodName(); | |
console.log(` Thrown by ${className}->${methodName}`); | |
const callingClass = Java.use(className); | |
const callingMethod = callingClass[methodName]; | |
if (callingMethod.implementation) return; // Already patched by Frida - skip it | |
console.log(' Attempting to patch automatically...'); | |
const returnTypeName = callingMethod.returnType.type; | |
callingMethod.implementation = function () { | |
console.log(` --> Bypassing ${className}->${methodName} (automatic exception patch)`); | |
// This is not a perfect fix! Most unknown cases like this are really just | |
// checkCert(cert) methods though, so doing nothing is perfect, and if we | |
// do need an actual return value then this is probably the best we can do, | |
// and at least we're logging the method name so you can patch it manually: | |
if (returnTypeName === 'void') { | |
return; | |
} else { | |
return null; | |
} | |
}; | |
console.log(` [+] ${className}->${methodName} (automatic exception patch)`); | |
} catch (e) { | |
console.log(' [ ] Failed to automatically patch failure'); | |
} | |
return this.$init(str); | |
}; | |
console.log('[+] SSLPeerUnverifiedException auto-patcher'); | |
} catch (err) { | |
console.log('[ ] SSLPeerUnverifiedException auto-patcher'); | |
} | |
/// -- Specific targeted hooks: -- /// | |
// HttpsURLConnection | |
try { | |
const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); | |
HttpsURLConnection.setDefaultHostnameVerifier.implementation = function (hostnameVerifier) { | |
console.log(' --> Bypassing HttpsURLConnection (setDefaultHostnameVerifier)'); | |
return; // Do nothing, i.e. don't change the hostname verifier | |
}; | |
console.log('[+] HttpsURLConnection (setDefaultHostnameVerifier)'); | |
} catch (err) { | |
console.log('[ ] HttpsURLConnection (setDefaultHostnameVerifier)'); | |
} | |
try { | |
const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); | |
HttpsURLConnection.setSSLSocketFactory.implementation = function (SSLSocketFactory) { | |
console.log(' --> Bypassing HttpsURLConnection (setSSLSocketFactory)'); | |
return; // Do nothing, i.e. don't change the SSL socket factory | |
}; | |
console.log('[+] HttpsURLConnection (setSSLSocketFactory)'); | |
} catch (err) { | |
console.log('[ ] HttpsURLConnection (setSSLSocketFactory)'); | |
} | |
try { | |
const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); | |
HttpsURLConnection.setHostnameVerifier.implementation = function (hostnameVerifier) { | |
console.log(' --> Bypassing HttpsURLConnection (setHostnameVerifier)'); | |
return; // Do nothing, i.e. don't change the hostname verifier | |
}; | |
console.log('[+] HttpsURLConnection (setHostnameVerifier)'); | |
} catch (err) { | |
console.log('[ ] HttpsURLConnection (setHostnameVerifier)'); | |
} | |
// SSLContext | |
try { | |
const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); | |
const SSLContext = Java.use('javax.net.ssl.SSLContext'); | |
const TrustManager = Java.registerClass({ | |
// Implement a custom TrustManager | |
name: 'dev.asd.test.TrustManager', | |
implements: [X509TrustManager], | |
methods: { | |
checkClientTrusted: function (chain, authType) { }, | |
checkServerTrusted: function (chain, authType) { }, | |
getAcceptedIssuers: function () { return []; } | |
} | |
}); | |
// Prepare the TrustManager array to pass to SSLContext.init() | |
const TrustManagers = [TrustManager.$new()]; | |
// Get a handle on the init() on the SSLContext class | |
const SSLContext_init = SSLContext.init.overload( | |
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom' | |
); | |
// Override the init method, specifying the custom TrustManager | |
SSLContext_init.implementation = function (keyManager, trustManager, secureRandom) { | |
console.log(' --> Bypassing Trustmanager (Android < 7) request'); | |
SSLContext_init.call(this, keyManager, TrustManagers, secureRandom); | |
}; | |
console.log('[+] SSLContext'); | |
} catch (err) { | |
console.log('[ ] SSLContext'); | |
} | |
// TrustManagerImpl (Android > 7) | |
try { | |
const array_list = Java.use("java.util.ArrayList"); | |
const TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); | |
// This step is notably what defeats the most common case: network security config | |
TrustManagerImpl.checkTrustedRecursive.implementation = function(a1, a2, a3, a4, a5, a6) { | |
console.log(' --> Bypassing TrustManagerImpl checkTrusted '); | |
return array_list.$new(); | |
} | |
TrustManagerImpl.verifyChain.implementation = function (untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { | |
console.log(' --> Bypassing TrustManagerImpl verifyChain: ' + host); | |
return untrustedChain; | |
}; | |
console.log('[+] TrustManagerImpl'); | |
} catch (err) { | |
console.log('[ ] TrustManagerImpl'); | |
} | |
// OkHTTPv3 (quadruple bypass) | |
try { | |
// Bypass OkHTTPv3 {1} | |
const okhttp3_Activity_1 = Java.use('okhttp3.CertificatePinner'); | |
okhttp3_Activity_1.check.overload('java.lang.String', 'java.util.List').implementation = function (a, b) { | |
console.log(' --> Bypassing OkHTTPv3 (list): ' + a); | |
return; | |
}; | |
console.log('[+] OkHTTPv3 (list)'); | |
} catch (err) { | |
console.log('[ ] OkHTTPv3 (list)'); | |
} | |
try { | |
// Bypass OkHTTPv3 {2} | |
// This method of CertificatePinner.check could be found in some old Android app | |
const okhttp3_Activity_2 = Java.use('okhttp3.CertificatePinner'); | |
okhttp3_Activity_2.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (a, b) { | |
console.log(' --> Bypassing OkHTTPv3 (cert): ' + a); | |
return; | |
}; | |
console.log('[+] OkHTTPv3 (cert)'); | |
} catch (err) { | |
console.log('[ ] OkHTTPv3 (cert)'); | |
} | |
try { | |
// Bypass OkHTTPv3 {3} | |
const okhttp3_Activity_3 = Java.use('okhttp3.CertificatePinner'); | |
okhttp3_Activity_3.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function (a, b) { | |
console.log(' --> Bypassing OkHTTPv3 (cert array): ' + a); | |
return; | |
}; | |
console.log('[+] OkHTTPv3 (cert array)'); | |
} catch (err) { | |
console.log('[ ] OkHTTPv3 (cert array)'); | |
} | |
try { | |
// Bypass OkHTTPv3 {4} | |
const okhttp3_Activity_4 = Java.use('okhttp3.CertificatePinner'); | |
okhttp3_Activity_4['check$okhttp'].implementation = function (a, b) { | |
console.log(' --> Bypassing OkHTTPv3 ($okhttp): ' + a); | |
return; | |
}; | |
console.log('[+] OkHTTPv3 ($okhttp)'); | |
} catch (err) { | |
console.log('[ ] OkHTTPv3 ($okhttp)'); | |
} | |
// Trustkit (triple bypass) | |
try { | |
// Bypass Trustkit {1} | |
const trustkit_Activity_1 = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier'); | |
trustkit_Activity_1.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (a, b) { | |
console.log(' --> Bypassing Trustkit OkHostnameVerifier(SSLSession): ' + a); | |
return true; | |
}; | |
console.log('[+] Trustkit OkHostnameVerifier(SSLSession)'); | |
} catch (err) { | |
console.log('[ ] Trustkit OkHostnameVerifier(SSLSession)'); | |
} | |
try { | |
// Bypass Trustkit {2} | |
const trustkit_Activity_2 = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier'); | |
trustkit_Activity_2.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (a, b) { | |
console.log(' --> Bypassing Trustkit OkHostnameVerifier(cert): ' + a); | |
return true; | |
}; | |
console.log('[+] Trustkit OkHostnameVerifier(cert)'); | |
} catch (err) { | |
console.log('[ ] Trustkit OkHostnameVerifier(cert)'); | |
} | |
try { | |
// Bypass Trustkit {3} | |
const trustkit_PinningTrustManager = Java.use('com.datatheorem.android.trustkit.pinning.PinningTrustManager'); | |
trustkit_PinningTrustManager.checkServerTrusted.implementation = function () { | |
console.log(' --> Bypassing Trustkit PinningTrustManager'); | |
}; | |
console.log('[+] Trustkit PinningTrustManager'); | |
} catch (err) { | |
console.log('[ ] Trustkit PinningTrustManager'); | |
} | |
// Appcelerator Titanium | |
try { | |
const appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager'); | |
appcelerator_PinningTrustManager.checkServerTrusted.implementation = function () { | |
console.log(' --> Bypassing Appcelerator PinningTrustManager'); | |
}; | |
console.log('[+] Appcelerator PinningTrustManager'); | |
} catch (err) { | |
console.log('[ ] Appcelerator PinningTrustManager'); | |
} | |
// OpenSSLSocketImpl Conscrypt | |
try { | |
const OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); | |
OpenSSLSocketImpl.verifyCertificateChain.implementation = function (certRefs, JavaObject, authMethod) { | |
console.log(' --> Bypassing OpenSSLSocketImpl Conscrypt'); | |
}; | |
console.log('[+] OpenSSLSocketImpl Conscrypt'); | |
} catch (err) { | |
console.log('[ ] OpenSSLSocketImpl Conscrypt'); | |
} | |
// OpenSSLEngineSocketImpl Conscrypt | |
try { | |
const OpenSSLEngineSocketImpl_Activity = Java.use('com.android.org.conscrypt.OpenSSLEngineSocketImpl'); | |
OpenSSLEngineSocketImpl_Activity.verifyCertificateChain.overload('[Ljava.lang.Long;', 'java.lang.String').implementation = function (a, b) { | |
console.log(' --> Bypassing OpenSSLEngineSocketImpl Conscrypt: ' + b); | |
}; | |
console.log('[+] OpenSSLEngineSocketImpl Conscrypt'); | |
} catch (err) { | |
console.log('[ ] OpenSSLEngineSocketImpl Conscrypt'); | |
} | |
// OpenSSLSocketImpl Apache Harmony | |
try { | |
const OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl'); | |
OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function (asn1DerEncodedCertificateChain, authMethod) { | |
console.log(' --> Bypassing OpenSSLSocketImpl Apache Harmony'); | |
}; | |
console.log('[+] OpenSSLSocketImpl Apache Harmony'); | |
} catch (err) { | |
console.log('[ ] OpenSSLSocketImpl Apache Harmony'); | |
} | |
// PhoneGap sslCertificateChecker (https://github.com/EddyVerbruggen/SSLCertificateChecker-PhoneGap-Plugin) | |
try { | |
const phonegap_Activity = Java.use('nl.xservices.plugins.sslCertificateChecker'); | |
phonegap_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (a, b, c) { | |
console.log(' --> Bypassing PhoneGap sslCertificateChecker: ' + a); | |
return true; | |
}; | |
console.log('[+] PhoneGap sslCertificateChecker'); | |
} catch (err) { | |
console.log('[ ] PhoneGap sslCertificateChecker'); | |
} | |
// IBM MobileFirst pinTrustedCertificatePublicKey (double bypass) | |
try { | |
// Bypass IBM MobileFirst {1} | |
const WLClient_Activity_1 = Java.use('com.worklight.wlclient.api.WLClient'); | |
WLClient_Activity_1.getInstance().pinTrustedCertificatePublicKey.overload('java.lang.String').implementation = function (cert) { | |
console.log(' --> Bypassing IBM MobileFirst pinTrustedCertificatePublicKey (string): ' + cert); | |
return; | |
}; | |
console.log('[+] IBM MobileFirst pinTrustedCertificatePublicKey (string)'); | |
} catch (err) { | |
console.log('[ ] IBM MobileFirst pinTrustedCertificatePublicKey (string)'); | |
} | |
try { | |
// Bypass IBM MobileFirst {2} | |
const WLClient_Activity_2 = Java.use('com.worklight.wlclient.api.WLClient'); | |
WLClient_Activity_2.getInstance().pinTrustedCertificatePublicKey.overload('[Ljava.lang.String;').implementation = function (cert) { | |
console.log(' --> Bypassing IBM MobileFirst pinTrustedCertificatePublicKey (string array): ' + cert); | |
return; | |
}; | |
console.log('[+] IBM MobileFirst pinTrustedCertificatePublicKey (string array)'); | |
} catch (err) { | |
console.log('[ ] IBM MobileFirst pinTrustedCertificatePublicKey (string array)'); | |
} | |
// IBM WorkLight (ancestor of MobileFirst) HostNameVerifierWithCertificatePinning (quadruple bypass) | |
try { | |
// Bypass IBM WorkLight {1} | |
const worklight_Activity_1 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning'); | |
worklight_Activity_1.verify.overload('java.lang.String', 'javax.net.ssl.SSLSocket').implementation = function (a, b) { | |
console.log(' --> Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSocket): ' + a); | |
return; | |
}; | |
console.log('[+] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSocket)'); | |
} catch (err) { | |
console.log('[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSocket)'); | |
} | |
try { | |
// Bypass IBM WorkLight {2} | |
const worklight_Activity_2 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning'); | |
worklight_Activity_2.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (a, b) { | |
console.log(' --> Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning (cert): ' + a); | |
return; | |
}; | |
console.log('[+] IBM WorkLight HostNameVerifierWithCertificatePinning (cert)'); | |
} catch (err) { | |
console.log('[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (cert)'); | |
} | |
try { | |
// Bypass IBM WorkLight {3} | |
const worklight_Activity_3 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning'); | |
worklight_Activity_3.verify.overload('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;').implementation = function (a, b) { | |
console.log(' --> Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning (string string): ' + a); | |
return; | |
}; | |
console.log('[+] IBM WorkLight HostNameVerifierWithCertificatePinning (string string)'); | |
} catch (err) { | |
console.log('[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (string string)'); | |
} | |
try { | |
// Bypass IBM WorkLight {4} | |
const worklight_Activity_4 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning'); | |
worklight_Activity_4.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (a, b) { | |
console.log(' --> Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSession): ' + a); | |
return true; | |
}; | |
console.log('[+] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSession)'); | |
} catch (err) { | |
console.log('[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSession)'); | |
} | |
// Conscrypt CertPinManager | |
try { | |
const conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager'); | |
conscrypt_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (a, b) { | |
console.log(' --> Bypassing Conscrypt CertPinManager: ' + a); | |
return true; | |
}; | |
console.log('[+] Conscrypt CertPinManager'); | |
} catch (err) { | |
console.log('[ ] Conscrypt CertPinManager'); | |
} | |
// CWAC-Netsecurity (unofficial back-port pinner for Android<4.2) CertPinManager | |
try { | |
const cwac_CertPinManager_Activity = Java.use('com.commonsware.cwac.netsecurity.conscrypt.CertPinManager'); | |
cwac_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (a, b) { | |
console.log(' --> Bypassing CWAC-Netsecurity CertPinManager: ' + a); | |
return true; | |
}; | |
console.log('[+] CWAC-Netsecurity CertPinManager'); | |
} catch (err) { | |
console.log('[ ] CWAC-Netsecurity CertPinManager'); | |
} | |
// Worklight Androidgap WLCertificatePinningPlugin | |
try { | |
const androidgap_WLCertificatePinningPlugin_Activity = Java.use('com.worklight.androidgap.plugin.WLCertificatePinningPlugin'); | |
androidgap_WLCertificatePinningPlugin_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (a, b, c) { | |
console.log(' --> Bypassing Worklight Androidgap WLCertificatePinningPlugin: ' + a); | |
return true; | |
}; | |
console.log('[+] Worklight Androidgap WLCertificatePinningPlugin'); | |
} catch (err) { | |
console.log('[ ] Worklight Androidgap WLCertificatePinningPlugin'); | |
} | |
// Netty FingerprintTrustManagerFactory | |
try { | |
const netty_FingerprintTrustManagerFactory = Java.use('io.netty.handler.ssl.util.FingerprintTrustManagerFactory'); | |
netty_FingerprintTrustManagerFactory.checkTrusted.implementation = function (type, chain) { | |
console.log(' --> Bypassing Netty FingerprintTrustManagerFactory'); | |
}; | |
console.log('[+] Netty FingerprintTrustManagerFactory'); | |
} catch (err) { | |
console.log('[ ] Netty FingerprintTrustManagerFactory'); | |
} | |
// Squareup CertificatePinner [OkHTTP<v3] (double bypass) | |
try { | |
// Bypass Squareup CertificatePinner {1} | |
const Squareup_CertificatePinner_Activity_1 = Java.use('com.squareup.okhttp.CertificatePinner'); | |
Squareup_CertificatePinner_Activity_1.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (a, b) { | |
console.log(' --> Bypassing Squareup CertificatePinner (cert): ' + a); | |
return; | |
}; | |
console.log('[+] Squareup CertificatePinner (cert)'); | |
} catch (err) { | |
console.log('[ ] Squareup CertificatePinner (cert)'); | |
} | |
try { | |
// Bypass Squareup CertificatePinner {2} | |
const Squareup_CertificatePinner_Activity_2 = Java.use('com.squareup.okhttp.CertificatePinner'); | |
Squareup_CertificatePinner_Activity_2.check.overload('java.lang.String', 'java.util.List').implementation = function (a, b) { | |
console.log(' --> Bypassing Squareup CertificatePinner (list): ' + a); | |
return; | |
}; | |
console.log('[+] Squareup CertificatePinner (list)'); | |
} catch (err) { | |
console.log('[ ] Squareup CertificatePinner (list)'); | |
} | |
// Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) | |
try { | |
// Bypass Squareup OkHostnameVerifier {1} | |
const Squareup_OkHostnameVerifier_Activity_1 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier'); | |
Squareup_OkHostnameVerifier_Activity_1.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (a, b) { | |
console.log(' --> Bypassing Squareup OkHostnameVerifier (cert): ' + a); | |
return true; | |
}; | |
console.log('[+] Squareup OkHostnameVerifier (cert)'); | |
} catch (err) { | |
console.log('[ ] Squareup OkHostnameVerifier (cert)'); | |
} | |
try { | |
// Bypass Squareup OkHostnameVerifier {2} | |
const Squareup_OkHostnameVerifier_Activity_2 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier'); | |
Squareup_OkHostnameVerifier_Activity_2.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (a, b) { | |
console.log(' --> Bypassing Squareup OkHostnameVerifier (SSLSession): ' + a); | |
return true; | |
}; | |
console.log('[+] Squareup OkHostnameVerifier (SSLSession)'); | |
} catch (err) { | |
console.log('[ ] Squareup OkHostnameVerifier (SSLSession)'); | |
} | |
// Android WebViewClient (double bypass) | |
try { | |
// Bypass WebViewClient {1} (deprecated from Android 6) | |
const AndroidWebViewClient_Activity_1 = Java.use('android.webkit.WebViewClient'); | |
AndroidWebViewClient_Activity_1.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (obj1, obj2, obj3) { | |
console.log(' --> Bypassing Android WebViewClient (SslErrorHandler)'); | |
}; | |
console.log('[+] Android WebViewClient (SslErrorHandler)'); | |
} catch (err) { | |
console.log('[ ] Android WebViewClient (SslErrorHandler)'); | |
} | |
try { | |
// Bypass WebViewClient {2} | |
const AndroidWebViewClient_Activity_2 = Java.use('android.webkit.WebViewClient'); | |
AndroidWebViewClient_Activity_2.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function (obj1, obj2, obj3) { | |
console.log(' --> Bypassing Android WebViewClient (WebResourceError)'); | |
}; | |
console.log('[+] Android WebViewClient (WebResourceError)'); | |
} catch (err) { | |
console.log('[ ] Android WebViewClient (WebResourceError)'); | |
} | |
// Apache Cordova WebViewClient | |
try { | |
const CordovaWebViewClient_Activity = Java.use('org.apache.cordova.CordovaWebViewClient'); | |
CordovaWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (obj1, obj2, obj3) { | |
console.log(' --> Bypassing Apache Cordova WebViewClient'); | |
obj3.proceed(); | |
}; | |
} catch (err) { | |
console.log('[ ] Apache Cordova WebViewClient'); | |
} | |
// Boye AbstractVerifier | |
try { | |
const boye_AbstractVerifier = Java.use('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier'); | |
boye_AbstractVerifier.verify.implementation = function (host, ssl) { | |
console.log(' --> Bypassing Boye AbstractVerifier: ' + host); | |
}; | |
} catch (err) { | |
console.log('[ ] Boye AbstractVerifier'); | |
} | |
console.log("Unpinning setup completed"); | |
console.log("---"); | |
}); | |
}, 0); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment