From 87c054b79d59ceae2efb34c1d6f7cd13d5e3edf8 Mon Sep 17 00:00:00 2001 From: Ajin Abraham Date: Tue, 5 Dec 2023 15:45:17 -0800 Subject: [PATCH] [HOTFIX] More Android & iOS Frida Scripts (#2299) Improved existing frida scripts More Android & iOS frida Scripts Code QA --- .../android/default/debugger_check_bypass.js | 194 +++- .../android/others/bypass-adb-detection.js | 207 ++++ .../others/bypass-emulator-detection.js | 213 ++++ .../bypass-react-native-emulator-detection.js | 31 + .../android/others/dump-library-exports.js | 46 + .../android/others/dump-okhttp-calls.js | 123 +++ .../helper-android-change-sdk-version.js | 12 + .../others/helper-android-spoof-gps.js | 35 + .../android/others/helper-eary-java.js | 40 + .../android/others/helper-heap-search.js | 54 + .../android/others/hook-billing.js | 55 + .../frida_scripts/android/others/hook-json.js | 98 ++ .../android/others/hook-logging.js | 85 ++ .../android/others/ssl-bypass-flutter.js | 71 ++ .../android/others/ssl-pinning-bypass.js | 998 ++++++++++++++++++ .../android/others/stop-app-terminate.js | 203 ++++ .../android/others/trace-bluetooth.js | 69 ++ .../android/others/trace-shared-preference.js | 102 ++ .../android/others/ui-deeplink-trace.js | 24 + ...lag-secure.js => ui-flag-secure-bypass.js} | 0 ...s-flutter-ssl.js => bypass-ssl-flutter.js} | 0 .../ios/others/bypass-ssl-trustkit.js | 33 + .../helper-ios-change-system-version.js | 45 + .../ios/others/helper-ios-spoof-gps.js | 23 + .../ios/others/trace-bluetooth.js | 68 ++ .../ios/others/ui-enable-webinspector.js | 50 + .../ios/others/ui-webview-trace.js | 59 ++ .../views/android/operations.py | 2 +- .../views/ios/corellium_apis.py | 20 +- .../views/ios/corellium_instance.py | 14 +- mobsf/MobSF/init.py | 2 +- .../android/dynamic_analysis.html | 4 +- poetry.lock | 10 +- pyproject.toml | 2 +- 34 files changed, 2968 insertions(+), 24 deletions(-) create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-adb-detection.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-emulator-detection.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-react-native-emulator-detection.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/dump-library-exports.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/dump-okhttp-calls.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-change-sdk-version.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-spoof-gps.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-eary-java.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-heap-search.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-billing.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-json.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-logging.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-bypass-flutter.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-pinning-bypass.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/stop-app-terminate.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-bluetooth.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-shared-preference.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-deeplink-trace.js rename mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/{ui-bypass-flag-secure.js => ui-flag-secure-bypass.js} (100%) rename mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/{bypass-flutter-ssl.js => bypass-ssl-flutter.js} (100%) create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-ssl-trustkit.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-change-system-version.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-spoof-gps.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/trace-bluetooth.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-enable-webinspector.js create mode 100644 mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-webview-trace.js diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/default/debugger_check_bypass.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/default/debugger_check_bypass.js index 91897710b9..aa50c92d3d 100644 --- a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/default/debugger_check_bypass.js +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/default/debugger_check_bypass.js @@ -1,8 +1,198 @@ Java.perform(function () { - // send("[Debugger Check Bypass] Activated"); + try { + // Bypass isDebuggerConnected() check var Debug = Java.use('android.os.Debug'); Debug.isDebuggerConnected.implementation = function () { - send('[Debugger Check Bypass] isDebuggerConnected() bypassed'); + send('[Debugger Check] isDebuggerConnected() check bypassed'); return false; } + } catch(e){} }); + // Following are based on: https://github.com/apkunpacker/FridaScripts +try { + /* Bypass Frida Detection Based On Port Number */ + Interceptor.attach(Module.findExportByName("libc.so", "connect"), { + onEnter: function(args) { + var memory = Memory.readByteArray(args[1], 64); + var b = new Uint8Array(memory); + if (b[2] == 0x69 && b[3] == 0xa2 && b[4] == 0x7f && b[5] == 0x00 && b[6] == 0x00 && b[7] == 0x01) { + this.frida_detection = true; + } + }, + onLeave: function(retval) { + if (this.frida_detection) { + send("[Debugger Check] Frida Port detection bypassed"); + retval.replace(-1); + } + } + }); +} catch(e){} +try { + Interceptor.attach(Module.findExportByName(null, "connect"), { + onEnter: function(args) { + var family = Memory.readU16(args[1]); + if (family !== 2) { + return + } + var port = Memory.readU16(args[1].add(2)); + port = ((port & 0xff) << 8) | (port >> 8); + if (port === 27042) { + send('[Debugger Check] Frida Port detection bypassed'); + Memory.writeU16(args[1].add(2), 0x0101); + } + } + }); +} catch(e){} +try { + /* Bypass TracerPid Detection Based On Pid Status */ + var fgetsPtr = Module.findExportByName("libc.so", "fgets"); + var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']); + Interceptor.replace(fgetsPtr, new NativeCallback(function(buffer, size, fp) { + var retval = fgets(buffer, size, fp); + var bufstr = Memory.readUtf8String(buffer); + if (bufstr.indexOf("TracerPid:") > -1) { + Memory.writeUtf8String(buffer, "TracerPid:\t0"); + send("[Debugger Check] TracerPID check bypassed"); + } + return retval; + }, 'pointer', ['pointer', 'int', 'pointer'])) +} catch(e){} + +try { + /* Bypass Ptrace Checks */ + Interceptor.attach(Module.findExportByName(null, "ptrace"), { + onEnter: function(args) {}, + onLeave: function(retval) { + send("[Debugger Check] Ptrace check bypassed"); + retval.replace(0); + } + }) +} catch(e){} + +try { + /* Watch Child Process Forking */ + var fork = Module.findExportByName(null, "fork") + Interceptor.attach(fork, { + onEnter: function(args) {}, + onLeave: function(retval) { + var pid = parseInt(retval.toString(16), 16) + send("[Debugger Check] Hook fork child process PID: " + pid) + } + }) +} catch(e){} + + +/* Xposed Detection Bypass */ +Java.perform(function() { + try { + var cont = Java.use("java.lang.String"); + cont.contains.overload("java.lang.CharSequence").implementation = function(checks) { + var check = checks.toString(); + if (check.indexOf("libdexposed") >= 0 || check.indexOf("libsubstrate.so") >= 0 || check.indexOf("libepic.so") >= 0 || check.indexOf("libxposed") >= 0) { + var BypassCheck = "libpkmkb.so"; + send("[Debugger Check] Xposed library check bypassed"); + return this.contains.call(this, BypassCheck); + } + return this.contains.call(this, checks); + } + } catch (erro) { + console.error(erro); + } + try { + var StacktraceEle = Java.use("java.lang.StackTraceElement"); + StacktraceEle.getClassName.overload().implementation = function() { + var Flag = false; + var ClazzName = this.getClassName(); + if (ClazzName.indexOf("com.saurik.substrate.MS$2") >= 0 || ClazzName.indexOf("de.robv.android.xposed.XposedBridge") >= 0) { + send("[Debugger Check] Debugger detection check bypassed for class: " + this.getClassName()); + Flag = true; + if (Flag) { + var StacktraceEle = Java.use("java.lang.StackTraceElement"); + StacktraceEle.getClassName.overload().implementation = function() { + var gMN = this.getMethodName(); + if (gMN.indexOf("handleHookedMethod") >= 0 || gMN.indexOf("invoked") >= 0) { + send("[Debugger Check] Debugger detection check bypassed for method: " + this.getMethodName()); + return "bye.pass"; + } + return this.getMethodName(); + } + } + return "com.android.vending" + } + return this.getClassName(); + } + } catch (errr) { + console.error(errr); + } +}) +/* VPN Related Checks */ +Java.perform(function() { + var NInterface = Java.use("java.net.NetworkInterface"); + try { + var NInterface = Java.use("java.net.NetworkInterface"); + NInterface.getName.overload().implementation = function() { + var IName = this.getName(); + if (IName == "tun0" || IName == "ppp0" || IName == "p2p0" || IName == "ccmni0" || IName == "tun") { + send("[Debugger Check] Bypassed Network Interface name check: " + JSON.stringify(this.getName())); + return "Bypass"; + } + return this.getName(); + } + } catch (err) { + console.error(err); + } + // HTTP(s) Proxy check + try { + var GetProperty = Java.use("java.lang.System"); + GetProperty.getProperty.overload("java.lang.String").implementation = function(getprop) { + if (getprop.indexOf("http.proxyHost") >= 0 || getprop.indexOf("http.proxyPort") >= 0) { + var newprop = "CKMKB" + send("[Debugger Check] HTTP(s) proxy check bypassed") + return this.getProperty.call(this, newprop); + } + return this.getProperty(getprop); + } + } catch (err) { + console.error(err); + } + // NetworkCapabilities check + try { + var NCap = Java.use("android.net.NetworkCapabilities"); + NCap.hasTransport.overload("int").implementation = function(values) { + if (values == 4){ + send("[Debugger Check] HasTransportcheck bypassed") + return false; + } else + return this.hasTransport(values); + } + } catch (e) { + console.error(e); + } +}) +/* Developer Mod Check Bypass */ +Java.perform(function() { + try{ + var SSecure = Java.use("android.provider.Settings$Secure"); + SSecure.getStringForUser.overload('android.content.ContentResolver', 'java.lang.String', 'int').implementation = function(Content, Name, Flag) { + if (Name.indexOf("development_settings_enabled") >= 0) { + send("[Debugger Check] Developer mode check bypassed for: " + Name) + return this.getStringForUser.call(this, Content, "bypassed", Flag); + } + return this.getStringForUser(Content, Name, Flag); + } + } catch(e){} +}) + +/* Playstore install source check */ +Java.perform(function() { + try{ + var Installer = Java.use("android.app.ApplicationPackageManager"); + Installer.getInstallerPackageName.overload('java.lang.String').implementation = function(Str) { + var playPkg = "com.android.vending"; + if (Str.toString().indexOf(playPkg) < 0) { + send("[Debugger Check] Play Store install source check bypassed. Original value: "+ Str.toString()); + return playPkg; + } + } + } catch(e){} +}) diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-adb-detection.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-adb-detection.js new file mode 100644 index 0000000000..2f627fee6d --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-adb-detection.js @@ -0,0 +1,207 @@ +/* + Description: Android ADB Detection Bypass frida script + Credit: meerkati + + Useful when bypassing USB debugging detection on Android! + If it doesn't work, remove the conditional statement + + Src: https://github.com/rsenet/FriList/blob/main/02_SecurityBypass/DebugMode_Emulator/android-adb-detection-bypass.js + Link: + https://developer.android.com/reference/android/os/Build.VERSION +*/ + +setTimeout(function() +{ + Java.perform(function() + { + var androidSettings = ['adb_enabled']; + var sdkVersion = Java.use('android.os.Build$VERSION'); + console.log("SDK Version : " + sdkVersion.SDK_INT.value); + + /* API 16 or lower Settings.Global Hook */ + if (sdkVersion.SDK_INT.value <= 16) + { + var settingSecure = Java.use('android.provider.Settings$Secure'); + + settingSecure.getInt.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingSecure.getInt(cr,name) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Secure.getInt(cr, name) Bypassed'); + return 0; + } + var ret = this.getInt(cr, name); + return ret; + } + + settingSecure.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').implementation = function(cr, name, def) + { + //console.log("[*]settingSecure.getInt(cr,name,def) : " + name); + if (name == (androidSettings[0])) + { + console.log('[+]Secure.getInt(cr, name, def) Bypassed'); + return 0; + } + var ret = this.getInt(cr, name, def); + return ret; + } + + settingSecure.getFloat.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingSecure.getFloat(cr,name) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Secure.getFloat(cr, name) Bypassed'); + return 0; + } + var ret = this.getFloat(cr, name) + return ret; + } + + settingSecure.getFloat.overload('android.content.ContentResolver', 'java.lang.String', 'float').implementation = function(cr, name, def) + { + //console.log("[*]settingSecure.getFloat(cr,name,def) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Secure.getFloat(cr, name, def) Bypassed'); + return 0; + } + var ret = this.getFloat(cr, name, def); + return ret; + } + + settingSecure.getLong.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingSecure.getLong(cr,name) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Secure.getLong(cr, name) Bypassed'); + return 0; + } + var ret = this.getLong(cr, name) + return ret; + } + + settingSecure.getLong.overload('android.content.ContentResolver', 'java.lang.String', 'long').implementation = function(cr, name, def) + { + //console.log("[*]settingSecure.getLong(cr,name,def) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Secure.getLong(cr, name, def) Bypassed'); + return 0; + } + var ret = this.getLong(cr, name, def); + return ret; + } + + settingSecure.getString.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingSecure.getString(cr,name) : " + name); + if (name == androidSettings[0]) + { + var stringClass = Java.use("java.lang.String"); + var stringInstance = stringClass.$new("0"); + + console.log('[+]Secure.getString(cr, name) Bypassed'); + return stringInstance; + } + var ret = this.getString(cr, name); + return ret; + } + } + + /* API 17 or higher Settings.Global Hook */ + if (sdkVersion.SDK_INT.value >= 17) + { + var settingGlobal = Java.use('android.provider.Settings$Global'); + + settingGlobal.getInt.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingGlobal.getInt(cr,name) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Global.getInt(cr, name) Bypassed'); + return 0; + } + var ret = this.getInt(cr, name); + return ret; + } + + settingGlobal.getInt.overload('android.content.ContentResolver', 'java.lang.String', 'int').implementation = function(cr, name, def) + { + //console.log("[*]settingGlobal.getInt(cr,name,def) : " + name); + if (name == (androidSettings[0])) + { + console.log('[+]Global.getInt(cr, name, def) Bypassed'); + return 0; + } + var ret = this.getInt(cr, name, def); + return ret; + } + + settingGlobal.getFloat.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingGlobal.getFloat(cr,name) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Global.getFloat(cr, name) Bypassed'); + return 0; + } + var ret = this.getFloat(cr, name); + return ret; + } + + settingGlobal.getFloat.overload('android.content.ContentResolver', 'java.lang.String', 'float').implementation = function(cr, name, def) + { + //console.log("[*]settingGlobal.getFloat(cr,name,def) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Global.getFloat(cr, name, def) Bypassed'); + return 0; + } + var ret = this.getFloat(cr, name, def); + return ret; + } + + settingGlobal.getLong.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingGlobal.getLong(cr,name) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Global.getLong(cr, name) Bypassed'); + return 0; + } + var ret = this.getLong(cr, name); + return ret; + } + + settingGlobal.getLong.overload('android.content.ContentResolver', 'java.lang.String', 'long').implementation = function(cr, name, def) + { + //console.log("[*]settingGlobal.getLong(cr,name,def) : " + name); + if (name == androidSettings[0]) + { + console.log('[+]Global.getLong(cr, name, def) Bypassed'); + return 0; + } + var ret = this.getLong(cr, name, def); + return ret; + } + + settingGlobal.getString.overload('android.content.ContentResolver', 'java.lang.String').implementation = function(cr, name) + { + //console.log("[*]settingGlobal.getString(cr,name) : " + name); + if (name == androidSettings[0]) + { + var stringClass = Java.use("java.lang.String"); + var stringInstance = stringClass.$new("0"); + + console.log('[+]Global.getString(cr, name) Bypassed'); + return stringInstance; + } + var ret = this.getString(cr, name); + return ret; + } + } + }); +}, 0); \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-emulator-detection.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-emulator-detection.js new file mode 100644 index 0000000000..f4b8211687 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/bypass-emulator-detection.js @@ -0,0 +1,213 @@ +/* + Description: Android Emulator Detection Bypass frida script + Credit: @Areizen_ + + Useful when bypassing USB debugging detection on Android! + If it doesn't work, remove the conditional statement + + Src: https://github.com/rsenet/FriList/blob/main/02_SecurityBypass/DebugMode_Emulator/android-emulator-detection-bypass.js + Link: + https://developer.android.com/reference/android/os/Build.VERSION +*/ + +Java.perform(function() +{ + console.log("--> Anti Emulator Detection Bypass (aka BluePill) - Script Loaded") + /*********************************************************** + *** IMPORTANT *** + uncomment instructions below to skip one or more bypasses + /***********************************************************/ + bypass_build_properties() + bypass_phonenumber() + bypass_deviceid() + bypass_imsi() + bypass_operator_name() + bypass_sim_operator_name() + bypass_has_file() + bypass_processbuilder() + bypass_system_properties() +}); + + +function replaceFinaleField(object, fieldName, value) +{ + var field = object.class.getDeclaredField(fieldName) + field.setAccessible(true) + field.set(null, value) +} + +function bypass_build_properties() +{ + console.log("Build Properties - Bypass Loaded") + // Class containing const that we want to modify + const Build = Java.use("android.os.Build") + + // reflection class for changing const + const Field = Java.use('java.lang.reflect.Field') + const Class = Java.use('java.lang.Class') + + // Replacing Build static fields + replaceFinaleField(Build, "FINGERPRINT", "abcd/C1505:4.1.1/11.3.A.2.13:user/release-keys") + replaceFinaleField(Build, "MODEL", "C1505") + replaceFinaleField(Build, "MANUFACTURER", "Sony") + replaceFinaleField(Build, "BRAND", "Xperia") + replaceFinaleField(Build, "BOARD", "7x27") + replaceFinaleField(Build, "ID", "11.3.A.2.13") + replaceFinaleField(Build, "SERIAL", "abcdef123") + replaceFinaleField(Build, "TAGS", "release-keys") + replaceFinaleField(Build, "USER", "administrator") +} + +function bypass_phonenumber() +{ + console.log("Phone Number - Bypass Loaded") + const TelephonyManager = Java.use('android.telephony.TelephonyManager') + + TelephonyManager.getLine1Number.overload().implementation = function() + { + console.log("Phone number - bypass done!") + return "060102030405" + } +} + +function bypass_deviceid() +{ + console.log("Device ID - Bypass Loaded") + const TelephonyManager = Java.use('android.telephony.TelephonyManager') + + TelephonyManager.getDeviceId.overload().implementation = function() + { + console.log("Device ID - bypass done!") + return "012343545456445" + } +} + +function bypass_imsi() +{ + console.log("IMSI - Bypass Loaded") + const TelephonyManager = Java.use('android.telephony.TelephonyManager') + + TelephonyManager.getSubscriberId.overload().implementation = function() + { + console.log("Device ID (getSubscriberId) - bypass done!") + return "310260000000111" + } +} + +function bypass_operator_name() +{ + console.log("Operator Name - Bypass Loaded") + const TelephonyManager = Java.use('android.telephony.TelephonyManager') + + TelephonyManager.getNetworkOperatorName.overload().implementation = function() + { + console.log("Operator Name - bypass done!") + return "not" + } +} + +function bypass_sim_operator_name() +{ + console.log("SIM Operator Name - Bypass Loaded") + const TelephonyManager = Java.use('android.telephony.TelephonyManager') + + TelephonyManager.getSimOperatorName.overload().implementation = function() + { + console.log("SIM Operator Name - bypass done!") + return "not" + } +} + +function bypass_has_file() +{ + console.log("Emulator related files check - Bypass Loaded") + const File = Java.use("java.io.File") + const KnownFiles= [ + "ueventd.android_x86.rc", + "x86.prop", + "ueventd.ttVM_x86.rc", + "init.ttVM_x86.rc", + "fstab.ttVM_x86", + "fstab.vbox86", + "init.vbox86.rc", + "ueventd.vbox86.rc", + "/dev/socket/qemud", + "/dev/qemu_pipe", + "/system/lib/libc_malloc_debug_qemu.so", + "/sys/qemu_trace", + "/system/bin/qemu-props", + "/dev/socket/genyd", + "/dev/socket/baseband_genyd", + "/proc/tty/drivers", + "/proc/cpuinfo" + ] + + File.exists.implementation = function () + { + var x = this.getAbsolutePath(); + for(var i=0; i + { + + //Create a new instance of HttpLoggingInterceptor class + function getInterceptor() + { + try + { + const HttpLoggingInterceptor = Java.use('okhttp3.logging.HttpLoggingInterceptor'); + const Level = Java.use('okhttp3.logging.HttpLoggingInterceptor$Level'); + + const MyLogger = Java.registerClass( + { + name: 'MyLogger', + superClass: Java.use('java.lang.Object'), + implements: [Java.use('okhttp3.logging.HttpLoggingInterceptor$Logger')], + methods: + { + log: [ + { + returnType: 'void', + argumentTypes: ['java.lang.String'], + implementation: function(message) + { + send(' [LOG] ' + message); + } + }] + }, + }); + + var logInstance = HttpLoggingInterceptor.$new(MyLogger.$new()); + + //If you want to log at the logcat just change to the line bellow + //var logInstance = HttpLoggingInterceptor.$new(); + logInstance.setLevel(Level.BODY.value); + + return logInstance; + + } + catch (err) + { + send("[-] Error creating interceptor") + send(err); + send(err.stack) + return null; + } + } + + try + { + var Builder = Java.use('okhttp3.OkHttpClient$Builder') + var build = Builder.build.overload(); + + build.implementation = function() + { + send('[+] OkHttpClient$Builder ==> Adding log interceptor') + + //Add the new interceptor before call the 'build' function + try + { + this.addInterceptor(getInterceptor()); + } + catch (err) + { + send('[-] OkHttpClient$Builder.addInterceptor error'); + } + + return build.call(this); + } + } + catch (err) + { + send('[-] OkHttpClient$Builder error'); + send(err); + } + }); +}, 1000); + + +Java.perform(function() +{ + function okhttp3RealCall(){ + var OkHttpClient = Java.use("okhttp3.OkHttpClient"); + var RealCall = Java.use("okhttp3.RealCall"); + var Buffer = Java.use("okio.Buffer"); + var StandardCharsets = Java.use("java.nio.charset.StandardCharsets"); + + RealCall.getResponseWithInterceptorChain.implementation = function() + { + var response = this.getResponseWithInterceptorChain() + var request = response.request() + send("REQUEST: " + request) + send(request.headers()) + var body = ""; + + if (request.headers().get("content-type") === "application/x-www-form-urlencoded") + { + var buffer = Buffer.$new() + request.body().writeTo(buffer) + body = buffer.readString(StandardCharsets.UTF_8.value) + } + + send(body) + send("RESPONSE: " + response) + send(response.headers()) + return response + } + } + try{ + okhttp3RealCall(); + } catch(err){} +}); \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-change-sdk-version.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-change-sdk-version.js new file mode 100644 index 0000000000..b3386dbffd --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-change-sdk-version.js @@ -0,0 +1,12 @@ +/* + Description: Android SDK version changer frida script + Credit: Unknown + Src: https://github.com/rsenet/FriList/blob/main/02_SecurityBypass/android-sdk-version-change.js + https://developer.android.com/reference/android/os/Build.VERSION +*/ + +Java.perform(function() +{ + var ver = Java.use('android.os.Build$VERSION'); + ver.SDK_INT.value = 15; +}); \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-spoof-gps.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-spoof-gps.js new file mode 100644 index 0000000000..c0a07a9075 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-android-spoof-gps.js @@ -0,0 +1,35 @@ +/* + Description: Android GPS Location Spoofing + Credit: @rsenet + + Src: https://github.com/rsenet/FriList/blob/main/02_SecurityBypass/Location/android-location-spoofing.js + Link: + https://developer.android.com/reference/android/location/Location +*/ + +const lat = 10.0000000; +const lng = 10.0000000; +const alt = 10.0000000; + +Java.perform(function () +{ + var Location = Java.use("android.location.Location"); + + Location.getLatitude.implementation = function() + { + send("Changing Latitude to " + lat); + return lat; + } + + Location.getLongitude.implementation = function() + { + send("Changing Longitude to " + lng); + return lng; + } + + Location.getAltitude.implementation = function() + { + send("Changing Altitude to " + alt); + return alt; + } +}) \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-eary-java.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-eary-java.js new file mode 100644 index 0000000000..3971d6780d --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-eary-java.js @@ -0,0 +1,40 @@ +// Source: https://github.com/apkunpacker/FridaScripts +var Duplicate = []; +Module.enumerateExportsSync("libart.so").forEach(function(exp) { + if (exp.name.indexOf("ClassLinker") != -1 && exp.name.indexOf("FindClassE") != -1) { + Interceptor.attach(exp.address, { + onEnter: function(args) { + this.name = Memory.readCString(args[2]); + }, + onLeave: function(retval) { + if (Duplicate.indexOf(this.name) >= 0) return; + if (retval.toInt32() !== 0) { + Duplicate.push(this.name); + let MClass = this.name.match(/^L(.*);$/); + if (MClass !== null && MClass.length > 1) { + const clearName = MClass[1].replace(/\//g, ".") + HookClass(clearName); + //console.log(clearName); //Print all loaded class + } + } + } + }) + } +}) + +function HookClass(ClassName) { + if (ClassName.indexOf("com.loaded.class.name.here") >= 0) { + console.log("Hooking : ", ClassName); + try { + Java.perform(function() { + var Cls = Java.use("com.loaded.class"); + Cls.a.overload("java.lang.String").implementation = function(str) { + console.warn("Ret : ", str); + return this.a(str); + } + }) + } catch (e) { + console.error(e); + } + } +} \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-heap-search.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-heap-search.js new file mode 100644 index 0000000000..4800eed8b9 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-heap-search.js @@ -0,0 +1,54 @@ +/************************************************************************ + * Name: Heap Search and method call + * OS: Android + * Author: @mobilesecurity_ + * Source: https://github.com/m0bilesecurity + * Info: make sure to replace placeholders + * {className} + * {classMethod} + * {args} +*************************************************************************/ + + +Java.performNow(function () { + var classname = "{className}" + var classmethod = "{classMethod}"; + + Java.choose(classname, { + onMatch: function (instance) { + try + { + var returnValue; + //{methodSignature} + returnValue = instance.{classMethod}({args}); //<-- replace v[i] with the value that you want to pass + + //Output + var s = ""; + s=s + "[*] Heap Search - START\\n" + + s=s + "Instance Found: " + instance.toString() + "\\n"; + s=s + "Calling method: \\n"; + s=s + " Class: " + classname + "\\n" + s=s + " Method: " + classmethod + "\\n" + s=s + "-->Output: " + returnValue + "\\n"; + + s = s + "[*] Heap Search - END\\n" + + send(s); + } + catch (err) + { + var s = ""; + s=s + "[*] Heap Search - START\\n" + s=s + "Instance NOT Found or Exception while calling the method\\n"; + s=s + " Class: " + classname + "\\n" + s=s + " Method: " + classmethod + "\\n" + s=s + "-->Exception: " + err + "\\n" + s=s + "[*] Heap Search - END\\n" + send(s) + } + + } + }); + +}); \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-billing.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-billing.js new file mode 100644 index 0000000000..ac8ad9f741 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-billing.js @@ -0,0 +1,55 @@ +// Source: https://github.com/apkunpacker/FridaScripts +Java.perform(function() { + var Redirect = Java.use("android.content.Intent"); + Redirect.$init.overload("java.lang.String").implementation = function(INITS) { + if (INITS.indexOf("billing") >= 0 || INITS.indexOf("license") >= 0) { + Redirect.setPackage.overload('java.lang.String').implementation = function(pkg) { + if (pkg == 'com.android.vending') { + var pkgFix = "com.android.vendinf"; + console.warn("setPackage Fixed :) "); + return this.setPackage.call(this, pkgFix); + } else { + return this.setPackage.call(this, pkg); + } + } + } + return this.$init(INITS); + } + try { + var EV = Java.use("com.android.org.conscrypt.OpenSSLSignature"); + EV.engineVerify.overload('[B').implementation = function(signatures) { + console.warn("engineVerify From Conscrypt Fixed"); + return true; + } + } catch (e) {} + try { + var EV = Java.use("org.apache.harmony.xnet.provider.jsse.OpenSSLSignature"); + EV.engineVerify.overload('[B').implementation = function(signatures) { + console.warn("engineVerify From Harmoney.xnet Fixed"); + return true; + } + } catch (e) {} + var VerifySign = Java.use("java.security.Signature"); + VerifySign.verify.overload('[B').implementation = function(paramBool) { + console.warn("Verify From java.security.Signature Fixed"); + return true; + } + var MD = Java.use("java.security.MessageDigest"); + MD.isEqual.overload("[B", "[B").implementation = function() { + return true; + } + try { + var VerifyDPayload = Java.use("com.sigmateam.iap.gpm.Purchases"); + VerifyDPayload.verifyDeveloperPayload.overload('org.onepf.oms.appstore.googleUtils.Purchase').implementation = function(paramBool) { + console.warn("Verify From com.sigmateam.iap.gpm.Purchases;->verifyDeveloperPayload Fixed"); + return true; + } + } catch (e) {} + try { + var VerifyP = Java.use("org.onepf.oms.appstore.googleUtils.Security"); + VerifyP.verifyPurchase.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(p1, p2, p3) { + console.warn("Verify From org.onepf.oms.appstore.googleUtils.Security;->verifyPurchase Fixed"); + return true; + } + } catch (e) {} +}) \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-json.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-json.js new file mode 100644 index 0000000000..ee38813de3 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-json.js @@ -0,0 +1,98 @@ +// Source: https://github.com/apkunpacker/FridaScripts +Java.performNow(function() { + try { + var JSONO = Java.use("org.json.JSONObject"); + JSONO.optString.overload("java.lang.String").implementation = function(str) { + var JsonRet = this.optString(str); + console.log("JsonOptStr : ", str, JsonRet); + return JsonRet; + } + JSONO.optString.overload("java.lang.String", "java.lang.String").implementation = function(str, str2) { + var JsonRet = this.optString(str, str2); + console.log("JsonOptStr2 : ", str, str2, JsonRet); + return JsonRet; + } + JSONO.numberToString.overload('java.lang.Number').implementation = function(N) { + var JsonRet = this.numberToString(N); + console.log("numberToString : ", N, JsonRet); + return JsonRet; + } + JSONO.getJSONArray.overload('java.lang.String').implementation = function(str) { + var JsonRet = this.getJSONArray(str); + console.log("getJSONArray : ", str, JsonRet); + return JsonRet; + } + JSONO.getJSONObject.overload('java.lang.String').implementation = function(str) { + var JsonRet = this.getJSONObject(str); + console.log("getJSONObject : ", str, JsonRet); + return JsonRet; + } + JSONO.names.overload().implementation = function() { + var JsonRet = this.names(str); + console.log("names : ", JsonRet); + return JsonRet; + } + JSONO.opt.overload('java.lang.String').implementation = function(str) { + var JsonRet = this.opt(str); + console.log("opt : ", str, JsonRet); + return JsonRet; + } + JSONO.optJSONArray.overload('java.lang.String').implementation = function(str) { + var JsonRet = this.optJSONArray(str); + console.log("optJSONArray : ", str, JsonRet); + return JsonRet; + } + JSONO.optJSONObject.overload('java.lang.String').implementation = function(str) { + var JsonRet = this.optJSONObject(str); + console.log("optJSONObject : ", str, JsonRet); + return JsonRet; + } + JSONO.put.overload('java.lang.String', 'double').implementation = function(str, d) { + var JsonRet = this.put(str, d); + console.log("put D : ", str, d, JsonRet); + return JsonRet; + } + JSONO.put.overload('java.lang.String', 'int').implementation = function(str, i) { + var JsonRet = this.put(str, i); + console.log("put i : ", str, i, JsonRet); + return JsonRet; + } + JSONO.put.overload('java.lang.String', 'long').implementation = function(str, l) { + var JsonRet = this.put(str, l); + console.log("put l : ", str, l, JsonRet); + return JsonRet; + } + JSONO.put.overload('java.lang.String', 'java.lang.Object').implementation = function(str, obj) { + var JsonRet = this.put(str, obj); + console.log("put Obj : ", str, obj, JsonRet); + return JsonRet; + } + JSONO.put.overload('java.lang.String', 'boolean').implementation = function(str, b) { + var JsonRet = this.put(str, b); + console.log("put bool : ", str, b, JsonRet); + return JsonRet; + } + JSONO.putOpt.overload('java.lang.String', 'java.lang.Object').implementation = function(str, ob) { + var JsonRet = this.putOpt(str, ob); + console.log("putOpt : ", str, ob, JsonRet); + return JsonRet; + } + JSONO.toJSONArray.overload('org.json.JSONArray').implementation = function(arr) { + var JsonRet = this.toJSONArray(arr); + console.log("toJSONArray : ", arr, JsonRet); + return JsonRet; + } + JSONO["toString"].overload('int').implementation = function(i) { + var JsonRet = this["toString"](i); + console.log("toString i : ", i, JsonRet); + return JsonRet; + } + JSONO["toString"].overload().implementation = function() { + var JsonRet = this["toString"](); + console.log("toString : ", JsonRet); + return JsonRet; + } + } catch (e) { + console.error(e); + } +}) diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-logging.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-logging.js new file mode 100644 index 0000000000..bc7f1f6046 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/hook-logging.js @@ -0,0 +1,85 @@ +// Source: https://github.com/apkunpacker/FridaScripts +Java.performNow(function() { + let Log = Java.use("android.util.Log"); + Log.d.overload("java.lang.String", "java.lang.String").implementation = function(a, b) { + console.log(a.toString()); + console.log(b.toString()); + return this.d(a, b); + }; + Log.d.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function(a, b, c) { + console.log(a.toString()); + console.log(b.toString()); + return this.d(a, b, c); + }; + Log.v.overload("java.lang.String", "java.lang.String").implementation = function(a, b) { + console.log(a.toString()); + console.log(b.toString()); + return this.v(a, b); + }; + Log.v.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function(a, b, c) { + console.log(a.toString()); + console.log(b.toString()); + return this.v(a, b, c); + }; + Log.i.overload("java.lang.String", "java.lang.String").implementation = function(a, b) { + console.log(a.toString()); + console.log(b.toString()); + return this.i(a, b); + }; + Log.i.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function(a, b, c) { + console.log(a.toString()); + console.log(b.toString()); + return this.i(a, b, c); + }; + Log.e.overload("java.lang.String", "java.lang.String").implementation = function(a, b) { + console.log(a.toString()); + console.log(b.toString()); + return this.e(a, b); + }; + Log.e.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function(a, b, c) { + console.log(a.toString()); + console.log(b.toString()); + return this.e(a, b, c); + }; + Log.w.overload("java.lang.String", "java.lang.String").implementation = function(a, b) { + console.log(a.toString()); + console.log(b.toString()); + return this.w(a, b); + }; + Log.w.overload("java.lang.String", "java.lang.Throwable").implementation = function(a, b) { + console.log(a.toString()); + return this.w(a, b); + }; + Log.w.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function(a, b, c) { + console.log(a.toString()); + console.log(b.toString()); + return this.w(a, b, c); + }; + Log.wtf.overload("java.lang.String", "java.lang.String").implementation = function(a, b) { + console.log(a.toString()); + console.log(b.toString()); + return this.wtf.overload("java.lang.String", "java.lang.String").call(this, a, b); + }; + Log.println.overload("int", "java.lang.String", "java.lang.String").implementation = function(a, b, c) { + console.log(a.toString()); + console.log(b.toString()); + console.log(c.toString()); + return this.println(a, b, c); + }; +}); +let LogPrint = Module.findExportByName("liblog.so", "__android_log_print"); +let LogWrite = Module.findExportByName("liblog.so", "__android_log_write"); +let LogVPrint = Module.findExportByName("liblog.so", "__android_log_vprint"); +let LogAssert = Module.findExportByName("liblog.so", "__android_log_assert"); +Interceptor.attach(LogPrint, function(args) { + console.log("Print : ", args[1].readCString(), args[2].readCString()); +}) +Interceptor.attach(LogWrite, function(args) { + console.log("Write : ", args[1].readCString(), args[2].readCString()); +}) +Interceptor.attach(LogVPrint, function(args) { + console.log("VPrint : ", args[1].readCString(), args[2].readCString()); +}) +Interceptor.attach(LogAssert, function(args) { + console.log("Assert : ", args[0].readCString(), args[1].readCString()); +}) diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-bypass-flutter.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-bypass-flutter.js new file mode 100644 index 0000000000..f5adc55c1a --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-bypass-flutter.js @@ -0,0 +1,71 @@ +// Source: https://github.com/apkunpacker/FridaScripts +console.warn(Process.arch, "environment Detected") +let do_dlopen = null; +let call_ctor = null; +let LibraryName = "libflutter.so"; +let moduleName = Process.arch == "arm" ? "linker" : "linker64"; +let reg = Process.arch == "arm" ? "r0" : "x0"; +let Arch = Process.arch; +Process.findModuleByName(moduleName) + .enumerateSymbols() + .forEach(function(sym) { + if (sym.name.indexOf('do_dlopen') !== -1) { + do_dlopen = sym.address; + } else if (sym.name.indexOf('call_constructor') !== -1) { + call_ctor = sym.address; + } +}) +Interceptor.attach(do_dlopen, function() { + let Lib = this.context[reg].readCString(); + if (Lib && Lib.indexOf(LibraryName) !== -1) { + Interceptor.attach(call_ctor, function() { + Hook(LibraryName); + }) + } +}) + +function Hook(Name) { + let Hooked = 0; + let Mod = Process.findModuleByName(Name); + let Arm64Pattern = [ + "F? 0F 1C F8 F? 5? 01 A9 F? 5? 02 A9 F? ?? 03 A9 ?? ?? ?? ?? 68 1A 40 F9", + "F? 43 01 D1 FE 67 01 A9 F8 5F 02 A9 F6 57 03 A9 F4 4F 04 A9 13 00 40 F9 F4 03 00 AA 68 1A 40 F9", + "FF 43 01 D1 FE 67 01 A9 ?? ?? 06 94 ?? 7? 06 94 68 1A 40 F9 15 15 41 F9 B5 00 00 B4 B6 4A 40 F9"]; + //"FF C3 01 D1 F? 7B 01 A9 FC 6F 02 A9 FA 67 03 A9 F8 5F 04 A9 F6 57 05 ?9"] + let ArmPattern = ["2D E9 F? 4? D0 F8 00 80 81 46 D8 F8 18 00 D0 F8 ??"]; + let ranges = Mod.enumerateRanges('r-x'); + ranges.forEach(range => { + if (Arch == "arm64") { + Arm64Pattern.forEach(pattern => { + Memory.scan(range.base, range.size, pattern, { + onMatch: function(address, size) { + if (Hooked == 0) { + Hooked = 1; + hook_ssl_verify_peer_cert(address, address.sub(Mod.base), Name); + } + } + }); + }); + } else if (Arch == "arm") { + ArmPattern.forEach(pattern => { + Memory.scan(range.base, range.size, pattern, { + onMatch: function(address, size) { + if (Hooked == 0) { + Hooked = 1; + hook_ssl_verify_peer_cert(address, address.sub(Mod.base), Name); + } + } + }); + }); + } + }); +} + +function hook_ssl_verify_peer_cert(address, offset, Name) { + console.log("ssl_verify_peer_cert Patched at : ", Name, address, offset) + try { + Interceptor.replace(address, new NativeCallback((pathPtr, flags) => { + return 0; + }, 'int', ['pointer', 'int'])); + } catch (e) {} +} diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-pinning-bypass.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-pinning-bypass.js new file mode 100644 index 0000000000..42f380076c --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ssl-pinning-bypass.js @@ -0,0 +1,998 @@ +// Source: https://github.com/apkunpacker/FridaScripts +function disableFlutterPinningv2() { + var config = { + "ios": { + "modulename": "Flutter", + "patterns": { + "arm64": ["FF 83 01 D1 FA 67 01 A9 F8 5F 02 A9 F6 57 03 A9 F4 4F 04 A9 FD 7B 05 A9 FD 43 01 91 F? 03 00 AA ?? 0? 40 F9 ?8 1? 40 F9 15 ?? 4? F9 B5 00 00 B4", ], + }, + }, + "android": { + "modulename": "libflutter.so", + "patterns": { + "arm64": ["F? 0F 1C F8 F? 5? 01 A9 F? 5? 02 A9 F? ?? 03 A9 ?? ?? ?? ?? 68 1A 40 F9", "F? 43 01 D1 FE 67 01 A9 F8 5F 02 A9 F6 57 03 A9 F4 4F 04 A9 13 00 40 F9 F4 03 00 AA 68 1A 40 F9", "FF 43 01 D1 FE 67 01 A9 ?? ?? 06 94 ?? 7? 06 94 68 1A 40 F9 15 15 41 F9 B5 00 00 B4 B6 4A 40 F9", ], + "arm": ["2D E9 F? 4? D0 F8 00 80 81 46 D8 F8 18 00 D0 F8 ??", ], + "x64": ["55 41 57 41 56 41 55 41 54 53 50 49 89 f? 4c 8b 37 49 8b 46 30 4c 8b a? ?? 0? 00 00 4d 85 e? 74 1? 4d 8b", "55 41 57 41 56 41 55 41 54 53 48 83 EC 18 49 89 FF 48 8B 1F 48 8B 43 30 4C 8B A0 28 02 00 00 4D 85 E4 74"] + } + } + }; + var TLSValidationDisabled = false; + if (Java.available) { + console.log("[+] Java Environment Detected"); + Java.perform(hookSystemLoadLibrary); + } else if (ObjC.available) { + console.log("[+] iOS environment detected. Not Supported"); + } + disableTLSValidation(); + setTimeout(disableTLSValidation, 2000, true); + + function hookSystemLoadLibrary() { + const System = Java.use('java.lang.System'); + const Runtime = Java.use('java.lang.Runtime'); + const SystemLoad_2 = System.loadLibrary.overload('java.lang.String'); + const VMStack = Java.use('dalvik.system.VMStack'); + SystemLoad_2.implementation = function(library) { + try { + const loaded = Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), library); + if (library === 'flutter') { + console.log("[+] libflutter.so loaded"); + disableTLSValidation(); + } + return loaded; + } catch (ex) { + console.log(ex); + } + }; + } + + function disableTLSValidation(fallback = false) { + if (TLSValidationDisabled) return; + var platformConfig = config[Java.available ? "android" : "ios"]; + var m = Process.findModuleByName(platformConfig["modulename"]); + // If there is no loaded Flutter module, the setTimeout may trigger a second time, but after that we give up + if (m === null) { + if (fallback) { + } + return; + } + if (Process.arch in platformConfig["patterns"]) { + findAndPatch(m, platformConfig["patterns"][Process.arch], Java.available && Process.arch == "arm" ? 1 : 0, fallback); + } else { + console.log("[!] Processor architecture not supported: ", Process.arch); + } + if (!TLSValidationDisabled) { + if (fallback) { + if (m.enumerateRanges('r-x').length == 0) { + console.log('[!] No memory ranges found in Flutter library. This is either a Frida bug, or the application is using some kind of RASP.'); + } else { + console.log('[!] ssl_verify_peer_cert not found. Please open an issue at https://github.com/NVISOsecurity/disable-flutter-tls-verification/issues'); + } + } else { + console.log('[!] ssl_verify_peer_cert not found. Trying again...'); + } + } + } + + function findAndPatch(m, patterns, thumb, fallback) { + console.log("[+] Flutter library found"); + var ranges = m.enumerateRanges('r-x'); + ranges.forEach(range => { + patterns.forEach(pattern => { + Memory.scan(range.base, range.size, pattern, { + onMatch: function(address, size) { + console.log('[+] ssl_verify_peer_cert found at offset: 0x' + (address - m.base).toString(16)); + // TLSValidationDisabled = true; + hook_ssl_verify_peer_cert(address.add(thumb)); + } + }); + }); + }); + } + + function hook_ssl_verify_peer_cert(address) { + Interceptor.replace(address, new NativeCallback((pathPtr, flags) => { + return 0; + }, 'int', ['pointer', 'int'])); + } +} + +function hook_ssl_verify_result(address) { + Interceptor.attach(address, { + onEnter: function(args) { + console.log("Disabling SSL validation") + }, + onLeave: function(retval) { + console.log("Retval: " + retval) + retval.replace(0x1); + } + }); +} + +function disablePinning() { + try { + var m = Process.findModuleByName("libflutter.so"); + var pattern = "2d e9 f0 4f a3 b0 82 46 50 20 10 70" + var res = Memory.scan(m.base, m.size, pattern, { + onMatch: function(address, size) { + console.log('[+] ssl_verify_result found at: ' + address.toString()); + hook_ssl_verify_result(address.add(0x01)); + }, + onError: function(reason) { + console.log('[!] There was an error scanning memory'); + }, + onComplete: function() { + console.log("All done") + } + }); + } catch (e) { + console.warn("[*] This is Not A Flutter Based APP"); + } +} + +function CommonMethods() { + try { + const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); + HttpsURLConnection.setDefaultHostnameVerifier.implementation = function(hostnameVerifier) { + console.log('[*] Bypassing HttpsURLConnection (setDefaultHostnameVerifier)'); + }; + console.log('[+] HttpsURLConnection (setDefaultHostnameVerifier)'); + } catch (err) {} + try { + const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); + HttpsURLConnection.setSSLSocketFactory.implementation = function(SSLSocketFactory) { + console.log('[*] Bypassing HttpsURLConnection (setSSLSocketFactory)'); + }; + console.log('[+] HttpsURLConnection (setSSLSocketFactory)'); + } catch (err) {} + try { + const HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); + HttpsURLConnection.setHostnameVerifier.implementation = function(hostnameVerifier) { + console.log('[*] Bypassing HttpsURLConnection (setHostnameVerifier)'); + }; + console.log('[+] HttpsURLConnection (setHostnameVerifier)'); + } catch (err) {} + try { + const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); + const SSLContext = Java.use('javax.net.ssl.SSLContext'); + const TrustManager = Java.registerClass({ + name: 'incogbyte.bypass.test.TrustManager', + implements: [X509TrustManager], + methods: { + checkClientTrusted: function(chain, authType) {}, + checkServerTrusted: function(chain, authType) {}, + getAcceptedIssuers: function() { + return []; + } + } + }); + const TrustManagers = [TrustManager.$new()]; + const SSLContext_init = SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom'); + 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) {} + try { + const array_list = Java.use("java.util.ArrayList"); + const TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); + 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) {} + try { + 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); + }; + console.log('[+] OkHTTPv3 (list)'); + } catch (err) {} + try { + 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); + }; + console.log('[+] OkHTTPv3 (cert)'); + } catch (err) {} + try { + 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); + }; + console.log('[+] OkHTTPv3 (cert array)'); + } catch (err) {} + try { + const okhttp3_Activity_4 = Java.use('okhttp3.CertificatePinner'); + okhttp3_Activity_4['check$okhttp'].implementation = function(a, b) { + console.log('[*] Bypassing OkHTTPv3 ($okhttp): ' + a); + }; + console.log('[+] OkHTTPv3 ($okhttp)'); + } catch (err) {} + try { + 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) {} + try { + 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) {} + try { + 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) {} + 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) {} + 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) {} + 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) {} + 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) {} + 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) {} + try { + 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) {} + try { + 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) {} + try { + 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) {} + try { + 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) {} + try { + 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) {} + try { + 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) {} + 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) {} + 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) {} + 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) {} + 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) {} + try { + 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) {} + try { + 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 null; + }; + console.log('[+] Squareup CertificatePinner (list)'); + } catch (err) {} + try { + 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) {} + try { + 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) {} + try { + 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) {} + try { + 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) {} + 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(); + }; + console.log('[+] Apache Cordova WebViewClient'); + } catch (err) {} + 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); + }; + console.log('[+] Boye AbstractVerifier'); + } catch (err) {} +} + +function dynamicPatching() { + var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); + var SSLContext = Java.use('javax.net.ssl.SSLContext'); + var TrustManager = Java.registerClass({ + name: 'incogbyte.bypass.test.TrustManager', + implements: [X509TrustManager], + methods: { + checkClientTrusted: function(chain, authType) {}, + checkServerTrusted: function(chain, authType) {}, + getAcceptedIssuers: function() { + return []; + } + } + }); + try { + var 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 {1}: ' + a); + }; + } catch (err) {} + try { + var 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 {2}: ' + a); + }; + } catch (err) {} + try { + var 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 {3}: ' + a); + }; + } catch (err) {} + try { + var okhttp3_Activity_4 = Java.use('okhttp3.CertificatePinner'); + okhttp3_Activity_4.check$okhttp.overload('java.lang.String', 'kotlin.jvm.functions.Function0').implementation = function(a, b) { + console.log('[+] Bypassing OkHTTPv3 {4}: ' + a); + return; + }; + } catch (err) {} + try { + var 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 {1}: ' + a); + return true; + }; + } catch (err) {} + try { + var 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 {2}: ' + a); + return true; + }; + } catch (err) {} + try { + var trustkit_PinningTrustManager = Java.use('com.datatheorem.android.trustkit.pinning.PinningTrustManager'); + trustkit_PinningTrustManager.checkServerTrusted.overload('[Ljava.security.cert.X509Certificate;', 'java.lang.String').implementation = function(chain, authType) { + console.log('[+] Bypassing Trustkit {3}'); + }; + } catch (err) {} + try { + var array_list = Java.use("java.util.ArrayList"); + var TrustManagerImpl_Activity_1 = Java.use('com.android.org.conscrypt.TrustManagerImpl'); + TrustManagerImpl_Activity_1.checkTrustedRecursive.implementation = function(certs, ocspData, tlsSctData, host, clientAuth, untrustedChain, trustAnchorChain, used) { + console.log('[+] Bypassing TrustManagerImpl (Android > 7) checkTrustedRecursive check: ' + host); + return array_list.$new(); + }; + } catch (err) {} + try { + var TrustManagerImpl_Activity_2 = Java.use('com.android.org.conscrypt.TrustManagerImpl'); + TrustManagerImpl_Activity_2.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { + console.log('[+] Bypassing TrustManagerImpl (Android > 7) verifyChain check: ' + host); + return untrustedChain; + }; + } catch (err) {} + try { + var appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager'); + appcelerator_PinningTrustManager.checkServerTrusted.implementation = function(chain, authType) { + console.log('[+] Bypassing Appcelerator PinningTrustManager'); + return; + }; + } catch (err) {} + try { + var fabric_PinningTrustManager = Java.use('io.fabric.sdk.android.services.network.PinningTrustManager'); + fabric_PinningTrustManager.checkServerTrusted.implementation = function(chain, authType) { + console.log('[+] Bypassing Fabric PinningTrustManager'); + return; + }; + } catch (err) {} + try { + var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); + OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, JavaObject, authMethod) { + console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt {1}'); + }; + } catch (err) {} + try { + var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); + OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certChain, authMethod) { + console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt {2}'); + }; + } catch (err) {} + try { + var 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); + }; + } catch (err) {} + try { + var OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl'); + OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function(asn1DerEncodedCertificateChain, authMethod) { + console.log('[+] Bypassing OpenSSLSocketImpl Apache Harmony'); + }; + } catch (err) {} + try { + var 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; + }; + } catch (err) {} + try { + var 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 {1}: ' + cert); + return; + }; + } catch (err) {} + try { + var 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 {2}: ' + cert); + return; + }; + } catch (err) {} + try { + var 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 {1}: ' + a); + return; + }; + } catch (err) {} + try { + var 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 {2}: ' + a); + return; + }; + } catch (err) {} + try { + var 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 {3}: ' + a); + return; + }; + } catch (err) {} + try { + var 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 {4}: ' + a); + return true; + }; + } catch (err) {} + try { + var conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager'); + conscrypt_CertPinManager_Activity.checkChainPinning.overload('java.lang.String', 'java.util.List').implementation = function(a, b) { + console.log('[+] Bypassing Conscrypt CertPinManager: ' + a); + return true; + }; + } catch (err) {} + try { + var legacy_conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager'); + legacy_conscrypt_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function(a, b) { + console.log('[+] Bypassing Conscrypt CertPinManager (Legacy): ' + a); + return true; + }; + } catch (err) {} + try { + var 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; + }; + } catch (err) {} + try { + var 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; + }; + } catch (err) {} + try { + var netty_FingerprintTrustManagerFactory = Java.use('io.netty.handler.ssl.util.FingerprintTrustManagerFactory'); + //var netty_FingerprintTrustManagerFactory = Java.use('org.jboss.netty.handler.ssl.util.FingerprintTrustManagerFactory'); + netty_FingerprintTrustManagerFactory.checkTrusted.implementation = function(type, chain) { + console.log('[+] Bypassing Netty FingerprintTrustManagerFactory'); + }; + } catch (err) {} + try { + var 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 {1}: ' + a); + return; + }; + } catch (err) {} + try { + var 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 {2}: ' + a); + return; + }; + } catch (err) {} + try { + var 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 {1}: ' + a); + return true; + }; + } catch (err) {} + try { + var 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 {2}: ' + a); + return true; + }; + } catch (err) {} + try { + var 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 check {1}'); + }; + } catch (err) {} + try { + var 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 check {2}'); + }; + } catch (err) {} + try { + var AndroidWebViewClient_Activity_3 = Java.use('android.webkit.WebViewClient'); + AndroidWebViewClient_Activity_3.onReceivedError.overload('android.webkit.WebView', 'int', 'java.lang.String', 'java.lang.String').implementation = function(obj1, obj2, obj3, obj4) { + console.log('[+] Bypassing Android WebViewClient check {3}'); + }; + } catch (err) {} + try { + var AndroidWebViewClient_Activity_4 = Java.use('android.webkit.WebViewClient'); + AndroidWebViewClient_Activity_4.onReceivedError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function(obj1, obj2, obj3) { + console.log('[+] Bypassing Android WebViewClient check {4}'); + }; + } catch (err) {} + try { + var 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 check'); + obj3.proceed(); + }; + } catch (err) {} + try { + var boye_AbstractVerifier = Java.use('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier'); + boye_AbstractVerifier.verify.implementation = function(host, ssl) { + console.log('[+] Bypassing Boye AbstractVerifier check: ' + host); + }; + } catch (err) {} + try { + var apache_AbstractVerifier = Java.use('org.apache.http.conn.ssl.AbstractVerifier'); + apache_AbstractVerifier.verify.implementation = function(a, b, c, d) { + console.log('[+] Bypassing Apache AbstractVerifier check: ' + a); + return; + }; + } catch (err) {} + try { + var CronetEngineBuilderImpl_Activity = Java.use("org.chromium.net.impl.CronetEngineBuilderImpl"); + CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.overload('boolean').implementation = function(a) { + console.log("[+] Disabling Public Key pinning for local trust anchors in Chromium Cronet"); + var cronet_obj_1 = CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true); + return cronet_obj_1; + }; + CronetEngine_Activity.addPublicKeyPins.overload('java.lang.String', 'java.util.Set', 'boolean', 'java.util.Date').implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) { + console.log("[+] Bypassing Chromium Cronet pinner: " + hostName); + var cronet_obj_2 = CronetEngine_Activity.addPublicKeyPins.call(this, hostName, pinsSha256, includeSubdomains, expirationDate); + return cronet_obj_2; + }; + } catch (err) {} + try { + var HttpCertificatePinning_Activity = Java.use('diefferson.http_certificate_pinning.HttpCertificatePinning'); + HttpCertificatePinning_Activity.checkConnexion.overload("java.lang.String", "java.util.List", "java.util.Map", "int", "java.lang.String").implementation = function(a, b, c, d, e) { + console.log('[+] Bypassing Flutter HttpCertificatePinning : ' + a); + return true; + }; + } catch (err) {} + try { + var SslPinningPlugin_Activity = Java.use('com.macif.plugin.sslpinningplugin.SslPinningPlugin'); + SslPinningPlugin_Activity.checkConnexion.overload("java.lang.String", "java.util.List", "java.util.Map", "int", "java.lang.String").implementation = function(a, b, c, d, e) { + console.log('[+] Bypassing Flutter SslPinningPlugin: ' + a); + return true; + }; + } catch (err) {} + + function rudimentaryFix(typeName) { + if (typeName === undefined) { + return; + } else if (typeName === 'boolean') { + return true; + } else { + return null; + } + } + try { + var UnverifiedCertError = Java.use('javax.net.ssl.SSLPeerUnverifiedException'); + UnverifiedCertError.$init.implementation = function(str) { + console.log('[!] Unexpected SSLPeerUnverifiedException occurred, trying to patch it dynamically...!'); + try { + var stackTrace = Java.use('java.lang.Thread').currentThread().getStackTrace(); + var exceptionStackIndex = stackTrace.findIndex(stack => stack.getClassName() === "javax.net.ssl.SSLPeerUnverifiedException"); + var callingFunctionStack = stackTrace[exceptionStackIndex + 1]; + var className = callingFunctionStack.getClassName(); + var methodName = callingFunctionStack.getMethodName(); + var callingClass = Java.use(className); + var callingMethod = callingClass[methodName]; + console.log('[!] Attempting to bypass uncommon SSL Pinning method on: ' + className + '.' + methodName + '!'); + if (callingMethod.implementation) { + return; + } + var returnTypeName = callingMethod.returnType.type; + callingMethod.implementation = function() { + rudimentaryFix(returnTypeName); + }; + } catch (e) { + if (String(e).includes(".overload")) { + var splittedList = String(e).split(".overload"); + for (let i = 2; i < splittedList.length; i++) { + var extractedOverload = splittedList[i].trim().split("(")[1].slice(0, -1).replaceAll("'", ""); + if (extractedOverload.includes(",")) { + var argList = extractedOverload.split(", "); + console.log('[!] Attempting overload of ' + className + '.' + methodName + ' with arguments: ' + extractedOverload + '!'); + if (argList.length == 2) { + callingMethod.overload(argList[0], argList[1]).implementation = function(a, b) { + rudimentaryFix(returnTypeName); + } + } else if (argNum == 3) { + callingMethod.overload(argList[0], argList[1], argList[2]).implementation = function(a, b, c) { + rudimentaryFix(returnTypeName); + } + } else if (argNum == 4) { + callingMethod.overload(argList[0], argList[1], argList[2], argList[3]).implementation = function(a, b, c, d) { + rudimentaryFix(returnTypeName); + } + } else if (argNum == 5) { + callingMethod.overload(argList[0], argList[1], argList[2], argList[3], argList[4]).implementation = function(a, b, c, d, e) { + rudimentaryFix(returnTypeName); + } + } else if (argNum == 6) { + callingMethod.overload(argList[0], argList[1], argList[2], argList[3], argList[4], argList[5]).implementation = function(a, b, c, d, e, f) { + rudimentaryFix(returnTypeName); + } + } + } else { + callingMethod.overload(extractedOverload).implementation = function(a) { + rudimentaryFix(returnTypeName); + } + } + } + } else { + console.log('[-] Failed to dynamically patch SSLPeerUnverifiedException ' + e + '!'); + } + } + return this.$init(str); + }; + } catch (err) {} +} +setTimeout(function() { + Java.perform(function() { + var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); + var SSLContext = Java.use('javax.net.ssl.SSLContext'); + var TrustManager = Java.registerClass({ + name: 'incogbyte.bypass.test.TrustManager', + implements: [X509TrustManager], + methods: { + checkClientTrusted: function(chain, authType) {}, + checkServerTrusted: function(chain, authType) {}, + getAcceptedIssuers: function() { + return []; + } + } + }); + setTimeout(disablePinning, 1000); + disableFlutterPinningv2(); + dynamicPatching(); + CommonMethods(); + try { + var okhttp3_Activity = Java.use('okhttp3.CertificatePinner'); + okhttp3_Activity.check.overload('java.lang.String', 'java.util.List').implementation = function(str) { + console.log('[+] Bypassing OkHTTPv3 {1}: ' + str); + }; + okhttp3_Activity.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function(str) { + console.log('[+] Bypassing OkHTTPv3 {2}: ' + str); + }; + } catch (err) {} + try { + var trustkit_Activity = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier'); + trustkit_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(str) { + console.log('[+] Bypassing Trustkit {1}: ' + str); + return true; + }; + trustkit_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(str) { + console.log('[+] Bypassing Trustkit {2}: ' + str); + return true; + }; + var trustkit_PinningTrustManager = Java.use('com.datatheorem.android.trustkit.pinning.PinningTrustManager'); + trustkit_PinningTrustManager.checkServerTrusted.implementation = function() { + console.log('[+] Bypassing Trustkit {3}'); + }; + } catch (err) {} + try { + var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); + TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { + console.log('[+] Bypassing TrustManagerImpl (Android > 7): ' + host); + return untrustedChain; + }; + } catch (err) {} + try { + var appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager'); + appcelerator_PinningTrustManager.checkServerTrusted.implementation = function() { + console.log('[+] Bypassing Appcelerator PinningTrustManager'); + }; + } catch (err) {} + try { + var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); + OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, JavaObject, authMethod) { + console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt'); + }; + } catch (err) {} + try { + var OpenSSLEngineSocketImpl_Activity = Java.use('com.android.org.conscrypt.OpenSSLEngineSocketImpl'); + OpenSSLSocketImpl_Activity.verifyCertificateChain.overload('[Ljava.lang.Long;', 'java.lang.String').implementation = function(str1, str2) { + console.log('[+] Bypassing OpenSSLEngineSocketImpl Conscrypt: ' + str2); + }; + } catch (err) {} + try { + var OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl'); + OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function(asn1DerEncodedCertificateChain, authMethod) { + console.log('[+] Bypassing OpenSSLSocketImpl Apache Harmony'); + }; + } catch (err) {} + try { + var phonegap_Activity = Java.use('nl.xservices.plugins.sslCertificateChecker'); + phonegap_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function(str) { + console.log('[+] Bypassing PhoneGap sslCertificateChecker: ' + str); + return true; + }; + } catch (err) {} + try { + var WLClient_Activity = Java.use('com.worklight.wlclient.api.WLClient'); + WLClient_Activity.getInstance().pinTrustedCertificatePublicKey.overload('java.lang.String').implementation = function(cert) { + console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {1}: ' + cert); + return; + }; + WLClient_Activity.getInstance().pinTrustedCertificatePublicKey.overload('[Ljava.lang.String;').implementation = function(cert) { + console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {2}: ' + cert); + return; + }; + } catch (err) {} + try { + var worklight_Activity = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning'); + worklight_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSocket').implementation = function(str) { + console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ' + str); + return; + }; + worklight_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(str) { + console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ' + str); + return; + }; + worklight_Activity.verify.overload('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;').implementation = function(str) { + console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ' + str); + return; + }; + worklight_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(str) { + console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ' + str); + return true; + }; + } catch (err) {} + try { + var conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager'); + conscrypt_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function(str) { + console.log('[+] Bypassing Conscrypt CertPinManager: ' + str); + return true; + }; + } catch (err) {} + try { + var cwac_CertPinManager_Activity = Java.use('com.commonsware.cwac.netsecurity.conscrypt.CertPinManager'); + cwac_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function(str) { + console.log('[+] Bypassing CWAC-Netsecurity CertPinManager: ' + str); + return true; + }; + } catch (err) {} + try { + var 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(str) { + console.log('[+] Bypassing Worklight Androidgap WLCertificatePinningPlugin: ' + str); + return true; + }; + } catch (err) {} + try { + var Squareup_CertificatePinner_Activity = Java.use('com.squareup.okhttp.CertificatePinner'); + Squareup_CertificatePinner_Activity.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function(str1, str2) { + console.log('[+] Bypassing Squareup CertificatePinner {1}: ' + str1); + return; + }; + Squareup_CertificatePinner_Activity.check.overload('java.lang.String', 'java.util.List').implementation = function(str1, str2) { + console.log('[+] Bypassing Squareup CertificatePinner {2}: ' + str1); + return; + }; + } catch (err) {} + try { + var Squareup_OkHostnameVerifier_Activity = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier'); + Squareup_OkHostnameVerifier_Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(str1, str2) { + console.log('[+] Bypassing Squareup OkHostnameVerifier {1}: ' + str1); + return true; + }; + Squareup_OkHostnameVerifier_Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(str1, str2) { + console.log('[+] Bypassing Squareup OkHostnameVerifier {2}: ' + str1); + return true; + }; + } catch (err) {} + try { + var AndroidWebViewClient_Activity = Java.use('android.webkit.WebViewClient'); + AndroidWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function(obj1, obj2, obj3) { + console.log('[+] Bypassing Android WebViewClient'); + }; + } catch (err) {} + try { + var 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) {} + try { + var 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) {} + var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl"); + try { + TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { + console.log("[+] TrustManagerImpl verifyChain called"); + return untrustedChain; + } + } catch (e) {} + try { + var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); + OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, authMethod) { + console.log(' OpenSSLSocketImpl.verifyCertificateChain'); + } + console.log('[+] OpenSSLSocketImpl pinning') + } catch (err) {} + try { + var Activity = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier"); + Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(str) { + console.log(' Trustkit.verify1: ' + str); + return true; + }; + Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(str) { + console.log(' Trustkit.verify2: ' + str); + return true; + }; + console.log('[+] Trustkit pinning') + } catch (err) {} + try { + var netBuilder = Java.use("org.chromium.net.CronetEngine$Builder"); + netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.implementation = function(arg) { + console.log(" Enables or disables public key pinning bypass for local trust anchors = " + arg); + var ret = netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true); + return ret; + }; + netBuilder.addPublicKeyPins.implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) { + console.log("[+] Сronet addPublicKeyPins hostName = " + hostName); + return this; + }; + } catch (err) {} + }); +}, 0); diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/stop-app-terminate.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/stop-app-terminate.js new file mode 100644 index 0000000000..c38ada2fa3 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/stop-app-terminate.js @@ -0,0 +1,203 @@ +/* +Made By @ApkUnpacker +Source: https://github.com/apkunpacker/FridaScripts +*/ +var GlobalLogs = false; +Java.perform(function() { + try { + var Installer = Java.use("android.app.ApplicationPackageManager"); + Installer.getInstallerPackageName.overload('java.lang.String').implementation = function(Str) { + console.log("Installer Name Fixed"); + if (GlobalLogs) { + ShowLogs(); + } + return "com.android.vending"; + } + var Installer2 = Java.use("android.content.pm.PackageManager"); + Installer2.getInstallerPackageName.overload('java.lang.String').implementation = function(Str) { + console.error("Installer Name Fixed 2"); + if (GlobalLogs) { + ShowLogs(); + } + return "com.android.vending"; + } + var system = Java.use("java.lang.System"); + system.exit.overload("int").implementation = function(var0) { + console.warn("[*] Exit Called"); + if (GlobalLogs) { + ShowLogs(); + } + } + Java.choose("android.app.Activity", { + onMatch: function(instance) { + instance.onDestroy.overload().implementation = function() { + console.log("[*] onDestroy() Called"); + } + }, + onComplete: function(retval) {} + }); + var act = Java.use("android.app.Activity"); + act.finish.overload().implementation = function() { + console.log("[*] Finish() Called"); + if (GlobalLogs) { + ShowLogs(); + } + } + var secure = Java.use("android.provider.Settings$Secure"); + secure.getInt.overload("android.content.ContentResolver", "java.lang.String", "int").implementation = function(str1, str2, str3) { + if (str2.indexOf("development_settings_enabled") >= 0 || str2.indexOf("adb_enabled") >= 0) { + var fix = "bypass"; + console.log("Developer Mode & ADB Checked "); + return this.getInt.call(this, str1, fix, str3); + } else return this.getInt.call(this, str1, str2, str3); + } + var act = Java.use("android.os.Process"); + act.myPid.overload().implementation = function() { + console.log("[*] Mypid() = ", this.myPid()); + return this.myPid(); + } + var Debugger = Java.use("android.os.Debug"); + Debugger.isDebuggerConnected.overload().implementation = function() { + console.log("[*] isDebuggerConnected() Called"); + return false; + } + var ss = Java.use("android.app.Service"); + ss.stopSelf.overload().implementation = function() { + console.log("[*] stopSelf() called "); + } + var Verify = Java.use("java.security.Signature"); + Verify.verify.overload("[B").implementation = function() { + console.warn("[*] Core Verify() called "); + return true; + } + var MD = Java.use("java.security.MessageDigest"); + MD.isEqual.overload("[B", "[B").implementation = function() { + console.log("[*] MD isEqual() called "); + return true; + } + var Pm = Java.use("android.content.pm.PackageManager"); + Pm.getPackageInfo.overload("java.lang.String", "int").implementation = function(pkg, flag) { + console.warn("getPackageInfo() with package", pkg, " and flag ", flag); + return this.getPackageInfo.overload("java.lang.String", "int").call(this, pkg, flag); + } + var act = Java.use("android.app.Activity"); + act.finishActivity.overload('int').implementation = function(arg) { + console.log("FinishActivity():-->>" + arg); + console.log("[*] FinishActivity() Called"); + } + var Proc = Java.use("android.os.Process"); + Proc.killProcess.overload('int').implementation = function(arg) { + console.log("KillProcess():-->>" + arg); + console.log("[*] KillProcess() Called"); + if (GlobalLogs) { + ShowLogs(); + } + } + var AR = Java.use("android.app.Activity"); + AR.onActivityResult.overload('int', 'int', 'android.content.Intent').implementation = function(a, b, c) { + console.log("onActivityResult():-->>" + a + " " + b + " " + c); + console.log("[*] onActivityResult() Called"); + } + var FinishAffinity = Java.use("android.app.Activity"); + FinishAffinity.finishAffinity.overload().implementation = function() { + console.log("[*] finishAffinity() Called"); + } + var FinishAndRemoveTask = Java.use("android.app.Activity"); + FinishAndRemoveTask.finishAndRemoveTask.overload().implementation = function() { + console.log("[*] FinishAndRemoveTask() Called"); + } + var StartActivity = Java.use("android.app.Activity"); + StartActivity.startActivity.overload("android.content.Intent").implementation = function(intent) { + console.warn("[*] startActivity() Called with " + intent); + if (GlobalLogs) { + ShowLogs(); + } + return this.startActivity(intent); + } + var ifinish = Java.use("android.app.Activity"); + ifinish.isFinishing.overload().implementation = function() { + var ret = this.isFinishing(); + console.log("[*] isFinishing() Called"); + return this.isFinishing(); + } + + function ShowLogs() { + Java.perform(function() { + var jAndroidLog = Java.use("android.util.Log"), + jException = Java.use("java.lang.Exception"); + console.warn("##########\n", jAndroidLog.getStackTraceString(jException.$new()), "##########\n"); + }); + } + } catch (e) { + console.error(e); + } +}) +Interceptor.attach(Module.findExportByName(null, "exit"), { + onEnter: function(args) { + console.warn("Native Exit() Called :-->:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n") + "\n"); + }, + onLeave: function(retval) {} +}); +Interceptor.attach(Module.findExportByName(null, "abort"), { + onEnter: function(args) { + console.warn("Native Abort() Called :-->:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n") + "\n"); + }, + onLeave: function(retval) {} +}); +var fork = Module.findExportByName(null, "fork") +Interceptor.attach(fork, { + onEnter: function(args) {}, + onLeave: function(retval) { + var pid = parseInt(retval.toString(16), 16) + console.log("Second Process PID : ", pid) + } +}) +Interceptor.attach(Module.findExportByName("libc.so", "system"), { + onEnter: function(args) { + var cmd = Memory.readCString(args[0]); + if (cmd.indexOf("kill") != -1) { + console.log("Bypass native system: " + cmd); + var NewKill = args[0].writeUtf8String("bypassed"); + args[0] = ptr(NewKill); + } + }, + onLeave: function(retval) {} +}); + + var abortPtr = Module.getExportByName('libc.so', 'abort'); + var abort = new NativeFunction(abortPtr, 'int', ['int']); + var exitPtr = Module.getExportByName('libc.so', 'exit'); + var exit = new NativeFunction(exitPtr, 'int', ['int']); + var _exitPtr = Module.getExportByName('libc.so', '_exit'); + var _exit = new NativeFunction(_exitPtr, 'int', ['int']); + var killPtr = Module.getExportByName('libc.so', 'kill'); + var kill = new NativeFunction(killPtr, 'int', ['int', 'int']); + var raisePtr = Module.getExportByName('libc.so', 'raise'); + var raise = new NativeFunction(raisePtr, 'int', ['int']); + var shutdownPtr = Module.getExportByName('libc.so', 'shutdown'); + var shutdown = new NativeFunction(shutdownPtr, 'int', ['int', 'int']); + Interceptor.replace(abortPtr, new NativeCallback(function(status) { + console.log('Abort Replaced'); + return 0; + }, 'int', ['int'])); + Interceptor.replace(exitPtr, new NativeCallback(function(status) { + console.log('Exit Replaced'); + return 0; + }, 'int', ['int'])); + Interceptor.replace(_exitPtr, new NativeCallback(function(status) { + console.log('_exit Replaced'); + return 0; + }, 'int', ['int'])); + Interceptor.replace(killPtr, new NativeCallback(function(pid, sig) { + console.log('Kill Replaced'); + return 0; + }, 'int', ['int', 'int'])); + Interceptor.replace(raisePtr, new NativeCallback(function(sig) { + console.log('Raise Replaced'); + return 0; + }, 'int', ['int'])); + Interceptor.replace(shutdownPtr, new NativeCallback(function(fd, how) { + console.log('Shutdown Replaced'); + return 0; + }, 'int', ['int', 'int'])); + diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-bluetooth.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-bluetooth.js new file mode 100644 index 0000000000..849719e1fb --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-bluetooth.js @@ -0,0 +1,69 @@ + +/* + Credit: optiv + Link: + https://github.com/optiv/blemon +*/ + +var Color = +{ + Reset: "\x1b[39;49;00m", + Black: "\x1b[30;01m", Blue: "\x1b[34;01m", Cyan: "\x1b[36;01m", Gray: "\x1b[37;11m", + Green: "\x1b[32;01m", Purple: "\x1b[35;01m", Red: "\x1b[31;01m", Yellow: "\x1b[33;01m", + Light: + { + Black: "\x1b[30;11m", Blue: "\x1b[34;11m", Cyan: "\x1b[36;11m", Gray: "\x1b[37;01m", + Green: "\x1b[32;11m", Purple: "\x1b[35;11m", Red: "\x1b[31;11m", Yellow: "\x1b[33;11m" + } +}; + +// thanks: https://awakened1712.github.io/hacking/hacking-frida/ +function bytes2hex(array) +{ + var result = ''; + for (var i = 0; i < array.length; ++i) + result += ('0' + (array[i] & 0xFF).toString(16)).slice(-2); + return result; +}; + + +Java.perform(function () +{ + var BTGattCB = Java.use("android.bluetooth.BluetoothGattCallback"); + // https://github.com/frida/frida/issues/310#issuecomment-462447292 + + BTGattCB.$init.overload().implementation = function () + { + console.log("[+] BluetoothGattCallback constructor called from " + this.$className); + const NewCB = Java.use(this.$className); + + NewCB.onCharacteristicRead.implementation = function (g, c, s) + { + const retVal = NewCB.onCharacteristicRead.call(this, g, c, s); + var uuid = c.getUuid(); + console.log(Color.Blue + "[BLE Read <=]" + Color.Light.Black + " UUID: " + uuid.toString() + Color.Reset + " data: 0x" + bytes2hex(c.getValue())); + return retVal; + }; + + NewCB.onCharacteristicWrite.implementation = function (g, c, s) + { + const retVal = NewCB.onCharacteristicWrite.call(this, g, c, s); + var uuid = c.getUuid(); + console.log(Color.Green + "[BLE Write =>]" + Color.Light.Black + " UUID: " + uuid.toString() + Color.Reset + " data: 0x" + bytes2hex(c.getValue())); + return retVal; + }; + + NewCB.onCharacteristicChanged.implementation = function (g, c) + { + const retVal = NewCB.onCharacteristicChanged.call(this, g, c); + var uuid = c.getUuid(); + console.log(Color.Cyan + "[BLE Notify <=]" + Color.Light.Black + " UUID: " + uuid.toString() + Color.Reset + " data: 0x" + bytes2hex(c.getValue())); + return retVal; + }; + + return this.$init(); + }; + +}); // end perform + + diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-shared-preference.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-shared-preference.js new file mode 100644 index 0000000000..5fcd4826b5 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/trace-shared-preference.js @@ -0,0 +1,102 @@ +/************************************************************************ + * Name: SharedPreferences Monitor + * OS: Android + * Author: @mobilesecurity_ + * Source: https://github.com/m0bilesecurity + * Info: + * android.app.SharedPreferencesImpl + * android.app.SharedPreferencesImpl$EditorImpl +*************************************************************************/ + +Java.perform(function () { + var SharedPreferencesImpl = Java.use("android.app.SharedPreferencesImpl"); + var SharedPreferencesImpl_EditorImpl = Java.use("android.app.SharedPreferencesImpl$EditorImpl"); + + SharedPreferencesImpl.contains.implementation = function (key) { + var value = this.contains.apply(this, arguments); + print("contains",key,value); + return value; + }; + + SharedPreferencesImpl.getInt.implementation = function (key, defValue) { + var value = this.getInt.apply(this, arguments); + print("getInt",key,value); + return value; + }; + + SharedPreferencesImpl.getFloat.implementation = function (key, defValue) { + var value = this.getFloat.apply(this, arguments); + print("getFloat",key,value); + return value; + }; + + SharedPreferencesImpl.getLong.implementation = function (key, defValue) { + var value = this.getLong.apply(this, arguments); + print("getLong",key,value); + return value; + }; + + SharedPreferencesImpl.getBoolean.implementation = function (key, defValue) { + var value = this.getBoolean.apply(this, arguments); + print("getBoolean",key,value); + return value; + }; + + SharedPreferencesImpl.getString.implementation = function (key, defValue) { + var value = this.getString.apply(this, arguments); + print("getString",key,value); + return value; + }; + + SharedPreferencesImpl.getStringSet.implementation = function (key, defValue) { + var value = this.getStringSet.apply(this, arguments); + print("getStringSet",key,value); + return value; + }; + + SharedPreferencesImpl_EditorImpl.putString.implementation = function (key, value) { + print("putString",key,value); + return this.putString.apply(this, arguments); + }; + + SharedPreferencesImpl_EditorImpl.putStringSet.implementation = function (key, values) { + print("putStringSet",key,values); + return this.putStringSet.apply(this, arguments); + }; + + SharedPreferencesImpl_EditorImpl.putInt.implementation = function (key, value) { + print("putInt",key,value); + return this.putInt.apply(this, arguments); + }; + + SharedPreferencesImpl_EditorImpl.putFloat.implementation = function (key, value) { + print("putFloat",key,value); + return this.putFloat.apply(this, arguments); + }; + + SharedPreferencesImpl_EditorImpl.putBoolean.implementation = function (key, value) { + print("putBoolean",key,value); + return this.putBoolean.apply(this, arguments); + }; + + SharedPreferencesImpl_EditorImpl.putLong.implementation = function (key, value) { + print("putLong",key,value); + return this.putLong.apply(this, arguments); + }; + + SharedPreferencesImpl_EditorImpl.remove.implementation = function (key) { + print("remove",key,""); + return this.remove.apply(this, arguments); + }; + + function print(method,key,value){ + var mkey = key ? key.toString() : 'null'; + var mvalue = value ? value.toString() : 'null'; + + send("API Monitor | "+ + "SharedPreferences" + " | " + + method + " - " + + "(" + mkey + ":" + mvalue + ")" + ); + } + }); \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-deeplink-trace.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-deeplink-trace.js new file mode 100644 index 0000000000..c5808ac864 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-deeplink-trace.js @@ -0,0 +1,24 @@ +// Source: https://codeshare.frida.re/@leolashkevych/android-deep-link-observer/ +Java.perform(function() { + var Intent = Java.use("android.content.Intent"); + Intent.getData.implementation = function() { + var action = this.getAction() !== null ? this.getAction().toString() : false; + if (action) { + console.log("[*] Intent.getData() was called"); + console.log("[*] Activity: " + this.getComponent().getClassName()); + console.log("[*] Action: " + action); + var uri = this.getData(); + if (uri !== null) { + console.log("\n[*] Data"); + uri.getScheme() && console.log("- Scheme:\t" + uri.getScheme() + "://"); + uri.getHost() && console.log("- Host:\t\t/" + uri.getHost()); + uri.getQuery() && console.log("- Params:\t" + uri.getQuery()); + uri.getFragment() && console.log("- Fragment:\t" + uri.getFragment()); + console.log("\n\n"); + } else { + console.log("[-] No data supplied."); + } + } + return this.getData(); + } +}); \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-bypass-flag-secure.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-flag-secure-bypass.js similarity index 100% rename from mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-bypass-flag-secure.js rename to mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/ui-flag-secure-bypass.js diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-flutter-ssl.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-ssl-flutter.js similarity index 100% rename from mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-flutter-ssl.js rename to mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-ssl-flutter.js diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-ssl-trustkit.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-ssl-trustkit.js new file mode 100644 index 0000000000..30b651139a --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/bypass-ssl-trustkit.js @@ -0,0 +1,33 @@ +/* + Description: iOS TrustKit Certificate Pinning ByPass + Usage: frida -U -f XXX -l ios-trustkit-pinning-bypass.js + Credit: Unknown + Src: https://github.com/rsenet/FriList/blob/main/02_SecurityBypass/CertificatePinning/ios-trustkit-pinning-bypass.js +*/ + +if (ObjC.available) +{ + console.log("SSLUnPinning Enabled"); + + for (var className in ObjC.classes) + { + if (ObjC.classes.hasOwnProperty(className)) + { + if (className == "TrustKit") + { + console.log("Found our target class : " + className); + var hook = ObjC.classes.TrustKit["+ initSharedInstanceWithConfiguration:"]; + + Interceptor.replace(hook.implementation, new NativeCallback(function() + { + console.log("Hooking TrustKit"); + return; + }, 'int', [])); + } + } + } +} +else +{ + console.log("Objective-C Runtime is not available!"); +} \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-change-system-version.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-change-system-version.js new file mode 100644 index 0000000000..24e79a9c88 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-change-system-version.js @@ -0,0 +1,45 @@ +/* + Description: iOS System Version changer frida script + Credit: rsenet + Src: https://github.com/rsenet/FriList/blob/main/02_SecurityBypass/ios-change-system-version.js + https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion +*/ + +if (ObjC.available) +{ + try + { + var desiredVersion = "16.0"; + var className = "UIDevice"; + var funcName = "- systemVersion"; + + var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]'); + + Interceptor.attach(hook.implementation, + { + onLeave: function(returnvalue) + { + // Display + console.log('Return Value Object (Original): ' + typeof returnvalue + ' | value: ' + returnvalue); + console.log('Intial System Version: ' + ObjC.Object(returnvalue).toString()); + //console.log(ObjC.Object(returnvalue).$className) + + // Change value + var new_version = ObjC.classes.NSString.stringWithString_(desiredVersion); + returnvalue.replace(new_version) + + // New display + console.log('New System Version: ' + ObjC.Object(new_version).toString()); + console.log("") + } + }); + } + catch(error) + { + console.log("[!] Exception: " + error.message); + } +} +else +{ + console.log("Objective-C Runtime is not available!"); +} \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-spoof-gps.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-spoof-gps.js new file mode 100644 index 0000000000..717d1f7b5b --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-ios-spoof-gps.js @@ -0,0 +1,23 @@ +/* + Description: iOS GPS Location Spoofing + Credit: Divya Mudgal + + Src: https://github.com/rsenet/FriList/blob/main/02_SecurityBypass/Location/ios-location-spoofing.js + Link: + https://developer.apple.com/documentation/corelocation/cllocation +*/ + +function spoof_location(spoof_latitude, spoof_longitude) +{ + var hook_cllocation = ObjC.classes["CLLocation"]["- coordinate"] + + Interceptor.attach(hook_cllocation.implementation, { + onLeave: function(return_value) + { + var spoofed_return_value = (new ObjC.Object(return_value)).initWithLatitude_longitude_(spoof_latitude, spoof_longitude) + return_value.replace(spoofed_return_value) + } + }); +} + +spoof_location(10.0000000,10.0000000) \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/trace-bluetooth.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/trace-bluetooth.js new file mode 100644 index 0000000000..af91841d9d --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/trace-bluetooth.js @@ -0,0 +1,68 @@ +/* + Credit: optiv + + Link: + https://github.com/optiv/blemon +*/ + +var Color = +{ + Reset: "\x1b[39;49;00m", + Black: "\x1b[30;01m", Blue: "\x1b[34;01m", Cyan: "\x1b[36;01m", Gray: "\x1b[37;11m", + Green: "\x1b[32;01m", Purple: "\x1b[35;01m", Red: "\x1b[31;01m", Yellow: "\x1b[33;01m", + Light: + { + Black: "\x1b[30;11m", Blue: "\x1b[34;11m", Cyan: "\x1b[36;11m", Gray: "\x1b[37;01m", + Green: "\x1b[32;11m", Purple: "\x1b[35;11m", Red: "\x1b[31;11m", Yellow: "\x1b[33;11m" + } +}; + +function pad(num, size) +{ + var s = num + ""; + while (s.length < size) s = "0" + s; + return s; +} + + +Interceptor.attach(ObjC.classes.CBPeripheral['- writeValue:forCharacteristic:type:'].implementation, +{ + onEnter: function (args) + { + var data = new ObjC.Object(args[2]); + var CBChar = new ObjC.Object(args[3]); + var dataBytes = Memory.readByteArray(data.bytes(), data.length()); + var b = new Uint8Array(dataBytes); + var hexData = ""; + + for (var i = 0; i < b.length; i++) + { + hexData += pad(b[i].toString(16), 2); + } + console.log(Color.Green + "[BLE Write =>]" + Color.Light.Black + " UUID: " + CBChar.$ivars['_UUID'] + Color.Reset + " data: 0x" + hexData); + } +}); //end Interceptor + +Interceptor.attach(ObjC.classes.CBCharacteristic['- value'].implementation, +{ + onEnter: function (args) + { + var CBChar = new ObjC.Object(args[0]); + // turns <12 34> into 1234 + var data = CBChar.$ivars['_value'] + + if (data != null) + { + data = data.toString().replace(/ /g, '').slice(1, -1) + } + + if (CBChar.$ivars['_isNotifying'] === true) + { + console.log(Color.Cyan + "[BLE Notify <=]" + Color.Light.Black + " UUID: " + CBChar.$ivars['_UUID'] + Color.Reset + " data: 0x" + data); + } + else + { + console.log(Color.Blue + "[BLE Read <=]" + Color.Light.Black + " UUID: " + CBChar.$ivars['_UUID'] + Color.Reset + " data: 0x" + data); + } + } +}); //end Interceptor diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-enable-webinspector.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-enable-webinspector.js new file mode 100644 index 0000000000..679594252c --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-enable-webinspector.js @@ -0,0 +1,50 @@ +/* + Description: iOS Enable WebInspector + Credit: leolashkevych + Src: https://github.com/rsenet/FriList/blob/main/01_Observer/Network/WebInspector/ios-webinspector-enable.js + Enable WebView debugging for all iOS apps. Before running the script, enable Web Inspector in Safari settings + (see https://github.com/OWASP/owasp-mastg/blob/master/Document/0x06h-Testing-Platform-Interaction.md#safari-web-inspector). + Jailbreak required. +*/ + +const CFRelease = new NativeFunction(Module.findExportByName(null, 'CFRelease'), 'void', ['pointer']); +const CFStringGetCStringPtr = new NativeFunction(Module.findExportByName(null, 'CFStringGetCStringPtr'),'pointer', ['pointer', 'uint32']); +const kCFStringEncodingUTF8 = 0x08000100; +const SecTaskCopyValueForEntitlement = Module.findExportByName(null, 'SecTaskCopyValueForEntitlement'); + +const entitlements = [ + 'com.apple.security.get-task-allow', + 'com.apple.webinspector.allow', + 'com.apple.private.webinspector.allow-remote-inspection', + 'com.apple.private.webinspector.allow-carrier-remote-inspection' +]; + +Interceptor.attach(SecTaskCopyValueForEntitlement, +{ + onEnter: function(args) + { + const pEntitlement = CFStringGetCStringPtr(args[1], kCFStringEncodingUTF8) + const entitlement = Memory.readUtf8String(pEntitlement) + + if (entitlements.indexOf(entitlement) > -1) + { + this.shouldOverride = true + this.entitlement = entitlement + } + }, + + onLeave: function(retVal) + { + if (this.shouldOverride) + { + console.log('Overriding value for entitlement: ', this.entitlement) + if (!retVal.isNull()) + { + console.log('Old value: ', retVal) + CFRelease(retVal) + } + retVal.replace(ObjC.classes.NSNumber.numberWithBool_(1)); + console.log('New value: ', retVal) + } + } +}); \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-webview-trace.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-webview-trace.js new file mode 100644 index 0000000000..4655837114 --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/ui-webview-trace.js @@ -0,0 +1,59 @@ +/* + Description: iOS WebView Observer + Usage: frida -U -f XXX -l ios-webview-observer.js + Credit: MASTG + Src: https://github.com/rsenet/FriList/blob/main/01_Observer/Network/Webview/ios-webview-observer.js + Link: + https://developer.apple.com/documentation/uikit/uiwebview + https://developer.apple.com/documentation/webkit/wkwebview + https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller +*/ + +if (ObjC.available) +{ + ObjC.choose(ObjC.classes['UIWebView'], + { + onMatch: function (ui) + { + console.log('onMatch: ', ui); + console.log('URL: ', ui.request().toString()); + }, + onComplete: function () + { + console.log('done for UIWebView!'); + } + }); + + ObjC.choose(ObjC.classes['WKWebView'], + { + onMatch: function (wk) + { + console.log('onMatch: ', wk); + console.log('URL: ', wk.URL().toString()); + console.log('javaScriptEnabled: ', wk.configuration().preferences().javaScriptEnabled()); + console.log('allowFileAccessFromFileURLs: ', wk.configuration().preferences().valueForKey_('allowFileAccessFromFileURLs').toString()); + console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString()); + console.log('allowUniversalAccessFromFileURLs: ', wk.configuration().valueForKey_('allowUniversalAccessFromFileURLs').toString()); + }, + onComplete: function () + { + console.log('done for WKWebView!'); + } + }); + + ObjC.choose(ObjC.classes['SFSafariViewController'], + { + onMatch: function (sf) + { + console.log('onMatch: ', sf); + }, + onComplete: function () + { + console.log('done for SFSafariViewController!'); + } + }); +} +else +{ + console.log("Objective-C Runtime is not available!"); +} \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/views/android/operations.py b/mobsf/DynamicAnalyzer/views/android/operations.py index 4d263327f8..8451635a12 100644 --- a/mobsf/DynamicAnalyzer/views/android/operations.py +++ b/mobsf/DynamicAnalyzer/views/android/operations.py @@ -227,7 +227,7 @@ def touch(request): or not is_number(y) or not is_number(max_x) or not is_number(max_y)): - return + return data # Should not be greater than max screen size swipe_x = str(min(int(float(x)) + 500, int(float(max_x)))) swipe_y = str(min(int(float(y)) + 500, int(float(max_y)))) diff --git a/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py b/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py index d1a8a869a8..45ae406786 100644 --- a/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py +++ b/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py @@ -31,12 +31,16 @@ def __init__(self, project_id) -> None: def api_ready(self): """Check API Availability.""" - r = requests.get(f'{self.api}/ready') - if r.status_code in SUCCESS_RESP: - return True - else: - logger.error('Corellium API is not ready.' - ' Status code: %s', r.status_code) + try: + r = requests.get(f'{self.api}/ready') + if r.status_code in SUCCESS_RESP: + return True + else: + logger.error('Corellium API is not ready.' + ' Status code: %s', r.status_code) + except Exception: + logger.error('Network unreachable.') + return False return False def api_auth(self): @@ -336,7 +340,7 @@ def device_input(self, event, x, y, max_x, max_y): or not is_number(y) or not is_number(max_x) or not is_number(max_y)): - return + return 'Invalid coordinates' # Should not be greater than max screen size swipe_x = min(int(x) + 200, int(max_x)) swipe_y = min(int(y) + 400, int(max_y)) @@ -391,8 +395,6 @@ def device_input(self, event, x, y, max_x, max_y): 'duration': 200, }] else: - if not is_number(x) or not is_number(y): - return data = [ {'buttons': ['finger'], 'position': [[x, y]], diff --git a/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py b/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py index 89f4277306..14ef70d233 100644 --- a/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py +++ b/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py @@ -730,12 +730,20 @@ def touch(request, api=False): if failed: return send_response(failed, api) ci = CorelliumInstanceAPI(instance_id) - ci.device_input(event, x_axis, y_axis, max_x, max_y) - data = {'status': 'ok'} + res = ci.device_input( + event, + x_axis, + y_axis, + max_x, + max_y) + if res != 'ok': + data['message'] = res + else: + data = {'status': 'ok'} except Exception as exp: logger.exception('Sending Touchscreen Events') data['message'] = str(exp) - return send_response(data) + return send_response(data, api) # AJAX + HTML diff --git a/mobsf/MobSF/init.py b/mobsf/MobSF/init.py index f2de9f0fc8..e956ef6754 100644 --- a/mobsf/MobSF/init.py +++ b/mobsf/MobSF/init.py @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) -VERSION = '3.8.2' +VERSION = '3.8.3' BANNER = """ __ __ _ ____ _____ _____ ___ | \/ | ___ | |__/ ___|| ___|_ _|___ / ( _ ) diff --git a/mobsf/templates/dynamic_analysis/android/dynamic_analysis.html b/mobsf/templates/dynamic_analysis/android/dynamic_analysis.html index db3524b810..a83e679f97 100644 --- a/mobsf/templates/dynamic_analysis/android/dynamic_analysis.html +++ b/mobsf/templates/dynamic_analysis/android/dynamic_analysis.html @@ -162,11 +162,11 @@

Apps in Device

- Start Dynamic Analysis + Start Dynamic Analysis

Pull & Static Analysis -

+

View Report

diff --git a/poetry.lock b/poetry.lock index b310ac3978..0a25725483 100644 --- a/poetry.lock +++ b/poetry.lock @@ -771,17 +771,17 @@ files = [ [[package]] name = "django" -version = "4.2.7" +version = "5.0" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "Django-4.2.7-py3-none-any.whl", hash = "sha256:e1d37c51ad26186de355cbcec16613ebdabfa9689bbade9c538835205a8abbe9"}, - {file = "Django-4.2.7.tar.gz", hash = "sha256:8e0f1c2c2786b5c0e39fe1afce24c926040fad47c8ea8ad30aaf1188df29fc41"}, + {file = "Django-5.0-py3-none-any.whl", hash = "sha256:3a9fd52b8dbeae335ddf4a9dfa6c6a0853a1122f1fb071a8d5eca979f73a05c8"}, + {file = "Django-5.0.tar.gz", hash = "sha256:7d29e14dfbc19cb6a95a4bd669edbde11f5d4c6a71fdaa42c2d40b6846e807f7"}, ] [package.dependencies] -asgiref = ">=3.6.0,<4" +asgiref = ">=3.7.0" sqlparse = ">=0.3.1" tzdata = {version = "*", markers = "sys_platform == \"win32\""} diff --git a/pyproject.toml b/pyproject.toml index 80d6e03dcd..527d157324 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "mobsf" -version = "3.8.2" +version = "3.8.3" description = "Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis." keywords = ["mobsf", "mobile security framework", "mobile security", "security tool", "static analysis", "dynamic analysis", "malware analysis"] authors = ["Ajin Abraham "]