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()
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()