Exemple #1
0
class SmaliThread(QThread):
    onFinished = pyqtSignal(name='onFinished')
    onError = pyqtSignal(name='onError')

    def __init__(self, parent=None, package_name=None):
        super(SmaliThread, self).__init__(parent)
        self._adb = Adb()
        self._package_name = package_name

    def run(self):
        if not self._package_name:
            self.onError.emit()
            return

        _path = self._adb.package_path(self._package_name)
        if not os.path.exists('.tmp'):
            os.mkdir('.tmp')

        if _path:
            self._adb.pull(_path, '.tmp/base.apk')
            if os.path.exists('.tmp/base.apk'):
                _baksmali_cmd = 'd2j-baksmali.sh'
                if os.name == 'nt':
                    _baksmali_cmd = _baksmali_cmd.replace('.sh', '.bat')
                try:
                    utils.do_shell_command(_baksmali_cmd +
                                           ' .tmp/base.apk -o .tmp/smali')
                    self.onFinished.emit()
                except:
                    # no d2j
                    self.onError.emit()
        else:
            self.onError.emit()
Exemple #2
0
    def __init__(self, parent=None, show_path=True):
        super(ApkList, self).__init__(parent=parent)

        self.adb = Adb()

        if not self.adb.available():
            return

        self.retrieve_thread = PackageRetrieveThread(self.adb)
        if self.retrieve_thread is not None:
            self.retrieve_thread.onAddPackage.connect(self._on_addpackage)

        if show_path:
            self.apk_model = QStandardItemModel(0, 2)
        else:
            self.apk_model = QStandardItemModel(0, 1)

        self.apk_model.setHeaderData(0, Qt.Horizontal, 'Name')

        if show_path:
            self.apk_model.setHeaderData(1, Qt.Horizontal, 'Path')

        self.setModel(self.apk_model)
        self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)

        self.doubleClicked.connect(self._on_apk_selected)

        if self.retrieve_thread is not None:
            if not self.retrieve_thread.isRunning():
                self.retrieve_thread.start()
    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())

        self._smali_thread = None
Exemple #4
0
    def __init__(self, parent=None, device_type='usb'):
        super().__init__(parent=parent)

        # dont show for local
        if device_type != 'usb':
            return

        self.parent = parent
        self.wait_for_devtype = device_type
        self.is_waiting = True
        self._adb = Adb()

        if not self._adb.min_required:
            return

        self._git = Git()
        self.setAutoFillBackground(True)
        self.setStyleSheet(
            'background-color: crimson; color: white; font-weight: bold; margin: 0; padding: 10px;'
        )
        self.setup()
        self._timer = QTimer()
        self._timer.setInterval(500)
        self._timer.timeout.connect(self._on_timer)
        self._timer.start()
        self._timer_step = 0
        frida.get_device_manager().on('added', self._on_device)
        frida.get_device_manager().on('removed', self._on_device)
        self.devices_thread = DevicesUpdateThread(self)
        self.devices_thread.onAddDevice.connect(self.on_add_deviceitem)
        self.devices_thread.onDevicesUpdated.connect(self._on_devices_finished)
        self._update_thread = FridaUpdateThread(self)
        self._update_thread._adb = self._adb
        self._update_thread.onStatusUpdate.connect(self._update_statuslbl)
        self._update_thread.onFinished.connect(self._frida_updated)
        self._update_thread.onError.connect(self._on_download_error)
        self.updated_frida_version = ''
        self.updated_frida_assets_url = {}
        self._device_id = None
        self._devices = []
        remote_frida = self._git.get_frida_version()
        if remote_frida is None:
            self.updated_frida_version = ''
            self.updated_frida_assets_url.clear()
        else:
            remote_frida = remote_frida[0]
            self.updated_frida_version = remote_frida['tag_name']
            for asset in remote_frida['assets']:
                try:
                    name = asset['name']
                    tag_start = name.index('android-')
                    if name.index('server') >= 0:
                        tag = name[tag_start + 8:-3]
                        self.updated_frida_assets_url[tag] = asset[
                            'browser_download_url']
                except ValueError:
                    pass
Exemple #5
0
    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
Exemple #6
0
    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
Exemple #7
0
    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)
Exemple #8
0
    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
Exemple #9
0
    def __init__(self, dwarf_args, flags=None, *args, **kwargs):
        super().__init__(flags, *args, **kwargs)

        self.app = App(self)
        self.adb = Adb(self.app)

        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:
            self.dwarf.spawn(dwarf_args.package, dwarf_args.script)
Exemple #10
0
    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)
Exemple #11
0
class DeviceBar(QWidget):
    """ DeviceBar

        Signals:
            onDeviceUpdated()
            onDeviceSelected(str) # str = id
            onDeviceChanged(str) # str = id

    """

    onDeviceUpdated = pyqtSignal(str, name="onDeviceUpdated")
    onDeviceSelected = pyqtSignal(str, name="onDeviceSelected")
    onDeviceChanged = pyqtSignal(str, name="onDeviceChanged")

    def __init__(self, parent=None, device_type='usb'):
        super().__init__(parent=parent)

        # dont show for local
        if device_type != 'usb':
            return

        self.parent = parent
        self.wait_for_devtype = device_type
        self.is_waiting = True
        self._adb = Adb()

        if not self._adb.min_required:
            return

        self._git = Git()
        self.setAutoFillBackground(True)
        self.setStyleSheet(
            'background-color: crimson; color: white; font-weight: bold; margin: 0; padding: 10px;'
        )
        self.setup()
        self._timer = QTimer()
        self._timer.setInterval(500)
        self._timer.timeout.connect(self._on_timer)
        self._timer.start()
        self._timer_step = 0
        frida.get_device_manager().on('added', self._on_device)
        frida.get_device_manager().on('removed', self._on_device)
        self.devices_thread = DevicesUpdateThread(self)
        self.devices_thread.onAddDevice.connect(self.on_add_deviceitem)
        self.devices_thread.onDevicesUpdated.connect(self._on_devices_finished)
        self._update_thread = FridaUpdateThread(self)
        self._update_thread._adb = self._adb
        self._update_thread.onStatusUpdate.connect(self._update_statuslbl)
        self._update_thread.onFinished.connect(self._frida_updated)
        self._update_thread.onError.connect(self._on_download_error)
        self.updated_frida_version = ''
        self.updated_frida_assets_url = {}
        self._device_id = None
        self._devices = []
        remote_frida = self._git.get_frida_version()
        if remote_frida is None:
            self.updated_frida_version = ''
            self.updated_frida_assets_url.clear()
        else:
            remote_frida = remote_frida[0]
            self.updated_frida_version = remote_frida['tag_name']
            for asset in remote_frida['assets']:
                try:
                    name = asset['name']
                    tag_start = name.index('android-')
                    if name.index('server') >= 0:
                        tag = name[tag_start + 8:-3]
                        self.updated_frida_assets_url[tag] = asset[
                            'browser_download_url']
                except ValueError:
                    pass

    def setup(self):
        """ Setup ui
        """
        h_box = QHBoxLayout()
        h_box.setContentsMargins(0, 0, 0, 0)
        self.update_label = QLabel('Waiting for Device')
        self.update_label.setFixedWidth(self.parent.width())
        self.update_label.setOpenExternalLinks(True)
        self.update_label.setTextFormat(Qt.RichText)
        self.update_label.setFixedHeight(35)
        self.update_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        self._install_btn = QPushButton('Install Frida', self.update_label)
        self._install_btn.setStyleSheet('padding: 0; border-color: white;')
        self._install_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                      25)
        self._install_btn.clicked.connect(self._on_install_btn)
        self._install_btn.setVisible(False)
        self._start_btn = QPushButton('Start Frida', self.update_label)
        self._start_btn.setStyleSheet('padding: 0; border-color: white;')
        self._start_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                    25)
        self._start_btn.clicked.connect(self._on_start_btn)
        self._start_btn.setVisible(False)
        self._update_btn = QPushButton('Update Frida', self.update_label)
        self._update_btn.setStyleSheet('padding: 0; border-color: white;')
        self._update_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                     25)
        self._update_btn.clicked.connect(self._on_install_btn)
        self._update_btn.setVisible(False)
        self._restart_btn = QPushButton('Restart Frida', self.update_label)
        self._restart_btn.setStyleSheet('padding: 0; border-color: white;')
        self._restart_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                      25)
        self._restart_btn.clicked.connect(self._on_restart_btn)
        self._restart_btn.setVisible(False)
        self._devices_combobox = QComboBox(self.update_label)
        self._devices_combobox.setStyleSheet(
            'padding: 2px 5px; border-color: white;')
        self._devices_combobox.setGeometry(self.update_label.width() - 320, 5,
                                           200, 25)
        self._devices_combobox.currentIndexChanged.connect(
            self._on_device_changed)
        self._devices_combobox.setVisible(False)
        h_box.addWidget(self.update_label)
        self.setLayout(h_box)

    def on_add_deviceitem(self, device_ident):
        """ Adds an Item to the DeviceComboBox
        """
        if device_ident['type'] == self.wait_for_devtype:
            if device_ident['name'] not in self._devices:
                self._devices.append(device_ident)
            self._timer_step = -1
            self.is_waiting = False

    def _on_device_changed(self, index):
        device = None
        device_id = self._devices_combobox.itemData(index)
        if device_id:
            try:
                device = frida.get_device(device_id)
            except:
                return

            if device:
                self._device_id = device.id
                self._check_device(device)
                self.onDeviceChanged.emit(self._device_id)

    def _check_device(self, frida_device):
        self.update_label.setStyleSheet('background-color: crimson;')
        self._install_btn.setVisible(False)
        self._update_btn.setVisible(False)
        self._start_btn.setVisible(False)
        self._restart_btn.setVisible(False)
        self._adb.device = frida_device.id
        self._device_id = frida_device.id
        if self._adb.available():
            self.update_label.setText('Device: ' + frida_device.name)
            # try getting frida version
            device_frida = self._adb.get_frida_version()
            # frida not found show install button
            if device_frida is None:
                self._install_btn.setVisible(True)
            else:
                # frida is old show update button
                if self.updated_frida_version != device_frida:
                    self._start_btn.setVisible(True)
                    self._update_btn.setVisible(False)
                    # old frida is running allow use of this version
                    if self._adb.is_frida_running():
                        self._start_btn.setVisible(False)
                        if self.updated_frida_assets_url:
                            self._update_btn.setVisible(True)
                        self.update_label.setStyleSheet(
                            'background-color: yellowgreen;')
                        self.onDeviceUpdated.emit(frida_device.id)
                # frida not running show start button
                elif device_frida and not self._adb.is_frida_running():
                    self._start_btn.setVisible(True)
                # frida is running with last version show restart button
                elif device_frida and self._adb.is_frida_running():
                    self.update_label.setStyleSheet(
                        'background-color: yellowgreen;')
                    self._restart_btn.setVisible(True)
                    self.onDeviceUpdated.emit(frida_device.id)

    def _on_devices_finished(self):
        if len(self._devices) > 1:
            self._devices_combobox.clear()
            self._devices_combobox.setVisible(True)
            self.update_label.setText('Please select the Device: ')
            for device in self._devices:
                self._devices_combobox.addItem(device['name'], device['id'])
        else:
            self._devices_combobox.setVisible(False)
            try:
                device = frida.get_device(self._devices[0]['id'])
                self._check_device(device)
            except:
                pass

    def _on_timer(self):
        if self._timer_step == -1:
            self._timer.stop()
            return

        if self._timer_step == 0:
            self.update_label.setText(self.update_label.text() + ' .')
            self._timer_step = 1
        elif self._timer_step == 1:
            self.update_label.setText(self.update_label.text() + '.')
            self._timer_step = 2
        elif self._timer_step == 2:
            self.update_label.setText(self.update_label.text() + '.')
            self._timer_step = 3
        else:
            self.update_label.setText(
                self.update_label.text()[:-self._timer_step])
            self._timer_step = 0
            if self.is_waiting and self.devices_thread is not None:
                if not self.devices_thread.isRunning():
                    self.devices_thread.start()

    def _on_download_error(self, text):
        self._timer_step = -1
        self.update_label.setStyleSheet('background-color: crimson;')
        self.update_label.setText(text)
        self._install_btn.setVisible(True)
        self._update_btn.setVisible(False)

    def _on_device(self):
        self._timer_step = 4
        self.is_waiting = True
        self._on_timer()

    def _on_install_btn(self):
        # urls are empty
        if not self.updated_frida_assets_url:
            return

        arch = self._adb.get_device_arch()
        request_url = ''

        if arch is not None and len(arch) > 1:
            arch = arch.join(arch.split())

            if arch == 'arm64' or arch == 'arm64-v8a':
                request_url = self.updated_frida_assets_url['arm64']
            elif arch == 'armeabi-v7a':
                request_url = self.updated_frida_assets_url['arm']
            else:
                if arch in self.updated_frida_assets_url:
                    request_url = self.updated_frida_assets_url[arch]

            try:
                if self._adb.available() and request_url.index(
                        'https://') == 0:
                    self._install_btn.setVisible(False)
                    self._update_btn.setVisible(False)

                    if self._update_thread is not None:
                        if not self._update_thread.isRunning():
                            self._update_thread.frida_update_url = request_url
                            self._update_thread.adb = self._adb
                            self._update_thread.start()

            except ValueError:
                # something wrong in .git_cache folder
                print("request_url not set")

    def _update_statuslbl(self, text):
        self._timer.stop()
        self._timer_step = 0
        self._timer.start()
        self.update_label.setText(text)

    def _frida_updated(self):
        #self._timer_step = 3
        #self.is_waiting = True
        self._on_devices_finished()

    def _on_start_btn(self):
        if self._adb.available():
            self._start_btn.setVisible(False)
            if self._adb.start_frida():
                #self.onDeviceUpdated.emit(self._device_id)
                self._on_devices_finished()
            else:
                self._start_btn.setVisible(True)

    def _on_restart_btn(self):
        if self._adb.available():
            self._restart_btn.setVisible(False)
            if self._adb.start_frida(restart=True):
                self._restart_btn.setVisible(True)
                #self.onDeviceUpdated.emit(self._device_id)
                self._on_devices_finished()
Exemple #12
0
class AndroidSession(Session):
    """ All Android Stuff goes here
        if u look for something android related its here then
    """
    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())

        if app_window.dwarf_args.package is None:
            self._device_window = DeviceWindow(self._app_window, 'usb')

        # main menu every session needs
        self._menu = []
        self._smali_thread = None

    @property
    def session_ui_sections(self):
        # what sections we want in session_ui
        return [
            'hooks', 'bookmarks', 'threads', 'registers', 'memory', 'console',
            'watchers', 'modules', 'jvm-inspector', 'jvm-debugger', 'ranges',
            'backtrace'
        ]

    @property
    def non_closable(self):
        return ['memory', 'ranges', 'modules', 'jvm-inspector', 'jvm-debugger']

    @property
    def session_type(self):
        """ return session name to show in menus etc
        """
        return 'Android'

    @property
    def main_menu(self):
        """ return our created menu
        """
        return self._menu

    def initialize(self, config):
        # session supports load/save then use config

        # setup ui etc for android
        self._setup_menu()
        # all fine were done wait for ui_ready
        self.onCreated.emit()

    def _setup_menu(self):
        """ Build Menus
        """
        # additional menus
        file_menu = QMenu('&Device')
        save_apk = QAction("&Save APK", self)
        save_apk.triggered.connect(self.save_apk)
        decompile_apk = QAction("&Decompile APK", self)
        decompile_apk.triggered.connect(self.decompile_apk)

        file_menu.addAction(save_apk)
        file_menu.addAction(decompile_apk)

        self._menu.append(file_menu)

        process_menu = QMenu('&Process')
        process_menu.addAction('Resume', self._on_proc_resume, Qt.Key_F5)
        process_menu.addAction('Restart', self._on_proc_restart, Qt.Key_F9)
        process_menu.addAction('Detach', self._on_detach, Qt.Key_F10)

        self._menu.append(process_menu)

        java_menu = QMenu('&Java')
        java_menu.addAction('Trace', self._on_java_trace)
        java_menu.addSeparator()
        java_menu.addAction('Classes', self._on_java_classes)
        self._menu.append(java_menu)

    def stop_session(self):
        # cleanup ur stuff

        # end session
        super().stop()

    def start(self, args):
        self.dwarf.onScriptDestroyed.connect(self.stop)
        if args.package is None:
            self._device_window.setModal(True)
            self._device_window.onSelectedProcess.connect(
                self.on_proc_selected)
            self._device_window.onSpwanSelected.connect(self.on_spawn_selected)
            self._device_window.onClosed.connect(self._on_devdlg_closed)
            self._device_window.show()
        else:
            if not args.device:
                self.dwarf.device = frida.get_usb_device()
            else:
                self.adb.device = args.device
                self.dwarf.device = frida.get_device(id=args.device)
            if not args.spawn:
                print('* Trying to attach to {0}'.format(args.package))
                try:
                    self.dwarf.attach(args.package, args.script, False)
                except Exception as e:  # pylint: disable=broad-except
                    print('-failed-')
                    print('Reason: ' + str(e))
                    print('Help: you can use -sp to force spawn')
                    self.stop()
                    exit(0)
            else:
                print('* Trying to spawn {0}'.format(args.package))
                try:
                    self.dwarf.spawn(args.package, args.script)
                except Exception as e:  # pylint: disable=broad-except
                    print('-failed-')
                    print('Reason: ' + str(e))
                    self.stop()
                    exit(0)

    def decompile_apk(self):
        apk_dlg = ApkListDialog(self._app_window)
        apk_dlg.onApkSelected.connect(self._decompile_package)
        apk_dlg.show()

    def _decompile_package(self, data):
        package, path = data
        if path is not None:
            # todo: make qthread
            AndroidDecompileUtil.decompile(self.adb, path)

    def save_apk(self):
        apk_dlg = ApkListDialog(self._app_window)
        apk_dlg.onApkSelected.connect(self._save_package)
        apk_dlg.show()

    def _save_package(self, data):
        package, path = data
        if path is not None:
            result = QFileDialog.getSaveFileName(
                caption='Location to save ' + package,
                directory='./' + package + '.apk',
                filter='*.apk')
            if result and result[0]:
                self.adb.pull(path, result[0])

    def on_proc_selected(self, data):
        device, pid = data
        if device:
            self.adb.device = device.id
            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 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 _on_proc_resume(self, tid=0):
        self.dwarf.dwarf_api('release', tid)

    def _on_proc_restart(self):
        self.dwarf.restart_proc()

    def _on_detach(self):
        self.dwarf.detach()
        self._smali_thread = None

    def _on_java_trace(self):
        should_request_classes = self._app_window.java_trace_panel is None
        self._app_window.show_main_tab('java-trace')
        if should_request_classes:
            self.dwarf.dwarf_api('enumerateJavaClasses')

    def _on_java_classes(self):
        self._app_window.show_main_tab('jvm-inspector')
        self.dwarf.dwarf_api('enumerateJavaClasses')

    def _on_devdlg_closed(self):
        if self.dwarf.device is None:
            self.stop_session()
Exemple #13
0
class ApkList(DwarfListView):
    """ Displays installed APKs
    """

    onApkSelected = pyqtSignal(list, name='onApkSelected')

    def __init__(self, parent=None, show_path=True):
        super(ApkList, self).__init__(parent=parent)

        self.adb = Adb()

        if not self.adb.available():
            return

        self.retrieve_thread = PackageRetrieveThread(self.adb)
        if self.retrieve_thread is not None:
            self.retrieve_thread.onAddPackage.connect(self._on_addpackage)

        if show_path:
            self.apk_model = QStandardItemModel(0, 2)
        else:
            self.apk_model = QStandardItemModel(0, 1)

        self.apk_model.setHeaderData(0, Qt.Horizontal, 'Name')

        if show_path:
            self.apk_model.setHeaderData(1, Qt.Horizontal, 'Path')

        self.setModel(self.apk_model)
        self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)

        self.doubleClicked.connect(self._on_apk_selected)

        if self.retrieve_thread is not None:
            if not self.retrieve_thread.isRunning():
                self.retrieve_thread.start()

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def refresh(self):
        """ Refresh Packages
        """
        if self.retrieve_thread is not None:
            if not self.retrieve_thread.isRunning():
                self.clear()
                self.retrieve_thread.start()

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_addpackage(self, package):
        if package:
            name = QStandardItem()
            name.setText(package[0])

            if self.apk_model.columnCount() == 2:
                path = QStandardItem()
                path.setText(package[1])

                self.apk_model.appendRow([name, path])
            else:
                self.apk_model.appendRow([name])

    def _on_apk_selected(self, model_index):
        item = self.apk_model.itemFromIndex(model_index).row()
        if item != -1:
            package = self.apk_model.item(item, 0).text()
            if self.apk_model.columnCount() == 2:
                path = self.apk_model.item(item, 1).text()
                self.onApkSelected.emit([package, path])
            else:
                self.onApkSelected.emit([package, None])
class AndroidSession(Session):
    """ All Android Stuff goes here
        if u look for something android related its here then
    """
    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())

        self._smali_thread = None

    @property
    def session_ui_sections(self):
        # what sections we want in session_ui
        return [
            'hooks', 'bookmarks', 'threads', 'registers', 'debug', 'console',
            'watchers', 'modules', 'jvm-inspector', 'jvm-debugger', 'ranges',
            'backtrace'
        ]

    @property
    def non_closable(self):
        return ['debug', 'ranges', 'modules', 'jvm-inspector', 'jvm-debugger']

    @property
    def session_type(self):
        """ return session name to show in menus etc
        """
        return 'android'

    @property
    def device_manager_type(self):
        return 'usb'

    @property
    def frida_device(self):
        return frida.get_usb_device()

    def _setup_menu(self):
        """ Build Menus
        """
        # additional menus
        file_menu = QMenu('&Device')
        save_apk = QAction("&Save APK", self)
        save_apk.triggered.connect(self.save_apk)
        decompile_apk = QAction("&Decompile APK", self)
        decompile_apk.triggered.connect(self.decompile_apk)

        file_menu.addAction(save_apk)
        file_menu.addAction(decompile_apk)

        self._menu.append(file_menu)

        super()._setup_menu()

        java_menu = QMenu('&Java')
        java_menu.addAction('Trace', self._on_java_trace)
        java_menu.addSeparator()
        java_menu.addAction('Classes', self._on_java_classes)
        self._menu.append(java_menu)

    def start(self, args):
        super().start(args)
        self.adb.device = self.dwarf.device

    def decompile_apk(self):
        apk_dlg = ApkListDialog(self._app_window)
        apk_dlg.onApkSelected.connect(self._decompile_package)
        apk_dlg.show()

    def _decompile_package(self, data):
        package, path = data
        if path is not None:
            # todo: make qthread
            AndroidDecompileUtil.decompile(self.adb, path)

    def save_apk(self):
        apk_dlg = ApkListDialog(self._app_window)
        apk_dlg.onApkSelected.connect(self._save_package)
        apk_dlg.show()

    def _save_package(self, data):
        package, path = data
        if path is not None:
            result = QFileDialog.getSaveFileName(
                caption='Location to save ' + package,
                directory='./' + package + '.apk',
                filter='*.apk')
            if result and result[0]:
                self.adb.pull(path, result[0])

    def _on_proc_selected(self, data):
        super()._on_proc_selected(data)
        device, pid = data
        if device:
            self.adb.device = device.id

    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_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 _on_java_trace(self):
        tag = 'jvm-tracer'
        should_request_classes = \
            self._app_window.java_trace_panel is None or tag not in self._app_window.ui_elements
        self._app_window.show_main_tab(tag)
        if should_request_classes:
            self.dwarf.dwarf_api('enumerateJavaClasses')

    def _on_java_classes(self):
        self._app_window.show_main_tab('jvm-inspector')
        self.dwarf.dwarf_api('enumerateJavaClasses')
Exemple #15
0
 def __init__(self, parent=None, device_id=None, package_name=None):
     super(SmaliThread, self).__init__(parent)
     self._adb = Adb()
     self._adb.device = device_id
     self._package_name = package_name
Exemple #16
0
class AndroidSession(Session):
    """ All Android Stuff goes here
        if u look for something android related its here then
    """
    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)

    @property
    def session_ui_sections(self):
        # what sections we want in session_ui
        return [
            'hooks', 'threads', 'registers', 'memory', 'console', 'watchers'
        ]

    @property
    def session_type(self):
        """ return session name to show in menus etc
        """
        return 'Android'

    @property
    def main_menu(self):
        """ return our created menu
        """
        return self._menu

    def initialize(self, config):
        # session supports load/save then use config

        # setup ui etc for android
        self._setup_menu()
        # all fine were done wait for ui_ready
        self.onCreated.emit()

    def _setup_menu(self):
        """ Build Menus
        """
        # additional menus
        file_menu = QMenu('&Device')
        save_apk = QAction("&Save APK", self)
        save_apk.triggered.connect(self.save_apk)
        decompile_apk = QAction("&Decompile APK", self)
        decompile_apk.triggered.connect(self.decompile_apk)

        file_menu.addAction(save_apk)
        file_menu.addAction(decompile_apk)

        self._menu.append(file_menu)

        process_menu = QMenu('&Process')
        process_menu.addAction('Resume', self._on_proc_resume, Qt.Key_F5)
        process_menu.addAction('Restart', self._on_proc_restart, Qt.Key_F9)
        process_menu.addAction('Detach', self._on_detach, Qt.Key_F10)

        self._menu.append(process_menu)

        java_menu = QMenu('&Java')
        java_menu.addAction('Trace', self._on_java_trace)
        java_menu.addSeparator()
        java_menu.addAction('Classes', self._on_java_classes)
        self._menu.append(java_menu)

    def stop_session(self):
        # cleanup ur stuff

        # end session
        super().stop()

    def start(self, args):
        self.dwarf.onScriptDestroyed.connect(self.stop)
        if args.package is None:
            self._device_window.setModal(True)
            self._device_window.onSelectedProcess.connect(
                self.on_proc_selected)
            self._device_window.onSpwanSelected.connect(self.on_spawn_selected)
            self._device_window.onClosed.connect(self._on_devdlg_closed)
            self._device_window.show()
        else:
            self.dwarf.device = frida.get_usb_device()
            if not args.spawn:
                print('* Trying to attach to {0}'.format(args.package))
                ret_val = self.dwarf.attach(args.package, args.script, False)
                if ret_val == 2:
                    print('Failed to attach: use -sp to force spawn')
                    self.stop()
                    exit()
            else:
                print('* Trying to spawn {0}'.format(args.package))
                ret_val = self.dwarf.spawn(args.package, args.script)
                if ret_val != 0:
                    print('-failed-')
                    exit(ret_val)

    def decompile_apk(self):
        apk_dlg = ApkListDialog(self._app_window)
        apk_dlg.onApkSelected.connect(self._decompile_package)
        apk_dlg.show()
        """
        packages = self.adb.list_packages()
        if packages:
            accept, items = ListDialog.build_and_show(
                self.build_packages_list,
                packages,
                double_click_to_accept=True)
            if accept:
                if len(items) > 0:
                    path = items[0].get_apk_path()
                    AndroidDecompileUtil.decompile(self.adb, path)"""

    def _decompile_package(self, data):
        package, path = data
        if path is not None:
            # todo: make qthread
            AndroidDecompileUtil.decompile(self.adb, path)

    def save_apk(self):
        apk_dlg = ApkListDialog(self._app_window)
        apk_dlg.onApkSelected.connect(self._save_package)
        apk_dlg.show()

    def _save_package(self, data):
        package, path = data
        if path is not None:
            result = QFileDialog.getSaveFileName(
                caption='Location to save ' + package,
                directory='./' + package + '.apk',
                filter='*.apk')
            if result and result[0]:
                self.adb.pull(path, result[0])

    def on_proc_selected(self, data):
        device, pid = data
        if device:
            self.dwarf.device = device
        if pid:
            self.dwarf.attach(pid)

    def on_spawn_selected(self, data):
        device, package_name = data
        if device:
            self.dwarf.device = device
        if package_name:
            if self.dwarf.spawn(package=package_name):
                self.stop()

            # smalistuff
            self._app_window.show_progress('Baksmali ' + package_name + ' ...')
            _smali_thread = SmaliThread(self, package_name)
            _smali_thread.onError.connect(self._app_window.hide_progress)
            _smali_thread.onFinished.connect(self._app_window.hide_progress)
            _smali_thread.start()

            self._on_java_classes()

    def _on_proc_resume(self, tid=0):
        if tid == 0:
            self._app_window.contexts_list_panel.clear()
            self._app_window.context_panel.clear()
            # self._app_window.backtrace_panel.setRowCount(0)
            self._app_window.memory_panel.clear_panel()
            self.dwarf.contexts.clear()

        self.dwarf.dwarf_api('release', tid)

    def _on_proc_restart(self):
        self.dwarf.dwarf_api('restart')
        self._on_proc_resume()

    def _on_detach(self):
        self.dwarf.detach()

    def _on_java_trace(self):
        should_request_classes = self._app_window.java_trace_panel is None
        if self._app_window.java_trace_panel is None:
            self._app_window._create_ui_elem('java-trace')

        self._app_window.show_main_tab('java-trace')
        if should_request_classes:
            self.dwarf.dwarf_api('enumerateJavaClasses')

    def _on_java_classes(self):
        #should_request_classes = self._app_window.java is None
        if self._app_window.java_inspector_panel is None:
            self._app_window._create_ui_elem('java-inspector')

        self._app_window.show_main_tab('java-inspector')
        self.dwarf.dwarf_api('enumerateJavaClasses')

    def _on_devdlg_closed(self):
        if self.dwarf.device is None:
            self.stop_session()
Exemple #17
0
 def __init__(self, parent=None, package_name=None):
     super(SmaliThread, self).__init__(parent)
     self._adb = Adb()
     self._package_name = package_name
     if not self._adb.available():
         return
Exemple #18
0
class DeviceBar(QWidget):

    onDeviceUpdated = pyqtSignal()

    def __init__(self, parent=None, device_type='usb'):
        super().__init__(parent=parent)
        if device_type == 'local':
            return
        self.parent = parent
        self.wait_for_devtype = device_type
        self.is_waiting = True
        self._adb = Adb()
        self._git = Git()
        self.setAutoFillBackground(True)
        self.setStyleSheet(
            'background-color: crimson; color: white; font-weight: bold; margin: 0; padding: 10px;'
        )
        self.setup()
        self._timer = QTimer()
        self._timer.setInterval(500)
        self._timer.timeout.connect(self._on_timer)
        self._timer.start()
        self._timer_step = 0
        frida.get_device_manager().on('added', self._on_device)
        frida.get_device_manager().on('removed', self._on_device)
        self.devices_thread = DevicesUpdateThread(self)
        self.devices_thread.onAddDevice.connect(self.on_add_deviceitem)
        self._update_thread = FridaUpdateThread(self)
        self._update_thread.on_status_text.connect(self._update_statuslbl)
        self._update_thread.on_finished.connect(self._frida_updated)
        self._update_thread.onError.connect(self._on_download_error)
        self.updated_frida_version = ''
        self.updated_frida_assets_url = {}
        remote_frida = self._git.get_frida_version()
        if remote_frida is None:
            self.updated_frida_version = ''
            self.updated_frida_assets_url.clear()
        else:
            remote_frida = remote_frida[0]
            self.updated_frida_version = remote_frida['tag_name']
            for asset in remote_frida['assets']:
                try:
                    name = asset['name']
                    tag_start = name.index('android-')
                    if name.index('server') >= 0:
                        tag = name[tag_start + 8:-3]
                        self.updated_frida_assets_url[tag] = asset[
                            'browser_download_url']
                except ValueError:
                    pass

    def setup(self):
        """ Setup ui
        """
        h_box = QHBoxLayout()
        h_box.setContentsMargins(0, 0, 0, 0)
        self.update_label = QLabel('Waiting for Device')
        self.update_label.setFixedWidth(self.parent.width())
        self.update_label.setOpenExternalLinks(True)
        self.update_label.setTextFormat(Qt.RichText)
        self.update_label.setFixedHeight(35)
        self.update_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        self._install_btn = QPushButton('Install Frida', self.update_label)
        self._install_btn.setStyleSheet('padding: 0; border-color: white;')
        self._install_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                      25)
        self._install_btn.clicked.connect(self._on_install_btn)
        self._install_btn.setVisible(False)
        self._start_btn = QPushButton('Start Frida', self.update_label)
        self._start_btn.setStyleSheet('padding: 0; border-color: white;')
        self._start_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                    25)
        self._start_btn.clicked.connect(self._on_start_btn)
        self._start_btn.setVisible(False)
        self._update_btn = QPushButton('Update Frida', self.update_label)
        self._update_btn.setStyleSheet('padding: 0; border-color: white;')
        self._update_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                     25)
        self._update_btn.clicked.connect(self._on_install_btn)
        self._update_btn.setVisible(False)
        self._restart_btn = QPushButton('Restart Frida', self.update_label)
        self._restart_btn.setStyleSheet('padding: 0; border-color: white;')
        self._restart_btn.setGeometry(self.update_label.width() - 110, 5, 100,
                                      25)
        self._restart_btn.clicked.connect(self._on_restart_btn)
        self._restart_btn.setVisible(False)
        h_box.addWidget(self.update_label)
        self.setLayout(h_box)

    def on_add_deviceitem(self, device_name, device_type):
        """ Adds an Item to the DeviceComboBox
        """
        if device_type == self.wait_for_devtype:
            self._timer_step = -1
            self.is_waiting = False
            self.update_label.setStyleSheet('background-color: yellowgreen;')
            self.update_label.setText('Device found: ' + device_name)
            self._adb._check_requirements()
            if self._adb.available():
                device_frida = self._adb.get_frida_version()
                if device_frida is None:
                    self._install_btn.setVisible(True)
                else:
                    if self.updated_frida_version != device_frida:
                        self._update_btn.setVisible(True)
                        if self._adb.is_frida_running():
                            self.onDeviceUpdated.emit()
                    elif device_frida and not self._adb.is_frida_running():
                        self._start_btn.setVisible(True)
                    elif device_frida and self._adb.is_frida_running():
                        self._restart_btn.setVisible(True)
                        self.onDeviceUpdated.emit()

    def _on_timer(self):
        if self._timer_step == -1:
            self._timer.stop()
            return

        if self._timer_step == 0:
            self.update_label.setText(self.update_label.text() + ' .')
            self._timer_step = 1
        elif self._timer_step == 1:
            self.update_label.setText(self.update_label.text() + '.')
            self._timer_step = 2
        elif self._timer_step == 2:
            self.update_label.setText(self.update_label.text() + '.')
            self._timer_step = 3
        else:
            self.update_label.setText(
                self.update_label.text()[:-self._timer_step])
            self._timer_step = 0
            if self.is_waiting and self.devices_thread is not None:
                if not self.devices_thread.isRunning():
                    self.devices_thread.start()

    def _on_download_error(self, text):
        self._timer_step = -1
        self.update_label.setStyleSheet('background-color: crimson;')
        self.update_label.setText(text)
        self._install_btn.setVisible(True)
        self._update_btn.setVisible(False)

    def _on_device(self):
        self._timer_step = 4
        self.is_waiting = True
        self._on_timer()

    def _on_install_btn(self):
        # urls are empty
        if not self.updated_frida_assets_url:
            return

        arch = self._adb.get_device_arch()
        request_url = ''

        if arch is not None and len(arch) > 1:
            arch = arch.join(arch.split())

            if arch == 'arm64' or arch == 'arm64-v8a':
                request_url = self.updated_frida_assets_url['arm64']
            elif arch == 'armeabi-v7a':
                request_url = self.updated_frida_assets_url['arm']
            else:
                if arch in self.updated_frida_assets_url:
                    request_url = self.updated_frida_assets_url[arch]

            try:
                if self._adb.available() and request_url.index(
                        'https://') == 0:
                    self._install_btn.setVisible(False)
                    self._update_btn.setVisible(False)

                    if self._update_thread is not None:
                        if not self._update_thread.isRunning():
                            self._update_thread.frida_url = request_url
                            self._update_thread.adb = self._adb
                            self._update_thread.start()

            except ValueError:
                # something wrong in .git_cache folder
                print("request_url not set")

    def _update_statuslbl(self, text):
        self._timer.stop()
        self._timer_step = 0
        self._timer.start()
        self.update_label.setText(text)

    def _frida_updated(self):
        self._timer_step = 3
        self.is_waiting = True
        self._on_timer()

    def _on_start_btn(self):
        if self._adb.available():
            self._start_btn.setVisible(False)
            if self._adb.start_frida():
                self.onDeviceUpdated.emit()
            else:
                self._start_btn.setVisible(True)

    def _on_restart_btn(self):
        if self._adb.available():
            self._restart_btn.setVisible(False)
            if self._adb.start_frida(restart=True):
                self._restart_btn.setVisible(True)
                self.onDeviceUpdated.emit()
        methodString = enable
        while (True):
            result = QcUsbSwitch.SendCommandAndGetResponse(methodString)
            if not result.Status.HasError():
                break
        return result

    @staticmethod
    def SendCommandAndGetResponse(methodStrings, timeout=30):
        executionString = CommonApplicationUtilities._ToolsPath + "QcUSBSwitchTool\\QcUSBSwitchTool.exe " + methodStrings

        logger.debug("Executing Command :" + executionString)
        result = CommandLine.RunCommand(executionString, timeout)
        if (result.Status.HasError()
                or (not 'Success' in result.CmdResult.Output)):
            logger.error(result.CmdResult.Output)
            result.Status.AddError(result.CmdResult.Output)

        return result


if __name__ == '__main__':
    for i in range(10):
        QcUsbSwitch.SetUsbConnection('usb_on')
        result = Adb.IsDeviceDetected()
        logger.info("first time: " + str(result.IsSuccess()))
        if result.HasError():
            logger.info("set usb on again")
            QcUsbSwitch.SetUsbConnection('usb_on')
            result = Adb.IsDeviceDetected()
            logger.info("second time: " + str(result.IsSuccess()))
    def InitEnvironmnet(self):
        if 'KratosLite' in TestSuiteConfig.HardwareType:
            try:
                #self.PowerHandler = KratosLite()
                self.PowerHandler = PTTKratoslite()

                result = self.PowerHandler.SetConfigurationFile(
                    TestSuiteConfig.ChannelConfiguration)
                #                 if result.HasError():
                #                     return result
                result = self.PowerHandler.PowerOn()
                result = self.PowerHandler.UsbOn()
                result = Adb.IsDeviceDetected()
                if result.HasError():
                    logger.info("set usb on again")
                    QcUsbSwitch.SetUsbConnection('usb_on')
                    result = Adb.IsDeviceDetected()
                    logger.info("second time: " + str(result.IsSuccess()))
                else:
                    logger.info("first time: " + str(result.IsSuccess()))
                result = Adb.SetAdbRoot()
                if result.HasError():
                    return result
                result = Adb.SetAdbRemount()
                if result.HasError():
                    return result

            except Exception as e:
                return StatusResult.Error('Failed to initialize KRATOSLITE: ',
                                          str(e))
        elif 'Kratos' in TestSuiteConfig.HardwareType:
            logger.info("----------supply with Kratos--------------")
            try:
                #self.PowerHandler = Kratos()
                self.PowerHandler = PTTKratos()
                result = self.PowerHandler.SetConfigurationFile(
                    TestSuiteConfig.ChannelConfiguration)
                #                 if result.HasError():
                #                     return result
                result = self.PowerHandler.PowerOn()
                result = self.PowerHandler.UsbOn()
            except Exception as e:
                logger.info(str(e))
                return StatusResult.Error('Failed to initialize KRATOS: ',
                                          str(e))
        elif 'Monitor' in TestSuiteConfig.HardwareType:
            try:
                self.PowerHandler = PTTPowerMonitor()
            except Exception as e:
                logger.info(str(e))
                return StatusResult.Error(
                    'Failed to initialize PowerMonitor: ', str(e))
        else:
            logger.error(
                "Can't support hardware type, please check TestSuiteConfig.HardwareType"
            )
            return
        logger.info(TestSuiteConfig.HardwareType +
                    " : initialization successful.")
        logger.info("Waiting for device ...")
        result = Adb.WaitForDevice(30)
        logger.info("wait for device ready...")
        result = AdbSettings.ReMountDevice()
        if result.HasError():
            logger.error("Unable to set root & remount privileges")
        self.Wakelock()
        self.Discharging()
        logger.info("Disable charging & Enable wakelock")