Skip to content

Instantly share code, notes, and snippets.

@brnoleal
Created May 1, 2024 16:27
Show Gist options
  • Save brnoleal/75d08872171551a9f58fb100c72350dd to your computer and use it in GitHub Desktop.
Save brnoleal/75d08872171551a9f58fb100c72350dd to your computer and use it in GitHub Desktop.
About This script is used for automated bypass fingerprint auth on android apps, its load after bypass emulator, and root detection from another github repo - https://github.com/sahabrifki/Android-Fingerprint-Bypass/tree/main
Java.perform(function () {
//Call in try catch as Biometric prompt is supported since api 28 (Android 9)
try { hookBiometricPrompt_authenticate(); }
catch (error) { console.log("hookBiometricPrompt_authenticate not supported on this android version") }
try { hookBiometricPrompt_authenticate2(); }
catch (error) { console.log("hookBiometricPrompt_authenticate not supported on this android version") }
try { hookFingerprintManagerCompat_authenticate(); }
catch (error) { console.log("hookFingerprintManagerCompat_authenticate failed"); }
try { hookFingerprintManager_authenticate(); }
catch (error) { console.log("hookFingerprintManager_authenticate failed"); }
});
var cipherList = [];
var StringCls = null;
Java.perform(function () {
StringCls = Java.use('java.lang.String');
});
function getArgsTypes(overloads) {
// there should be just one overload for the constructor
// overloads.len == 1 check
var results = []
var i,j;
for (i in overloads) {
console.log('[*] Overload number ind: '+i);
//if (overloads[i].hasOwnProperty('argumentTypes')) {
var parameters = []
for (j in overloads[i].argumentTypes) {
parameters.push("'" + overloads[i].argumentTypes[j].className + "'")
}
// }
results.push('(' + parameters.join(', ') + ');')
}
return results.join('\n')
}
function getAuthResult(resultObj, cryptoInst) {
//var clax = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult');
var clax = resultObj;
var resu = getArgsTypes(clax['$init'].overloads);
//console.log(resu);
resu = resu.replace(/\'android\.hardware\.biometrics\.BiometricPrompt\$CryptoObject\'/, 'cryptoInst');
resu = resu.replace(/\'android\.hardware\.fingerprint\.FingerprintManager\$CryptoObject\'/, 'cryptoInst');
resu = resu.replace('\'int\'', '0');
resu = resu.replace('\'boolean\'', 'false');
resu = resu.replace(/'.*'/, 'null');
//console.log(resu);
resu = "resultObj.$new"+resu;
var authenticationResultInst = eval(resu);
console.log("cryptoInst:, " + cryptoInst + " class: " + cryptoInst.$className);
return authenticationResultInst;
}
function getBiometricPromptAuthResult() {
var sweet_cipher = null;
var cryptoObj = Java.use('android.hardware.biometrics.BiometricPrompt$CryptoObject');
var cryptoInst = cryptoObj.$new(sweet_cipher);
var authenticationResultObj = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult');
var authenticationResultInst = getAuthResult(authenticationResultObj, cryptoInst);
return authenticationResultInst
}
function hookBiometricPrompt_authenticate() {
var biometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt')['authenticate'].overload('android.os.CancellationSignal', 'java.util.concurrent.Executor', 'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback');
console.log("Hooking BiometricPrompt.authenticate()...");
biometricPrompt.implementation = function (cancellationSignal, executor, callback) {
console.log("[BiometricPrompt.BiometricPrompt()]: cancellationSignal: " + cancellationSignal + ", executor: " + ", callback: " + callback);
var authenticationResultInst = getBiometricPromptAuthResult();
callback.onAuthenticationSucceeded(authenticationResultInst);
console.log("[BiometricPrompt.BiometricPrompt()]: callback.onAuthenticationSucceeded(NULL) called!");
}
}
function hookBiometricPrompt_authenticate2() {
var biometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt')['authenticate'].overload('android.hardware.biometrics.BiometricPrompt$CryptoObject', 'android.os.CancellationSignal', 'java.util.concurrent.Executor', 'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback');
console.log("Hooking BiometricPrompt.authenticate2()...");
biometricPrompt.implementation = function (crypto, cancellationSignal, executor, callback) {
console.log("[BiometricPrompt.BiometricPrompt2()]: crypto:" + crypto + ", cancellationSignal: " + cancellationSignal + ", executor: " + ", callback: " + callback);
var authenticationResultInst = getBiometricPromptAuthResult();
callback.onAuthenticationSucceeded(authenticationResultInst);
}
}
function hookFingerprintManagerCompat_authenticate() {
/*
void authenticate (FingerprintManagerCompat.CryptoObject crypto,
int flags,
CancellationSignal cancel,
FingerprintManagerCompat.AuthenticationCallback callback,
Handler handler)
*/
var fingerprintManagerCompat = null;
var cryptoObj = null;
var authenticationResultObj = null;
try {
fingerprintManagerCompat = Java.use('android.support.v4.hardware.fingerprint.FingerprintManagerCompat');
cryptoObj = Java.use('android.support.v4.hardware.fingerprint.FingerprintManagerCompat$CryptoObject');
authenticationResultObj = Java.use('android.support.v4.hardware.fingerprint.FingerprintManagerCompat$AuthenticationResult');
} catch (error) {
try {
fingerprintManagerCompat = Java.use('androidx.core.hardware.fingerprint.FingerprintManagerCompat');
cryptoObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManagerCompat$CryptoObject');
authenticationResultObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManagerCompat$AuthenticationResult');
}
catch (error) {
console.log("FingerprintManagerCompat class not found!");
return
}
}
console.log("Hooking FingerprintManagerCompat.authenticate()...");
var fingerprintManagerCompat_authenticate = fingerprintManagerCompat['authenticate'];
fingerprintManagerCompat_authenticate.implementation = function (crypto, flags, cancel, callback, handler) {
console.log("[FingerprintManagerCompat.authenticate()]: crypto: " + crypto + ", flags: " + flags + ", cancel:" + cancel + ", callback: " + callback + ", handler: " + handler);
//console.log(enumMethods(callback.$className));
callback['onAuthenticationFailed'].implementation = function () {
console.log("[onAuthenticationFailed()]:");
var sweet_cipher = null;
var cryptoInst = cryptoObj.$new(sweet_cipher);
var authenticationResultInst = getAuthResult(authenticationResultObj, cryptoInst);
callback.onAuthenticationSucceeded(authenticationResultInst);
}
return this.authenticate(crypto, flags, cancel, callback, handler);
}
}
function hookFingerprintManager_authenticate() {
/*
public void authenticate (FingerprintManager.CryptoObject crypto,
CancellationSignal cancel,
int flags,
FingerprintManager.AuthenticationCallback callback,
Handler handler)
Error: authenticate(): has more than one overload, use .overload(<signature>) to choose from:
.overload('android.hardware.fingerprint.FingerprintManager$CryptoObject', 'android.os.CancellationSignal', 'int', 'android.hardware.fingerprint.FingerprintManager$AuthenticationCallback', 'android.os.Handler')
.overload('android.hardware.fingerprint.FingerprintManager$CryptoObject', 'android.os.CancellationSignal', 'int', 'android.hardware.fingerprint.FingerprintManager$AuthenticationCallback', 'android.os.Handler', 'int')
*/
var fingerprintManager = null;
var cryptoObj = null;
var authenticationResultObj = null;
try {
fingerprintManager = Java.use('android.hardware.fingerprint.FingerprintManager');
cryptoObj = Java.use('android.hardware.fingerprint.FingerprintManager$CryptoObject');
authenticationResultObj = Java.use('android.hardware.fingerprint.FingerprintManager$AuthenticationResult');
} catch (error) {
try {
fingerprintManager = Java.use('androidx.core.hardware.fingerprint.FingerprintManager');
cryptoObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManager$CryptoObject');
authenticationResultObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManager$AuthenticationResult');
}
catch (error) {
console.log("FingerprintManager class not found!");
return
}
}
console.log("Hooking FingerprintManager.authenticate()...");
var fingerprintManager_authenticate = fingerprintManager['authenticate'].overload('android.hardware.fingerprint.FingerprintManager$CryptoObject', 'android.os.CancellationSignal', 'int', 'android.hardware.fingerprint.FingerprintManager$AuthenticationCallback', 'android.os.Handler');
fingerprintManager_authenticate.implementation = function (crypto, cancel, flags, callback, handler) {
console.log("[FingerprintManager.authenticate()]: crypto: " + crypto + ", flags: " + flags + ", cancel:" + cancel + ", callback: " + callback + ", handler: " + handler);
var sweet_cipher = null;
var cryptoInst = cryptoObj.$new(sweet_cipher);
var authenticationResultInst = getAuthResult(authenticationResultObj, cryptoInst);
callback.onAuthenticationSucceeded(authenticationResultInst);
return this.authenticate(crypto, cancel, flags, callback, handler);
}
}
function enumMethods(targetClass) {
var hook = Java.use(targetClass);
var ownMethods = hook.class.getDeclaredMethods();
return ownMethods;
}
const commonPaths = [
"/data/local/bin/su",
"/data/local/su",
"/data/local/xbin/su",
"/dev/com.koushikdutta.superuser.daemon/",
"/sbin/su",
"/system/app/Superuser.apk",
"/system/bin/failsafe/su",
"/system/bin/su",
"/su/bin/su",
"/system/etc/init.d/99SuperSUDaemon",
"/system/sd/xbin/su",
"/system/xbin/busybox",
"/system/xbin/daemonsu",
"/system/xbin/su",
"/system/sbin/su",
"/vendor/bin/su",
"/cache/su",
"/data/su",
"/dev/su",
"/system/bin/.ext/su",
"/system/usr/we-need-root/su",
"/system/app/Kinguser.apk",
"/data/adb/magisk",
"/sbin/.magisk",
"/cache/.disable_magisk",
"/dev/.magisk.unblock",
"/cache/magisk.log",
"/data/adb/magisk.img",
"/data/adb/magisk.db",
"/data/adb/magisk_simple",
"/init.magisk.rc",
"/system/xbin/ku.sud",
"/data/adb/ksu",
"/data/adb/ksud",
];
const ROOTmanagementApp = [
"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.topjohnwu.magisk",
"me.weishu.kernelsu",
];
/**
* Bypass Emulator Detection
* @param {any} function(
* @returns {any}
*/
Java.perform(function() {
Java.use("android.os.Build").PRODUCT.value = "gracerltexx";
Java.use("android.os.Build").MANUFACTURER.value = "samsung";
Java.use("android.os.Build").BRAND.value = "samsung";
Java.use("android.os.Build").DEVICE.value = "gracerlte";
Java.use("android.os.Build").MODEL.value = "SM-N935F";
Java.use("android.os.Build").HARDWARE.value = "samsungexynos8890";
Java.use("android.os.Build").FINGERPRINT.value =
"samsung/gracerltexx/gracerlte:8.0.0/R16NW/N935FXXS4BRK2:user/release-keys";
try {
Java.use("java.io.File").exists.implementation = function() {
var name = Java.use("java.io.File").getName.call(this);
var catched = ["qemud", "qemu_pipe", "drivers", "cpuinfo"].indexOf(name) > -1;
if (catched) {
console.log("the pipe " + name + " existence is hooked");
return false;
} else {
return this.exists.call(this);
}
};
} catch (err) {
console.log("[-] java.io.File.exists never called [-]");
}
// rename the package names
try {
Java.use("android.app.ApplicationPackageManager").getPackageInfo.overload(
"java.lang.String",
"int"
).implementation = function(name, flag) {
var catched = ["com.example.android.apis", "com.android.development"].indexOf(name) >
-1;
if (catched) {
console.log("the package " + name + " is renamed with fake name");
name = "fake.package.name";
}
return this.getPackageInfo.call(this, name, flag);
};
} catch (err) {
console.log(
"[-] ApplicationPackageManager.getPackageInfo never called [-]"
);
}
// hook the `android_getCpuFamily` method
// https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.c#1067
// Note: If you pass "null" as the first parameter for "Module.findExportByName" it will search in all modules
try {
Interceptor.attach(Module.findExportByName(null, "android_getCpuFamily"), {
onLeave: function(retval) {
// const int ANDROID_CPU_FAMILY_X86 = 2;
// const int ANDROID_CPU_FAMILY_X86_64 = 5;
if ([2, 5].indexOf(retval) > -1) {
// const int ANDROID_CPU_FAMILY_ARM64 = 4;
retval.replace(4);
}
},
});
} catch (err) {
console.log("[-] android_getCpuFamily never called [-]");
// TODO: trace RegisterNatives in case the libraries are stripped.
}
});
/**
* Bypass Root Detection
* @param {any} function(
* @returns {any}
*/
setTimeout(function() {
function stackTraceHere(isLog) {
var Exception = Java.use("java.lang.Exception");
var Log = Java.use("android.util.Log");
var stackinfo = Log.getStackTraceString(Exception.$new());
if (isLog) {
console.log(stackinfo);
} else {
return stackinfo;
}
}
function stackTraceNativeHere(isLog) {
var backtrace = Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress)
.join("\n\t");
console.log(backtrace);
}
function bypassJavaFileCheck() {
var UnixFileSystem = Java.use("java.io.UnixFileSystem");
UnixFileSystem.checkAccess.implementation = function(file, access) {
var stack = stackTraceHere(false);
const filename = file.getAbsolutePath();
if (filename.indexOf("magisk") >= 0) {
console.log("Anti Root Detect - check file: " + filename);
return false;
}
if (commonPaths.indexOf(filename) >= 0) {
console.log("Anti Root Detect - check file: " + filename);
return false;
}
return this.checkAccess(file, access);
};
}
function bypassNativeFileCheck() {
var fopen = Module.findExportByName("libc.so", "fopen");
Interceptor.attach(fopen, {
onEnter: function(args) {
this.inputPath = args[0].readUtf8String();
},
onLeave: function(retval) {
if (retval.toInt32() != 0) {
if (commonPaths.indexOf(this.inputPath) >= 0) {
console.log("Anti Root Detect - fopen : " + this.inputPath);
retval.replace(ptr(0x0));
}
}
},
});
var access = Module.findExportByName("libc.so", "access");
Interceptor.attach(access, {
onEnter: function(args) {
this.inputPath = args[0].readUtf8String();
},
onLeave: function(retval) {
if (retval.toInt32() == 0) {
if (commonPaths.indexOf(this.inputPath) >= 0) {
console.log("Anti Root Detect - access : " + this.inputPath);
retval.replace(ptr(-1));
}
}
},
});
}
function setProp() {
var Build = Java.use("android.os.Build");
var TAGS = Build.class.getDeclaredField("TAGS");
TAGS.setAccessible(true);
TAGS.set(null, "release-keys");
var FINGERPRINT = Build.class.getDeclaredField("FINGERPRINT");
FINGERPRINT.setAccessible(true);
FINGERPRINT.set(
null,
"google/crosshatch/crosshatch:10/QQ3A.200805.001/6578210:user/release-keys"
);
// Build.deriveFingerprint.inplementation = function(){
// var ret = this.deriveFingerprint() //该函数无法通过反射调用
// console.log(ret)
// return ret
// }
var system_property_get = Module.findExportByName(
"libc.so",
"__system_property_get"
);
Interceptor.attach(system_property_get, {
onEnter(args) {
this.key = args[0].readCString();
this.ret = args[1];
},
onLeave(ret) {
if (this.key == "ro.build.fingerprint") {
var tmp =
"google/crosshatch/crosshatch:10/QQ3A.200805.001/6578210:user/release-keys";
var p = Memory.allocUtf8String(tmp);
Memory.copy(this.ret, p, tmp.length + 1);
}
},
});
}
//android.app.PackageManager
function bypassRootAppCheck() {
var ApplicationPackageManager = Java.use(
"android.app.ApplicationPackageManager"
);
ApplicationPackageManager.getPackageInfo.overload(
"java.lang.String",
"int"
).implementation = function(str, i) {
// console.log(str)
if (ROOTmanagementApp.indexOf(str) >= 0) {
console.log("Anti Root Detect - check package : " + str);
str = "ashen.one.ye.not.found";
}
return this.getPackageInfo(str, i);
};
//shell pm check
}
function bypassShellCheck() {
var String = Java.use("java.lang.String");
var ProcessImpl = Java.use("java.lang.ProcessImpl");
ProcessImpl.start.implementation = function(
cmdarray,
env,
dir,
redirects,
redirectErrorStream
) {
if (cmdarray[0] == "mount") {
console.log("Anti Root Detect - Shell : " + cmdarray.toString());
arguments[0] = Java.array("java.lang.String", [String.$new("")]);
return ProcessImpl.start.apply(this, arguments);
}
if (cmdarray[0] == "getprop") {
console.log("Anti Root Detect - Shell : " + cmdarray.toString());
const prop = ["ro.secure", "ro.debuggable"];
if (prop.indexOf(cmdarray[1]) >= 0) {
arguments[0] = Java.array("java.lang.String", [String.$new("")]);
return ProcessImpl.start.apply(this, arguments);
}
}
if (cmdarray[0].indexOf("which") >= 0) {
const prop = ["su"];
if (prop.indexOf(cmdarray[1]) >= 0) {
console.log("Anti Root Detect - Shell : " + cmdarray.toString());
arguments[0] = Java.array("java.lang.String", [String.$new("")]);
return ProcessImpl.start.apply(this, arguments);
}
}
return ProcessImpl.start.apply(this, arguments);
};
}
console.log("Attach");
bypassNativeFileCheck();
bypassJavaFileCheck();
setProp();
bypassRootAppCheck();
bypassShellCheck();
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.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
.overload("java.lang.String", "int")
.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);
}
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 path = Memory.readCString(args[0]);
path = path.split("/");
var executable = path[path.length - 1];
var shouldFakeReturn = RootBinaries.indexOf(executable) > -1;
if (shouldFakeReturn) {
Memory.writeUtf8String(args[0], "/notexists");
send("Bypass native fopen");
}
},
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("boolean").implementation = function() {
var text = this.readLine.overload("boolean").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;
};
}
});
}, 0);
/**
* Bypass Multiple SSL Pinning
* @param {any} function(
* @returns {any}
*/
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");
}
// Appmattus
try {
const appmatus_Activity = Java.use(
"com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyInterceptor"
);
appmatus_Activity["intercept"].implementation = function(a) {
console.log(" --> Bypassing Appmattus (Transparency)");
return a.proceed(a.request());
};
console.log("[+] Appmattus (CertificateTransparencyInterceptor)");
} catch (err) {
console.log("[ ] Appmattus (CertificateTransparencyInterceptor)");
}
try {
const CertificateTransparencyTrustManager = Java.use(
"com.appmattus.certificatetransparency.internal.verifier.CertificateTransparencyTrustManager"
);
CertificateTransparencyTrustManager["checkServerTrusted"].overload(
"[Ljava.security.cert.X509Certificate;",
"java.lang.String"
).implementation = function(x509CertificateArr, str) {
console.log(
" --> Bypassing Appmattus (CertificateTransparencyTrustManager)"
);
};
CertificateTransparencyTrustManager["checkServerTrusted"].overload(
"[Ljava.security.cert.X509Certificate;",
"java.lang.String",
"java.lang.String"
).implementation = function(x509CertificateArr, str, str2) {
console.log(
" --> Bypassing Appmattus (CertificateTransparencyTrustManager)"
);
return Java.use("java.util.ArrayList").$new();
};
console.log("[+] Appmattus (CertificateTransparencyTrustManager)");
} catch (err) {
console.log("[ ] Appmattus (CertificateTransparencyTrustManager)");
}
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