diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/auxiliary/string_compare.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/auxiliary/string_compare.js index 8b4fe2a3d7..81f9aa98ca 100644 --- a/mobsf/DynamicAnalyzer/tools/frida_scripts/android/auxiliary/string_compare.js +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/android/auxiliary/string_compare.js @@ -12,4 +12,4 @@ Java.perform(function () { } return response; } -}); \ 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-early-java.js similarity index 100% rename from mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-eary-java.js rename to mobsf/DynamicAnalyzer/tools/frida_scripts/android/others/helper-early-java.js diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/default/jailbreak_bypass.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/default/jailbreak_bypass.js index 53ac31ec4f..b644ed02b4 100644 --- a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/default/jailbreak_bypass.js +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/default/jailbreak_bypass.js @@ -134,10 +134,84 @@ function bypassJailbreakDetection(){ } } -try { - if (ObjC.available) { - bypassJailbreakDetection(); - } else { - send('[Jailbreak Detection Bypass] error: Objective-C Runtime is not available!'); + +function bypassJailbreakDetection2() { + try { + + var resolver = new ApiResolver('objc'); + + resolver.enumerateMatches('*[* *jail**]', { + onMatch: function(match) { + var ptr = match["address"]; + Interceptor.attach(ptr, { + onEnter: function() {}, + onLeave: function(retval) { + retval.replace(0x0); + } + }); + }, + onComplete: function() {} + }); + + resolver.enumerateMatches('*[* fileExistsAtPath*]', { + onMatch: function(match) { + var ptr = match["address"]; + Interceptor.attach(ptr, { + onEnter: function(args) { + var path = ObjC.Object(args[2]).toString(); + this.jailbreakCall = false; + for (var i = 0; i < paths.length; i++) { + if (paths[i] == path) { + this.jailbreakCall = true; + } + } + }, + onLeave: function(retval) { + if (this.jailbreakCall) { + retval.replace(0x0); + } + } + }); + }, + onComplete: function() {} + }); + + resolver.enumerateMatches('*[* canOpenURL*]', { + onMatch: function(match) { + var ptr = match["address"]; + Interceptor.attach(ptr, { + onEnter: function(args) { + var url = ObjC.Object(args[2]).toString(); + this.jailbreakCall = false; + if (url.indexOf("cydia") >= 0) { + this.jailbreakCall = true; + } + }, + onLeave: function(retval) { + if (this.jailbreakCall) { + retval.replace(0x0); + } + } + }); + }, + onComplete: function() {} + }); + send("[Jailbreak Detection Bypass 2] success"); + } + catch(e) { + send('[Jailbreak Detection Bypass 2] script error:' + e.toString()); + } } -} catch(err) {} \ No newline at end of file + + try { + if (ObjC.available) { + bypassJailbreakDetection(); + // Disable the below if the app is crashing + setTimeout(() => { + bypassJailbreakDetection2(); + }, "1000"); + } else { + send('[Jailbreak Detection Bypass] error: Objective-C Runtime is not available!'); + } + } catch(err) {} + \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/default/jailbreak_bypass2.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/default/jailbreak_bypass2.js deleted file mode 100644 index f8e83dcf9f..0000000000 --- a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/default/jailbreak_bypass2.js +++ /dev/null @@ -1,161 +0,0 @@ -var paths = [ - "/Applications/blackra1n.app", - "/Applications/Cydia.app", - "/Applications/FakeCarrier.app", - "/Applications/Icy.app", - "/Applications/IntelliScreen.app", - "/Applications/MxTube.app", - "/Applications/RockApp.app", - "/Applications/SBSetttings.app", - "/Applications/WinterBoard.app", - "/bin/bash", - "/bin/sh", - "/bin/su", - "/etc/apt", - "/etc/ssh/sshd_config", - "/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist", - "/Library/MobileSubstrate/DynamicLibraries/Veency.plist", - "/Library/MobileSubstrate/MobileSubstrate.dylib", - "/pguntether", - "/private/var/lib/cydia", - "/private/var/mobile/Library/SBSettings/Themes", - "/private/var/stash", - "/private/var/tmp/cydia.log", - "/System/Library/LaunchDaemons/com.ikey.bbot.plist", - "/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist", - "/usr/bin/cycript", - "/usr/bin/ssh", - "/usr/bin/sshd", - "/usr/libexec/sftp-server", - "/usr/libexec/ssh-keysign", - "/usr/sbin/frida-server", - "/usr/sbin/sshd", - "/var/cache/apt", - "/var/lib/cydia", - "/var/log/syslog", - "/var/mobile/Media/.evasi0n7_installed", - "/var/tmp/cydia.log", - "/etc/apt", - "/Library/MobileSubstrate/MobileSubstrate.dylib", - "/Applications/Cydia.app", - "/Applications/blackra1n.app", - "/Applications/FakeCarrier.app", - "/Applications/Icy.app", - "/Applications/IntelliScreen.app", - "/Applications/MxTube.app", - "/Applications/RockApp.app", - "/Applications/SBSetttings.app", - "/private/var/lib/apt/", - "/Applications/WinterBoard.app", - "/usr/sbin/sshd", - "/private/var/tmp/cydia.log", - "/usr/binsshd", - "/usr/libexec/sftp-server", - "/Systetem/Library/LaunchDaemons/com.ikey.bbot.plist", - "/System/Library/LaunchDaemons/com.saurik.Cy@dia.Startup.plist", - "/var/log/syslog", - "/bin/bash", - "/bin/sh", - "/etc/ssh/sshd_config", - "/usr/libexec/ssh-keysign", - "/Library/MobileSubstrate/DynamicLibraries/Veency.plist", - "/System/Library/LaunchDaemons/com.ikey.bbot.plist", - "/private/var/stash", - "/usr/bin/cycript", - "/usr/bin/ssh", - "/usr/bin/sshd", - "/var/cache/apt", - "/var/lib/cydia", - "/var/tmp/cydia.log", - "/Applications/SBSettings.app", - "/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist", - "/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist", - "/private/var/lib/apt", - "/private/var/lib/cydia", - "/private/var/mobile/Library/SBSettings/Themes", - "/var/lib/apt", - "/private/jailbreak.txt", - "/bin/su", - "/pguntether", - "/usr/sbin/frida-server", - "/private/Jailbreaktest.txt", - "/var/mobile/Media/.evasi0n7_installed", - "cydia://package/com.example.package" -]; - -function bypassJailbreakDetection2() { -try { - - var resolver = new ApiResolver('objc'); - - resolver.enumerateMatches('*[* *jail**]', { - onMatch: function(match) { - var ptr = match["address"]; - Interceptor.attach(ptr, { - onEnter: function() {}, - onLeave: function(retval) { - retval.replace(0x0); - } - }); - }, - onComplete: function() {} - }); - - resolver.enumerateMatches('*[* fileExistsAtPath*]', { - onMatch: function(match) { - var ptr = match["address"]; - Interceptor.attach(ptr, { - onEnter: function(args) { - var path = ObjC.Object(args[2]).toString(); - this.jailbreakCall = false; - for (var i = 0; i < paths.length; i++) { - if (paths[i] == path) { - this.jailbreakCall = true; - } - } - }, - onLeave: function(retval) { - if (this.jailbreakCall) { - retval.replace(0x0); - } - } - }); - }, - onComplete: function() {} - }); - - resolver.enumerateMatches('*[* canOpenURL*]', { - onMatch: function(match) { - var ptr = match["address"]; - Interceptor.attach(ptr, { - onEnter: function(args) { - var url = ObjC.Object(args[2]).toString(); - this.jailbreakCall = false; - if (url.indexOf("cydia") >= 0) { - this.jailbreakCall = true; - } - }, - onLeave: function(retval) { - if (this.jailbreakCall) { - retval.replace(0x0); - } - } - }); - }, - onComplete: function() {} - }); - send("[Jailbreak Detection Bypass 2] success"); - } - catch(e) { - send('[Jailbreak Detection Bypass 2] script error:' + e.toString()); - } -} - - -try { - if (ObjC.available) { - bypassJailbreakDetection2(); - } else { - send('[Jailbreak Detection Bypass 2] error: Objective-C Runtime is not available!'); - } -} catch(err) {} diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/data-dir.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/data-dir.js index 6e99404148..2e118f8e6e 100644 --- a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/data-dir.js +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/data-dir.js @@ -59,7 +59,9 @@ function getDataProtectionKeysForAllPaths() { send('Dumping Application Directory file information'); try { - send(JSON.stringify({'[MBSFDUMP] datadir': getDataProtectionKeysForAllPaths()})); + setTimeout(() => { + send(JSON.stringify({'[MBSFDUMP] datadir': getDataProtectionKeysForAllPaths()})); + }, "2000"); } catch(err) {} // /******************************************************************************** diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/nsuserdefaults.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/nsuserdefaults.js index 41f799db45..1853e5a0c9 100644 --- a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/nsuserdefaults.js +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/dump/nsuserdefaults.js @@ -28,5 +28,8 @@ function ns_userdefaults() { } try{ - ns_userdefaults(); + setTimeout(() => { + ns_userdefaults(); + }, "2000"); + } catch(err) {} \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-backtrace.js b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-backtrace.js new file mode 100644 index 0000000000..95cdaab66e --- /dev/null +++ b/mobsf/DynamicAnalyzer/tools/frida_scripts/ios/others/helper-backtrace.js @@ -0,0 +1,16 @@ +// Get caller of the function using backtrace + +// From: https://node-security.com/posts/frida-for-ios/ +function getBacktrace(){ + send('Get the caller of the function using backtrace'); + Interceptor.attach(ObjC.classes.NSFileManager['- fileExistsAtPath:'].implementation, { + onEnter: function (args) { + const backtrace = Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"); + console.log(backtrace + "\n"); + console.log(ObjC.Object(args[2]).toString()); + } + }); +} +try { + getBacktrace(); +} catch(err) {} \ No newline at end of file diff --git a/mobsf/DynamicAnalyzer/views/android/frida_core.py b/mobsf/DynamicAnalyzer/views/android/frida_core.py index 0e4e442267..6926b66f97 100644 --- a/mobsf/DynamicAnalyzer/views/android/frida_core.py +++ b/mobsf/DynamicAnalyzer/views/android/frida_core.py @@ -147,6 +147,7 @@ def spawn(self): except frida.TimedOutError: logger.error('Timed out while waiting for device to appear') except (frida.ProcessNotFoundError, + frida.ProcessNotRespondingError, frida.TransportError, frida.InvalidOperationError): pass @@ -184,6 +185,7 @@ def session(self, pid, package): except frida.NotSupportedError: logger.exception('Not Supported Error') except (frida.ProcessNotFoundError, + frida.ProcessNotRespondingError, frida.TransportError, frida.InvalidOperationError): pass diff --git a/mobsf/DynamicAnalyzer/views/android/frida_scripts.py b/mobsf/DynamicAnalyzer/views/android/frida_scripts.py index 1626be7ac1..847c759f8d 100644 --- a/mobsf/DynamicAnalyzer/views/android/frida_scripts.py +++ b/mobsf/DynamicAnalyzer/views/android/frida_scripts.py @@ -7,7 +7,7 @@ def get_content(file_name): tools_dir = Path(settings.TOOLS_DIR) - aux_dir = tools_dir / 'frida_scripts' / 'ios' / 'auxiliary' + aux_dir = tools_dir / 'frida_scripts' / 'android' / 'auxiliary' script = aux_dir / file_name if script.exists(): diff --git a/mobsf/DynamicAnalyzer/views/android/tests_frida.py b/mobsf/DynamicAnalyzer/views/android/tests_frida.py index e45649079f..11204a4a89 100644 --- a/mobsf/DynamicAnalyzer/views/android/tests_frida.py +++ b/mobsf/DynamicAnalyzer/views/android/tests_frida.py @@ -102,6 +102,9 @@ def instrument(request, api=False): elif action == 'ps': logger.info('Enumerating running applications') data['message'] = frida_obj.ps() + elif action == 'get': + # Get injected Frida script. + data['message'] = frida_obj.get_script() if action in ('spawn', 'session'): if pid and pid.isdigit(): # Attach to a different pid/bundle id diff --git a/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py b/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py index 45ae406786..e672a9ad88 100644 --- a/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py +++ b/mobsf/DynamicAnalyzer/views/ios/corellium_apis.py @@ -344,6 +344,10 @@ def device_input(self, event, x, y, max_x, max_y): # 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)) + # Just to prevent linter complaining + # Make use of these variables in future + swipe_x = swipe_y + swipe_y = swipe_x if event == 'home': data = [{ 'buttons': ['holdButton'], @@ -374,8 +378,9 @@ def device_input(self, event, x, y, max_x, max_y): elif event == 'swipe_down': data = [{ 'startButtons': ['finger'], - 'start': [[x, swipe_y]], - 'end': [[swipe_x, y]], + 'start': [[300, 600]], + 'bezierPoints': [[[700, 350]], [[850, 375]]], + 'end': [[950, 400]], 'duration': 200, }] elif event == 'swipe_left': diff --git a/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py b/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py index 14ef70d233..ee96970e5c 100644 --- a/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py +++ b/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py @@ -358,7 +358,7 @@ def appsync_ipa_install(ssh_string): out = ssh_execute_cmd(target, 'appinst /tmp/app.ipa') target.close() jumpbox.close() - if 'Failed' in out: + if 'Successfully installed' not in out: logger.error('AppSync IPA Install Failed.\n%s', out) return out logger.info(out) diff --git a/mobsf/DynamicAnalyzer/views/ios/corellium_ssh.py b/mobsf/DynamicAnalyzer/views/ios/corellium_ssh.py index b768fe37ed..b296520694 100644 --- a/mobsf/DynamicAnalyzer/views/ios/corellium_ssh.py +++ b/mobsf/DynamicAnalyzer/views/ios/corellium_ssh.py @@ -212,8 +212,7 @@ def ssh_jump_host(ssh_string): generate_keypair_if_not_exists(home) keyf = home / 'ssh_key.private' jumpbox = paramiko.SSHClient() - jumpbox.load_system_host_keys() - jumpbox.set_missing_host_key_policy(paramiko.WarningPolicy()) + jumpbox.set_missing_host_key_policy(paramiko.AutoAddPolicy()) jumpbox.connect( bastion_host, username=bastion_user, @@ -226,8 +225,7 @@ def ssh_jump_host(ssh_string): 'direct-tcpip', dest_addr, src_addr) target = paramiko.SSHClient() - target.load_system_host_keys() - target.set_missing_host_key_policy(paramiko.WarningPolicy()) + target.set_missing_host_key_policy(paramiko.AutoAddPolicy()) target.connect( private_ip, username=user, diff --git a/mobsf/DynamicAnalyzer/views/ios/frida_core.py b/mobsf/DynamicAnalyzer/views/ios/frida_core.py index 025b15f305..bfe3fa447b 100644 --- a/mobsf/DynamicAnalyzer/views/ios/frida_core.py +++ b/mobsf/DynamicAnalyzer/views/ios/frida_core.py @@ -53,6 +53,11 @@ def __init__( self.frida_log = self.ipa_dir / 'mobsf_frida_out.txt' self.dump_file = self.ipa_dir / 'mobsf_dump_file.txt' self.container_file = self.ipa_dir / 'mobsf_app_container_path.txt' + self.not_supported_text = ( + 'Failed to instrument the app with Frida. ' + 'This app is not supported by Frida. ' + 'Are you able to run the app on ' + 'this device?') def get_scripts(self, script_type, selected_scripts): """Get Frida Scripts.""" @@ -159,7 +164,7 @@ def spawn(self): self.clean_up() _PID = frida.get_remote_device().spawn([self.bundle_id]) except frida.NotSupportedError: - logger.exception('Not Supported Error') + logger.error(self.not_supported_text) return except frida.ServerNotRunningError: self.frida_ssh_forward() @@ -170,9 +175,10 @@ def spawn(self): except frida.TimedOutError: logger.error('Timed out while waiting for device to appear') except frida.NotSupportedError: - logger.exception('Not Supported Error') + logger.error(self.not_supported_text) return except (frida.ProcessNotFoundError, + frida.ProcessNotRespondingError, frida.TransportError, frida.InvalidOperationError): pass @@ -193,10 +199,11 @@ def session(self, pid, bundle_id): # No front most app, spawn the app or # pid is not the front most app _PID = device.spawn([self.bundle_id]) + logger.info('Spawning %s', self.bundle_id) # pid is the fornt most app session = device.attach(_PID) except frida.NotSupportedError: - logger.exception('Not Supported Error') + logger.error(self.not_supported_text) return except Exception: logger.warning('Cannot attach to pid, spawning again') @@ -214,8 +221,9 @@ def session(self, pid, bundle_id): script.unload() session.detach() except frida.NotSupportedError: - logger.exception('Not Supported Error') + logger.error(self.not_supported_text) except (frida.ProcessNotFoundError, + frida.ProcessNotRespondingError, frida.TransportError, frida.InvalidOperationError): pass diff --git a/mobsf/DynamicAnalyzer/views/ios/tests_frida.py b/mobsf/DynamicAnalyzer/views/ios/tests_frida.py index e0fd70a465..51c59d05bb 100644 --- a/mobsf/DynamicAnalyzer/views/ios/tests_frida.py +++ b/mobsf/DynamicAnalyzer/views/ios/tests_frida.py @@ -92,6 +92,9 @@ def ios_instrument(request, api=False): elif action == 'ps': logger.info('Enumerating running applications') data['message'] = frida_obj.ps() + elif action == 'get': + # Get injected Frida script. + data['message'] = frida_obj.get_script() if action in ('spawn', 'session'): if pid and pid.isdigit(): # Attach to a different pid/bundle id diff --git a/mobsf/MobSF/init.py b/mobsf/MobSF/init.py index e956ef6754..a8d4e4b236 100644 --- a/mobsf/MobSF/init.py +++ b/mobsf/MobSF/init.py @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) -VERSION = '3.8.3' +VERSION = '3.8.4' BANNER = """ __ __ _ ____ _____ _____ ___ | \/ | ___ | |__/ ___|| ___|_ _|___ / ( _ ) diff --git a/mobsf/templates/dynamic_analysis/android/dynamic_analyzer.html b/mobsf/templates/dynamic_analysis/android/dynamic_analyzer.html index 124ca2b1ca..2cdf972ec1 100644 --- a/mobsf/templates/dynamic_analysis/android/dynamic_analyzer.html +++ b/mobsf/templates/dynamic_analysis/android/dynamic_analyzer.html @@ -8,6 +8,7 @@ +