Example #1
0
    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_commits()
        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('')
Example #2
0
    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

            if self._adb_available:
                self._adb_available = False
                adb_devices = utils.do_shell_command('adb devices')

                try:
                    if adb_devices:
                        adb_devices = adb_devices.split(os.linesep)

                        for i, adb_device in enumerate(adb_devices):
                            if not adb_device:  # skip empty lines at bottom
                                continue
                            if i == 0:  # skip first line 'List of devices attached'
                                continue
                            if adb_device.startswith(
                                    '*'
                            ):  # skip these lines '* daemon started successfully *'
                                continue

                            self._adb_available = True

                    if not self._adb_available:
                        print(
                            'No Devices! Make sure \'Usb-Debugging\' is enabled in DeveloperSettings'
                        )

                except Exception as e:
                    print(e)

        # 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
Example #3
0
    def _cleanup(self):
        if os.name != 'nt':
            utils.do_shell_command("pkill radare2")
        else:
            try:
                utils.do_shell_command("taskkill /IM radare2.exe /F")
                #utils.do_shell_command("tskill radare2")
            except IOError as io_error:
                if io_error.errno == 2:
                    print('error: cant execute tskill')

        for path in os.listdir('.'):
            if '.r2pipe' in path:
                try:
                    shutil.rmtree(path)
                except:
                    # instance of dwarf already running
                    pass
Example #4
0
def pip_install_package(package_name):
    try:
        from dwarf_debugger.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
Example #5
0
    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
Example #6
0
    def run(self):
        return
        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)
Example #7
0
    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
Example #8
0
 def _is_frida_running():
     # untested
     utils.do_shell_command(
         'ssh -p2222 [email protected] ps -A | grep \'frida\'')
Example #9
0
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_debugger.lib import utils
    from dwarf_debugger.lib.git import Git
    from dwarf_debugger.lib.prefs import Prefs
    from dwarf_debugger.ui.app import AppWindow

    from PyQt5.QtCore import Qt
    from PyQt5.QtGui import QIcon
    from PyQt5.QtWidgets import QApplication

    import dwarf_debugger.resources  # pylint: disable=unused-import

    QApplication.setDesktopSettingsAware(True)
    QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
    QApplication.setLayoutDirection(Qt.LeftToRight)

    QApplication.setOrganizationName("https://github.com/iGio90/Dwarf")
    QApplication.setApplicationName("Dwarf")
    QApplication.setApplicationDisplayName('Dwarf')

    qapp = QApplication([])

    # 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_debugger.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['tag_name']:
            print('Updating local frida version to ' +
                  remote_frida['tag_name'])
            try:
                res = utils.do_shell_command(
                    'pip3 install frida --upgrade --user')
                if 'Successfully installed frida-' + remote_frida[
                        '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)
Example #10
0
    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

            res = self._do_adb_command('shell mount | grep system')
            if '/system_root' in res:
                self._syspart_name = '/system_root'

            # 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 ' + self._syspart_name)
            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 ' +
                                           self._syspart_name)
                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