def run(self): self.on_status_text.emit('fetching commit list...') try: utils.do_shell_command('git --version') except IOError as io_error: if io_error.errno == 2: # git command not available self.on_status_text.emit( 'error: git not available on your system') return _git = Git() data = _git.get_dwarf_releases() if data is None: self.on_status_text.emit('Failed to fetch commit list. Try later.') return # TODO: check for dev/release version and updated version most_recent_remote_commit = '' most_recent_local_commit = utils.do_shell_command( 'git log -1 master --pretty=format:%H') most_recent_date = '' for commit in data: if most_recent_remote_commit == '': most_recent_remote_commit = commit['sha'] if most_recent_remote_commit != most_recent_local_commit: self.on_update_available.emit() commit = commit['commit'] date = commit['committer']['date'].split('T') if most_recent_date != date[0]: if most_recent_date != '': self.on_add_commit.emit('', True) self.on_add_commit.emit(date[0], True) most_recent_date = date[0] s = ('{0} - {1} ({2})'.format(date[1][:-1], commit['message'], commit['author']['name'])) self.on_add_commit.emit(s, False) if most_recent_remote_commit != most_recent_local_commit: self.on_finished.emit( 'There is an newer Version available... You can use the UpdateButton in Menu' ) else: # keep: it clears status text self.on_finished.emit('')
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( dex2jar + ' .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') try: java_version.index('java version') except: utils.show_message_box('failed to find java') return utils.do_shell_command( 'java -jar tools/luyten.jar .decompile/base.jar &')
def pip_install_package(package_name): try: from dwarf.lib.utils import do_shell_command res = do_shell_command('pip3 install ' + package_name + ' --upgrade --user') if 'Successfully installed' in res: return True elif 'Requirement already up-to-date' in res: return True else: return False except Exception: # pylint: disable=broad-except return False
def _do_adb_command(self, cmd, timeout=60): """ helper for calling adb """ if not self.is_adb_available(): return None # TODO: for android sdk emulator its using -e res = utils.do_shell_command( 'adb -s ' + self._device_serial + ' ' + cmd, timeout=timeout) if res and 'no device' in res: return None return res
def run(self): self.on_status_text.emit('updating dwarf...') try: utils.do_shell_command('git --version') except IOError as io_error: if io_error.errno == 2: # git command not available self.on_status_text.emit( 'error while updating: git not available on your system') self.on_finished.emit( 'error while updating: git not available on your system') return utils.do_shell_command( 'git fetch -q https://github.com/iGio90/Dwarf.git') utils.do_shell_command('git checkout -f -q master') utils.do_shell_command('git reset --hard FETCH_HEAD') sha = utils.do_shell_command('git log -1 master --pretty=format:%H') s = ('Dwarf updated to commit := {0} - Please restart...'.format(sha)) self.on_status_text.emit(s) self.on_finished.emit(sha)
def _check_min_required(self): """ Checks if adb is available """ self._adb_available = False try: adb_version = utils.do_shell_command('adb --version') if adb_version: 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
def decompile(adb, apk_path): if not os.path.exists('.decompile'): os.mkdir('.decompile') adb.su_cmd('cp ' + apk_path + ' /sdcard/dwarf-decompile.apk') adb.pull('/sdcard/dwarf-decompile.apk', '.decompile/base.apk') adb.su_cmd('rm /sdcard/dwarf-decompile.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( dex2jar + ' .decompile/base.apk -o .decompile/base.jar -f') if not external_tools.tool_exist('luyten.jar'): if os.name == 'nt': external_tools.get_tool( 'https://github.com/deathmarine/Luyten/releases/download/v0.5.4_Rebuilt_with_Latest_depenencies/luyten-0.5.4.exe', 'luyten.exe') else: external_tools.get_tool( 'https://github.com/deathmarine/Luyten/releases/download/v0.5.4_Rebuilt_with_Latest_depenencies/luyten-0.5.4.jar', 'luyten.jar') java_version = utils.do_shell_command('java -version') try: if os.name == 'nt': utils.do_shell_command( 'tools/luyten.exe .decompile/base.jar &') else: utils.do_shell_command( 'java -jar tools/luyten.jar .decompile/base.jar &') except: pass
def run_dwarf(): """ fire it up """ os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # os.environ["QT_SCALE_FACTOR"] = "1" # os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "0" # os.environ["QT_SCREEN_SCALE_FACTORS"] = "1" from dwarf.lib import utils from dwarf.lib.git import Git from dwarf.lib.prefs import Prefs from dwarf.ui.app import AppWindow from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication import dwarf.resources # pylint: disable=unused-import qapp = QApplication([]) qapp.setDesktopSettingsAware(True) qapp.setAttribute(Qt.AA_EnableHighDpiScaling) qapp.setAttribute(Qt.AA_UseHighDpiPixmaps) qapp.setLayoutDirection(Qt.LeftToRight) qapp.setOrganizationName("https://github.com/iGio90/Dwarf") qapp.setApplicationName("Dwarf") qapp.setApplicationDisplayName('Dwarf') # set icon _icon = None if os.name == "nt": if os.path.exists(utils.resource_path('assets/dwarf.ico')): _icon = QIcon(utils.resource_path('assets/dwarf.ico')) else: _icon = QIcon(':/assets/dwarf.ico') else: if os.path.exists(utils.resource_path('assets/dwarf.png')): _icon = QIcon(utils.resource_path('assets/dwarf.png')) else: _icon = QIcon(':/assets/dwarf.png') if _icon: qapp.setWindowIcon(_icon) _prefs = Prefs() local_update_disabled = _prefs.get('disable_local_frida_update', False) args = process_args() """ did_first_run = _prefs.get('did_first_run', False) if False: from dwarf.ui.dialogs.dialog_setup import SetupDialog # did_first_run: _prefs.put('did_first_run', True) SetupDialog.showDialog(_prefs) """ if not local_update_disabled: _git = Git() import frida remote_frida = _git.get_frida_version() local_frida = frida.__version__ if remote_frida and local_frida != remote_frida[0]['tag_name']: print('Updating local frida version to ' + remote_frida[0]['tag_name']) try: res = utils.do_shell_command( 'pip3 install frida --upgrade --user') if 'Successfully installed frida-' + remote_frida[0][ 'tag_name'] in res: _on_restart() elif 'Requirement already up-to-date' in res: if os.path.exists('.git_cache'): shutil.rmtree('.git_cache', ignore_errors=True) else: print('failed to update local frida') print(res) except Exception as e: # pylint: disable=broad-except, invalid-name print('failed to update local frida') print(str(e)) if os.name == 'nt': # windows stuff import ctypes try: if os.path.exists(utils.resource_path('assets/dwarf.ico')): # write ini to show folder with dwarficon folder_stuff = "[.ShellClassInfo]\n" folder_stuff += "IconResource=dwarf\\assets\\dwarf.ico,0\n" folder_stuff += "[ViewState]\n" folder_stuff += "Mode=\n" folder_stuff += "Vid=\n" folder_stuff += "FolderType=Generic\n" try: ini_path = os.path.dirname( os.path.abspath(__file__) ) + os.sep + os.pardir + os.sep + 'desktop.ini' with open(ini_path, 'w') as ini: ini.writelines(folder_stuff) # set fileattributes to hidden + systemfile ctypes.windll.kernel32.SetFileAttributesW( ini_path, 0x02 | 0x04 | ~0x20 ) # FILE_ATTRIBUTE_HIDDEN = 0x02 | FILE_ATTRIBUTE_SYSTEM = 0x04 except PermissionError: # its hidden+system already pass # fix for showing dwarf icon in windows taskbar instead of pythonicon _appid = u'iGio90.dwarf.debugger' ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( _appid) ctypes.windll.user32.SetProcessDPIAware() except Exception: # pylint: disable=broad-except pass try: # parse target as pid args.pid = int(args.any) except ValueError: args.pid = 0 # default to local if not specified if args.target is None: args.target = 'local' app_window = AppWindow(args) if _icon: app_window.setWindowIcon(_icon) app_window.onRestart.connect(_on_restart) try: sys.exit(qapp.exec_()) except SystemExit as sys_err: if sys_err.code == 0: # thanks for using dwarf print('Thank\'s for using Dwarf\nHave a nice day...') else: # something was wrong print('sysexit with: %d' % sys_err.code)
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') # nox fix res = self.su_cmd('mount -o ro,remount /system') if res and 'invalid' in res: self._alternate_su_binary = 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 = 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
def _is_frida_running(): # untested utils.do_shell_command( 'ssh -p2222 [email protected] ps -A | grep \'frida\'')