Skip to content

Commit a9de033

Browse files
authored
[HOTFIX] AppSec PNW 2024, Deeplink Trigger Support for Android Dynamic Analyzer (#2402)
* iOS Dynamic Analyzer String Compare Frida script improvement * Android Dynamic Analyzer Deeplink UI trigger support * Android & iOS Dynamic Analyzer UI Improvements * Android & iOS Dynamic Analyzer Bug fixes
1 parent 39ba3e6 commit a9de033

File tree

13 files changed

+319
-199
lines changed

13 files changed

+319
-199
lines changed

mobsf/DynamicAnalyzer/tools/frida_scripts/ios/auxiliary/string-compare.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ function captureStringCompare() {
22
send('Capturing string comparisons')
33
Interceptor.attach(ObjC.classes.__NSCFString['- isEqualToString:'].implementation, {
44
onEnter: function (args) {
5+
var src = new ObjC.Object(ptr(args[0])).toString()
56
var str = new ObjC.Object(ptr(args[2])).toString()
6-
send('[AUXILIARY] [__NSCFString isEqualToString:] -> '+ str);
7+
send('[AUXILIARY] [__NSCFString isEqualToString:] -> \nstring 1: '+ src + '\nstring 2: '+ str);
78
}
89
});
910
}
1011

1112
function captureStringCompare2(){
1213
Interceptor.attach(ObjC.classes.NSTaggedPointerString['- isEqualToString:'].implementation, {
1314
onEnter: function (args) {
15+
var src = new ObjC.Object(ptr(args[0])).toString()
1416
var str = new ObjC.Object(ptr(args[2])).toString()
15-
send('[AUXILIARY] NSTaggedPointerString[- isEqualToString:] -> '+ str);
17+
send('[AUXILIARY] NSTaggedPointerString[- isEqualToString:] -> \nstring 1: '+ src + '\nstring 2: '+ str);
1618
}
1719
});
1820
}

mobsf/DynamicAnalyzer/views/android/dynamic_analyzer.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
get_proxy_ip,
3535
is_md5,
3636
print_n_send_error_response,
37+
python_dict,
3738
python_list,
3839
strict_package_check,
3940
)
@@ -155,9 +156,11 @@ def dynamic_analyzer(request, checksum, api=False):
155156
static_android_db.EXPORTED_ACTIVITIES)
156157
activities = python_list(
157158
static_android_db.ACTIVITIES)
159+
deeplinks = python_dict(
160+
static_android_db.BROWSABLE_ACTIVITIES)
158161
except ObjectDoesNotExist:
159162
logger.warning(
160-
'Failed to get Activities. '
163+
'Failed to get Activities/Deeplinks. '
161164
'Static Analysis not completed for the app.')
162165
env = Environment(identifier)
163166
if not env.connect_n_mount():
@@ -218,6 +221,7 @@ def dynamic_analyzer(request, checksum, api=False):
218221
'version': settings.MOBSF_VER,
219222
'activities': activities,
220223
'exported_activities': exported_activities,
224+
'deeplinks': deeplinks,
221225
'title': 'Dynamic Analyzer'}
222226
template = 'dynamic_analysis/android/dynamic_analyzer.html'
223227
if api:

mobsf/DynamicAnalyzer/views/android/environment.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ def get_environment(self):
368368
return 'emulator'
369369
elif (b'genymotion' in out.lower()
370370
or any(char.isdigit() for char in ver)):
371-
logger.info('Found Genymotion x86 Android VM')
371+
logger.info('Found Genymotion Android VM')
372372
return 'genymotion'
373373
elif b'corellium' in out:
374374
logger.info('Found Corellium ARM Android VM')
@@ -652,7 +652,7 @@ def frida_setup(self):
652652
elif arch == 'x86_64':
653653
frida_arch = 'x86_64'
654654
else:
655-
logger.error('Make sure a Genymotion Android x86 VM'
655+
logger.error('Make sure a Genymotion Android VM'
656656
' or Android Studio Emulator'
657657
' instance is running')
658658
return

mobsf/DynamicAnalyzer/views/android/frida_core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ def api_handler(self, api):
228228
loaded_class_methods = []
229229
implementations = []
230230
try:
231+
if not self.extras:
232+
return
231233
raction = self.extras.get('rclass_action')
232234
rclass = self.extras.get('rclass_name')
233235
rclass_pattern = self.extras.get('rclass_pattern')

mobsf/DynamicAnalyzer/views/android/tests_common.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
stop_httptools,
2929
)
3030
from mobsf.MobSF.utils import (
31+
cmd_injection_check,
3132
is_md5,
3233
python_list,
3334
)
@@ -50,7 +51,7 @@
5051
@permission_required(Permissions.SCAN)
5152
@require_http_methods(['POST'])
5253
def start_activity(request, api=False):
53-
"""Lunch a specific activity."""
54+
"""Launch a specific activity."""
5455
try:
5556
env = Environment()
5657
activity = request.POST['activity']
@@ -77,6 +78,31 @@ def start_activity(request, api=False):
7778
data = {'status': 'failed', 'message': str(exp)}
7879
return send_response(data, api)
7980

81+
# AJAX
82+
83+
84+
@login_required
85+
@permission_required(Permissions.SCAN)
86+
@require_http_methods(['POST'])
87+
def start_deeplink(request, api=False):
88+
"""Launch a specific deeplink."""
89+
try:
90+
env = Environment()
91+
url = request.POST['url']
92+
md5_hash = request.POST['hash']
93+
94+
valid_md5 = is_md5(md5_hash)
95+
if cmd_injection_check(url) or not valid_md5:
96+
return invalid_params(api)
97+
env.adb_command(
98+
['am', 'start', '-a',
99+
'android.intent.action.VIEW',
100+
'-d', url], True)
101+
data = {'status': 'ok'}
102+
except Exception as exp:
103+
logger.exception('Start Activity')
104+
data = {'status': 'failed', 'message': str(exp)}
105+
return send_response(data, api)
80106

81107
# AJAX
82108

mobsf/DynamicAnalyzer/views/ios/frida_core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ def api_handler(self, api):
268268
self.container_file.write_text(self.app_container)
269269
except frida.InvalidOperationError:
270270
pass
271+
if not self.extras:
272+
return
271273
raction = self.extras.get('rclass_action')
272274
rclass = self.extras.get('rclass_name')
273275
rclass_pattern = self.extras.get('rclass_pattern')

mobsf/MobSF/init.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
logger = logging.getLogger(__name__)
1212

13-
VERSION = '4.0.3'
13+
VERSION = '4.0.4'
1414
BANNER = """
1515
__ __ _ ____ _____ _ _ ___
1616
| \/ | ___ | |__/ ___|| ___|_ _| || | / _ \

mobsf/MobSF/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@
281281
re_path(r'^start_activity/$',
282282
tests_common.start_activity,
283283
name='start_activity'),
284+
re_path(r'^start_deeplink/$',
285+
tests_common.start_deeplink,
286+
name='start_deeplink'),
284287
re_path(r'^download_data/$', tests_common.download_data),
285288
re_path(r'^collect_logs/$', tests_common.collect_logs),
286289
re_path(r'^tls_tests/$', tests_common.tls_tests),

mobsf/templates/dynamic_analysis/android/dynamic_analysis.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ <h3 class="card-title">Android Runtime not found!</h3>
8888
<div class="col-md-9">
8989
<h4>MobSF Dynamic Analyzer Supports</h4>
9090
<h5>
91-
<strong>• Genymotion Android VM</strong> version 4.1 - 11.0 (x86, upto API 30)<br/>
91+
<strong>• Genymotion Android VM</strong> version 4.1 - 11.0 (arm64, x86, upto API 30)<br/>
9292
<strong>• Android Emulator AVD</strong> (non production) version 5.0 - 9.0 (arm, arm64, x86, and x86_64 upto API 28)<br/>
9393
<strong>• Corellium Android VM</strong> (userdebug builds) version 7.1.2 - 11.0 (arm64 upto API 30)
9494
</h5>
9595
<p>
9696
{% if android_version %}
97-
Recommended Android version is <strong>9.0</strong><br/>
97+
Android version >= <strong>9.0</strong> recommended<br/>
9898
Detected Android Version: <strong>{{android_version}}</strong>, SDK: <strong>{{ android_sdk }}</strong> <br/>
9999
{% if android_sdk|floatformat > android_supported|floatformat %}
100100
<script src="{% static "adminlte/plugins/sweetalert2/sweetalert2.min.js" %}"></script>

0 commit comments

Comments
 (0)