def logcat(request): logger.info('Starting Logcat streaming') try: pkg = request.GET.get('package') if pkg: if not strict_package_check(pkg): return print_n_send_error_response(request, 'Invalid package name') template = 'dynamic_analysis/android/logcat.html' return render(request, template, {'package': pkg}) app_pkg = request.GET.get('app_package') if app_pkg: if not strict_package_check(app_pkg): return print_n_send_error_response(request, 'Invalid package name') adb = os.environ['MOBSF_ADB'] g = proc.Group() g.run([adb, 'logcat', app_pkg + ':V', '*:*']) def read_process(): while g.is_pending(): lines = g.readlines() for _, line in lines: time.sleep(.01) yield 'data:{}\n\n'.format(line) return StreamingHttpResponse(read_process(), content_type='text/event-stream') return print_n_send_error_response(request, 'Invalid parameters') except Exception: logger.exception('Logcat Streaming') err = 'Error in Logcat streaming' return print_n_send_error_response(request, err)
def instrument(request): """Instrument app with frida.""" data = {} try: logger.info('Starting Instrumentation') package = request.POST['package'] md5_hash = request.POST['hash'] default_hooks = request.POST['default_hooks'] auxiliary_hooks = request.POST['auxiliary_hooks'] code = request.POST['frida_code'] # Fill extras extras = {} class_name = request.POST.get('cls_name') if class_name: extras['cls_name'] = class_name.strip() class_search = request.POST.get('cls_search') if class_search: extras['cls_search'] = class_search.strip() cls_trace = request.POST.get('cls_trace') if cls_trace: extras['cls_trace'] = cls_trace.strip() if (is_attack_pattern(default_hooks) or not strict_package_check(package) or not is_md5(md5_hash)): return invalid_params() frida_obj = Frida(md5_hash, package, default_hooks.split(','), auxiliary_hooks.split(','), extras, code) trd = threading.Thread(target=frida_obj.connect) trd.daemon = True trd.start() data = {'status': 'ok'} except Exception as exp: logger.exception('Instrumentation failed') data = {'status': 'failed', 'message': str(exp)} return json_response(data)
def collect_logs(request): """Collecting Data and Cleanup.""" logger.info('Collecting Data and Cleaning Up') data = {} try: env = Environment() md5_hash = request.POST['hash'] package = request.POST['package'] if (not strict_package_check(package) or not is_md5(md5_hash)): return invalid_params() apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') lout = os.path.join(apk_dir, 'logcat.txt') dout = os.path.join(apk_dir, 'dump.txt') logger.info('Downloading logcat logs') logcat = env.adb_command(['logcat', '-d', package + ':V', '*:*']) with open(lout, 'wb') as flip: flip.write(logcat) logger.info('Downloading dumpsys logs') dumpsys = env.adb_command(['dumpsys'], True) with open(dout, 'wb') as flip: flip.write(dumpsys) if env.get_android_version() < 5: download_xposed_log(apk_dir) env.adb_command(['am', 'force-stop', package], True) logger.info('Stopping app') # Unset Global Proxy env.unset_global_proxy() data = {'status': 'ok'} except Exception as exp: logger.exception('Data Collection & Clean Up failed') data = {'status': 'failed', 'message': str(exp)} return json_response(data)
def class_trace(classes): """Trace all methods of a class.""" filtered = [] if ',' not in classes: filtered.append(classes.strip()) else: for clz in classes.split(','): filtered.append(clz.strip()) for klz in filtered: if not strict_package_check(klz): return '' content = get_content('class_trace.js') return content.replace('{{CLASSES}}', str(filtered))
def get_methods(klazz): """Get Class methods and implementations.""" if not strict_package_check(klazz): return '' content = get_content('get_methods.js') return content.replace('{{CLASS}}', klazz)