def final_test(request): """Collecting Data and Cleanup""" global TCP_SERVER_MODE print("\n[INFO] Collecting Data and Cleaning Up") try: if request.method == 'POST': data = {} md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.findall(r";|\$\(|\|\||&&", package): print("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') if re.match('^[0-9a-f]{32}$', md5_hash): # Stop ScreenCast Client if it is running TCP_SERVER_MODE = "off" base_dir = settings.BASE_DIR apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') toolsdir = os.path.join(base_dir, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) # Change to check output of subprocess when analysis is done # Can't RCE os.system(adb + ' -s ' + get_identifier() + ' logcat -d dalvikvm:W ActivityManager:I > "' + apk_dir + 'logcat.txt"') print("\n[INFO] Downloading Logcat logs") subprocess.call([ adb, "-s", get_identifier(), "pull", "/data/data/de.robv.android.xposed.installer/log/error.log", apk_dir + "x_logcat.txt" ]) print("\n[INFO] Downloading Droidmon API Monitor Logcat logs") # Can't RCE os.system(adb + ' -s ' + get_identifier() + ' shell dumpsys > "' + apk_dir + 'dump.txt"') print("\n[INFO] Downloading Dumpsys logs") subprocess.call([ adb, "-s", get_identifier(), "shell", "am", "force-stop", package ]) print("\n[INFO] Stopping Application") subprocess.call([ adb, "-s", get_identifier(), "shell", "am", "force-stop", "opensecurity.screencast" ]) print("\n[INFO] Stopping ScreenCast Service") data = {'final': 'yes'} return HttpResponse(json.dumps(data), content_type='application/json') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Clean Up") return HttpResponseRedirect('/error/')
def final_test(request): """Collecting Data and Cleanup""" global TCP_SERVER_MODE logger.info("Collecting Data and Cleaning Up") try: if request.method == 'POST': data = {} md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.findall(r";|\$\(|\|\||&&", package): return print_n_send_error_response(request, "Possible RCE Attack", True) if re.match('^[0-9a-f]{32}$', md5_hash): # Stop ScreenCast Client if it is running TCP_SERVER_MODE = "off" base_dir = settings.BASE_DIR apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') adb = getADB() # Change to check output of subprocess when analysis is done # Can't RCE os.system(adb + ' -s ' + get_identifier() + ' logcat -d dalvikvm:W ActivityManager:I > "' + apk_dir + 'logcat.txt"') logger.info("Downloading Logcat logs") adb_command([ "pull", "/data/data/de.robv.android.xposed.installer/log/error.log", apk_dir + "x_logcat.txt" ]) logger.info("Downloading Droidmon API Monitor Logcat logs") # Can't RCE os.system(adb + ' -s ' + get_identifier() + ' shell dumpsys > "' + apk_dir + 'dump.txt"') logger.info("Downloading Dumpsys logs") adb_command(["am", "force-stop", package], True) logger.info("Stopping Application") adb_command(["am", "force-stop", "opensecurity.screencast"], True) logger.info("Stopping ScreenCast Service") data = {'final': 'yes'} return HttpResponse(json.dumps(data), content_type='application/json') else: return print_n_send_error_response(request, "Invalid Scan Hash", True) else: return print_n_send_error_response(request, "Only POST allowed", True) except: PrintException("Data Collection & Clean Up") return print_n_send_error_response( request, "Data Collection & Clean Up failed", True)
def screen_cast(request): """Start or Stop ScreenCast Feature""" print("\n[INFO] Invoking ScreenCast Service in VM/Device") try: global TCP_SERVER_MODE data = {} if request.method == 'POST': mode = request.POST['mode'] toolsdir = os.path.join( settings.BASE_DIR, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": ip_address = '10.0.2.2' else: ip_address = settings.SCREEN_IP port = str(settings.SCREEN_PORT) if mode == "on": args = [adb, "-s", get_identifier(), "shell", "am", "startservice", "-a", ip_address + ":" + port, "opensecurity.screencast/.StartScreenCast"] data = {'status': 'on'} TCP_SERVER_MODE = "on" elif mode == "off": args = [adb, "-s", get_identifier(), "shell", "am", "force-stop", "opensecurity.screencast"] data = {'status': 'off'} TCP_SERVER_MODE = "off" if (mode in ["on", "off"]): try: subprocess.call(args) screen_trd = threading.Thread(target=screencast_service) screen_trd.setDaemon(True) screen_trd.start() except: PrintException("[ERROR] Casting Screen") data = {'status': 'error'} return HttpResponse(json.dumps(data), content_type='application/json') else: data = {'status': 'failed'} else: data = {'status': 'failed'} return HttpResponse(json.dumps(data), content_type='application/json') except: PrintException("[ERROR] Casting Screen") return HttpResponseRedirect('/error/')
def final_test(request): """Collecting Data and Cleanup.""" global TCP_SERVER_MODE logger.info('Collecting Data and Cleaning Up') try: if request.method == 'POST': data = {} md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.findall(r';|\$\(|\|\||&&', package): return print_n_send_error_response(request, 'Possible RCE Attack', True) if re.match('^[0-9a-f]{32}$', md5_hash): # Stop ScreenCast Client if it is running TCP_SERVER_MODE = 'off' apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') adb = get_adb() # Change to check output of subprocess when analysis is done # Can't RCE cmd = ('{} -s {} logcat -d dalvikvm:' 'W ActivityManager:I > "{}logact.txt"').format( adb, get_identifier(), apk_dir) os.system(cmd) logger.info('Downloading Logcat logs') xposed_out = ('/data/data/' 'de.robv.android.xposed.installer' '/log/error.log') adb_command(['pull', xposed_out, apk_dir + 'x_logcat.txt']) logger.info('Downloading Droidmon API Monitor Logcat logs') # Can't RCE cmd = '{} -s {} shell dumpsys > "{}dump.txt"'.format( adb, get_identifier(), apk_dir) os.system(cmd) logger.info('Downloading Dumpsys logs') adb_command(['am', 'force-stop', package], True) logger.info('Stopping Application') adb_command(['am', 'force-stop', 'opensecurity.screencast'], True) logger.info('Stopping ScreenCast Service') data = {'final': 'yes'} return HttpResponse(json.dumps(data), content_type='application/json') else: return print_n_send_error_response(request, 'Invalid Scan Hash', True) else: return print_n_send_error_response(request, 'Only POST allowed', True) except Exception: err = 'Data Collection & Clean Up failed' logger.exception(err) return print_n_send_error_response(request, err, True)
def final_test(request): """Collecting Data and Cleanup""" global TCP_SERVER_MODE print("\n[INFO] Collecting Data and Cleaning Up") try: if request.method == 'POST': data = {} md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.findall(r";|\$\(|\|\||&&", package): print("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') if re.match('^[0-9a-f]{32}$', md5_hash): # Stop ScreenCast Client if it is running TCP_SERVER_MODE = "off" base_dir = settings.BASE_DIR apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') adb = getADB() # Change to check output of subprocess when analysis is done # Can't RCE os.system(adb + ' -s ' + get_identifier() + ' logcat -d dalvikvm:W ActivityManager:I > "' + apk_dir + 'logcat.txt"') print("\n[INFO] Downloading Logcat logs") adb_command(["pull", "/data/data/de.robv.android.xposed.installer/log/error.log", apk_dir + "x_logcat.txt"]) print("\n[INFO] Downloading Droidmon API Monitor Logcat logs") # Can't RCE os.system(adb + ' -s ' + get_identifier() + ' shell dumpsys > "' + apk_dir + 'dump.txt"') print("\n[INFO] Downloading Dumpsys logs") adb_command(["am", "force-stop", package], True) print("\n[INFO] Stopping Application") adb_command( ["am", "force-stop", "opensecurity.screencast"], True) print("\n[INFO] Stopping ScreenCast Service") data = {'final': 'yes'} return HttpResponse(json.dumps(data), content_type='application/json') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Clean Up") return HttpResponseRedirect('/error/')
def getPidByPackage(adb, package): params = [adb, "-s", get_identifier(), "shell", "ps", "|grep", package] findPid = None retry = 0 def tryOnce(): pid_result = str(subprocess.check_output(params), encoding="utf-8") pid_result = pid_result.split("\n") for ps_item in pid_result: ps_item = ps_item.strip().split() #['u0_a19', '2396', '295', '580112', '51832', 'ffffffff', '94cca347', 'R', 'com.kuxuexi.math.high'] if (len(ps_item) < 5): continue pid = ps_item[1] packagename = ps_item[-1] if (packagename == package): return pid return None for retry in range(0, 3): findPid = tryOnce() if (findPid is not None): break time.sleep(3) if (findPid is not None): print("package: %s ==> pid: %s" % (package, findPid)) return findPid raise Exception("pid not found by packageName: %s", package)
def help_boot_avd(): try: emulator = get_identifier() # Wait for the adb to answer args = [settings.ADB_BINARY, "-s", emulator, "wait-for-device"] logger.info("help_boot_avd: wait-for-device") subprocess.call(args) # Make sure adb running as root logger.info("help_boot_avd: root") adb_command(['root']) # Make sure adb running as root logger.info("help_boot_avd: remount") adb_command(['remount']) # Make sure the system verity feature is disabled (Obviously, modified the system partition) logger.info("help_boot_avd: disable-verity") adb_command(['disable-verity']) # Make SELinux permissive - in case SuperSu/Xposed didn't patch things right logger.info("help_boot_avd: setenforce") adb_command(['setenforce', '0'], shell=True) logger.info("help_boot_avd: finished!") return True except: PrintException("help_boot_avd") return False
def auto_app_test(adb, app_info): print(u'\n[INFO] 开始自动化测试...') # monkey script 测试,用于进入初始化界面 monkey_script_test(adb, app_info) packagename = app_info['packagename'] # monkey 测试,输出太多,重定向输出 p = subprocess.Popen([ adb, '-s', get_identifier(), 'shell', 'monkey', '-p', packagename, '--ignore-crashes', '--ignore-timeouts', '--monitor-native-crashes', '-v', '-v', '-v', '1000' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 设置超时检查 start_time = time.time() while True: if p.poll() is not None: #useless_out, useless_err = p.communicate() break if time.time() - start_time > 60: p.terminate() break time.sleep(0.5) # TODO: 添加其他测试方法 return
def help_boot_avd(): try: emulator = get_identifier() # Wait for the adb to answer args = [settings.ADB_BINARY, "-s", emulator, "wait-for-device"] print("[INFO] help_boot_avd: wait-for-device") subprocess.call(args) # Make sure adb running as root print("[INFO] help_boot_avd: root") adb_command(['root']) # Make sure adb running as root print("[INFO] help_boot_avd: remount") adb_command(['remount']) # Make sure the system verity feature is disabled (Obviously, modified the system partition) print("[INFO] help_boot_avd: disable-verity") adb_command(['disable-verity']) # Make SELinux permissive - in case SuperSu/Xposed didn't patch things right print("[INFO] help_boot_avd: setenforce") adb_command(['setenforce', '0'], shell=True) print("[INFO] help_boot_avd: finished!") return True except: PrintException("[ERROR] help_boot_avd") return False
def auto_app_test(app_info): base_dir = settings.BASE_DIR toolsdir = os.path.join(base_dir, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) print(u'\n[INFO] 开始自动化测试...') # monkey script 测试,用于进入初始化界面 monkey_script_test(adb, app_info) packagename = app_info['packagename'] # monkey 测试,输出太多,重定向输出 p = subprocess.Popen([ adb, '-s', get_identifier(), 'shell', 'monkey', '-p', packagename, '--ignore-crashes', '--ignore-timeouts', '--monitor-native-crashes', '-v', '-v', '-v', '300' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 设置超时检查 start_time = time.time() while True: if p.poll() is not None: #useless_out, useless_err = p.communicate() break if time.time() - start_time > 60: p.terminate() break time.sleep(0.5) # TODO: 添加其他测试方法 return
def execute_adb(request): """Execute ADB Commands""" print("\n[INFO] Executing ADB Commands") try: if request.method == 'POST': data = {} cmd = request.POST['cmd'] ''' Allow dangerous chars as it's functional TODO: Deal with it. ''' adb = getADB() args = [adb, "-s", get_identifier()] + cmd.split(' ') resp = "error" try: resp = adb except: PrintException("[ERROR] Executing ADB Commands") data = {'cmd': 'yes', 'resp': resp.decode("utf8", "ignore")} return HttpResponse(json.dumps(data), content_type='application/json') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Executing ADB Commands") return HttpResponseRedirect('/error/')
def execute_adb(request): """Execute ADB Commands""" print("\n[INFO] Executing ADB Commands") try: if request.method == 'POST': data = {} cmd = request.POST['cmd'] ''' Allow dangerous chars as it's functional TODO: Deal with it. ''' toolsdir = os.path.join( settings.BASE_DIR, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) args = [adb, "-s", get_identifier()] + cmd.split(' ') resp = "error" try: resp = subprocess.check_output(args) except: PrintException("[ERROR] Executing ADB Commands") data = {'cmd': 'yes', 'resp': resp.decode("utf8", "ignore")} return HttpResponse(json.dumps(data), content_type='application/json') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Executing ADB Commands") return HttpResponseRedirect('/error/')
def touch(request): """Sending Touch Events""" print("\n[INFO] Sending Touch Events") try: data = {} if (request.method == 'POST') and (is_number(request.POST['x'])) and (is_number(request.POST['y'])): x_axis = request.POST['x'] y_axis = request.POST['y'] toolsdir = os.path.join( settings.BASE_DIR, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) args = [adb, "-s", get_identifier(), "shell", "input", "tap", x_axis, y_axis] data = {'status': 'success'} try: subprocess.call(args) except: data = {'status': 'error'} PrintException("[ERROR] Performing Touch Action") else: data = {'status': 'failed'} return HttpResponse(json.dumps(data), content_type='application/json') except: PrintException("[ERROR] Sending Touch Events") return HttpResponseRedirect('/error/')
def clip_dump(request): """Dump Android ClipBoard""" print("\n[INFO] Starting Clipboard Dump Service in VM/Device") try: data = {} if request.method == 'POST': toolsdir = os.path.join( settings.BASE_DIR, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) args = [adb, "-s", get_identifier(), "shell", "am", "startservice", "opensecurity.clipdump/.ClipDumper"] try: subprocess.call(args) data = {'status': 'success'} except: PrintException("[ERROR] Dumping Clipboard") data = {'status': 'error'} else: data = {'status': 'failed'} return HttpResponse(json.dumps(data), content_type='application/json') except: PrintException("[ERROR] Dumping Clipboard") return HttpResponseRedirect('/error/')
def getPidByPackage(adb, package): params = [adb, "-s", get_identifier(), "shell", "ps"] findPid = None retry = 0 while retry < 3 and findPid is None: retry = retry + 1 pid_result = subprocess.check_output(params) pid_result = pid_result.split("\n") for ps_item in pid_result: ps_item = ps_item.strip().split() #['u0_a19', '2396', '295', '580112', '51832', 'ffffffff', '94cca347', 'R', 'com.kuxuexi.math.high'] if (len(ps_item) < 5): continue pid = ps_item[1] packagename = ps_item[-1] if (packagename == package): findPid = pid break if findPid is None: time.sleep(1) if findPid is not None: print("package: %s ==> pid: %s" % (package, findPid)) return findPid raise Exception("pid not found by packageName: %s", package) raise Exception("pid not found by packageName")
def download_logs(adb, download_dir): subprocess.call([ adb, "-s", get_identifier(), "pull", "/data/data/de.robv.android.xposed.installer/log/error.log", download_dir + "x_logcat_temp.txt" ]) print("\n[INFO] Downloading Droidmon API Monitor Logcat logs") return
def stop_avd(adb): """Stop AVD""" print("\n[INFO] Stopping MobSF Emulator") try: # adb -s emulator-xxxx emu kill FNULL = open(os.devnull, 'w') args = [adb, '-s', get_identifier(), 'emu', 'kill'] subprocess.call(args, stderr=FNULL) except: PrintException("[ERROR] Stopping MobSF Emulator")
def take_screenshot(request): """Take Screenshot""" print("\n[INFO] Taking Screenshot") try: if request.method == 'POST': md5_hash = request.POST['md5'] if re.match('^[0-9a-f]{32}$', md5_hash): data = {} rand_int = random.randint(1, 1000000) base_dir = settings.BASE_DIR # make sure that list only png from this directory screen_dir = os.path.join( settings.UPLD_DIR, md5_hash + '/screenshots-apk/') if not os.path.exists(screen_dir): os.makedirs(screen_dir) toolsdir = os.path.join( base_dir, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) subprocess.call([adb, "-s", get_identifier(), "shell", "screencap", "-p", "/data/local/screen.png"]) subprocess.call([adb, "-s", get_identifier(), "pull", "/data/local/screen.png", screen_dir + "screenshot-" + str(rand_int) + ".png"]) print("\n[INFO] Screenshot Taken") data = {'screenshot': 'yes'} return HttpResponse(json.dumps(data), content_type='application/json') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Taking Screenshot") return HttpResponseRedirect('/error/')
def download_logs(adb, download_dir): log_temp_path = os.path.join(download_dir, 'x_logcat_temp.txt') subprocess.call([ adb, "-s", get_identifier(), "pull", "/data/data/de.robv.android.xposed.installer/log/error.log", log_temp_path ]) print(time.time(), "[INFO] Downloading Droidmon API Monitor Logcat logs", log_temp_path) # TODO: 下载其他有用文件 return
def clean(): base_dir = settings.BASE_DIR toolsdir = os.path.join(base_dir, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) print("\n[INFO] Stopping ADB") subprocess.call([adb, "-s", get_identifier(), "kill-server"]) # Close VM args = [settings.VBOX, 'controlvm', settings.UUID, 'poweroff'] subprocess.call(args) print("\n[INFO] VM Closed") return
def download_logs_thread(adb, download_dir, package): #change to strace the pid ''' step1: get pid by ps | grep packageName step2: adb shell strace -T -tt -e trace=all -p pid > to windows_file ''' if not os.path.isdir(download_dir): os.makedirs(download_dir) pid = getPidByPackage(adb, package) print("package: %s ==> pid: %s" % (package, pid)) start_time = time.asctime(time.localtime(time.time())) print("strace start at: %s" % start_time) params = [ adb, "-s", get_identifier(), "shell", "strace", "-T", "-tt", "-e", "trace=all", "-p", pid ] strace = subprocess.Popen(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE) strace_file = os.path.join(download_dir, 'systemcall.txt') with open(strace_file, 'w') as sc_file: try: # strace for 60 seconds outs, errs = strace.communicate(timeout=60) except subprocess.TimeoutExpired: strace.kill() outs, errs = strace.communicate() sinfo = str(outs.read()) end_time = time.asctime(time.localtime(time.time())) print("strace end at: %s" % end_time) print("sinfo len: %s" % len(sinfo)) if (Is_Downloading): sc_file.write(sinfo) # global Is_Downloading # while Is_Downloading: # download_logs(adb, download_dir) # log_path = os.path.join(download_dir, 'x_logcat.txt') # log_temp_path = os.path.join(download_dir, 'x_logcat_temp.txt') # if os.path.exists(log_path): # log_size = os.path.getsize(log_path) # log_temp_size = os.path.getsize(log_temp_path) # if log_size < log_temp_size: # shutil.copy(log_temp_path, log_path) # else: # shutil.copy(log_temp_path, log_path) # os.remove(log_temp_path) # time.sleep(10) return
def download_logs_thread(adb, download_dir, package): #change to strace the pid ''' step1: get pid by ps | grep packageName step2: strace, result store on vm adb shell strace -T -tt -e trace=all -f -F -o /data/local/tmp/strace -p 2395 step3: pull to pc ''' if not os.path.isdir(download_dir): os.makedirs(download_dir) #step 1 pid = getPidByPackage(adb, package) #step 2 params = [adb, "-s", get_identifier(), "shell",\ "strace", "-T", "-tt", "-e", "trace=all", "-f", "-F", "-o", "/data/local/tmp/strace",\ "-p", pid] strace = subprocess.Popen(params) t_start = time.time() print("strace start: %s" % time.asctime(time.localtime(time.time()))) try: # strace for 60 seconds _, _ = strace.communicate(timeout=100) except subprocess.TimeoutExpired: strace.kill() end_time = time.asctime(time.localtime(time.time())) print("strace end at: %s" % end_time) #step3 strace_file = os.path.join(download_dir, 'systemcall.txt') subprocess.call([ adb, "-s", get_identifier(), "pull", "/data/local/tmp/strace", strace_file ]) return
def avd_load_wait(adb): """Wait for AVD Load""" emulator = get_identifier() print("[INFO] Wait for emulator to load") args = [adb, "-s", emulator, "wait-for-device"] subprocess.call(args) print("[INFO] Wait for dev.boot_complete loop") while True: args = [adb, "-s", emulator, "shell", "getprop", "dev.bootcomplete"] try: result = subprocess.check_output(args) except: result = None if result is not None and result.strip() == "1": break else: time.sleep(1) print("[INFO] Wait for sys.boot_complete loop") while True: args = [adb, "-s", emulator, "shell", "getprop", "sys.boot_completed"] try: result = subprocess.check_output(args) except: result = None if result is not None and result.strip() == "1": break else: time.sleep(1) print("[INFO] Wait for svc.boot_complete loop") while True: args = [adb, "-s", emulator, "shell", "getprop", "init.svc.bootanim"] try: result = subprocess.check_output(args) except: result = None if result is not None and result.strip() == "stopped": break else: time.sleep(1) time.sleep(5) # Remount the partitions for RW subprocess.call([adb, "-s", emulator, "remount"])
def monkey_test(adb, app_info): welcome_jump(adb, app_info) packagename = app_info['packagename'] p = subprocess.Popen([ adb, '-s', get_identifier(), 'shell', 'monkey', '-p', packagename, '--ignore-crashes', '--ignore-timeouts', '--monitor-native-crashes', '-v', '-v', '-v', '1000' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) start_time = time.time() while check_run_state(): if p.poll() is not None: #useless_out, useless_err = p.communicate() break if time.time() - start_time > 60: break time.sleep(0.5) p.terminate() return
def dump_data(request): """Downloading Application Data from Device""" print("\n[INFO] Downloading Application Data from Device") try: if request.method == 'POST': data = {} package = request.POST['pkg'] md5_hash = request.POST['md5'] if re.match('^[0-9a-f]{32}$', md5_hash): if re.findall(r";|\$\(|\|\||&&", package): print("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') base_dir = settings.BASE_DIR apk_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') toolsdir = os.path.join( base_dir, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) # Let's try to close Proxy a bit early as we don't have much # control on the order of thread execution stop_capfuzz(settings.PORT) print("\n[INFO] Deleting Dump Status File") subprocess.call([adb, "-s", get_identifier(), "shell", "rm", "/sdcard/mobsec_status"]) print("\n[INFO] Creating TAR of Application Files.") if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": # tar -cvf /data/local/"+pkg+".tar /data/data/"+pkg+"/", subprocess.call([adb, "-s", get_identifier(), "shell", "/data/local/tmp/tar.sh", package]) else: subprocess.call([adb, "-s", get_identifier(), "shell", "am", "startservice", "-a", package, "opensecurity.ajin.datapusher/.GetPackageLocation"]) print("\n[INFO] Waiting for TAR dump to complete...") if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_REAL_DEVICE": timeout = settings.DEVICE_TIMEOUT else: timeout = settings.VM_TIMEOUT start_time = time.time() while True: current_time = time.time() if b"MOBSEC-TAR-CREATED" in subprocess.check_output([adb, "-s", get_identifier(), "shell", "cat", "/sdcard/mobsec_status"]): break if (current_time - start_time) > timeout: print( "\n[ERROR] TAR Generation Failed. Process timed out.") break print("\n[INFO] Dumping Application Files from Device/VM") subprocess.call([adb, "-s", get_identifier(), "pull", "/data/local/" + package + ".tar", apk_dir + package + ".tar"]) if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": stop_avd(adb) print("\n[INFO] Stopping ADB") subprocess.call([adb, "-s", get_identifier(), "kill-server"]) data = {'dump': 'yes'} return HttpResponse(json.dumps(data), content_type='application/json') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Downloading Application Data from Device") return HttpResponseRedirect('/error/')
def mobsf_ca(request): """Install and Remove MobSF Proxy RootCA""" try: if request.method == 'POST': data = {} act = request.POST['action'] rootca = get_ca_dir() toolsdir = os.path.join( settings.BASE_DIR, 'DynamicAnalyzer/tools/') # TOOLS DIR adb = getADB(toolsdir) if act == "install": print("\n[INFO] Installing RootCA") subprocess.call([adb, "-s", get_identifier(), "push", rootca, "/data/local/tmp/" + settings.ROOT_CA]) if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": # For some reason, avd emulator does not have cp binary subprocess.call([adb, "-s", get_identifier(), "shell", "/data/local/tmp/busybox", "cp", "/data/local/tmp/" + settings.ROOT_CA, "/system/etc/security/cacerts/" + settings.ROOT_CA]) subprocess.call([adb, "-s", get_identifier(), "shell", "chmod", "644", "/system/etc/security/cacerts/" + settings.ROOT_CA]) else: subprocess.call([adb, "-s", get_identifier(), "shell", "su", "-c", "cp", "/data/local/tmp/" + settings.ROOT_CA, "/system/etc/security/cacerts/" + settings.ROOT_CA]) subprocess.call([adb, "-s", get_identifier(), "shell", "su", "-c", "chmod", "644", "/system/etc/security/cacerts/" + settings.ROOT_CA]) subprocess.call([adb, "-s", get_identifier(), "shell", "rm", "/data/local/tmp/" + settings.ROOT_CA]) data = {'ca': 'installed'} elif act == "remove": print("\n[INFO] Removing RootCA") if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": subprocess.call([adb, "-s", get_identifier(), "shell", "rm", "/system/etc/security/cacerts/" + settings.ROOT_CA]) else: subprocess.call([adb, "-s", get_identifier(), "shell", "su", "-c", "rm", "/system/etc/security/cacerts/" + settings.ROOT_CA]) data = {'ca': 'removed'} return HttpResponse(json.dumps(data), content_type='application/json') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] RootCA Handler") return HttpResponseRedirect('/error/')
def activity_tester(request): """Activity Tester""" print("\n[INFO] Activity Tester") try: md5_hash = request.POST['md5'] package = request.POST['pkg'] if re.match('^[0-9a-f]{32}$', md5_hash): if re.findall(r";|\$\(|\|\||&&", package): print("[ATTACK] Possible RCE") return HttpResponseRedirect('/error/') if request.method == 'POST': base_dir = settings.BASE_DIR app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') toolsdir = os.path.join( base_dir, 'DynamicAnalyzer/tools/') # TOOLS DIR screen_dir = os.path.join(app_dir, 'screenshots-apk/') if not os.path.exists(screen_dir): os.makedirs(screen_dir) data = {} adb = getADB(toolsdir) static_android_db = StaticAnalyzerAndroid.objects.filter( MD5=md5_hash) if static_android_db.exists(): print("\n[INFO] Fetching Activity List from DB") activities = python_list(static_android_db[0].ACTIVITIES) if activities: act_no = 0 print("\n[INFO] Starting Activity Tester...") print("\n[INFO] " + str(len(activities)) + " Activities Identified") for line in activities: try: act_no += 1 print("\n[INFO] Launching Activity - " + str(act_no) + ". " + line) subprocess.call( [adb, "-s", get_identifier(), "shell", "am", "start", "-n", package + "/" + line]) # AVD is much slower, it should get extra time if settings.ANDROID_DYNAMIC_ANALYZER == "MobSF_AVD": wait(8) else: wait(4) subprocess.call( [adb, "-s", get_identifier(), "shell", "screencap", "-p", "/data/local/screen.png"]) #? get appended from Air :-() if activity names are used subprocess.call( [adb, "-s", get_identifier(), "pull", "/data/local/screen.png", screen_dir + "act-" + str(act_no) + ".png"]) print("\n[INFO] Activity Screenshot Taken") subprocess.call([adb, "-s", get_identifier(), "shell", "am", "force-stop", package]) print("\n[INFO] Stopping App") except: PrintException("Activity Tester") data = {'acttest': 'done'} else: print("\n[INFO] Activity Tester - No Activity Found!") data = {'acttest': 'noact'} return HttpResponse(json.dumps(data), content_type='application/json') else: print("\n[ERROR] Entry does not exist in DB.") return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') else: return HttpResponseRedirect('/error/') except: PrintException("[ERROR] Activity Tester") return HttpResponseRedirect('/error/')
def monkey_script_test(adb, app_info): monkey_script_pattern = ''' type=user count=10 speed=1.0 start data >> captureDispatchPointer(0,0,0,200,600,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,200,600,1,1,-1,1,1,0,0) UserWait(1000) captureDispatchPointer(0,0,0,400,600,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,400,600,1,1,-1,1,1,0,0) UserWait(1000) captureDispatchPointer(0,0,0,600,600,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,600,600,1,1,-1,1,1,0,0) UserWait(1000) captureDispatchPointer(0,0,0,200,800,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,200,800,1,1,-1,1,1,0,0) UserWait(1000) captureDispatchPointer(0,0,0,600,1000,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,600,1000,1,1,-1,1,1,0,0) UserWait(3000) LaunchActivity({packagename}, {mainactivity}) UserWait(5000) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) Drag({screen_x_right},{screen_y_middle},{screen_x_left},{screen_y_middle},70) UserWait({drag_wait}) captureDispatchPointer(0,0,0,{screen_x_middle},100,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},100,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},200,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},200,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},300,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},300,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},400,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},400,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},500,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},500,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},600,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},600,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},700,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},700,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},800,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},800,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},900,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},900,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},1000,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},1000,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},1100,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},1100,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,0,{screen_x_middle},1200,1,1,-1,1,1,0,0) captureDispatchPointer(0,0,1,{screen_x_middle},1200,1,1,-1,1,1,0,0) UserWait(1000) captureDispatchPress(4) captureDispatchPress(4) captureDispatchPress(4) ''' drag_wait = 750 packagename = app_info['packagename'] mainactivity = app_info['mainactivity'] if mainactivity.startswith('.'): mainactivity = packagename + mainactivity screen_x_right = 750 screen_y_middle = 640 screen_x_left = 50 screen_x_middle = 400 monkey_script_data = monkey_script_pattern.format( drag_wait=drag_wait, packagename=packagename, mainactivity=mainactivity, screen_x_right=screen_x_right, screen_y_middle=screen_y_middle, screen_x_left=screen_x_left, screen_x_middle=screen_x_middle) UPLOAD_DIR = settings.UPLD_DIR monkey_script_file_name = os.path.join( os.path.join(UPLOAD_DIR, app_info['file_md5']), 'monkey_script.txt') with open(monkey_script_file_name, 'w') as f: f.write(monkey_script_data) subprocess.call([ adb, "-s", get_identifier(), "push", monkey_script_file_name, "/data/local/tmp" ]) subprocess.call([ adb, "-s", get_identifier(), "shell", "monkey", "-f", "/data/local/tmp/monkey_script.txt", "1" ]) print(u'\n[INFO] 跳过初始化界面') return