def __init__(self, app_window): super(ScriptsDialog, self).__init__(app_window) self.script = None self._app_window = app_window self._script_manager = ScriptsManager() self._git = Git() self.setMinimumWidth(800) box = QVBoxLayout() self.table = ScriptsTable(self) self.table.onScriptSelected.connect(self._item_selected) self.table.setMinimumWidth(800) # create a centered dot icon _section_width = self.table.header().sectionSize(3) self._new_pixmap = QPixmap(max(_section_width, 40), 20) self._new_pixmap.fill(Qt.transparent) painter = QPainter(self._new_pixmap) rect = QRect((_section_width * 0.5) - 5, 0, 20, 20) painter.setBrush(QColor('#666')) painter.setPen(QColor('#666')) painter.drawEllipse(rect) self._dot_icon = QIcon(self._new_pixmap) box.addWidget(self.table) lbl = QLabel('OS Support - A: Android I: IOS W: Windows') box.addWidget(lbl) self.setLayout(box) self._init_list()
def get_paths(self, path): # type: (str) -> t.List[str] """Return the list of available content paths under the given path.""" git = Git(path) paths = git.get_file_names(['--cached', '--others', '--exclude-standard']) return paths
def get_merged_commit(args, commit): # pylint: disable=unused-argument """ :type args: CommonConfig :type commit: str :rtype: str | None """ if not commit: return None git = Git() try: show_commit = git.run_git( ['show', '--no-patch', '--no-abbrev', commit]) except SubprocessError as ex: # This should only fail for pull requests where the commit does not exist. # Merge runs would fail much earlier when attempting to checkout the commit. raise ApplicationError( 'Commit %s was not found:\n\n%s\n\n' 'GitHub may not have fully replicated the commit across their infrastructure.\n' 'It is also possible the commit was removed by a force push between job creation and execution.\n' 'Find the latest run for the pull request and restart failed jobs as needed.' % (commit, ex.stderr.strip())) head_commit = git.run_git(['show', '--no-patch', '--no-abbrev', 'HEAD']) if show_commit == head_commit: # Commit is HEAD, so this is not a pull request or the base branch for the pull request is up-to-date. return None match_merge = re.search(r'^Merge: (?P<parents>[0-9a-f]{40} [0-9a-f]{40})$', head_commit, flags=re.MULTILINE) if not match_merge: # The most likely scenarios resulting in a failure here are: # A new run should or does supersede this job, but it wasn't cancelled in time. # A job was superseded and then later restarted. raise ApplicationError( 'HEAD is not commit %s or a merge commit:\n\n%s\n\n' 'This job has likely been superseded by another run due to additional commits being pushed.\n' 'Find the latest run for the pull request and restart failed jobs as needed.' % (commit, head_commit.strip())) parents = set(match_merge.group('parents').split(' ')) if len(parents) != 2: raise ApplicationError('HEAD is a %d-way octopus merge.' % len(parents)) if commit not in parents: raise ApplicationError('Commit %s is not a parent of HEAD.' % commit) parents.remove(commit) last_commit = parents.pop() return last_commit
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
class ScriptsManager(QObject): """ ScriptManager signals: scriptsUpdated() """ scriptsUpdated = pyqtSignal(name='scriptsUpdated') def __init__(self): super(ScriptsManager, self).__init__() self._git = Git() self.scripts = {} self.update_scripts() def update_scripts(self): scripts = self._git.get_dwarf_scripts() if scripts is None: return scripts = scripts.replace(' ', '').replace('\t', '').split('\n') submodule_path = '[submodule"' url_path = 'url=' module_name = '' for line in scripts: if line.startswith(submodule_path): module_name = line.replace(submodule_path, "") module_name = module_name[:-2] elif line.startswith(url_path): url = line.replace(url_path, "") if url.endswith('.git'): url = url[:-4] url = url.replace('https://github.com', 'https://raw.githubusercontent.com') info_url = url + '/master/dwarf.json' script_url = url + '/master/script.js' info = self._git.get_script_info(info_url) if info is None: continue self.scripts[module_name] = { 'info': info, 'script': script_url } self.scriptsUpdated.emit() def get_script(self, script_name): return self.scripts[script_name] def get_scripts(self): return self.scripts
def __init__(self, app_window): self.app_window = app_window self.app = app_window.get_app_instance() self.java_available = False self.loading_library = False # frida device self.device = None # process self.pid = 0 self.process = None self.script = None # hooks self.hooks = {} self.on_loads = {} self.java_hooks = {} self.temporary_input = '' self.native_pending_args = None self.java_pending_args = None # core utils self.prefs = Prefs() self.git = Git() self.script_manager = ScriptsManager(self) self.keystone_installed = False try: import keystone.keystone_const self.keystone_installed = True except: pass
def detect_changes_local(args): """ :type args: TestConfig :rtype: list[str] """ git = Git(args) result = LocalChanges(args, git) display.info( 'Detected branch %s forked from %s at commit %s' % (result.current_branch, result.fork_branch, result.fork_point)) if result.untracked and not args.untracked: display.warning( 'Ignored %s untracked file(s). Use --untracked to include them.' % len(result.untracked)) if result.committed and not args.committed: display.warning( 'Ignored %s committed change(s). Omit --ignore-committed to include them.' % len(result.committed)) if result.staged and not args.staged: display.warning( 'Ignored %s staged change(s). Omit --ignore-staged to include them.' % len(result.staged)) if result.unstaged and not args.unstaged: display.warning( 'Ignored %s unstaged change(s). Omit --ignore-unstaged to include them.' % len(result.unstaged)) names = set() if args.tracked: names |= set(result.tracked) if args.untracked: names |= set(result.untracked) if args.committed: names |= set(result.committed) if args.staged: names |= set(result.staged) if args.unstaged: names |= set(result.unstaged) if not args.metadata.changes: args.metadata.populate_changes(result.diff) for path in result.untracked: if is_binary_file(path): args.metadata.changes[path] = ((0, 0), ) continue with open(path, 'r') as source_fd: line_count = len(source_fd.read().splitlines()) args.metadata.changes[path] = ((1, line_count), ) return sorted(names)
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 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 backup_repos(self, repos): info('[%s] backing up repositories' % self.type) for repo in repos: try: repo_name = get_repo_name(repo, self.type) path = os.path.join(self.directory, repo_name) git = Git(repo, path, repo_name, self.verbose) if os.path.isdir(path): remote_refs = len(git.list_remote_refs()) if remote_refs == 0: continue git.fetch() git.reset_origin_hard() else: git.clone() except Exception: self.errors.append(repo_name)
def __init__(self, app_window): self.app_window = app_window self.app = app_window.get_app_instance() self.java_available = False self.loading_library = False # frida device self.device = None # process self.pid = 0 self.process = None self.script = None # kernel self.kernel = Kernel(self) # hooks self.hooks = {} self.on_loads = {} self.java_hooks = {} self.temporary_input = '' self.native_pending_args = None self.java_pending_args = None # context self.arch = '' self.pointer_size = 0 self.contexts = {} self.context_tid = 0 # tracers self.native_traced_tid = 0 # core utils self.bus = EventBus() self.emulator = Emulator(self) self.git = Git() self.prefs = Prefs() self.script_manager = ScriptsManager(self) self.keystone_installed = False try: import keystone.keystone_const self.keystone_installed = True except: pass
def detect_changes_local(args): """ :type args: TestConfig :rtype: list[str] """ git = Git(args) result = LocalChanges(args, git) display.info( 'Detected branch %s forked from %s at commit %s' % (result.current_branch, result.fork_branch, result.fork_point)) if result.untracked and not args.untracked: display.warning( 'Ignored %s untracked file(s). Use --untracked to include them.' % len(result.untracked)) if result.committed and not args.committed: display.warning( 'Ignored %s committed change(s). Omit --ignore-committed to include them.' % len(result.committed)) if result.staged and not args.staged: display.warning( 'Ignored %s staged change(s). Omit --ignore-staged to include them.' % len(result.staged)) if result.unstaged and not args.unstaged: display.warning( 'Ignored %s unstaged change(s). Omit --ignore-unstaged to include them.' % len(result.unstaged)) names = set() if args.tracked: names |= set(result.tracked) if args.untracked: names |= set(result.untracked) if args.committed: names |= set(result.committed) if args.staged: names |= set(result.staged) if args.unstaged: names |= set(result.unstaged) return sorted(names)
def detect_changes_shippable(args): """Initialize change detection on Shippable. :type args: CommonConfig :rtype: list[str] """ git = Git(args) result = ShippableChanges(args, git) if result.is_pr: job_type = 'pull request' elif result.is_tag: job_type = 'tag' else: job_type = 'merge commit' display.info('Processing %s for branch %s commit %s' % (job_type, result.branch, result.commit)) return result.paths
def setup(self): self.repo_path = "../repo/path/" self.commit_range = "tag1..tag2" self.file = "file.txt" self.message = "1.2.3.4 release notes" self.tag_cmd = list(TAG_CMD) self.tag_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.tag_cmd[2] = '--work-tree=' + self.repo_path self.log_cmd = list(LOG_CMD) self.log_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.log_cmd[2] = '--work-tree=' + self.repo_path self.log_cmd.append(self.commit_range) self.add_cmd = list(ADD_CMD) self.add_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.add_cmd[2] = '--work-tree=' + self.repo_path self.add_cmd.append(self.file) self.cmt_cmd = list(CMT_CMD) self.cmt_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.cmt_cmd[2] = '--work-tree=' + self.repo_path self.cmt_cmd.append('"' + self.message + '"') self.push_cmd = list(PUSH_CMD) self.push_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.push_cmd[2] = '--work-tree=' + self.repo_path self.pull_cmd = list(PULL_CMD) self.pull_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.pull_cmd[2] = '--work-tree=' + self.repo_path self.fetch_cmd = list(FETCH_CMD) self.fetch_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.fetch_cmd[2] = '--work-tree=' + self.repo_path self.checkout_cmd = list(CHECKOUT_CMD) self.checkout_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.checkout_cmd[2] = '--work-tree=' + self.repo_path self.sut = Git()
def detect_changes_shippable(args): """Initialize change detection on Shippable. :type args: TestConfig :rtype: list[str] | None """ git = Git(args) result = ShippableChanges(args, git) if result.is_pr: job_type = 'pull request' elif result.is_tag: job_type = 'tag' else: job_type = 'merge commit' display.info('Processing %s for branch %s commit %s' % (job_type, result.branch, result.commit)) if not args.metadata.changes: args.metadata.populate_changes(result.diff) return result.paths
def main(): git = Git(config.GIT_REPO, config.GIT_WORKING_COPY) git.clone()
parent_parsers = [spreadsheet_parser, github_parser] parser = argparse.ArgumentParser( description='Add YouTube metadata and publish new videos', parents=parent_parsers) args = parser.parse_args() spreadsheet = Spreadsheet(args.spreadsheet_id) youtube = YouTube() print('Getting all talks from spreadsheet with YouTube IDs') talks = spreadsheet.get_unpublished_youtube_talks() print('{} unpublished talks'.format(len(talks))) ids = [talk.youtube_id for talk in talks] print('Getting videos from YouTube') videos = youtube.get_videos(ids) for talk in talks: print('Unpublished talk: {}'.format(talk.title)) video = filter(lambda x: talk.youtube_id == x.youtube_id, videos)[0] print('\tYouTube ID: {}'.format(video.youtube_id)) print('\tSetting metadata and setting status to UNLISTED') title = '{} ({})'.format(talk.title, talk.speakers) video.publish(title, talk.description) print('\tAdding to website') git = Git(args.repo_user, args.repo) git.add_youtube_to_talk(talk.slug, video.youtube_id) print('\tUpdating spreadsheet to set published status to true') talk.published_status = True
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()
from lib.EmailHandler import EmailHandler import itsdangerous import hashlib import geopy import tinys3 from lib.git import Git from flask import Flask, request app = Flask(__name__) logger = app.logger logger.setLevel(logging.DEBUG) geocoder = geopy.geocoders.OpenCage(config.OPENCAGE_API_KEY, timeout=5) git = Git(config.GIT_REPO, config.GIT_WORKING_COPY) s3 = tinys3.Connection( config.AWS_ACCESS_KEY_ID, config.AWS_SECRET_ACCESS_KEY, default_bucket=config.S3_IMAGE_BUCKET, tls=True, ) mail_handler = EmailHandler(s3, config.S3_IMAGE_PATH_PREFIX, geocoder, git, config.COMMIT_CHANGES) signer = itsdangerous.Signer(config.ADDR_VALIDATION_HMAC_KEY, sep="^", digest_method=hashlib.sha256) @app.route("/email/<sender>/<addr_hash>", methods=["POST"])
def __init__(self): super(ScriptsManager, self).__init__() self._git = Git() self.scripts = {} self.update_scripts()
class ScriptsDialog(QDialog): """ Scripts """ def __init__(self, app_window): super(ScriptsDialog, self).__init__(app_window) self.script = None self._app_window = app_window self._script_manager = ScriptsManager() self._git = Git() self.setMinimumWidth(800) box = QVBoxLayout() self.table = ScriptsTable(self) self.table.onScriptSelected.connect(self._item_selected) self.table.setMinimumWidth(800) # create a centered dot icon _section_width = self.table.header().sectionSize(3) self._new_pixmap = QPixmap(max(_section_width, 40), 20) self._new_pixmap.fill(Qt.transparent) painter = QPainter(self._new_pixmap) rect = QRect((_section_width * 0.5) - 5, 0, 20, 20) painter.setBrush(QColor('#666')) painter.setPen(QColor('#666')) painter.drawEllipse(rect) self._dot_icon = QIcon(self._new_pixmap) box.addWidget(self.table) lbl = QLabel('OS Support - A: Android I: IOS W: Windows') box.addWidget(lbl) self.setLayout(box) self._init_list() def _init_list(self): for script_name in sorted(self._script_manager.get_scripts().keys()): script = self._script_manager.get_script(script_name) info = script['info'] _name = QStandardItem() _name.setText(script_name) _name.setToolTip(info['name']) _author = QStandardItem() if 'author' in info: _author.setTextAlignment(Qt.AlignCenter) _author.setText(info['author']) _android = QStandardItem() if 'android' in info: _android.setIcon(self._dot_icon) _ios = QStandardItem() if 'ios' in info: _ios.setIcon(self._dot_icon) _windows = QStandardItem() if 'windows' in info: _windows.setIcon(self._dot_icon) _desc = QStandardItem() if 'description' in info: _desc.setText(info['description']) self.table.add_item( [_name, _author, _android, _ios, _windows, _desc]) def _item_selected(self, script_name): script_url = self._script_manager.get_script(script_name)['script'] script = self._git.get_script(script_url) self.script = script self.accept() @staticmethod def pick(app): """ helper """ dialog = ScriptsDialog(app) result = dialog.exec_() return result == QDialog.Accepted, dialog.script
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" args = process_args() #_check_dependencies() # not enabled atm from lib import utils from lib.git import Git from lib.prefs import Prefs from ui.app import AppWindow _prefs = Prefs() local_update_disabled = _prefs.get('disable_local_frida_update', False) 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: # write ini to show folder with dwarficon folder_stuff = "[.ShellClassInfo]\n" folder_stuff += "IconResource=assets\\dwarf.ico,0\n" folder_stuff += "[ViewState]\n" folder_stuff += "Mode=\n" folder_stuff += "Vid=\n" folder_stuff += "FolderType=Generic\n" try: with open('desktop.ini', 'w') as ini: ini.writelines(folder_stuff) # set fileattributes to hidden + systemfile ctypes.windll.kernel32.SetFileAttributesW( r'desktop.ini', 0x02 | 0x04 ) # 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 from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication 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") # set icon if os.name == "nt" and os.path.exists( utils.resource_path('assets/dwarf.ico')): _icon = QIcon(utils.resource_path('assets/dwarf.ico')) qapp.setWindowIcon(_icon) else: if os.path.exists(utils.resource_path('assets/dwarf.png')): _icon = QIcon(utils.resource_path('assets/dwarf.png')) qapp.setWindowIcon(_icon) app_window = AppWindow(args) 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)
class TestGit(): def setup(self): self.repo_path = "../repo/path/" self.commit_range = "tag1..tag2" self.file = "file.txt" self.message = "1.2.3.4 release notes" self.tag_cmd = list(TAG_CMD) self.tag_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.tag_cmd[2] = '--work-tree=' + self.repo_path self.log_cmd = list(LOG_CMD) self.log_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.log_cmd[2] = '--work-tree=' + self.repo_path self.log_cmd.append(self.commit_range) self.add_cmd = list(ADD_CMD) self.add_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.add_cmd[2] = '--work-tree=' + self.repo_path self.add_cmd.append(self.file) self.cmt_cmd = list(CMT_CMD) self.cmt_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.cmt_cmd[2] = '--work-tree=' + self.repo_path self.cmt_cmd.append('"' + self.message + '"') self.push_cmd = list(PUSH_CMD) self.push_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.push_cmd[2] = '--work-tree=' + self.repo_path self.pull_cmd = list(PULL_CMD) self.pull_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.pull_cmd[2] = '--work-tree=' + self.repo_path self.fetch_cmd = list(FETCH_CMD) self.fetch_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.fetch_cmd[2] = '--work-tree=' + self.repo_path self.checkout_cmd = list(CHECKOUT_CMD) self.checkout_cmd[1] = '--git-dir=' + self.repo_path + '.git' self.checkout_cmd[2] = '--work-tree=' + self.repo_path self.sut = Git() def test___map_cmd_does_not_mutate_cmd_template(self): expected = ('git', '--git-dir=____', '--work-tree=____', 'tag') self.sut._Git__map_cmd(TAG_CMD, self.repo_path) eq_(expected, TAG_CMD) def test___map_cmd_replaces_git_dir_as_expected(self): expected = '--git-dir=' + self.repo_path + '.git' actual = self.sut._Git__map_cmd(TAG_CMD, self.repo_path)[1] eq_(expected, actual) def test___map_cmd_replaces_work_tree_as_expected(self): expected = '--work-tree=' + self.repo_path actual = self.sut._Git__map_cmd(TAG_CMD, self.repo_path)[2] eq_(expected, actual) @mock.patch('lib.git.subprocess') def test_tag_calls_subprocess_check_output_as_expected(self, mock_subprocess): self.sut.tag(self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(self.tag_cmd) @mock.patch('lib.git.subprocess') def test_tag_returns_expected_value(self, mock_subprocess): mock_return = "a\nb\nc" expected = ["a", "b", "c"] mock_subprocess.check_output.return_value = mock_return eq_(expected, self.sut.tag(self.repo_path)) @mock.patch('lib.git.subprocess') def test_log_calls_subprocess_check_output_as_expected(self, mock_subprocess): self.sut.log(self.commit_range, self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(self.log_cmd) @mock.patch('lib.git.subprocess') def test_log_returns_expected_value(self, mock_subprocess): mock_return = "abc\n" + LOG_SEPARATOR + \ "\ndef\n" + LOG_SEPARATOR + "\n" expected = ["abc", "def"] mock_subprocess.check_output.return_value = mock_return eq_(expected, self.sut.log(self.commit_range, self.repo_path)) @mock.patch('lib.git.subprocess') def test_log_operates_as_expected(self, mock_subprocess): # mock_subprocess.check_output.side_effect = log_for_tag_side_effect self.sut.log(self.commit_range, self.repo_path) mock_subprocess.check_output.assert_called_once_with(self.log_cmd) def test_get_tag_range_operates_as_expected(self): tags = ["my", "dog", "fido"] actual = self.sut.get_tag_range("my", tags) eq_("my", actual) actual = self.sut.get_tag_range("dog", tags) eq_("my..dog", actual) @raises(ValueError) def test_get_tag_range_raises_ValueError_when_tag_not_found(self): tags = ["my", "dog", "fido"] self.sut.get_tag_range("tag", tags) @mock.patch('lib.git.subprocess') def test_add_calls_check_output_as_expected(self, mock_subprocess): self.sut.add(self.file, self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(self.add_cmd) @mock.patch('lib.git.subprocess') def test_commit_calls_check_output_as_expected(self, mock_subprocess): self.sut.commit(self.message, self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(self.cmt_cmd) @mock.patch('lib.git.subprocess') def test_push_calls_check_output_as_expected(self, mock_subprocess): remote = "myremote" branch = "mybranch" push_cmd = self.push_cmd push_cmd.append(remote) push_cmd.append(branch) self.sut.push(remote, branch, self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(push_cmd) @mock.patch('lib.git.subprocess') def test_pull_calls_check_output_as_expected(self, mock_subprocess): remote = "myremote" branch = "mybranch" pull_cmd = self.pull_cmd pull_cmd.append(remote) pull_cmd.append(branch) self.sut.pull(remote, branch, self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(pull_cmd) @mock.patch('lib.git.subprocess') def test_fetch_calls_check_output_as_expected(self, mock_subprocess): remote = "myremote" fetch_cmd = self.fetch_cmd fetch_cmd[4] = remote self.sut.fetch(remote, self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(fetch_cmd) @mock.patch('lib.git.subprocess') def test_checkout_calls_check_output_as_expected(self, mock_subprocess): branch = "mybranch" checkout_cmd = self.checkout_cmd checkout_cmd.append(branch) self.sut.checkout(branch, self.repo_path) ok_(mock_subprocess.check_output.called) mock_subprocess.check_output.assert_called_once_with(checkout_cmd) @mock.patch('lib.git.util') def test_get_tags_by_pattern_operates_as_expected(self, mock_util): pattern = "tag11" tags = ["tag1", "tag11", "tag21"] self.sut.tag = mock.MagicMock() self.sut.tag.return_value = tags mock_util.string_has_pattern.side_effect = [False, True, False] actual = self.sut.get_tags_by_pattern(pattern, self.repo_path) self.sut.tag.assert_called_once_with(self.repo_path) eq_(3, mock_util.string_has_pattern.call_count) eq_([tags[1]], actual)