def on_memory_modified(self, pos, length): data_pos = self.memory_panel.base + pos data = self.memory_panel.data[pos:pos + length] data = [data[0]] # todo: strange js part if self.dwarf.dwarf_api('writeBytes', [data_pos, data]): pass else: utils.show_message_box('Failed to write Memory')
def get_frida_version(self): if not self.adb_available: utils.show_message_box('adb not found') return None r = self._do_adb_command('adb shell frida --version') try: if len(r) == 0 or r.index('frida: not found') >= 0: return '0' except: return r
def show_graph_view(self): if self._working: utils.show_message_box('please wait for the other works to finish') else: self.app.show_progress('r2: building graph view') self._working = True self.r2graph = R2Graph(self.pipe) self.r2graph.onR2Graph.connect(self._on_finish_graph) self.r2graph.start()
def show_decompiler_view(self): if self._working: utils.show_message_box('please wait for the other works to finish') else: self.app.show_progress('r2: decompiling function') self._working = True self.r2decompiler = R2Decompiler(self.pipe, self.with_r2dec) self.r2decompiler.onR2Decompiler.connect(self._on_finish_decompiler) self.r2decompiler.start()
def load_script(self, script=None, spawned=False, break_at_start=False): try: if not os.path.exists('lib/core.js'): raise self.CoreScriptNotFoundError('core.js not found!') with open('lib/core.js', 'r') as core_script: script_content = core_script.read() self._script = self._process.create_script(script_content, runtime='v8') self._script.on('message', self._on_message) self._script.on('destroyed', self._on_script_destroyed) self._script.load() break_at_start = break_at_start or self._app_window.dwarf_args.break_start # we invalidate the arg in any case (set this from ui needs a store in args for an eventual restore session) self._app_window.dwarf_args.break_start = break_at_start is_debug = self._app_window.dwarf_args.debug_script # this break_at_start have same behavior from args or from the checkbox i added self._script.exports.init(break_at_start, is_debug, spawned) if script is not None: if os.path.exists(script): with open(script, 'r') as script_file: user_script = script_file.read() self.dwarf_api('evaluateFunction', user_script) # resume immediately self.resume_proc() self.onScriptLoaded.emit() return 0 except frida.ProcessNotFoundError: error_msg = 'Process not found (ProcessNotFoundError)' was_error = True except frida.ProcessNotRespondingError: error_msg = 'Process not responding (ProcessNotRespondingError)' was_error = True except frida.TimedOutError: error_msg = 'Frida timeout (TimedOutError)' was_error = True except frida.ServerNotRunningError: error_msg = 'Frida not running (ServerNotRunningError)' was_error = True except frida.TransportError: error_msg = 'Frida timeout was reached (TransportError)' was_error = True if was_error: utils.show_message_box(error_msg) self._on_destroyed() return 1
def attach(self, pid, script=None, print_debug_error=True): """ Attach to pid """ if self.device is None: raise self.NoDeviceAssignedError('No Device assigned') if self._process is not None: self.detach() was_error = False error_msg = '' # for commandline arg if isinstance(pid, str): try: process = self.device.get_process(pid) pid = [process.pid, process.name] except frida.ProcessNotFoundError as error: print(error) return 2 if not isinstance(pid, list): return 1 try: self._process = self.device.attach(pid[0]) self._process.enable_jit() self._pid = pid[0] except frida.ProcessNotFoundError: error_msg = 'Process not found' was_error = True except frida.ProcessNotRespondingError: error_msg = 'Process not responding' was_error = True except frida.TimedOutError: error_msg = 'Frida timeout' was_error = True except frida.ServerNotRunningError: error_msg = 'Frida not running' was_error = True # keep for debug except Exception as error: # pylint: disable=broad-except error_msg = error was_error = True if was_error: if print_debug_error: utils.show_message_box('Failed to attach to ' + pid[1], error_msg) return 2 self.onAttached.emit([self.pid, pid[1]]) self.load_script(script) return 0
def on_proc_selected(self, data): device, pid = data if device: self.dwarf.device = device if pid: try: self.dwarf.attach(pid) except Exception as e: utils.show_message_box('Failed attaching to {0}'.format(pid), str(e)) self.stop() return
def __init__(self, app_window): super(AndroidSession, self).__init__(app_window) self.adb = Adb() if not self.adb.min_required: utils.show_message_box(self.adb.get_states_string()) if app_window.dwarf_args.package is None: self._device_window = DeviceWindow(self._app_window, 'usb') self._smali_thread = None
def attach(self, pid_or_package, script=None): if self.process is not None: self.detach() device = frida.get_usb_device() try: self.process = device.attach(pid_or_package) except Exception as e: utils.show_message_box( 'Failed to attach to %s' % str(pid_or_package), str(e)) return self.load_script(script)
def load_script(self, script=None): try: if not os.path.exists('lib/core.js'): raise self.CoreScriptNotFoundError('core.js not found!') with open('lib/core.js', 'r') as core_script: script_content = core_script.read() self._script = self._process.create_script(script_content, runtime='v8') self._script.on('message', self._on_message) self._script.on('destroyed', self._on_destroyed) self._script.load() is_debug = self._app_window.dwarf_args.debug_script if is_debug: self._script.exports.debug(True) if script is not None: if os.path.exists(script): with open(script, 'r') as script_file: user_script = script_file.read() self.dwarf_api('evaluateFunction', user_script) self.onScriptLoaded.emit() # resume immediately on android and ios if self._app_window.session_manager.session.session_type == 'Android': self.resume_proc() return 0 except frida.ProcessNotFoundError: error_msg = 'Process not found (ProcessNotFoundError)' was_error = True except frida.ProcessNotRespondingError: error_msg = 'Process not responding (ProcessNotRespondingError)' was_error = True except frida.TimedOutError: error_msg = 'Frida timeout (TimedOutError)' was_error = True except frida.ServerNotRunningError: error_msg = 'Frida not running (ServerNotRunningError)' was_error = True except frida.TransportError: error_msg = 'Frida timeout was reached (TransportError)' was_error = True if was_error: utils.show_message_box(error_msg) self._on_destroyed() return 1
def on_dwarf_updated(self, sha): if 'error' in sha: utils.show_message_box(sha) return print('') print('') print('Dwarf updated to commit := ' + sha) print('') print('') utils.show_message_box('Dwarf updated to commit := ' + sha, 'Please restart...') sys.exit(0)
def _show_plugin_about(self, plugin): plugin = self.plugin_manager.plugins[plugin] if plugin: info = plugin.__get_plugin_info__() version = utils.safe_read_map(info, 'version', '') description = utils.safe_read_map(info, 'description', '') author = utils.safe_read_map(info, 'author', '') homepage = utils.safe_read_map(info, 'homepage', '') license_ = utils.safe_read_map(info, 'license', '') utils.show_message_box( 'Name: {0}\nVersion: {1}\nDescription: {2}\nAuthor: {3}\nHomepage: {4}\nLicense: {5}'. format(plugin.name, version, description, author, homepage, license_))
def __init__(self, app_window): super(AndroidSession, self).__init__(app_window) self._app_window = app_window self.adb = Adb() if not self.adb.min_required: utils.show_message_box(self.adb.get_states_string()) self._device_window = DeviceWindow(self._app_window, 'usb') # main menu every session needs self._menu = [] self._smali_thread = None
def spawn(self, package, script=None): if self.process is not None: self.detach() device = frida.get_usb_device() self.app_window.get_adb().kill_package(package) try: pid = device.spawn(package) self.process = device.attach(pid) except Exception as e: utils.show_message_box('Failed to spawn to %s' % package, str(e)) return self.load_script(script) device.resume(pid)
def __init__(self, app_window): super(AndroidSession, self).__init__(app_window) self._app_window = app_window self.adb = Adb() if not self.adb.is_adb_available(): utils.show_message_box(self.adb.get_states_string()) self._device_window = DeviceWindow(self._app_window, 'usb') # main menu every session needs self._menu = [QMenu(self.session_type + ' Session')] #self._menu[0].addAction('Save Session', self._save_session) self._menu[0].addAction('Close Session', self.stop_session)
def spawn(self, package, script=None): if self.device is None: return if self.process is not None: self.detach() try: pid = self.device.spawn(package) self.process = self.device.attach(pid) except Exception as e: utils.show_message_box('Failed to spawn to %s' % package, str(e)) return self.load_script(script) self.device.resume(pid)
def __init__(self, app_window): super(AndroidSession, self).__init__(app_window) self._app_window = app_window self.adb = Adb() if not self.adb.min_required: utils.show_message_box(self.adb.get_states_string()) self._device_window = DeviceWindow(self._app_window, 'usb') # main menu every session needs self._menu = [QMenu(self.session_type + ' Session')] self._menu[0].addAction('Save Session', self.dwarf.save_session) self._menu[0].addAction('Close Session', self.stop_session) self._smali_thread = None
def list_packages(self): if not self.adb_available: utils.show_message_box('adb not found') return None packages = utils.do_shell_command('adb shell pm list packages -f').split('\n') ret = [] for package in packages: parts = package.split(':') if len(parts) < 2: continue needed = parts[1].split('.apk=') p = AndroidPackage() p.path = needed[0] + '.apk' p.package = needed[1] ret.append(p) return ret
def spawn(self, package, script=None): if self.device is None: raise self.NoDeviceAssignedError('No Device assigned') if self._process is not None: self.detach() try: self._pid = self.device.spawn(package) self._process = self.device.attach(self._pid) self._process.enable_jit() self._spawned = True except Exception as e: utils.show_message_box('Failed to spawn to %s' % package, str(e)) return 2 self.onAttached.emit([self.pid, package]) self.load_script(script) return 0
def trigger_write_instruction(self, item): if not self.dwarf.keystone_installed: details = '' try: import keystone.keystone_const except Exception as e: details = str(e) utils.show_message_box( 'keystone-engine not found. Install it to enable instructions patching', details=details) return accept, inst, arch, mode = WriteInstructionDialog().show_dialog( input_content='%s %s' % (self.item(item.row(), 1).text(), self.item(item.row(), 2).text()), arch=self.ks_arch, mode=self.ks_mode) self.ks_arch = 'KS_ARCH_' + arch.upper() self.ks_mode = 'KS_MODE_' + mode.upper() if accept and len(inst) > 0: import keystone try: ks = keystone.Ks( getattr(keystone.keystone_const, self.ks_arch), getattr(keystone.keystone_const, self.ks_mode)) encoding, count = ks.asm(inst) asm_widget = self.item(item.row(), 0) offset = asm_widget.get_offset() if self.dwarf.dwarf_api('writeBytes', [asm_widget.get_address(), encoding]): new_data = bytearray(self.range.data) for i in range(0, len(encoding)): try: new_data[self.asm_data_start + offset + i] = encoding[i] except Exception as e: if isinstance(e, IndexError): break self.range.data = bytes(new_data) self.disa() except Exception as e: self.dwarf.log(e)
def spawn(self, package, script=None): if self.device is None: # fallback to usb device # can come from -p in args self.device = frida.get_usb_device() if self.device is None: return if self.process is not None: self.detach() try: pid = self.device.spawn(package) self.process = self.device.attach(pid) except Exception as e: utils.show_message_box('Failed to spawn to %s' % package, str(e)) return self.load_script(script) self.device.resume(pid)
def __init__(self, app, *__args): super().__init__(*__args) self.app = app self.startup_script = '' self.menu_bar = None self.status_bar = None _app = QApplication.instance() for w in _app.topLevelWidgets(): if isinstance(w, QMainWindow): #self.menu_bar = w.get_menu() self.status_bar = w.get_statusbar() self.update_action = QAction('Update Dwarf') self.update_action.triggered.connect(self.update_dwarf) self.setup_ui() self.updated_frida_version = '' self.updated_frida_assets_url = {} self.frida_update_thread = None self.devices_thread = None self.procs_update_thread = None self.spawns_update_thread = None self.update_commits_thread = None self.update_dwarf_thread = None self.setup_threads() frida.get_device_manager().on('added', self.update_device_ui) frida.get_device_manager().on('removed', self.update_device_ui) if not self.app.get_adb().available(): # additional check for null local device if frida.get_local_device() is None: utils.show_message_box('adb/device/emu not found or not rooted! see details or output', self.app.get_adb().get_states_string()) self.update_ui_sync()
def spawn(self, package, script=None): if self.device is None: # fallback to usb device # can come from -p in args err = self._get_device() if err > 0: return err if self.process is not None: self.detach() try: self.pid = self.device.spawn(package) self.process = self.device.attach(self.pid) self._spawned = True except Exception as e: utils.show_message_box('Failed to spawn to %s' % package, str(e)) return 2 self.load_script(script) return 0
def attach(self, pid_or_package, script=None, print_debug_error=True): if self.device is None: # fallback to usb device # can come from -p in args err = self._get_device() if err > 0: return err if self.process is not None: self.detach() try: self.process = self.device.attach(pid_or_package) self.pid = self.process._impl.pid self._spawned = False except Exception as e: if print_debug_error: utils.show_message_box('Failed to attach to %s' % str(pid_or_package), str(e)) return 2 self.load_script(script) return 0
def on_spawn_selected(self, data): device, package_name, break_at_start = data if device: self.adb.device = device.id self.dwarf.device = device if package_name: # smalistuff if self._smali_thread is None: self._app_window.show_progress('Baksmali ' + package_name + ' ...') self._smali_thread = SmaliThread(self, device.id, package_name) self._smali_thread.onError.connect(self._app_window.hide_progress) self._smali_thread.onFinished.connect(self._app_window.hide_progress) self._smali_thread.start() try: self.dwarf.spawn(package=package_name, break_at_start=break_at_start) except Exception as e: utils.show_message_box('Failed spawning {0}'.format(package_name), str(e)) self.stop() return self._on_java_classes()
def __init__(self, dwarf_args, flags=None, *args, **kwargs): super().__init__(flags, *args, **kwargs) self.app = App(self) self.adb = Adb() self.dwarf = Dwarf(self) self.update_title() self.setCentralWidget(self.app) self.app.setup_ui() self.menu = MenuBar(self) if dwarf_args.package is not None: # we skip welcome ui here if not self.get_adb().available(): # additional check if we have a local server to starts with if frida.get_local_device() is None: utils.show_message_box( 'adb/device/emu not found or not rooted! see details or output', self.app.get_adb().get_states_string()) return if dwarf_args.spawn is not None: err = self.dwarf.spawn(dwarf_args.package, dwarf_args.script) else: err = self.dwarf.attach(dwarf_args.package, dwarf_args.script, print_debug_error=False) if err > 0: if err == 1: # no device? kidding? pass elif err == 2: # no proc to attach - fallback to spawn err = self.dwarf.spawn(dwarf_args.package, dwarf_args.script)
def decompile(adb, apk_path): if not os.path.exists('.decompile'): os.mkdir('.decompile') adb.pull(apk_path, '.decompile/base.apk') dex2jar = 'd2j-dex2jar.sh' if os.name == 'nt': dex2jar = 'd2j-dex2jar.bat' try: utils.do_shell_command(dex2jar).index('version') except: utils.show_message_box('failed to find %s' % dex2jar) return utils.do_shell_command('d2j-dex2jar.sh %s' % '.decompile/base.apk -o .decompile/base.jar -f') if not external_tools.tool_exist('luyten.jar'): external_tools.get_tool( 'https://github.com/deathmarine/Luyten/releases/download/v0.5.3/luyten-0.5.3.jar', 'luyten.jar') java_version = utils.do_shell_command('java -version') if 'java version' not in java_version and 'openjdk version' not in java_version: utils.show_message_box('failed to find java') return utils.do_shell_command( 'java -jar tools/luyten.jar .decompile/base.jar &')
def _check_requirements(self): # pylint: disable=too-many-branches, too-many-statements """ Checks for adb and root on device """ self._adb_available = False self._dev_emu = False self._is_root = False self._is_su = False try: adb_version = utils.do_shell_command('adb --version') if adb_version is not None: if adb_version and 'Android Debug Bridge' in adb_version: self._adb_available = True else: self._adb_available = False # io error is handled here not in do_shell_command # if adb isnt there it gives file not found except IOError as io_error: # file not found if io_error.errno == 2: self._adb_available = False if self._adb_available: # try some su command res = utils.do_shell_command( 'adb shell su -c \'mount -o ro,remount /system\'') if res is not None: # adb not authorized if res and 'device unauthorized' in res: # kill adb daemon utils.do_shell_command('adb kill-server') utils.show_message_box( 'device not authorized! allow access from this computer on the device' ) if res and 'no devices/emulators' in res: self._dev_emu = False elif res and 'device not found' in res: self._dev_emu = False else: self._dev_emu = True # user can run su? if res and 'Permission denied' in res: self._is_su = False elif res and 'su: not found' in res: self._is_su = False else: if self._dev_emu: self._is_su = True # no su -> try if the user is already root # on some emulators user is root if not self._is_su and self._dev_emu: res = utils.do_shell_command( 'adb shell mount -o ro,remount /system') if res is not None: if res and 'not user mountable' in res: # no root user self._is_root = False elif res == '': # cmd executed fine self._is_root = True else: # dont know some other output self._is_root = False print('rootcheck: %s' % res) if self._dev_emu: # get some infos about the device and keep for later self._sdk_version = self._do_adb_command( 'adb shell getprop ro.build.version.sdk') self._sdk_version = self._sdk_version.join( self._sdk_version.split()) # cleans '\r\n' self._android_version = self._do_adb_command( 'adb shell getprop ro.build.version.release') self._android_version = self._android_version.join( self._android_version.split()) try: self._oreo_plus = (int( self._android_version.split('.')[0]) >= 8) except ValueError: try: self._oreo_plus = (int(self._sdk_version) > 25) except ValueError: pass # fix some frida server problems # frida default port: 27042 utils.do_shell_command('adb forward tcp:27042 tcp:27042') # check if we have pidof if self._oreo_plus: res = self._do_adb_command('adb shell pidof') self._have_pidof = 'not found' not in res # check for root if self._is_root: res = self.su_cmd('id') self._is_root = 'uid=0' in res
def _on_search_error(self, msg): utils.show_message_box(msg)
def _check_requirements(self): # pylint: disable=too-many-branches, too-many-statements """ Checks root on device """ self._dev_emu = False self._is_root = False self._is_su = False self._alternate_su_binary = False if not self._device_serial: return if self._adb_available: # try some command date_res = self._do_adb_command('shell date') # adb not authorized if date_res and 'device unauthorized' in date_res: # kill adb daemon utils.do_shell_command('adb kill-server') utils.show_message_box( 'device not authorized! allow access from this computer on the device' ) if date_res and 'no devices/emulators' in date_res: self._dev_emu = False return elif date_res and 'device not found' in date_res: self._dev_emu = False return else: self._dev_emu = True if self._dev_emu and date_res: try: # if date was fine it should end with year # Thu Feb 8 16:47:32 MST 2001 date_res = date_res.split(' ') res_year = int(date_res[len(date_res) - 1]) except ValueError: return # TODO: raise exceptions # try some su command to check for su binary res = self._do_adb_command('shell su -c date') if res and 'invalid' in res: res = self._do_adb_command('shell su 0 date') if res: self._alternate_su_binary = True if res: try: # if su date was fine it should end with year # Thu Feb 8 16:47:32 MST 2001 su_res = res.split(' ') res_year = int(su_res[len(su_res) - 1]) if res_year: # su cmd is available self._is_su = True # check if both date results matches otherwise its no valid result res_len = len(su_res) date_len = len(date_res) if su_res[res_len - 1] == date_res[date_len - 1]: # year if su_res[res_len - 2] == date_res[date_len - 2]: # timezone if su_res[res_len - 4] == date_res[date_len - 4]: # day if su_res[res_len - 5] == date_res[date_len - 5]: # month self._is_root = True except ValueError: pass # check status of selinux res = self._do_adb_command('shell getenforce') if res: res = res.join(res.split()) if res != 'Permissive' and res != 'Disabled': self._do_adb_command('shell setenforce 0') # no su -> try if the user is already root # on some emulators user is root if not self._is_su and self._dev_emu: res = self._do_adb_command('shell mount -o ro,remount /system') if res or res == '': if res and 'not user mountable' in res: # no root user self._is_root = False elif res == '': # cmd executed fine self._is_root = True else: # dont know some other output self._is_root = False # check for uid 0 res = self._do_adb_command('shell id') # root should be 0 # https://superuser.com/questions/626843/does-the-root-account-always-have-uid-gid-0/626845#626845 self._is_root = 'uid=0' in res if self._dev_emu: # get some infos about the device and keep for later self._sdk_version = self._do_adb_command( 'shell getprop ro.build.version.sdk') if self._sdk_version: self._sdk_version = self._sdk_version.join( self._sdk_version.split()) # cleans '\r\n' self._android_version = self._do_adb_command( 'shell getprop ro.build.version.release') if self._android_version: self._android_version = self._android_version.join( self._android_version.split()) try: self._oreo_plus = (int( self._android_version.split('.')[0]) >= 8) except ValueError: try: self._oreo_plus = (int(self._sdk_version) > 25) except ValueError: pass # fix some frida server problems # frida default port: 27042 utils.do_shell_command('adb forward tcp:27042 tcp:27042') # check if we have pidof res = self._do_adb_command('shell pidof -s pidof') self._have_pidof = 'not found' not in res res = self._do_adb_command('shell killall') self._have_killall = 'not found' not in res # check for correct userid if self._is_root: res = self.su_cmd('id') # root should be 0 # https://superuser.com/questions/626843/does-the-root-account-always-have-uid-gid-0/626845#626845 self._is_root = 'uid=0' in res