def explore_service(self, service, package, droidmate_conn): cmd = 'am startservice -n \"' + package + '/' + service + '\"' adb.adb_shell(cmd, device="emulator-5554", timeout=self.timeout) # DroidMate exploration if self.droidmate: try: droidmate_conn.send_go() except RuntimeError: self.droidmate = False else: time.sleep(3)
def setup(self): base_directory = os.getcwd() # setup command to start vpn server server_cmd = base_directory + '/vpn/VpnServer tun0' \ ' 40009 test -m 1400 -a 10.0.0.2 32 -d 8.8.8.8 -r 0.0.0.0 0 -z ' + self.package # try to start vpn server try: self.vpn_server = Popen(server_cmd, shell=True) except CalledProcessError as e: raise RuntimeError(e.output) # tcpdump command tcpdump_cmd = 'tcpdump -i tun0 -v -w ' + self.path # try to start tcpdump try: self.tcpdump = Popen(tcpdump_cmd, shell=True, stderr=PIPE) except CalledProcessError as e: raise RuntimeError(e.output) # check if tcpdump started successful test_err = str(self.tcpdump.stderr.readline(), "ascii") if "listening" not in test_err: raise RuntimeError(test_err) # start vpn app app_success, app_output = adb.adb_shell( 'am start -n com.example.tobki42.vpnsolution/.MainActivity', device="emulator-5554") # check if vpn app started successful if (not app_success) or ("Starting" not in app_output): self.vpn_server.kill() self.tcpdump.kill() raise RuntimeError(app_output) self.running = True return
def explore_activity(self, activity, package, droidmate_conn): cmd = 'am start -n \"' + package + '/' + activity + '\"' adb.adb_shell(cmd, device="emulator-5554", timeout=self.timeout) # DroidMate exploration pid = self.get_pid(package) if self.droidmate: try: droidmate_conn.send_go() except RuntimeError: self.droidmate = False else: time.sleep(3) # force stop of app in case of errors cmd = 'am force-stop ' + package adb.adb_shell(cmd, device="emulator-5554", timeout=self.timeout) return pid
def explore_receiver(self, receiver: str, package: str, action: str, category: str, data: str, droidmate_conn: droidmate.Droidmate): cmd = 'am broadcast -n \"' + package + '/' + receiver + '\"' if action: cmd = cmd + ' -a ' + action if category: cmd = cmd + ' -c ' + category if data: cmd = cmd + ' -d ' + data adb.adb_shell(cmd, device="emulator-5554", timeout=self.timeout) # DroidMate exploration if self.droidmate: try: droidmate_conn.send_go() except RuntimeError: self.droidmate = False else: time.sleep(3)
def stimulate(self): count = 0 # iterate over list of all standard broadcast_actions while (not self.check_interrupted()) and (count < len( self.system_events)): action = self.system_events[count] count += 1 EventStimulation.log('Sending system event -- action: ' + action) # send broadcast to target apk EventStimulation.log( adb.adb_shell('am broadcast -a ' + action + ' -p ' + self.package)[1]) wait = randint(5, 12) EventStimulation.log('Waiting for ' + str(wait) + ' seconds') time.sleep(wait)
def get_pid(package: str): cmd = 'ps | grep ' + package count = 0 while True: output = adb.adb_shell(cmd, device="emulator-5554", timeout=180)[1] if output: break else: count += 1 if count > 20: raise TimeoutError time.sleep(1) try: return re.sub('\s+', ',', output).split(',')[1] except IndexError: return None
def handle_fail(app, path, x86): # delete invalid odex file adb.adb_shell("rm " + path, device="emulator-5554") # check if backup of the merged target app has been created ls_out = adb.adb_shell("ls /sdcard/", device="emulator-5554")[1] if app in ls_out: # get merged apk and pull it to host ls_list = ls_out.split("\r\n") app_merged_signed = [x for x in ls_list if app in x][0] adb.adb_pull("/sdcard/" + app_merged_signed, destination=app_merged_signed, device="emulator-5554", timeout=1200) # try to merge dex files with Dexmerger if not Artist.prepare_apk(app_merged_signed): return False # push the newly merged apk back to emulator adb.adb_push(app_merged_signed, destination="/sdcard/" + app + ".apk", device="emulator-5554") # run optimization and artist injections again try: os.remove(app_merged_signed) except CalledProcessError: pass dex2oat_cmd = "'export LD_LIBRARY_PATH=/data/app/saarland.cispa.artist.artistgui-1/" \ "lib/x86_64:/data/user/0/saarland.cispa.artist.artistgui/files/artist/lib/;" \ + "/data/user/0/saarland.cispa.artist.artistgui/files/artist/dex2oat " \ + "--oat-file=" + path \ + " --compiler-backend=Optimizing --compiler-filter=everything" \ " --generate-debug-info --compile-pic --checksum-rewriting" \ + " --dex-file=/sdcard/" + app + ".apk" \ + " --dex-location=/data/app/" + app + "-1/base.apk" if not x86: dex2oat_cmd += " --instruction-set=x86_64" \ " --instruction-set-features=smp,ssse3,sse4.1,sse4.2,-avx,-avx2" \ " --instruction-set-variant=x86_64 --instruction-set-features=default'" else: dex2oat_cmd += " --instruction-set=x86" \ " --instruction-set-features=smp,ssse3,sse4.1,sse4.2,-avx,-avx2" \ " --instruction-set-variant=x86 --instruction-set-features=default'" adb.adb_shell(dex2oat_cmd, device="emulator-5554") if "No such file or directory" not in adb.adb_shell("ls " + path)[1]: return True else: return False else: return False
def instrument(app, x86) -> (bool, str): # start artistgui instrumentation of target app activity = 'saarland.cispa.artist.artistgui' + '/.' + 'MainActivity' cmd = 'am start -n ' + activity + ' --es INTENT_EXTRA_PACKAGE ' + app (start_success, start_out) = adb.adb_shell(cmd, device='emulator-5554') # check if artistgui started successful if not start_success: return False, start_out # get path to base.odex if x86: path = "/data/app/" + app + "-1/oat/x86/base.odex" else: path = "/data/app/" + app + "-1/oat/x86_64/base.odex" # delete old odex file adb.adb_shell("rm " + path, device="emulator-5554") success = False # wait till new base.odex is created for i in range(0, 240): sleep(5) ls_out = adb.adb_shell("ls -al " + path, device="emulator-5554") # artistgui cleanup sets permissions to 777 -> artist success if "-rwxrwxrwx" in ls_out: success = True break # artistgui exception handling sets permissions to 770 -> artist failed if "-rwxrwx---" in ls_out: success = False break # close artistgui cmd = 'am force-stop ' + 'saarland.cispa.artist.artistgui' adb.adb_shell(cmd, device="emulator-5554") if success: return True else: # try to instrument app again return Artist.handle_fail(app, path, x86)
def explore(self, app_obj: app.App): pids = [] try: # pass target apk to droidmate_dir if self.droidmate: # prepare connection to droidmate_dir droidmate_conn = droidmate.Droidmate(app_obj.path_to_apk) try: droidmate_conn.send_go() except RuntimeError: self.droidmate = False droidmate_conn = None else: droidmate_conn = None for activity in app_obj.activities: pid = self.explore_activity(str(activity, "ascii"), app_obj.package_name, droidmate_conn) if pid not in pids: pids.append(pid) for service in app_obj.services: # start the main activity to reset the app pid = self.generate_pid(app_obj) if pid not in pids: pids.append(pid) self.explore_service(str(service, "ascii"), app_obj.package_name, droidmate_conn) for receiver in app_obj.receivers: # start the main activity to reset the app pid = self.generate_pid(app_obj) if pid not in pids: pids.append(pid) filters = app_obj.receivers[receiver] action = '' category = '' data = '' for f in filters: arg = f.split(':') if arg[0] == 'action': action = arg[1] elif arg[0] == 'category': category = arg[1] elif arg[0] == 'data': data = arg[1] self.explore_receiver(receiver, app_obj.package_name, action, category, data, droidmate_conn) # get names of content providers # the information that androguard returns when scanning for content providers is not useful for us providers = adb.adb_shell('dumpsys package providers | grep ' + app_obj.package_name, device="emulator-5554")[1].split('\n') for provider in providers: if '[' in provider and ']:' in provider: provider = re.sub('\[|\]|\s|:', '', provider) self.explore_provider(provider) # stop droidmate_dir if self.droidmate: droidmate_conn.send_stop() except TimeoutError: raise TimeoutError(pids) except KeyboardInterrupt: raise KeyboardInterrupt(pids) return pids, self.droidmate
def generate_pid(app_obj: app.App): cmd = 'am start -n \"' + app_obj.package_name + '/' + app_obj.main_activity + '\"' adb.adb_shell(cmd, device="emulator-5554") return Androguard.get_pid(app_obj.package_name)
def explore_provider(self, provider: str): # we don't know the exact paths so we simply try to execute a query on the provider itself cmd = 'content query --uri content://' + provider + ' --user 0' adb.adb_shell(cmd, device="emulator-5554", timeout=self.timeout)