mirror of
https://github.com/MobSF/Mobile-Security-Framework-MobSF.git
synced 2026-10-12 02:06:59 +00:00
Dynamic Analysis with Genymotion. Supports Android 4.1 -9.0 Static Analyzer Threaded baksmali Improved Recent Scan Browser PDF Generation Dynamic Analyzer Restructuring Dynamic Analyzer Code QA and Modularization Automatic MobSFy with Xposed and Frida Full pass on all versions of android with basic features Streaming logcat Live API Monitor Better SQlite DB View In line frida scripting + loading from frida code share basic frida env, ssl unpin, root check, debugger detection bypass. Custom Frida Scripts and integration Frida Log Viewer Frida scripts loader Frida custom user script loader
147 lines
5.1 KiB
Python
147 lines
5.1 KiB
Python
import os
|
|
import glob
|
|
import logging
|
|
from pathlib import Path
|
|
import sys
|
|
import time
|
|
|
|
from django.conf import settings
|
|
|
|
import frida
|
|
|
|
from DynamicAnalyzer.views.android.environment import Environment
|
|
from DynamicAnalyzer.views.android.frida_scripts import (
|
|
class_pattern,
|
|
class_trace,
|
|
get_loaded_classes,
|
|
get_methods,
|
|
string_catch,
|
|
string_compare)
|
|
|
|
from MobSF.utils import (get_device,
|
|
is_file_exists)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Frida:
|
|
|
|
def __init__(self, app_hash, package, defaults, auxiliary, extras, code):
|
|
self.hash = app_hash
|
|
self.package = package
|
|
self.defaults = defaults
|
|
self.auxiliary = auxiliary
|
|
self.extras = extras
|
|
self.code = code
|
|
self.frida_dir = os.path.join(settings.TOOLS_DIR,
|
|
'frida_scripts')
|
|
self.apk_dir = os.path.join(settings.UPLD_DIR, self.hash + '/')
|
|
self.api_mon = os.path.join(self.apk_dir, 'mobsf_api_monitor.txt')
|
|
self.frida_log = os.path.join(self.apk_dir, 'mobsf_frida_out.txt')
|
|
|
|
def get_default_scripts(self):
|
|
"""Get default Frida Scripts."""
|
|
combined_script = []
|
|
header = []
|
|
def_scripts = os.path.join(self.frida_dir, 'default')
|
|
files = [f for f in glob.glob(
|
|
def_scripts + '**/*.js', recursive=True)]
|
|
for item in files:
|
|
script = Path(item)
|
|
if script.stem in self.defaults:
|
|
header.append('send("Loaded Frida Script - {}");'.format(
|
|
script.stem))
|
|
combined_script.append(script.read_text())
|
|
return header + combined_script
|
|
|
|
def get_auxiliary(self):
|
|
"""Get auxiliary hooks."""
|
|
scripts = []
|
|
for itm in self.auxiliary:
|
|
if itm == 'enum_class':
|
|
scripts.append(get_loaded_classes())
|
|
elif itm == 'string_catch':
|
|
scripts.append(string_catch())
|
|
elif itm == 'string_compare':
|
|
scripts.append(string_compare())
|
|
elif itm == 'enum_methods' and 'cls_name' in self.extras:
|
|
scripts.append(get_methods(self.extras['cls_name']))
|
|
elif itm == 'search_class' and 'cls_search' in self.extras:
|
|
scripts.append(class_pattern(self.extras['cls_search']))
|
|
elif itm == 'trace_class' and 'cls_trace' in self.extras:
|
|
scripts.append(class_trace(self.extras['cls_trace']))
|
|
return scripts
|
|
|
|
def get_script(self):
|
|
"""Get final script."""
|
|
scripts = self.get_default_scripts()
|
|
scripts.extend(self.get_auxiliary())
|
|
scripts.extend([self.code])
|
|
final = 'setTimeout(function() {{ {} }}, 0)'.format(
|
|
'\n'.join(scripts))
|
|
return final
|
|
|
|
def frida_response(self, message, data):
|
|
"""Function to handle frida responses."""
|
|
if 'payload' in message:
|
|
msg = message['payload']
|
|
api_mon = 'MobSF-API-Monitor: '
|
|
aux = '[AUXILIARY] '
|
|
if not isinstance(msg, str):
|
|
msg = str(msg)
|
|
if msg.startswith(api_mon):
|
|
self.write_log(self.api_mon, msg.replace(api_mon, ''))
|
|
elif msg.startswith(aux):
|
|
self.write_log(self.frida_log,
|
|
msg.replace(aux, '[*] ') + '\n')
|
|
else:
|
|
logger.debug('[Frida] %s', msg)
|
|
self.write_log(self.frida_log, msg + '\n')
|
|
else:
|
|
logger.error('[Frida] %s', message)
|
|
|
|
def connect(self):
|
|
"""Connect to Frida Server."""
|
|
session = None
|
|
try:
|
|
env = Environment()
|
|
self.clean_up()
|
|
env.run_frida_server()
|
|
device = frida.get_device(get_device(), settings.FRIDA_TIMEOUT)
|
|
pid = device.spawn([self.package])
|
|
device.resume(pid)
|
|
logger.info('Spawning %s', self.package)
|
|
time.sleep(2)
|
|
session = device.attach(pid)
|
|
except frida.ServerNotRunningError:
|
|
logger.warning('Frida server is not running')
|
|
self.connect()
|
|
except frida.TimedOutError:
|
|
logger.error('Timed out while waiting for device to appear')
|
|
except (frida.ProcessNotFoundError,
|
|
frida.TransportError,
|
|
frida.InvalidOperationError):
|
|
pass
|
|
except Exception:
|
|
logger.exception('Error Connecting to Frida')
|
|
try:
|
|
if session:
|
|
script = session.create_script(self.get_script())
|
|
script.on('message', self.frida_response)
|
|
script.load()
|
|
sys.stdin.read()
|
|
script.unload()
|
|
session.detach()
|
|
except Exception:
|
|
logger.exception('Error Connecting to Frida')
|
|
|
|
def clean_up(self):
|
|
if is_file_exists(self.api_mon):
|
|
os.remove(self.api_mon)
|
|
if is_file_exists(self.frida_log):
|
|
os.remove(self.frida_log)
|
|
|
|
def write_log(self, file_path, data):
|
|
with open(file_path, 'a') as flip:
|
|
flip.write(data)
|