Esempio n. 1
0
    def __init__(self, app):
        super(DataPanel, self).__init__(app)

        self.app = app
        self.data = {}

        self.setOrientation(Qt.Horizontal)
        self.setHandleWidth(1)

        self._key_list_model = QStandardItemModel(0, 1)
        self.key_lists = DwarfListView(parent=self.app)
        self.key_lists.setHeaderHidden(True)
        self.key_lists.setModel(self._key_list_model)
        self.key_lists.doubleClicked.connect(self.list_item_double_clicked)

        self.addWidget(self.key_lists)

        self.editor = QPlainTextEdit()
        self.addWidget(self.editor)

        self.hex_view = HexEditor(self.app)
        self.hex_view.setVisible(False)
        self.addWidget(self.hex_view)
        #self.setStretchFactor(0, 8)
        self.setStretchFactor(1, 4)
Esempio n. 2
0
    def __init__(self, parent=None, show_progress_dlg=False):
        super(SearchPanel, self).__init__(parent=parent)
        self._app_window = parent

        if self._app_window.dwarf is None:
            print('SearchPanel created before Dwarf exists')
            return

        self._app_window.dwarf.onMemoryScanResult.connect(
            self._on_search_result)

        self._ranges_model = None
        self._result_model = None

        self._blocking_search = show_progress_dlg
        self.progress = None
        self._pattern_length = 0

        self._search_results = []

        box = QVBoxLayout()

        self.input = QLineEdit()
        self.input.setPlaceholderText(
            'search for a sequence of bytes in hex format: deadbeef123456aabbccddeeff...'
        )
        box.addWidget(self.input)

        self.check_all_btn = QPushButton('check all')
        self.check_all_btn.clicked.connect(self._on_click_check_all)
        self.uncheck_all_btn = QPushButton('uncheck all')
        self.uncheck_all_btn.clicked.connect(self._on_click_uncheck_all)
        self.search_btn = QPushButton('search')
        self.search_btn.clicked.connect(self._on_click_search)

        h_box = QHBoxLayout()
        h_box.addWidget(self.check_all_btn)
        h_box.addWidget(self.uncheck_all_btn)
        h_box.addWidget(self.search_btn)
        box.addLayout(h_box)

        self.ranges = DwarfListView(self)
        self.ranges.clicked.connect(self._on_show_results)
        self.results = DwarfListView(self)
        self.results.setVisible(False)

        h_box = QHBoxLayout()
        h_box.addWidget(self.ranges)
        h_box.addWidget(self.results)
        box.addLayout(h_box)

        self.setLayout(box)

        self._setup_models()
Esempio n. 3
0
class DataPanel(QSplitter):
    def __init__(self, app):
        super(DataPanel, self).__init__(app)

        self.app = app
        self.data = {}

        self.setOrientation(Qt.Horizontal)
        self.setHandleWidth(1)

        self._key_list_model = QStandardItemModel(0, 1)
        self.key_lists = DwarfListView(parent=self.app)
        self.key_lists.setHeaderHidden(True)
        self.key_lists.setModel(self._key_list_model)
        self.key_lists.doubleClicked.connect(self.list_item_double_clicked)
        self.key_lists.setContextMenuPolicy(Qt.CustomContextMenu)
        self.key_lists.customContextMenuRequested.connect(
            self._on_context_menu)
        self.addWidget(self.key_lists)

        self.editor = QPlainTextEdit()
        self.addWidget(self.editor)

        self.hex_view = HexEditor(self.app)
        self.hex_view.setVisible(False)
        self.addWidget(self.hex_view)
        #self.setStretchFactor(0, 8)
        self.setStretchFactor(1, 4)

    def clear(self):
        self._key_list_model.clear()
        self.editor.setPlainText('')
        self.hex_view.clear_panel()

    def append_data(self, data_type, key, text_data):
        if key not in self.data:
            self._key_list_model.appendRow([QStandardItem(key)])
        self.data[key] = [data_type, text_data]

    def list_item_double_clicked(self, item):
        item = self._key_list_model.itemFromIndex(item)
        if self.data[item.text()][0] == 'plain':
            self.hex_view.setVisible(False)
            self.editor.setVisible(True)
            self.editor.setPlainText(self.data[item.text()][1])
        else:
            self.editor.setVisible(False)
            self.hex_view.setVisible(True)
            self.hex_view.bytes_per_line = 16
            self.hex_view.set_data(self.data[item.text()][1])

    def _on_context_menu(self, pos):
        context_menu = QMenu(self)

        index = self.key_lists.indexAt(pos).row()
        if index != -1:
            context_menu.addAction('Clear', self.clear)
            global_pt = self.key_lists.mapToGlobal(pos)
            context_menu.exec(global_pt)
Esempio n. 4
0
class DataPanel(QSplitter):
    def __init__(self, app):
        super(DataPanel, self).__init__(app)

        self.app = app
        self.data = {}

        self.setOrientation(Qt.Horizontal)
        self.setHandleWidth(1)

        self._key_list_model = QStandardItemModel(0, 1)
        self.key_lists = DwarfListView(parent=self.app)
        self.key_lists.setHeaderHidden(True)
        self.key_lists.setModel(self._key_list_model)
        self.key_lists.doubleClicked.connect(self.list_item_double_clicked)

        self.addWidget(self.key_lists)

        self.editor = QPlainTextEdit()
        self.addWidget(self.editor)

        self.hex_view = HexEditor(self.app)
        self.hex_view.setVisible(False)
        self.addWidget(self.hex_view)
        #self.setStretchFactor(0, 8)
        self.setStretchFactor(1, 4)

    def clear(self):
        self._key_list_model.clear()
        self.editor.setPlainText('')
        self.hex_view.clear_panel()

    def append_data(self, data_type, key, text_data):
        if key not in self.data:
            self._key_list_model.appendRow([QStandardItem(key)])
        self.data[key] = [data_type, text_data]

    def list_item_double_clicked(self, item):
        item = self._key_list_model.itemFromIndex(item)
        if self.data[item.text()][0] == 'plain':
            self.hex_view.setVisible(False)
            self.editor.setVisible(True)
            self.editor.setPlainText(self.data[item.text()][1])
        else:
            self.editor.setVisible(False)
            self.hex_view.setVisible(True)
            self.hex_view.bytes_per_line = 16
            self.hex_view.set_data(self.data[item.text()][1])
Esempio n. 5
0
    def __init__(self, parent=None):
        super(JavaInspector, self).__init__(parent)

        self._app_window = parent

        self._app_window.dwarf.onEnumerateJavaMethodsComplete.connect(
            self._on_method_enumeration_complete)
        self._app_window.dwarf.onEnumerateJavaClassesStart.connect(
            self._on_class_enumeration_start)
        self._app_window.dwarf.onEnumerateJavaClassesMatch.connect(
            self._on_class_enumeration_match)
        self._app_window.dwarf.onEnumerateJavaClassesComplete.connect(
            self._on_class_enumeration_complete)

        self._java_classes = DwarfListView(self)
        self._javaclass_model = QStandardItemModel(0, 1)
        self._javaclass_model.setHeaderData(0, Qt.Horizontal, 'Class')
        self._java_classes.setModel(self._javaclass_model)
        self._java_classes.selectionModel().selectionChanged.connect(
            self._class_clicked)
        self._java_classes.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._java_classes.setContextMenuPolicy(Qt.CustomContextMenu)
        self._java_classes.customContextMenuRequested.connect(
            self._on_class_contextmenu)
        self._java_classes.doubleClicked.connect(self._class_dblclicked)

        self._java_methods = DwarfListView(self)
        self._javamethod_model = QStandardItemModel(0, 1)
        self._javamethod_model.setHeaderData(0, Qt.Horizontal, 'Method')
        self._java_methods.setModel(self._javamethod_model)
        self._java_methods.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._java_methods.setContextMenuPolicy(Qt.CustomContextMenu)
        self._java_methods.customContextMenuRequested.connect(
            self._on_method_contextmenu)
        self._java_methods.doubleClicked.connect(self._method_dblclicked)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(0, 0, 0, 0)
        h_box.addWidget(self._java_classes)
        h_box.addWidget(self._java_methods)
        self.setLayout(h_box)
Esempio n. 6
0
    def __init__(self, device, parent=None):
        super(ProcessList, self).__init__(parent=parent)

        # if not isinstance(device, frida.core.Device):
        #    print('No FridaDevice')
        #    return

        self._device = device

        self.process_list = DwarfListView()

        model = QStandardItemModel(0, 2, parent)
        model.setHeaderData(0, Qt.Horizontal, "PID")
        model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                            Qt.TextAlignmentRole)
        model.setHeaderData(1, Qt.Horizontal, "Name")

        self.process_list.doubleClicked.connect(self._on_item_clicked)

        v_box = QVBoxLayout()
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self.process_list)
        self.refresh_button = QPushButton('Refresh')
        self.refresh_button.clicked.connect(self._on_refresh_procs)
        self.refresh_button.setEnabled(False)
        v_box.addWidget(self.refresh_button)
        self.setLayout(v_box)

        self.process_list.setModel(model)
        self.process_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)

        self.procs_update_thread = ProcsThread(self, self._device)
        self.procs_update_thread.add_proc.connect(self._on_add_proc)
        self.procs_update_thread.is_error.connect(self._on_error)
        self.procs_update_thread.is_finished.connect(self._on_refresh_finished)
        self.procs_update_thread.device = self._device
        self.procs_update_thread.start()
Esempio n. 7
0
    def __init__(self,
                 parent=None,
                 setup_list_cb=None,
                 setup_list_cb_args=None,
                 double_click_to_accept=False,
                 checkable=False):
        super(ListDialog, self).__init__(parent)

        self.right_click_handler = None

        layout = QVBoxLayout(self)
        self.list = DwarfListView()  # QListWidget()

        self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        if double_click_to_accept:
            self.list.doubleClicked.connect(self.accept)

        if setup_list_cb is not None:
            setup_list_cb(self.list, setup_list_cb_args)

        layout.addWidget(self.list)
        if checkable:
            buttons = QHBoxLayout()
            select_all = QPushButton('select all')
            select_all.clicked.connect(self.select_all)
            buttons.addWidget(select_all)
            unselect_all = QPushButton('unselect all')
            unselect_all.clicked.connect(self.unselect_all)
            buttons.addWidget(unselect_all)
            ok = QPushButton('ok')
            ok.clicked.connect(self.accept)
            buttons.addWidget(ok)
            cancel = QPushButton('cancel')
            cancel.clicked.connect(self.close)
            buttons.addWidget(cancel)
            layout.addLayout(buttons)
Esempio n. 8
0
    def __init__(self, app, *__args):
        super().__init__(*__args)

        self.app = app
        self.emulator = self.app.dwarf.emulator
        self.until_address = 0

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        self._toolbar = QToolBar()
        self._toolbar.addAction('Start', self.handle_start)
        self._toolbar.addAction('Step', self.handle_step)
        self._toolbar.addAction('Stop', self.handle_stop)
        self._toolbar.addAction('Clean', self.handle_clean)
        self._toolbar.addAction('Options', self.handle_options)

        layout.addWidget(self._toolbar)

        self.tabs = QTabWidget()
        self.assembly = DisassemblyView(self.app)
        self.assembly.display_jumps = False
        self.assembly.follow_jumps = False
        self.memory_table = MemoryPanel(self.app)
        self.memory_table._read_only = True
        self.tabs.addTab(self.assembly, 'Code')
        self.tabs.addTab(self.memory_table, 'Memory')

        layout.addWidget(self.tabs)

        h_box = QHBoxLayout()
        self.ranges_list = DwarfListView(self.app)
        self.ranges_list.doubleClicked.connect(self.ranges_item_double_clicked)
        self._ranges_model = QStandardItemModel(0, 2)
        self._ranges_model.setHeaderData(0, Qt.Horizontal, 'Memory')
        self._ranges_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(1, Qt.Horizontal, 'Size')
        self.ranges_list.setModel(self._ranges_model)

        self._access_list = DwarfListView(self.app)
        self._access_list.doubleClicked.connect(
            self.access_item_double_clicked)
        self._access_model = QStandardItemModel(0, 3)
        self._access_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._access_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._access_model.setHeaderData(1, Qt.Horizontal, 'Access')
        self._access_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._access_model.setHeaderData(2, Qt.Horizontal, 'Value')
        self._access_list.setModel(self._access_model)
        h_box.addWidget(self.ranges_list)
        h_box.addWidget(self._access_list)

        layout.addLayout(h_box)
        self.setLayout(layout)

        self.console = self.app.console.get_emu_console()

        self.emulator.onEmulatorStart.connect(self.on_emulator_start)
        self.emulator.onEmulatorStop.connect(self.on_emulator_stop)
        # self.emulator.onEmulatorStep.connect(self.on_emulator_step)
        self.emulator.onEmulatorHook.connect(self.on_emulator_hook)
        self.emulator.onEmulatorMemoryHook.connect(
            self.on_emulator_memory_hook)
        self.emulator.onEmulatorMemoryRangeMapped.connect(
            self.on_emulator_memory_range_mapped)
        self.emulator.onEmulatorLog.connect(self.on_emulator_log)

        self._require_register_result = None
        self._last_instruction_address = 0
Esempio n. 9
0
class EmulatorPanel(QWidget):
    def __init__(self, app, *__args):
        super().__init__(*__args)

        self.app = app
        self.emulator = self.app.dwarf.emulator
        self.until_address = 0

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        self._toolbar = QToolBar()
        self._toolbar.addAction('Start', self.handle_start)
        self._toolbar.addAction('Step', self.handle_step)
        self._toolbar.addAction('Stop', self.handle_stop)
        self._toolbar.addAction('Clean', self.handle_clean)
        self._toolbar.addAction('Options', self.handle_options)

        layout.addWidget(self._toolbar)

        self.tabs = QTabWidget()
        self.assembly = DisassemblyView(self.app)
        self.assembly.display_jumps = False
        self.assembly.follow_jumps = False
        self.memory_table = MemoryPanel(self.app)
        self.memory_table._read_only = True
        self.tabs.addTab(self.assembly, 'Code')
        self.tabs.addTab(self.memory_table, 'Memory')

        layout.addWidget(self.tabs)

        h_box = QHBoxLayout()
        self.ranges_list = DwarfListView(self.app)
        self.ranges_list.doubleClicked.connect(self.ranges_item_double_clicked)
        self._ranges_model = QStandardItemModel(0, 2)
        self._ranges_model.setHeaderData(0, Qt.Horizontal, 'Memory')
        self._ranges_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(1, Qt.Horizontal, 'Size')
        self.ranges_list.setModel(self._ranges_model)

        self._access_list = DwarfListView(self.app)
        self._access_list.doubleClicked.connect(
            self.access_item_double_clicked)
        self._access_model = QStandardItemModel(0, 3)
        self._access_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._access_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._access_model.setHeaderData(1, Qt.Horizontal, 'Access')
        self._access_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._access_model.setHeaderData(2, Qt.Horizontal, 'Value')
        self._access_list.setModel(self._access_model)
        h_box.addWidget(self.ranges_list)
        h_box.addWidget(self._access_list)

        layout.addLayout(h_box)
        self.setLayout(layout)

        self.console = self.app.console.get_emu_console()

        self.emulator.onEmulatorStart.connect(self.on_emulator_start)
        self.emulator.onEmulatorStop.connect(self.on_emulator_stop)
        # self.emulator.onEmulatorStep.connect(self.on_emulator_step)
        self.emulator.onEmulatorHook.connect(self.on_emulator_hook)
        self.emulator.onEmulatorMemoryHook.connect(
            self.on_emulator_memory_hook)
        self.emulator.onEmulatorMemoryRangeMapped.connect(
            self.on_emulator_memory_range_mapped)
        self.emulator.onEmulatorLog.connect(self.on_emulator_log)

        self._require_register_result = None
        self._last_instruction_address = 0

    def resizeEvent(self, event):
        self.ranges_list.setFixedHeight((self.height() / 100) * 25)
        self.ranges_list.setFixedWidth((self.width() / 100) * 30)
        self._access_list.setFixedHeight((self.height() / 100) * 25)
        return super().resizeEvent(event)

    def handle_clean(self):
        self.ranges_list.clear()
        self._access_list.clear()
        self.assembly._lines.clear()
        self.assembly.viewport().update()
        # self.memory_table.setRowCount(0)
        self.console.clear()
        self.emulator.clean()

    def handle_options(self):
        EmulatorConfigsDialog.show_dialog(self.app.dwarf)

    def handle_start(self):
        ph = ''
        if self.until_address > 0:
            ph = hex(self.until_address)
        address, inp = InputDialog.input_pointer(
            self.app, input_content=ph, hint='pointer to last instruction')
        if address > 0:
            self.until_address = address
            self.emulator.emulate(self.until_address)
            # if err > 0:
            #    self.until_address = 0
            #    self.console.log('cannot start emulator. err: %d' % err)
            #    return

    def handle_step(self):
        try:
            result = self.emulator.emulate()
            if not result:
                self.console.log('Emulation failed')
        except self.emulator.EmulatorAlreadyRunningError:
            self.console.log('Emulator already runnging')
        except self.emulator.EmulatorSetupFailedError as error:
            self.until_address = 0
            self.console.log(error)

    def handle_stop(self):
        self.emulator.stop()

    def on_emulator_hook(self, instruction):
        self.app.context_panel.set_context(0, 2, self.emulator.current_context)
        # check if the previous hook is waiting for a register result
        if self._require_register_result is not None:
            row = 1
            res = '%s = %s' % (self._require_register_result[1],
                               hex(
                                   self.emulator.uc.reg_read(
                                       self._require_register_result[0])))
            if len(self.assembly._lines) > 1:
                if self.assembly._lines[len(self.assembly._lines) -
                                        row] is None:
                    row = 2
                self.assembly._lines[len(self.assembly._lines) -
                                     row].string = res
                # invalidate
                self._require_register_result = None

        # check if the code jumped
        self._last_instruction_address = instruction.address

        self.assembly.add_instruction(instruction)

        # add empty line if jump
        if instruction.is_jump:
            self.assembly.add_instruction(None)

        # implicit regs read are notified later through mem access
        if len(instruction.regs_read) == 0:
            if len(instruction.operands) > 0:
                for i in instruction.operands:
                    if i.type == CS_OP_REG:
                        self._require_register_result = [
                            i.value.reg,
                            instruction.reg_name(i.value.reg)
                        ]
                        break
        self.assembly.verticalScrollBar().setValue(len(self.assembly._lines))
        self.assembly.viewport().update()

    def on_emulator_log(self, log):
        self.app.console_panel.show_console_tab('emulator')
        self.console.log(log)

    def on_emulator_memory_hook(self, data):
        uc, access, address, value = data
        _address = QStandardItem()
        str_frmt = ''
        if self.ranges_list.uppercase_hex:
            if self.app.dwarf.pointer_size > 4:
                str_frmt = '0x{0:016X}'.format(address)
            else:
                str_frmt = '0x{0:08X}'.format(address)
        else:
            if self.app.dwarf.pointer_size > 4:
                str_frmt = '0x{0:016x}'.format(address)
            else:
                str_frmt = '0x{0:08x}'.format(address)
        _address.setText(str_frmt)
        _address.setTextAlignment(Qt.AlignCenter)

        _access = QStandardItem()
        if access == UC_MEM_READ:
            _access.setText('READ')
        elif access == UC_MEM_WRITE:
            _access.setText('WRITE')
        elif access == UC_MEM_FETCH:
            _access.setText('FETCH')
        _access.setTextAlignment(Qt.AlignCenter)

        _value = QStandardItem()
        _value.setText(str(value))

        self._access_model.appendRow([_address, _access, _value])

        res = None
        row = 1
        if len(self.assembly._lines) > 1:
            if self.assembly._lines[len(self.assembly._lines) - row] is None:
                row = 2
            if access == UC_MEM_READ:
                if self._require_register_result is not None:
                    res = '%s = %s' % (self._require_register_result[1],
                                       hex(value))
            else:
                if self.assembly._lines[len(self.assembly._lines) -
                                        row].string:
                    res = '%s, %s = %s' % (self.assembly._lines[
                        len(self.assembly._lines) - row].string, hex(address),
                                           hex(value))
                else:
                    res = '%s = %s' % (hex(address), hex(value))
            if res is not None:
                # invalidate
                self._require_register_result = None

                self.assembly._lines[len(self.assembly._lines) -
                                     row].string = res

    def on_emulator_memory_range_mapped(self, data):
        address, size = data
        _address = QStandardItem()
        str_frmt = ''
        if self.ranges_list.uppercase_hex:
            if self.app.dwarf.pointer_size > 4:
                str_frmt = '0x{0:016X}'.format(address)
            else:
                str_frmt = '0x{0:08X}'.format(address)
        else:
            if self.app.dwarf.pointer_size > 4:
                str_frmt = '0x{0:016x}'.format(address)
            else:
                str_frmt = '0x{0:08x}'.format(address)
        _address.setText(str_frmt)
        _address.setTextAlignment(Qt.AlignCenter)
        _size = QStandardItem()
        _size.setText("{0:,d}".format(int(size)))
        self._ranges_model.appendRow([_address, _size])

    def on_emulator_start(self):
        pass

    def on_emulator_stop(self):
        self.app.context_panel.set_context(0, 2, self.emulator.current_context)
        # check if the previous hook is waiting for a register result
        if self._require_register_result is not None:
            row = 1
            res = '%s = %s' % (self._require_register_result[1],
                               hex(
                                   self.emulator.uc.reg_read(
                                       self._require_register_result[0])))
            if len(self.assembly._lines) > 1:
                if self.assembly._lines[len(self.assembly._lines) -
                                        row] is None:
                    row = 2
                self.assembly._lines[len(self.assembly._lines) -
                                     row].string = res
                # invalidate
                self._require_register_result = None

    def ranges_item_double_clicked(self, model_index):
        row = self._ranges_model.itemFromIndex(model_index).row()
        if row != -1:
            item = self._ranges_model.item(row, 0).text()
            self.memory_table.read_memory(item)
            self.tabs.setCurrentIndex(1)

    def access_item_double_clicked(self, model_index):
        row = self._access_model.itemFromIndex(model_index).row()
        if row != -1:
            item = self._access_model.item(row, 0).text()
            self.memory_table.read_memory(item)
            self.tabs.setCurrentIndex(1)
Esempio n. 10
0
    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(BookmarksPanel, self).__init__(parent=parent)

        self._app_window = parent

        if self._app_window.dwarf is None:
            print('BookmarksPanel created before Dwarf exists')
            return

        self._bookmarks_list = DwarfListView()
        self._bookmarks_list.doubleClicked.connect(self._on_dblclicked)
        self._bookmarks_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._bookmarks_list.customContextMenuRequested.connect(
            self._on_contextmenu)

        self._bookmarks_model = QStandardItemModel(0, 2)
        self._bookmarks_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._bookmarks_model.setHeaderData(1, Qt.Horizontal, 'Notes')

        self._bookmarks_list.setModel(self._bookmarks_model)

        self._bookmarks_list.header().setStretchLastSection(False)
        self._bookmarks_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._bookmarks_list.header().setSectionResizeMode(
            1, QHeaderView.Stretch | QHeaderView.Interactive)

        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self._bookmarks_list)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        self.btn1 = QPushButton(
            QIcon(utils.resource_path('assets/icons/plus.svg')), '')
        self.btn1.setFixedSize(20, 20)
        self.btn1.clicked.connect(lambda: self._create_bookmark(-1))
        btn2 = QPushButton(QIcon(utils.resource_path('assets/icons/dash.svg')),
                           '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(utils.resource_path('assets/icons/trashcan.svg')), '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(self.btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)
        self.setLayout(v_box)

        self._bold_font = QFont(self._bookmarks_list.font())
        self._bold_font.setBold(True)

        shortcut_addnative = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_A),
                                       self._app_window, self._create_bookmark)
        shortcut_addnative.setAutoRepeat(False)
Esempio n. 11
0
class BookmarksPanel(QWidget):
    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(BookmarksPanel, self).__init__(parent=parent)

        self._app_window = parent

        if self._app_window.dwarf is None:
            print('BookmarksPanel created before Dwarf exists')
            return

        self._bookmarks_list = DwarfListView()
        self._bookmarks_list.doubleClicked.connect(self._on_dblclicked)
        self._bookmarks_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._bookmarks_list.customContextMenuRequested.connect(
            self._on_contextmenu)

        self._bookmarks_model = QStandardItemModel(0, 2)
        self._bookmarks_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._bookmarks_model.setHeaderData(1, Qt.Horizontal, 'Notes')

        self._bookmarks_list.setModel(self._bookmarks_model)

        self._bookmarks_list.header().setStretchLastSection(False)
        self._bookmarks_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._bookmarks_list.header().setSectionResizeMode(
            1, QHeaderView.Stretch | QHeaderView.Interactive)

        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self._bookmarks_list)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        self.btn1 = QPushButton(
            QIcon(utils.resource_path('assets/icons/plus.svg')), '')
        self.btn1.setFixedSize(20, 20)
        self.btn1.clicked.connect(lambda: self._create_bookmark(-1))
        btn2 = QPushButton(QIcon(utils.resource_path('assets/icons/dash.svg')),
                           '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(utils.resource_path('assets/icons/trashcan.svg')), '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(self.btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)
        self.setLayout(v_box)

        self._bold_font = QFont(self._bookmarks_list.font())
        self._bold_font.setBold(True)

        shortcut_addnative = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_A),
                                       self._app_window, self._create_bookmark)
        shortcut_addnative.setAutoRepeat(False)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def delete_items(self):
        """ Delete selected Items
        """
        index = self._bookmarks_list.selectionModel().currentIndex().row()
        if index != -1:
            self._on_delete_bookmark(index)
            self._bookmarks_model.removeRow(index)

    def clear_list(self):
        """ Clear the List
        """
        # go through all items and tell it gets removed
        for item in range(self._bookmarks_model.rowCount()):
            if item:
                self._on_delete_bookmark(item)

        if self._bookmarks_model.rowCount() > 0:
            # something was wrong it should be empty
            self._bookmarks_model.removeRows(0,
                                             self._bookmarks_model.rowCount())

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_dblclicked(self, index):
        self._app_window.jump_to_address(
            self._bookmarks_model.item(index, 0).text())

    def _on_contextmenu(self, pos):
        context_menu = QMenu(self)
        index = self._bookmarks_list.indexAt(pos).row()
        if index != -1:
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._bookmarks_model.item(index, 0).text()))
            context_menu.addAction(
                'Jump to address', lambda: self._app_window.jump_to_address(
                    self._bookmarks_model.item(index, 0).text()))

            # todo: add hook address menu

            context_menu.addSeparator()
            context_menu.addAction('Edit',
                                   lambda: self._create_bookmark(index=index))
            context_menu.addAction('Delete',
                                   lambda: self._on_delete_bookmark(index))
            context_menu.addSeparator()
        context_menu.addAction('New', lambda: self._create_bookmark())
        global_pt = self._bookmarks_list.mapToGlobal(pos)
        context_menu.exec(global_pt)

    # + button
    def _create_bookmark(self, index=-1, ptr=''):
        note = ''

        if ptr == '':
            if isinstance(index, int) and index >= 0:
                ptr = self._bookmarks_model.item(index, 0).text()
                note = self._bookmarks_model.item(index, 1).text()

            ptr, input_ = InputDialog.input_pointer(parent=self._app_window,
                                                    input_content=ptr)
        else:
            try:
                ptr = int(ptr, 16)
            except:
                ptr = 0

        if ptr > 0:

            index = self._bookmarks_model.findItems(hex(ptr), Qt.MatchExactly)
            if len(index) > 0:
                index = index[0].row()
                note = self._bookmarks_model.item(index, 1).text()
            else:
                index = -1

            accept, note = InputDialog.input(hint='Insert notes for %s' %
                                             hex(ptr),
                                             input_content=note)
            if accept:
                if index < 0:
                    self._bookmarks_model.appendRow(
                        [QStandardItem(hex(ptr)),
                         QStandardItem(note)])
                else:
                    item = self._bookmarks_model.item(index, 0)
                    item.setText(hex(ptr))
                    item = self._bookmarks_model.item(index, 1)
                    item.setText(note)

    # shortcuts/menu

    def _on_delete_bookmark(self, index):
        self._bookmarks_model.removeRow(index)
Esempio n. 12
0
    def __init__(self, parent=None):
        super(WelcomeDialog, self).__init__(parent=parent)

        self._prefs = parent.prefs

        self._sub_titles = [
            ['duck', 'dumb', 'doctor', 'dutch', 'dark', 'dirty', 'debugging'],
            ['warriors', 'wardrobes', 'waffles', 'wishes', 'worcestershire'],
            ['are', 'aren\'t', 'ain\'t', 'appears to be'],
            ['rich', 'real', 'riffle', 'retarded', 'rock'],
            [
                'as f**k', 'fancy', 'f****d', 'front-ended', 'falafel',
                'french fries'
            ],
        ]

        self._update_thread = None

        self._recent_list_model = QStandardItemModel(0, 6)
        self._recent_list_model.setHeaderData(0, Qt.Horizontal, 'Path')
        self._recent_list_model.setHeaderData(1, Qt.Horizontal, 'Session')
        self._recent_list_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(2, Qt.Horizontal, 'Hooks')
        self._recent_list_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(3, Qt.Horizontal, 'Watchers')
        self._recent_list_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(4, Qt.Horizontal, 'OnLoads')
        self._recent_list_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(5, Qt.Horizontal, 'Bookmarks')
        self._recent_list_model.setHeaderData(5, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        #self._recent_list_model.setHeaderData(6, Qt.Horizontal, 'Custom script')
        #self._recent_list_model.setHeaderData(6, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)

        self._recent_list = DwarfListView(self)
        self._recent_list.setModel(self._recent_list_model)

        self._recent_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._recent_list.header().setSectionResizeMode(1, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(2, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(3, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(4, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(5, QHeaderView.Stretch)
        #self._recent_list.header().setSectionResizeMode(6, QHeaderView.Stretch)

        self._recent_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._recent_list.customContextMenuRequested.connect(
            self._on_recent_sessions_context_menu)
        self._recent_list.doubleClicked.connect(
            self._on_recent_session_double_click)

        # setup size and remove/disable titlebuttons
        self.desktop_geom = qApp.desktop().availableGeometry()
        self.setFixedSize(self.desktop_geom.width() * .45,
                          self.desktop_geom.height() * .4)
        self.setGeometry(
            QStyle.alignedRect(Qt.LeftToRight, Qt.AlignCenter, self.size(),
                               qApp.desktop().availableGeometry()))
        self.setSizeGripEnabled(False)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
        self.setWindowFlag(Qt.WindowCloseButtonHint, True)
        self.setModal(True)

        # setup ui elements
        self.setup_ui()

        random.seed(a=None, version=2)

        self.update_commits_thread = DwarfCommitsThread(parent)
        self.update_commits_thread.on_update_available.connect(
            self._on_dwarf_isupdate)
        self.update_commits_thread.start()
        # center
        self.setGeometry(
            QStyle.alignedRect(Qt.LeftToRight, Qt.AlignCenter, self.size(),
                               qApp.desktop().availableGeometry()))
Esempio n. 13
0
class WelcomeDialog(QDialog):
    onSessionSelected = pyqtSignal(str, name='onSessionSelected')
    onSessionRestore = pyqtSignal(dict, name='onSessionRestore')
    onUpdateComplete = pyqtSignal(name='onUpdateComplete')
    onIsNewerVersion = pyqtSignal(name='onIsNewerVersion')

    def __init__(self, parent=None):
        super(WelcomeDialog, self).__init__(parent=parent)

        self._prefs = parent.prefs

        self._sub_titles = [
            ['duck', 'dumb', 'doctor', 'dutch', 'dark', 'dirty', 'debugging'],
            ['warriors', 'wardrobes', 'waffles', 'wishes', 'worcestershire'],
            ['are', 'aren\'t', 'ain\'t', 'appears to be'],
            ['rich', 'real', 'riffle', 'retarded', 'rock'],
            [
                'as f**k', 'fancy', 'f****d', 'front-ended', 'falafel',
                'french fries'
            ],
        ]

        self._update_thread = None

        self._recent_list_model = QStandardItemModel(0, 6)
        self._recent_list_model.setHeaderData(0, Qt.Horizontal, 'Path')
        self._recent_list_model.setHeaderData(1, Qt.Horizontal, 'Session')
        self._recent_list_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(2, Qt.Horizontal, 'Hooks')
        self._recent_list_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(3, Qt.Horizontal, 'Watchers')
        self._recent_list_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(4, Qt.Horizontal, 'OnLoads')
        self._recent_list_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._recent_list_model.setHeaderData(5, Qt.Horizontal, 'Bookmarks')
        self._recent_list_model.setHeaderData(5, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        #self._recent_list_model.setHeaderData(6, Qt.Horizontal, 'Custom script')
        #self._recent_list_model.setHeaderData(6, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)

        self._recent_list = DwarfListView(self)
        self._recent_list.setModel(self._recent_list_model)

        self._recent_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._recent_list.header().setSectionResizeMode(1, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(2, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(3, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(4, QHeaderView.Stretch)
        self._recent_list.header().setSectionResizeMode(5, QHeaderView.Stretch)
        #self._recent_list.header().setSectionResizeMode(6, QHeaderView.Stretch)

        self._recent_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._recent_list.customContextMenuRequested.connect(
            self._on_recent_sessions_context_menu)
        self._recent_list.doubleClicked.connect(
            self._on_recent_session_double_click)

        # setup size and remove/disable titlebuttons
        self.desktop_geom = qApp.desktop().availableGeometry()
        self.setFixedSize(self.desktop_geom.width() * .45,
                          self.desktop_geom.height() * .4)
        self.setGeometry(
            QStyle.alignedRect(Qt.LeftToRight, Qt.AlignCenter, self.size(),
                               qApp.desktop().availableGeometry()))
        self.setSizeGripEnabled(False)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
        self.setWindowFlag(Qt.WindowCloseButtonHint, True)
        self.setModal(True)

        # setup ui elements
        self.setup_ui()

        random.seed(a=None, version=2)

        self.update_commits_thread = DwarfCommitsThread(parent)
        self.update_commits_thread.on_update_available.connect(
            self._on_dwarf_isupdate)
        self.update_commits_thread.start()
        # center
        self.setGeometry(
            QStyle.alignedRect(Qt.LeftToRight, Qt.AlignCenter, self.size(),
                               qApp.desktop().availableGeometry()))

    def setup_ui(self):
        """ Setup Ui
        """
        main_wrap = QVBoxLayout()
        main_wrap.setContentsMargins(0, 0, 0, 0)

        # updatebar on top
        self.update_bar = UpdateBar(self)
        self.update_bar.onUpdateNowClicked.connect(self._update_dwarf)
        self.update_bar.setVisible(False)
        main_wrap.addWidget(self.update_bar)

        # main content
        h_box = QHBoxLayout()
        h_box.setContentsMargins(15, 15, 15, 15)
        wrapper = QVBoxLayout()
        head = QHBoxLayout()
        head.setContentsMargins(50, 10, 0, 10)
        # dwarf icon
        icon = QLabel()
        icon.setPixmap(QPixmap(utils.resource_path('assets/dwarf.svg')))
        icon.setAlignment(Qt.AlignCenter)
        icon.setMinimumSize(QSize(125, 125))
        icon.setMaximumSize(QSize(125, 125))
        head.addWidget(icon)

        # main title
        v_box = QVBoxLayout()
        title = QLabel('Dwarf')
        title.setContentsMargins(0, 0, 0, 0)
        title.setFont(QFont('Anton', 100, QFont.Bold))
        title.setMaximumHeight(125)
        title.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        title.setAlignment(Qt.AlignCenter)
        head.addWidget(title)

        sub_title_text = (self._pick_random_word(0) + ' ' +
                          self._pick_random_word(1) + ' ' +
                          self._pick_random_word(2) + ' ' +
                          self._pick_random_word(3) + ' ' +
                          self._pick_random_word(4))
        sub_title_text = sub_title_text[:1].upper() + sub_title_text[1:]
        self._sub_title = QLabel(sub_title_text)
        self._sub_title.setFont(QFont('OpenSans', 16, QFont.Bold))
        font_metric = QFontMetrics(self._sub_title.font())
        self._char_width = font_metric.widthChar('#')
        self._sub_title.setAlignment(Qt.AlignCenter)
        self._sub_title.setContentsMargins(175, 0, 0, 20)
        self._sub_title.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Minimum)
        v_box.addLayout(head)
        v_box.addWidget(self._sub_title)

        wrapper.addLayout(v_box)

        recent = QLabel('Last saved Sessions')
        font = recent.font()
        font.setPointSize(11)
        font.setBold(True)
        #font.setPointSize(10)
        recent.setFont(font)
        wrapper.addWidget(recent)
        wrapper.addWidget(self._recent_list)
        h_box.addLayout(wrapper, stretch=False)
        buttonSpacer = QSpacerItem(15, 100, QSizePolicy.Fixed,
                                   QSizePolicy.Minimum)
        h_box.addItem(buttonSpacer)
        wrapper = QVBoxLayout()

        btn = QPushButton()
        ico = QIcon(QPixmap(utils.resource_path('assets/android.svg')))
        btn.setIconSize(QSize(75, 75))
        btn.setIcon(ico)
        btn.setToolTip('New Android Session')
        btn.clicked.connect(self._on_android_button)
        wrapper.addWidget(btn)

        btn = QPushButton()
        ico = QIcon(QPixmap(utils.resource_path('assets/apple.svg')))
        btn.setIconSize(QSize(75, 75))
        btn.setIcon(ico)
        btn.setToolTip('New iOS Session')
        btn.clicked.connect(self._on_ios_button)
        wrapper.addWidget(btn)

        btn = QPushButton()
        ico = QIcon(QPixmap(utils.resource_path('assets/local.svg')))
        btn.setIconSize(QSize(75, 75))
        btn.setIcon(ico)
        btn.setToolTip('New Local Session')
        btn.clicked.connect(self._on_local_button)
        wrapper.addWidget(btn)

        btn = QPushButton()
        ico = QIcon(QPixmap(utils.resource_path('assets/remote.svg')))
        btn.setIconSize(QSize(75, 75))
        btn.setIcon(ico)
        btn.setToolTip('New Remote Session')
        btn.clicked.connect(self._on_remote_button)
        wrapper.addWidget(btn)

        session_history = self._prefs.get(prefs.RECENT_SESSIONS, default=[])
        invalid_session_files = []
        for recent_session_file in session_history:
            if os.path.exists(recent_session_file):
                with open(recent_session_file, 'r') as f:
                    exported_session = json.load(f)
                hooks = '0'
                watchers = '0'
                on_loads = 0
                bookmarks = '0'
                #have_user_script = False
                if 'hooks' in exported_session and exported_session[
                        'hooks'] is not None:
                    hooks = str(len(exported_session['hooks']))
                if 'watchers' in exported_session and exported_session[
                        'watchers'] is not None:
                    watchers = str(len(exported_session['watchers']))
                if 'nativeOnLoads' in exported_session and exported_session[
                        'nativeOnLoads'] is not None:
                    on_loads += len(exported_session['nativeOnLoads'])
                if 'javaOnLoads' in exported_session and exported_session[
                        'javaOnLoads'] is not None:
                    on_loads += len(exported_session['javaOnLoads'])
                if 'bookmarks' in exported_session and exported_session[
                        'bookmarks'] is not None:
                    bookmarks = str(len(exported_session['bookmarks']))
                if 'user_script' in exported_session and exported_session[
                        'user_script']:
                    have_user_script = exported_session['user_script'] != ''

                #user_script_item = QStandardItem()
                #if have_user_script:
                #user_script_item.setIcon(self._dot_icon)

                on_loads = str(on_loads)

                recent_session_file_item = QStandardItem(recent_session_file)
                recent_session_file_item.setData(exported_session,
                                                 Qt.UserRole + 2)

                item_1 = QStandardItem(exported_session['session'])
                item_1.setTextAlignment(Qt.AlignCenter)
                item_2 = QStandardItem(hooks)
                item_2.setTextAlignment(Qt.AlignCenter)
                item_3 = QStandardItem(watchers)
                item_3.setTextAlignment(Qt.AlignCenter)
                item_4 = QStandardItem(on_loads)
                item_4.setTextAlignment(Qt.AlignCenter)
                item_5 = QStandardItem(bookmarks)
                item_5.setTextAlignment(Qt.AlignCenter)
                #item_6 = QStandardItem(user_script_item)
                #item_6.setTextAlignment(Qt.AlignCenter)

                self._recent_list_model.insertRow(
                    self._recent_list_model.rowCount(), [
                        recent_session_file_item, item_1, item_2, item_3,
                        item_4, item_5
                    ])
            else:
                invalid_session_files.append(recent_session_file)
        for invalid in invalid_session_files:
            session_history.pop(session_history.index(invalid))
        self._prefs.put(prefs.RECENT_SESSIONS, session_history)

        h_box.addLayout(wrapper, stretch=False)
        main_wrap.addLayout(h_box)
        self.setLayout(main_wrap)

    def _on_dwarf_isupdate(self):
        self.update_bar.setVisible(True)
        self.setFixedHeight(self.height() + self.update_bar.height())
        self.onIsNewerVersion.emit()

    def _update_dwarf(self):
        self._update_thread = DwarfUpdateThread(self)
        self._update_thread.on_finished.connect(self._update_finished)
        if not self._update_thread.isRunning():
            self._update_thread.start()

    def _update_finished(self):
        self.onUpdateComplete.emit()

    def _on_android_button(self):
        self.onSessionSelected.emit('Android')
        self.close()

    def _on_local_button(self):
        self.onSessionSelected.emit('Local')
        self.close()

    def _on_ios_button(self):
        self.onSessionSelected.emit('Ios')
        self.close()

    def _on_remote_button(self):
        self.onSessionSelected.emit('Remote')
        self.close()

    def _pick_random_word(self, arr):
        return self._sub_titles[arr][random.randint(
            0,
            len(self._sub_titles[arr]) - 1)]

    def _on_recent_sessions_context_menu(self, pos):
        index = self.list_view.indexAt(pos).row()
        glbl_pt = self.list_view.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Delete recent session', lambda: self._remove_recent_sessions(
                    self._recent_list_model.item(index, 0).text()))

            context_menu.exec_(glbl_pt)

    def _remove_recent_session(self, session_file):
        if os.path.exists(session_file):
            os.remove(session_file)
            session_history = self._prefs.get(prefs.RECENT_SESSIONS,
                                              default=[])
            if session_file in session_history:
                session_history.pop(session_history.index(session_file))
                self._prefs.put(prefs.RECENT_SESSIONS, session_history)

    def _on_recent_session_double_click(self, model_index):
        row = self._recent_list_model.itemFromIndex(model_index).row()
        recent_session_file = self._recent_list_model.item(row, 0)
        recent_session_data = recent_session_file.data(Qt.UserRole + 2)
        self.onSessionRestore.emit(recent_session_data)

    def showEvent(self, QShowEvent):
        """ override to change font size when subtitle is cutted
        """
        if len(self._sub_title.text()) * self._char_width > (
                self._sub_title.width() - 155):
            self._sub_title.setFont(QFont('OpenSans', 14, QFont.Bold))
        return super().showEvent(QShowEvent)
Esempio n. 14
0
    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(WatchersPanel, self).__init__(parent=parent)
        self._app_window = parent

        if self._app_window.dwarf is None:
            print('Watcherpanel created before Dwarf exists')
            return

        self._uppercase_hex = True
        self.setAutoFillBackground(True)

        # connect to dwarf
        self._app_window.dwarf.onWatcherAdded.connect(self._on_watcher_added)
        self._app_window.dwarf.onWatcherRemoved.connect(
            self._on_watcher_removed)

        # setup our model
        self._watchers_model = QStandardItemModel(0, 5)
        self._watchers_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._watchers_model.setHeaderData(1, Qt.Horizontal, 'R')
        self._watchers_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)
        self._watchers_model.setHeaderData(2, Qt.Horizontal, 'W')
        self._watchers_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)
        self._watchers_model.setHeaderData(3, Qt.Horizontal, 'X')
        self._watchers_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)
        self._watchers_model.setHeaderData(4, Qt.Horizontal, 'S')
        self._watchers_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)

        # setup ui
        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        self.list_view = DwarfListView()
        self.list_view.setModel(self._watchers_model)
        self.list_view.header().setSectionResizeMode(0, QHeaderView.Stretch)
        self.list_view.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setSectionResizeMode(
            3, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setSectionResizeMode(
            4, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setStretchLastSection(False)
        self.list_view.doubleClicked.connect(self._on_item_dblclick)
        self.list_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.list_view.customContextMenuRequested.connect(self._on_contextmenu)

        v_box.addWidget(self.list_view)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        icon = QIcon()
        icon.addPixmap(QPixmap(utils.resource_path('assets/icons/plus.svg')))
        btn1 = QPushButton(icon, '')
        btn1.setFixedSize(20, 20)
        btn1.clicked.connect(self._on_additem_clicked)
        btn2 = QPushButton(
            QIcon(QPixmap(utils.resource_path('assets/icons/dash.svg'))), '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(QPixmap(utils.resource_path('assets/icons/trashcan.svg'))),
            '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)

        # create a centered dot icon
        _section_width = self.list_view.header().sectionSize(2)
        self._new_pixmap = QPixmap(_section_width, 20)
        self._new_pixmap.fill(Qt.transparent)
        painter = QPainter(self._new_pixmap)
        rect = QRect((_section_width * 0.5), 0, 20, 20)
        painter.setBrush(QColor('#666'))
        painter.setPen(QColor('#666'))
        painter.drawEllipse(rect)
        self._dot_icon = QIcon(self._new_pixmap)

        # shortcuts
        shortcut_add = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W),
                                 self._app_window, self._on_additem_clicked)
        shortcut_add.setAutoRepeat(False)

        self.setLayout(v_box)
Esempio n. 15
0
    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(HooksPanel, self).__init__(parent=parent)

        self._app_window = parent

        if self._app_window.dwarf is None:
            print('HooksPanel created before Dwarf exists')
            return

        # connect to dwarf
        self._app_window.dwarf.onAddJavaHook.connect(self._on_add_hook)
        self._app_window.dwarf.onAddNativeHook.connect(self._on_add_hook)
        self._app_window.dwarf.onAddNativeOnLoadHook.connect(self._on_add_hook)
        self._app_window.dwarf.onHitNativeOnLoad.connect(
            self._on_hit_native_on_load)
        self._app_window.dwarf.onDeleteHook.connect(self._on_hook_deleted)

        self._hooks_list = DwarfListView()
        self._hooks_list.doubleClicked.connect(self._on_dblclicked)
        self._hooks_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._hooks_list.customContextMenuRequested.connect(
            self._on_contextmenu)
        self._hooks_model = QStandardItemModel(0, 5)

        self._hooks_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._hooks_model.setHeaderData(1, Qt.Horizontal, 'T')
        self._hooks_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                        Qt.TextAlignmentRole)
        self._hooks_model.setHeaderData(2, Qt.Horizontal, 'Input')
        self._hooks_model.setHeaderData(3, Qt.Horizontal, '{}')
        self._hooks_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter,
                                        Qt.TextAlignmentRole)
        self._hooks_model.setHeaderData(4, Qt.Horizontal, '<>')
        self._hooks_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter,
                                        Qt.TextAlignmentRole)

        self._hooks_list.setModel(self._hooks_model)

        self._hooks_list.header().setStretchLastSection(False)
        self._hooks_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._hooks_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._hooks_list.header().setSectionResizeMode(2, QHeaderView.Stretch)
        self._hooks_list.header().setSectionResizeMode(
            3, QHeaderView.ResizeToContents)
        self._hooks_list.header().setSectionResizeMode(
            4, QHeaderView.ResizeToContents)

        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self._hooks_list)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        self.btn1 = QPushButton(
            QIcon(utils.resource_path('assets/icons/plus.svg')), '')
        self.btn1.setFixedSize(20, 20)
        self.btn1.clicked.connect(self._on_additem_clicked)
        btn2 = QPushButton(QIcon(utils.resource_path('assets/icons/dash.svg')),
                           '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(utils.resource_path('assets/icons/trashcan.svg')), '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(self.btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)
        self.setLayout(v_box)

        self._bold_font = QFont(self._hooks_list.font())
        self._bold_font.setBold(True)

        shortcut_addnative = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_N),
                                       self._app_window, self._on_addnative)
        shortcut_addnative.setAutoRepeat(False)

        shortcut_addjava = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_J),
                                     self._app_window, self._on_addjava)
        shortcut_addjava.setAutoRepeat(False)

        shortcut_add_native_on_load = QShortcut(
            QKeySequence(Qt.CTRL + Qt.Key_O), self._app_window,
            self._on_add_native_on_load)
        shortcut_add_native_on_load.setAutoRepeat(False)

        # new menu
        self.new_menu = QMenu('New')
        self.new_menu.addAction('Native', self._on_addnative)
        self.new_menu.addAction('Java', self._on_addjava)
        self.new_menu.addAction('Module loading', self._on_add_native_on_load)
        if self._app_window.dwarf.java_available:
            self.new_menu.addAction('Java class loading',
                                    self._on_add_native_on_load)
Esempio n. 16
0
class SearchPanel(QWidget):
    """ SearchPanel
    """

    onShowMemoryRequest = pyqtSignal(str, name='onShowMemoryRequest')

    def __init__(self, parent=None, show_progress_dlg=False):
        super(SearchPanel, self).__init__(parent=parent)
        self._app_window = parent

        if self._app_window.dwarf is None:
            print('SearchPanel created before Dwarf exists')
            return

        self._app_window.dwarf.onMemoryScanResult.connect(
            self._on_search_result)

        self._ranges_model = None
        self._result_model = None

        self._blocking_search = show_progress_dlg
        self.progress = None
        self._pattern_length = 0

        self._search_results = []

        self.setContentsMargins(0, 0, 0, 0)

        main_wrap = QVBoxLayout()
        main_wrap.setContentsMargins(1, 1, 1, 1)

        wrapping_wdgt = QWidget()
        wrapping_wdgt.setContentsMargins(10, 10, 10, 10)
        v_box = QVBoxLayout(wrapping_wdgt)
        v_box.setContentsMargins(0, 0, 0, 0)
        self.input = QLineEdit()
        self.input.setPlaceholderText(
            'search for a sequence of bytes in hex format: deadbeef123456aabbccddeeff...'
        )
        v_box.addWidget(self.input)

        self.check_all_btn = QPushButton('check all')
        self.check_all_btn.clicked.connect(self._on_click_check_all)
        self.uncheck_all_btn = QPushButton('uncheck all')
        self.uncheck_all_btn.clicked.connect(self._on_click_uncheck_all)
        self.search_btn = QPushButton('search')
        self.search_btn.clicked.connect(self._on_click_search)

        h_box = QHBoxLayout()
        h_box.addWidget(self.check_all_btn)
        h_box.addWidget(self.uncheck_all_btn)
        h_box.addWidget(self.search_btn)
        v_box.addLayout(h_box)

        main_wrap.addWidget(wrapping_wdgt)

        self.ranges = DwarfListView(self)
        self.ranges.clicked.connect(self._on_show_results)
        self.results = DwarfListView(self)
        self.results.setVisible(False)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(0, 0, 0, 0)
        h_box.addWidget(self.ranges)
        h_box.addWidget(self.results)
        main_wrap.addLayout(h_box)

        main_wrap.setSpacing(0)

        self.setLayout(main_wrap)

        self._setup_models()

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def _setup_models(self):
        self._ranges_model = QStandardItemModel(0, 7)

        # just replicate ranges panel model
        self._ranges_model.setHeaderData(
            0, Qt.Horizontal, 'x'
        )  # TODO: replace with checkbox in header - remove checkall btns
        self._ranges_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self._ranges_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(2, Qt.Horizontal, 'Size')
        self._ranges_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(3, Qt.Horizontal, 'Protection')
        self._ranges_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(4, Qt.Horizontal, 'FileOffset')
        self._ranges_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(5, Qt.Horizontal, 'FileSize')
        self._ranges_model.setHeaderData(5, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self._ranges_model.setHeaderData(6, Qt.Horizontal, 'FilePath')

        self.ranges.setModel(self._ranges_model)
        self.ranges.header().setSectionResizeMode(0,
                                                  QHeaderView.ResizeToContents)
        self.ranges.header().setSectionResizeMode(1,
                                                  QHeaderView.ResizeToContents)
        self.ranges.header().setSectionResizeMode(2,
                                                  QHeaderView.ResizeToContents)
        self.ranges.header().setSectionResizeMode(3,
                                                  QHeaderView.ResizeToContents)
        self.ranges.header().setSectionResizeMode(4,
                                                  QHeaderView.ResizeToContents)
        self.ranges.header().setSectionResizeMode(5,
                                                  QHeaderView.ResizeToContents)

        self.ranges.doubleClicked.connect(self._on_range_dblclick)

        # setup results model
        self._result_model = QStandardItemModel(0, 1)
        self._result_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self.results.setModel(self._result_model)
        self.results.doubleClicked.connect(self._on_dblclicked)

    def set_ranges(self, ranges):
        """ Fills Rangelist with Data
        """
        self.ranges.header().setSectionResizeMode(0, QHeaderView.Fixed)
        if isinstance(ranges, list):
            self._ranges_model.removeRows(0, self._ranges_model.rowCount())
            for range_entry in ranges:
                if 'protection' in range_entry and isinstance(
                        range_entry['protection'], str):
                    if 'r' not in range_entry['protection']:
                        # skip not readable range
                        continue

                else:
                    continue
                # create items to add
                str_frmt = ''
                if self.ranges._uppercase_hex:
                    str_frmt = '0x{0:X}'
                else:
                    str_frmt = '0x{0:x}'

                addr = QStandardItem()
                addr.setTextAlignment(Qt.AlignCenter)
                addr.setText(str_frmt.format(int(range_entry['base'], 16)))

                size = QStandardItem()
                size.setTextAlignment(Qt.AlignRight)
                size.setText("{0:,d}".format(int(range_entry['size'])))

                protection = QStandardItem()
                protection.setTextAlignment(Qt.AlignCenter)
                protection.setText(range_entry['protection'])

                file_path = None
                file_addr = None
                file_size = None

                if len(range_entry) > 3:
                    if range_entry['file']['path']:
                        file_path = QStandardItem()
                        file_path.setText(range_entry['file']['path'])

                    if range_entry['file']['offset']:
                        file_addr = QStandardItem()
                        file_addr.setTextAlignment(Qt.AlignCenter)
                        file_addr.setText(
                            str_frmt.format(range_entry['file']['offset']))

                    if range_entry['file']['size']:
                        file_size = QStandardItem()
                        file_size.setTextAlignment(Qt.AlignRight)
                        file_size.setText("{0:,d}".format(
                            int(range_entry['file']['size'])))

                checkbox = QStandardItem()
                checkbox.setCheckable(True)

                self._ranges_model.appendRow([
                    checkbox, addr, size, protection, file_addr, file_size,
                    file_path
                ])

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_range_dblclick(self, model_index):
        item = self._ranges_model.itemFromIndex(model_index)
        if item:
            if self._ranges_model.item(model_index.row(),
                                       0).checkState() != Qt.Checked:
                self._ranges_model.item(model_index.row(),
                                        0).setCheckState(Qt.Checked)
            else:
                self._ranges_model.item(model_index.row(),
                                        0).setCheckState(Qt.Unchecked)

    def _on_click_check_all(self):
        for i in range(self._ranges_model.rowCount()):
            self._ranges_model.item(i, 0).setCheckState(Qt.Checked)

    def _on_click_uncheck_all(self):
        for i in range(self._ranges_model.rowCount()):
            self._ranges_model.item(i, 0).setCheckState(Qt.Unchecked)

    def _on_dblclicked(self, model_index):
        item = self._result_model.itemFromIndex(model_index)
        if item:
            self.onShowMemoryRequest.emit(
                self._result_model.item(model_index.row(), 0).text())

    def _on_click_search(self):
        pattern = self.input.text()
        if pattern == '':
            return 1

        # check if we already provide a hex string as input
        try:
            test = pattern.replace(' ', '')
            int(test, 16)
            pattern = test
        except ValueError:
            # search for string
            pattern = binascii.hexlify(pattern.encode('utf8')).decode('utf8')

        ranges = []
        self._search_results = []
        for i in range(self._ranges_model.rowCount()):
            item = self._ranges_model.item(i, 0)
            if item.checkState() == Qt.Checked:
                addr = self._ranges_model.item(i, 1)
                size = self._ranges_model.item(i, 2)
                ranges.append([addr.text(), size.text()])

        if len(ranges) == 0:
            return 1

        if self._blocking_search:
            self.progress = QProgressDialog()
            self.progress.setFixedSize(300, 50)
            self.progress.setAutoFillBackground(True)
            self.progress.setWindowModality(Qt.WindowModal)
            self.progress.setWindowTitle('Please wait')
            self.progress.setLabelText('searching...')
            self.progress.setSizeGripEnabled(False)
            self.progress.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
            self.progress.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
            self.progress.setWindowFlag(Qt.WindowCloseButtonHint, False)
            self.progress.setModal(True)
            self.progress.setCancelButton(None)
            self.progress.setRange(0, 0)
            self.progress.setMinimumDuration(0)
            self.progress.forceShow()

        self._app_window.show_progress('searching...')
        self.input.setEnabled(False)
        self.search_btn.setEnabled(False)
        self.check_all_btn.setEnabled(False)
        self.uncheck_all_btn.setEnabled(False)

        self._pattern_length = len(pattern) * .5

        search_thread = SearchThread(self._app_window.dwarf, self)
        search_thread.onCmdCompleted.connect(self._on_search_complete)
        search_thread.onError.connect(self._on_search_error)
        search_thread.pattern = pattern
        search_thread.ranges = ranges
        search_thread.start()

    def _on_search_result(self, data):
        self._search_results.append(data)

    def _on_search_complete(self):
        self.input.setEnabled(True)
        self.search_btn.setEnabled(True)
        self.check_all_btn.setEnabled(True)
        self.uncheck_all_btn.setEnabled(True)
        self._app_window.hide_progress()
        if self._blocking_search:
            self.progress.cancel()

        self._ranges_model.removeColumns(4, 3)
        self._ranges_model.setHeaderData(3, Qt.Horizontal, 'Search Results')
        self._ranges_model.setHeaderData(3, Qt.Horizontal, None,
                                         Qt.TextAlignmentRole)

        results_count = 0
        is_selected = False
        for i in range(self._ranges_model.rowCount()):
            item = self._ranges_model.item(i, 0)
            if item.checkState() == Qt.Checked:
                item.setCheckState(Qt.Unchecked)
                if not is_selected:
                    is_selected = True
                    self.ranges.setCurrentIndex(self._ranges_model.index(i, 0))
            else:
                self._search_results.insert(i, None)
                self._ranges_model.item(i, 3).setText('')
                self._ranges_model.item(i, 3).setTextAlignment(Qt.AlignLeft)
                continue

            if len(self._search_results[i]):
                results_count += len(self._search_results[i])
                self._ranges_model.item(i, 3).setText('Matches: {0}'.format(
                    len(self._search_results[i])))
                self._ranges_model.item(i, 3).setTextAlignment(Qt.AlignLeft)
            else:
                self._ranges_model.item(i, 3).setText('')
                self._ranges_model.item(i, 3).setTextAlignment(Qt.AlignLeft)

        self._app_window.set_status_text(
            'Search complete: {0} matches'.format(results_count))
        if results_count:
            for i in self._search_results:
                if i and len(i):
                    self.results.setVisible(True)
                    for result in i:
                        self._result_model.appendRow(
                            QStandardItem(result['address']))

                    break

    def _on_search_error(self, msg):
        utils.show_message_box(msg)

    def _on_show_results(self):
        if self._search_results:
            self.results.clear()
            if self._app_window.memory_panel:
                self._app_window.memory_panel.remove_highlights('search')
            selected_index = self.ranges.selectionModel().currentIndex().row()
            if selected_index is not None:
                item_txt = self._ranges_model.item(selected_index, 3).text()
                if item_txt == '':
                    return

                for result in self._search_results[selected_index]:
                    self._result_model.appendRow(
                        QStandardItem(result['address']))

                    # TODO: fix hexview highlights performance
                    """
Esempio n. 17
0
class ModulesPanel(QWidget):
    """ ModulesPanel

        Signals:
            onAddHook([ptr, funcname]) - MenuItem AddHook
            onDumpBinary([ptr, size#int]) - MenuItem DumpBinary
            onModuleSelected([ptr, size#int]) - ModuleDoubleClicked
            onModuleFuncSelected(ptr) - FunctionDoubleClicked
    """
    # pylint: disable=too-many-instance-attributes

    onAddHook = pyqtSignal(list, name='onAddHook')
    onDumpBinary = pyqtSignal(list, name='onDumpBinary')
    onModuleSelected = pyqtSignal(list, name='onModuleSelected')
    onModuleFuncSelected = pyqtSignal(str, name='onModuleFuncSelected')

    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(ModulesPanel, self).__init__(parent)
        self._app_window = parent

        if self._app_window.dwarf is None:
            print('ModulesPanel created before Dwarf exists')
            return

        self._app_window.dwarf.onSetModules.connect(self.set_modules)

        self._uppercase_hex = True

        # setup models
        self.modules_list = None
        self.modules_model = QStandardItemModel(0, 4, self)
        self.modules_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self.modules_model.setHeaderData(1, Qt.Horizontal, 'Base')
        self.modules_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.modules_model.setHeaderData(2, Qt.Horizontal, 'Size')
        self.modules_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.modules_model.setHeaderData(3, Qt.Horizontal, 'Path')

        self.imports_list = None
        self.imports_model = QStandardItemModel(0, 4, self)
        self.imports_model.setHeaderData(0, Qt.Horizontal, 'Import')
        self.imports_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.imports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.imports_model.setHeaderData(2, Qt.Horizontal, 'Module')
        self.imports_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.imports_model.setHeaderData(3, Qt.Horizontal, 'Type')

        self.exports_list = None
        self.exports_model = QStandardItemModel(0, 3, self)
        self.exports_model.setHeaderData(0, Qt.Horizontal, 'Export')
        self.exports_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.exports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.exports_model.setHeaderData(2, Qt.Horizontal, 'Type')

        self.symbols_list = None
        self.symbols_model = QStandardItemModel(0, 3, self)
        self.symbols_model.setHeaderData(0, Qt.Horizontal, 'Export')
        self.symbols_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.symbols_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.symbols_model.setHeaderData(2, Qt.Horizontal, 'Type')

        # setup ui
        main_wrapper = QVBoxLayout()
        main_wrapper.setContentsMargins(0, 0, 0, 0)
        h_box = QHBoxLayout()
        self.modules_list = DwarfListView()
        self.modules_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.modules_list.customContextMenuRequested.connect(
            self._on_modules_contextmenu)
        self.modules_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.modules_list.clicked.connect(self._module_clicked)
        self.modules_list.doubleClicked.connect(self._module_dblclicked)
        self.modules_list.setModel(self.modules_model)
        self.modules_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.modules_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.modules_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        h_box.addWidget(self.modules_list)
        self.modules_list.selectionModel().selectionChanged.connect(
            self._module_clicked)

        hv_box = QVBoxLayout()
        self.imports_list = DwarfListView()
        self.imports_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.imports_list.customContextMenuRequested.connect(
            self._on_imports_contextmenu)
        self.imports_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.imports_list.doubleClicked.connect(self._import_dblclicked)
        self.imports_list.setModel(self.imports_model)
        self.imports_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.imports_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.imports_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.imports_list.setVisible(False)
        self.exports_list = DwarfListView()
        self.exports_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.exports_list.customContextMenuRequested.connect(
            self._on_exports_contextmenu)
        self.exports_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.exports_list.doubleClicked.connect(self._export_dblclicked)
        self.exports_list.setModel(self.exports_model)
        self.exports_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.exports_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.exports_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.exports_list.setVisible(False)
        self.symbols_list = DwarfListView()
        self.symbols_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.symbols_list.doubleClicked.connect(self._symbol_dblclicked)
        self.symbols_list.setModel(self.symbols_model)
        self.symbols_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.symbols_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.symbols_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.symbols_list.setVisible(False)
        hv_box.addWidget(self.imports_list)
        hv_box.addWidget(self.exports_list)
        hv_box.addWidget(self.symbols_list)
        h_box.addLayout(hv_box)
        main_wrapper.addLayout(h_box)
        self.setLayout(main_wrapper)

    # ************************************************************************
    # **************************** Properties ********************************
    # ************************************************************************
    @property
    def uppercase_hex(self):
        """ HexDisplayStyle
        """
        return self._uppercase_hex

    @uppercase_hex.setter
    def uppercase_hex(self, value):
        """ HexDisplayStyle
        """
        if isinstance(value, bool):
            self._uppercase_hex = value
        elif isinstance(value, str):
            self._uppercase_hex = (value == 'upper')

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def set_modules(self, modules):
        """ Fills the ModulesList with data
        """
        self.modules_list.clear()
        for module in modules:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(module['name'])

            base = QStandardItem()
            base.setTextAlignment(Qt.AlignCenter)

            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'

            base.setText(str_fmt.format(int(module['base'], 16)))

            size = QStandardItem()
            size.setTextAlignment(Qt.AlignRight)
            size.setText("{0:,d}".format(int(module['size'])))

            path = QStandardItem()
            path.setTextAlignment(Qt.AlignLeft)
            path.setText(module['path'])

            self.modules_model.appendRow([name, base, size, path])

    def update_modules(self):
        """ DwarfApiCall updateModules
        """
        return self._app_window.dwarf.dwarf_api('updateModules')

    def set_imports(self, imports):
        """ Fills the ImportsList with data
        """
        self.imports_list.clear()
        for import_ in imports:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(import_['name'])

            address = QStandardItem()
            address.setTextAlignment(Qt.AlignCenter)

            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'

            address.setText(str_fmt.format(int(import_['address'], 16)))

            module = QStandardItem()
            if 'module' in import_:
                module.setTextAlignment(Qt.AlignLeft)
                module.setText(import_['module'])

            type_ = QStandardItem()
            if 'type' in import_:
                type_.setTextAlignment(Qt.AlignLeft)
                type_.setText(import_['type'])

            self.imports_model.appendRow([name, address, module, type_])

    def set_exports(self, exports):
        """ Fills the ExportsList with data
        """
        self.exports_list.clear()
        for export in exports:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(export['name'])

            address = QStandardItem()
            address.setTextAlignment(Qt.AlignCenter)
            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'
            address.setText(str_fmt.format(int(export['address'], 16)))

            type_ = QStandardItem()
            type_.setTextAlignment(Qt.AlignLeft)
            type_.setText(export['type'])

            self.exports_model.appendRow([name, address, type_])

    def set_symbols(self, symbols):
        """ Fills the SymbolsList with data
        """
        self.symbols_list.clear()
        for symbol in symbols:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(symbol['name'])

            address = QStandardItem()
            address.setTextAlignment(Qt.AlignCenter)
            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'
            address.setText(str_fmt.format(int(symbol['address'], 16)))

            type_ = QStandardItem()
            type_.setTextAlignment(Qt.AlignLeft)
            type_.setText(symbol['type'])

            self.symbols_model.appendRow([name, address, type_])

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _module_clicked(self):
        """ Module Clicked updates imports/exports/symbols
        """
        module_index = self.modules_list.selectionModel().currentIndex().row()
        module = self.modules_model.item(module_index, 0)  # module name
        if module is None:
            return

        imports = self._app_window.dwarf.dwarf_api('enumerateImports',
                                                   module.text())
        if imports and (imports is not None):
            imports = json.loads(imports)
            if imports:
                self.set_imports(imports)
                self.imports_list.setVisible(True)
            else:
                self.imports_list.setVisible(False)

        exports = self._app_window.dwarf.dwarf_api('enumerateExports',
                                                   module.text())
        if exports and exports is not None:
            exports = json.loads(exports)
            if exports:
                self.set_exports(exports)
                self.exports_list.setVisible(True)
            else:
                self.exports_list.setVisible(False)

        symbols = self._app_window.dwarf.dwarf_api('enumerateSymbols',
                                                   module.text())
        if symbols and symbols is not None:
            symbols = json.loads(symbols)
            if symbols:
                self.set_symbols(symbols)
                self.symbols_list.setVisible(True)
            else:
                self.symbols_list.setVisible(False)

    def _module_dblclicked(self):
        """ Module DoubleClicked
        """
        module_index = self.modules_list.selectionModel().currentIndex().row()
        base = self.modules_model.item(module_index, 1).text()
        size = self.modules_model.item(module_index, 2).text().replace(',', '')
        self.onModuleSelected.emit([base, size])

    def _import_dblclicked(self):
        """ ImportFunction DoubleClicked
        """
        index = self.imports_list.selectionModel().currentIndex().row()
        addr = self.imports_model.item(index, 1).text()
        self.onModuleFuncSelected.emit(addr)

    def _export_dblclicked(self):
        """ ExportFunction DoubleClicked
        """
        index = self.exports_list.selectionModel().currentIndex().row()
        addr = self.exports_model.item(index, 1).text()
        self.onModuleFuncSelected.emit(addr)

    def _symbol_dblclicked(self):
        """ Symbol DoubleClicked
        """
        index = self.symbols_list.selectionModel().currentIndex().row()
        addr = self.symbols_model.item(index, 1).text()
        self.onModuleFuncSelected.emit(addr)

    def _on_modules_contextmenu(self, pos):
        """ Modules ContextMenu
        """
        index = self.modules_list.indexAt(pos).row()
        glbl_pt = self.modules_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Dump Binary', lambda: self._on_dumpmodule(
                    self.modules_model.item(index, 1).text(),
                    self.modules_model.item(index, 2).text()))
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self.modules_model.item(index, 1).text()))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy Name', lambda: utils.copy_str_to_clipboard(
                    self.modules_model.item(index, 0).text()))
            context_menu.addAction(
                'Copy Path', lambda: utils.copy_str_to_clipboard(
                    self.modules_model.item(index, 3).text()))
            context_menu.addSeparator()

        context_menu.addAction('Refresh', self.update_modules)
        context_menu.exec_(glbl_pt)

    def _on_imports_contextmenu(self, pos):
        """ ImportList ContextMenu
        """
        index = self.imports_list.indexAt(pos).row()
        if index != -1:
            glbl_pt = self.imports_list.mapToGlobal(pos)
            context_menu = QMenu(self)
            func_name = self.imports_model.item(index, 0).text()
            addr = self.imports_model.item(index, 1).text()
            context_menu.addAction('Add Hook',
                                   lambda: self._add_hook(addr, func_name))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self.imports_model.item(index, 1).text()))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy FunctionName',
                lambda: utils.copy_str_to_clipboard(func_name))
            context_menu.addAction(
                'Copy ModuleName', lambda: utils.copy_str_to_clipboard(
                    self.imports_model.item(index, 2).text()))
            context_menu.exec_(glbl_pt)

    def _on_exports_contextmenu(self, pos):
        """ ExportsList ContextMenu
        """
        index = self.exports_list.indexAt(pos).row()
        if index != -1:
            glbl_pt = self.exports_list.mapToGlobal(pos)
            context_menu = QMenu(self)
            func_name = self.exports_model.item(index, 0).text()
            addr = self.exports_model.item(index, 1).text()
            context_menu.addAction('Add Hook',
                                   lambda: self._add_hook(addr, func_name))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self.exports_model.item(index, 1).text()))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy FunctionName',
                lambda: utils.copy_str_to_clipboard(func_name))
            context_menu.exec_(glbl_pt)

    def _on_dumpmodule(self, ptr, size):
        """ MenuItem DumpBinary
        """
        if isinstance(ptr, int):
            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'
            ptr = str_fmt.format(ptr)

        size = size.replace(',', '')
        self.onDumpBinary.emit([ptr, size])

    def _add_hook(self, ptr, name=None):
        """ MenuItem AddHook
        """
        if name is None:
            name = ptr
        if isinstance(ptr, str):
            if ptr.startswith('0x') or ptr.startswith('#'):
                self.onAddHook.emit([ptr, name])
        elif isinstance(ptr, int):
            str_fmt = '0x{0:x}'
            self.onAddHook.emit(str_fmt.format([ptr, name]))
Esempio n. 18
0
class ContextPanel(QTabWidget):
    # consts
    CONTEXT_TYPE_NATIVE = 0
    CONTEXT_TYPE_JAVA = 1
    CONTEXT_TYPE_EMULATOR = 2

    onShowMemoryRequest = pyqtSignal(str, name='onShowMemoryRequest')

    def __init__(self, parent=None):
        super(ContextPanel, self).__init__(parent=parent)

        self._app_window = parent
        self.setAutoFillBackground(True)

        self._nativectx_model = QStandardItemModel(0, 4)
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')
        #self._nativectx_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(3, Qt.Horizontal, 'Telescope')

        self._nativectx_list = DwarfListView()
        self._nativectx_list.setModel(self._nativectx_model)

        self._nativectx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._nativectx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._nativectx_list.customContextMenuRequested.connect(
            self._on_native_contextmenu)

        self._emulatorctx_model = QStandardItemModel(0, 3)
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')

        self._emulatorctx_list = DwarfListView()
        self._emulatorctx_list.setModel(self._emulatorctx_model)

        self._emulatorctx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._emulatorctx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)

        self._emulatorctx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._emulatorctx_list.customContextMenuRequested.connect(
            self._on_emulator_contextmenu)

        self._javactx_model = QStandardItemModel(0, 3)
        self._javactx_model.setHeaderData(0, Qt.Horizontal, 'Argument')
        self._javactx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                          Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(1, Qt.Horizontal, 'Class')
        #self._javactx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(2, Qt.Horizontal, 'Value')

        self._javactx_list = DwarfListView()
        self._javactx_list.setModel(self._javactx_model)

        self._javactx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._javactx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._javactx_list.customContextMenuRequested.connect(
            self._on_java_contextmenu)

        self.addTab(self._nativectx_list, 'Native')
        self.show_context_tab('Native')

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def clear(self):
        self._nativectx_list.clear()
        self._emulatorctx_list.clear()
        self._javactx_list.clear()

    def set_context(self, ptr, context_type, context):
        if isinstance(context, str):
            context = json.loads(context)

        if context_type == ContextPanel.CONTEXT_TYPE_NATIVE:
            self._nativectx_list.clear()
            self._set_native_context(ptr, context)
        elif context_type == ContextPanel.CONTEXT_TYPE_JAVA:
            self._javactx_list.clear()
            self._set_java_context(ptr, context)
        elif context_type == ContextPanel.CONTEXT_TYPE_EMULATOR:
            self._emulatorctx_list.clear()
            self._set_emulator_context(ptr, context)
        else:
            raise Exception('unknown context type')

    def have_context(self):
        return self.count() > 0

    def show_context_tab(self, tab_name):
        index = 0
        tab_name = tab_name.join(tab_name.split()).lower()
        if tab_name == 'native':
            index = self.indexOf(self._nativectx_list)
        elif tab_name == 'emulator':
            index = self.indexOf(self._emulatorctx_list)
        elif tab_name == 'java':
            index = self.indexOf(self._javactx_list)

        if self.count() > 0:
            self.setCurrentIndex(index)

    def _set_native_context(self, ptr, context):
        if self.indexOf(self._nativectx_list) == -1:
            self.addTab(self._nativectx_list, 'Native')
            self.show_context_tab('Native')
        else:
            self.show_context_tab('Native')

        context_ptr = ptr

        for register in context:
            reg_name = QStandardItem()
            reg_name.setTextAlignment(Qt.AlignCenter)
            if context[register]['isValidPointer']:
                reg_name.setForeground(Qt.red)
                reg_name.setData(context_ptr)

            value_x = QStandardItem()
            # value_x.setTextAlignment(Qt.AlignCenter)
            value_dec = QStandardItem()
            # value_dec.setTextAlignment(Qt.AlignCenter)
            telescope = QStandardItem()

            reg_name.setText(register)

            if context[register] is not None:
                str_fmt = '0x{0:x}'
                if self._nativectx_list.uppercase_hex:
                    str_fmt = '0x{0:X}'

                value_x.setText(
                    str_fmt.format(int(context[register]['value'], 16)))

                value_dec.setText('{0:d}'.format(
                    int(context[register]['value'], 16)))

                if context[register]['isValidPointer']:
                    if 'telescope' in context[register] and context[register][
                            'telescope'] is not None:
                        telescope = QStandardItem()
                        telescope.setText(
                            str(context[register]['telescope'][1]))
                        if context[register]['telescope'][0] == 2:
                            telescope.setData(
                                context[register]['telescope'][1],
                                Qt.UserRole + 1)

                        if context[register]['telescope'][0] == 0:
                            telescope.setForeground(Qt.darkGreen)
                        elif context[register]['telescope'][0] == 2:
                            telescope.setForeground(Qt.white)
                        elif context[register]['telescope'][0] != 1:
                            telescope.setForeground(Qt.darkGray)

            self._nativectx_model.insertRow(0, [reg_name, value_x, value_dec, telescope])
            self._nativectx_list.resizeColumnToContents(0)

    def _set_emulator_context(self, ptr, context):
        if self.indexOf(self._emulatorctx_list) == -1:
            self.addTab(self._emulatorctx_list, 'Emulator')
            self.show_context_tab('Emulator')
        else:
            self.show_context_tab('Emulator')

        context_ptr = ptr

        context = context.__dict__

        for register in sorted(context):
            # todo: ???
            if register.startswith('_'):
                continue

            reg_name = QStandardItem()
            reg_name.setTextAlignment(Qt.AlignCenter)
            reg_name.setForeground(QColor('#39c'))
            value_x = QStandardItem()
            # value_x.setTextAlignment(Qt.AlignCenter)
            value_dec = QStandardItem()
            # value_dec.setTextAlignment(Qt.AlignCenter)

            reg_name.setText(register)
            reg_name.setData(context_ptr)

            if context[register] is not None:
                if isinstance(context[register], int):
                    str_fmt = '0x{0:x}'
                    if self._emulatorctx_list.uppercase_hex:
                        str_fmt = '0x{0:X}'

                    value_x.setText(str_fmt.format(context[register]))

                    value_dec.setText('{0:d}'.format(context[register]))

            self._emulatorctx_model.appendRow([reg_name, value_x, value_dec])
            self._emulatorctx_list.resizeColumnToContents(0)
            self._emulatorctx_list.resizeColumnToContents(1)

    def _set_java_context(self, ptr, context):
        if self.indexOf(self._javactx_list) == -1:
            self.addTab(self._javactx_list, 'Java')
            self.show_context_tab('Java')
        else:
            self.show_context_tab('Java')

        for arg in context:
            _arg = QStandardItem()
            _arg.setText(arg)

            _class = QStandardItem()
            _class.setText(context[arg]['className'])
            if isinstance(context[arg]['handle'], str):
                _class.setForeground(Qt.lightGray)

            _value = QStandardItem()
            if context[arg] is not None:
                _value.setText('null')
                _value.setForeground(Qt.gray)

            self._javactx_model.appendRow([_arg, _class, _value])
            self._javactx_list.resizeColumnToContents(0)
            self._javactx_list.resizeColumnToContents(1)

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_native_contextmenu(self, pos):
        index = self._nativectx_list.indexAt(pos).row()
        glbl_pt = self._nativectx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Jump to address', lambda: self._app_window.jump_to_address(
                    self._nativectx_model.item(index, 1).text()))
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._nativectx_model.item(index, 1).text()))
            context_menu.addAction(
                'Jump to address', lambda: self.onShowMemoryRequest.emit(
                    self._nativectx_model.item(index, 1).text()))
        context_menu.exec_(glbl_pt)

    def _on_emulator_contextmenu(self, pos):
        index = self._emulatorctx_list.indexAt(pos).row()
        glbl_pt = self._emulatorctx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            pass
        context_menu.exec_(glbl_pt)

    def _on_java_contextmenu(self, pos):
        index = self._javactx_list.indexAt(pos).row()
        glbl_pt = self._javactx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            pass
        context_menu.exec_(glbl_pt)
Esempio n. 19
0
    def __init__(self, parent=None):
        super(ContextPanel, self).__init__(parent=parent)

        self._app_window = parent
        self.setAutoFillBackground(True)

        self._app_window.dwarf.onContextChanged.connect(
            self._on_context_changed)

        self._nativectx_model = QStandardItemModel(0, 4)
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')
        #self._nativectx_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(3, Qt.Horizontal, 'Telescope')

        self._nativectx_list = DwarfListView()
        self._nativectx_list.setModel(self._nativectx_model)

        self._nativectx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._nativectx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._nativectx_list.customContextMenuRequested.connect(
            self._on_native_contextmenu)

        self._emulatorctx_model = QStandardItemModel(0, 3)
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')

        self._emulatorctx_list = DwarfListView()
        self._emulatorctx_list.setModel(self._emulatorctx_model)

        self._emulatorctx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._emulatorctx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)

        self._emulatorctx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._emulatorctx_list.customContextMenuRequested.connect(
            self._on_emulator_contextmenu)

        self._javactx_model = QStandardItemModel(0, 3)
        self._javactx_model.setHeaderData(0, Qt.Horizontal, 'Argument')
        self._javactx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                          Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(1, Qt.Horizontal, 'Class')
        #self._javactx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(2, Qt.Horizontal, 'Value')

        self._javactx_list = DwarfListView()
        self._javactx_list.setModel(self._javactx_model)

        self._javactx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._javactx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._javactx_list.customContextMenuRequested.connect(
            self._on_java_contextmenu)

        self.addTab(self._nativectx_list, 'Native')
        self.show_context_tab('Native')
Esempio n. 20
0
class ContextPanel(QTabWidget):
    # consts
    CONTEXT_TYPE_NATIVE = 0
    CONTEXT_TYPE_JAVA = 1
    CONTEXT_TYPE_EMULATOR = 2

    onShowMemoryRequest = pyqtSignal(str, name='onShowMemoryRequest')

    def __init__(self, parent=None):
        super(ContextPanel, self).__init__(parent=parent)

        self._app_window = parent
        self.setAutoFillBackground(True)

        self._app_window.dwarf.onContextChanged.connect(
            self._on_context_changed)

        self._nativectx_model = QStandardItemModel(0, 4)
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')
        #self._nativectx_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(3, Qt.Horizontal, 'Telescope')

        self._nativectx_list = DwarfListView()
        self._nativectx_list.setModel(self._nativectx_model)

        self._nativectx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._nativectx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._nativectx_list.customContextMenuRequested.connect(
            self._on_native_contextmenu)

        self._emulatorctx_model = QStandardItemModel(0, 3)
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')

        self._emulatorctx_list = DwarfListView()
        self._emulatorctx_list.setModel(self._emulatorctx_model)

        self._emulatorctx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._emulatorctx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)

        self._emulatorctx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._emulatorctx_list.customContextMenuRequested.connect(
            self._on_emulator_contextmenu)

        self._javactx_model = QStandardItemModel(0, 3)
        self._javactx_model.setHeaderData(0, Qt.Horizontal, 'Argument')
        self._javactx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                          Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(1, Qt.Horizontal, 'Class')
        #self._javactx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(2, Qt.Horizontal, 'Value')

        self._javactx_list = DwarfListView()
        self._javactx_list.setModel(self._javactx_model)

        self._javactx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._javactx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._javactx_list.customContextMenuRequested.connect(
            self._on_java_contextmenu)

        self.addTab(self._nativectx_list, 'Native')
        self.show_context_tab('Native')

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def clear(self):
        self._nativectx_list.clear()
        self._emulatorctx_list.clear()
        self._javactx_list.clear()

    def set_context(self, ptr, context_type, context):
        if isinstance(context, str):
            context = json.loads(context)

        if context_type == ContextPanel.CONTEXT_TYPE_NATIVE:
            self._nativectx_list.clear()
            self._set_native_context(ptr, context)
        elif context_type == ContextPanel.CONTEXT_TYPE_JAVA:
            self._javactx_list.clear()
            self._set_java_context(ptr, context)
        elif context_type == ContextPanel.CONTEXT_TYPE_EMULATOR:
            self._emulatorctx_list.clear()
            self._set_emulator_context(ptr, context)
        else:
            raise Exception('unknown context type')

    def have_context(self):
        return self.count() > 0

    def show_context_tab(self, tab_name):
        index = 0
        tab_name = tab_name.join(tab_name.split()).lower()
        if tab_name == 'native':
            index = self.indexOf(self._nativectx_list)
        elif tab_name == 'emulator':
            index = self.indexOf(self._emulatorctx_list)
        elif tab_name == 'java':
            index = self.indexOf(self._javactx_list)

        if self.count() > 0:
            self.setCurrentIndex(index)

    def _set_native_context(self, ptr, context):
        if self.indexOf(self._nativectx_list) == -1:
            self.addTab(self._nativectx_list, 'Native')
            self.show_context_tab('Native')
        else:
            self.show_context_tab('Native')

        context_ptr = ptr

        reg_order = []
        if self._app_window.dwarf.arch == 'arm':  # arm
            reg_order = [
                'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9',
                'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'sp', 'lr', 'sb',
                'sl', 'fp', 'ip', 'pc'
            ]
        elif self._app_window.dwarf.arch == 'arm64':
            reg_order = [
                'x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9',
                'x10', 'x11', 'x12', 'x13', 'x14', 'x15', 'x16', 'x17', 'x18',
                'x19', 'x20', 'x21', 'x22', 'x23', 'x24', 'x25', 'x26', 'x27',
                'x28', 'x29', 'x30', 'w0', 'w1', 'w2', 'w3', 'w4', 'w5', 'w6',
                'w7', 'w8', 'w9', 'w10', 'w11', 'w12', 'w13', 'w14', 'w15',
                'w16', 'w17', 'w18', 'w19', 'w20', 'w21', 'w22', 'w23', 'w24',
                'w25', 'w26', 'w27', 'w28', 'w29', 'w30', 'sp', 'lr', 'fp',
                'wsp', 'wzr', 'xzr', 'nzcv', 'ip0', 'ip1', 's0', 's1', 's2',
                's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11', 's12',
                's13', 's14', 's15', 's16', 's17', 's18', 's19', 's20', 's21',
                's22', 's23', 's24', 's25', 's26', 's27', 's28', 's29', 's30',
                's31', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8',
                'd9', 'd10', 'd11', 'd12', 'd13', 'd14', 'd15', 'd16', 'd17',
                'd18', 'd19', 'd20', 'd21', 'd22', 'd23', 'd24', 'd25', 'd26',
                'd27', 'd28', 'd29', 'd30', 'd31', 'q0', 'q1', 'q2', 'q3',
                'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10', 'q11', 'q12', 'q13',
                'q14', 'q15', 'q16', 'q17', 'q18', 'q19', 'q20', 'q21', 'q22',
                'q23', 'q24', 'q25', 'q26', 'q27', 'q28', 'q29', 'q30', 'q31',
                'sp', 'lr', 'sb', 'sl', 'fp', 'ip', 'pc'
            ]
        elif self._app_window.dwarf.arch == 'ia32':
            reg_order = [
                'eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'esp', 'r8d', 'r9d',
                'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d', 'ebp', 'eip',
                'sp', 'pc'
            ]
        elif self._app_window.dwarf.arch == 'x64':  # x64
            reg_order = [
                'rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi', 'rbp', 'rsp', 'r8',
                'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'esp', 'ebp',
                'rip', 'eip', 'sp', 'pc'
            ]

        sorted_regs = {b: i for i, b in enumerate(reg_order)}

        for register in sorted(context, key=lambda x: sorted_regs[x]):
            reg_name = QStandardItem()
            reg_name.setTextAlignment(Qt.AlignCenter)
            if context[register]['isValidPointer']:
                reg_name.setForeground(Qt.red)
                reg_name.setData(context_ptr)

            value_x = QStandardItem()
            # value_x.setTextAlignment(Qt.AlignCenter)
            value_dec = QStandardItem()
            # value_dec.setTextAlignment(Qt.AlignCenter)
            telescope = QStandardItem()

            reg_name.setText(register)

            if context[register] is not None:
                str_fmt = '0x{0:x}'
                if self._nativectx_list.uppercase_hex:
                    str_fmt = '0x{0:X}'

                value_x.setText(
                    str_fmt.format(int(context[register]['value'], 16)))

                value_dec.setText('{0:d}'.format(
                    int(context[register]['value'], 16)))

                if context[register]['isValidPointer']:
                    if 'telescope' in context[register] and context[register][
                            'telescope'] is not None:
                        telescope = QStandardItem()

                        telescope_value = str(
                            context[register]['telescope'][1]).replace(
                                '\n', ' ')
                        if len(telescope_value) > 25:
                            telescope_value = telescope_value[:25] + '...'

                        telescope.setText(telescope_value)
                        if context[register]['telescope'][0] == 2:
                            telescope.setData(
                                context[register]['telescope'][1],
                                Qt.UserRole + 1)

                        if context[register]['telescope'][0] == 0:
                            telescope.setForeground(Qt.darkGreen)
                        elif context[register]['telescope'][0] == 2:
                            telescope.setForeground(Qt.white)
                        elif context[register]['telescope'][0] != 1:
                            telescope.setForeground(Qt.darkGray)

            self._nativectx_model.appendRow(
                [reg_name, value_x, value_dec, telescope])
            self._nativectx_list.resizeColumnToContents(0)

    def _set_emulator_context(self, ptr, context):
        if self.indexOf(self._emulatorctx_list) == -1:
            self.addTab(self._emulatorctx_list, 'Emulator')
            self.show_context_tab('Emulator')
        else:
            self.show_context_tab('Emulator')

        context_ptr = ptr
        context = context.__dict__

        for register in context:
            if register.startswith('_'):
                continue

            reg_name = QStandardItem()
            reg_name.setTextAlignment(Qt.AlignCenter)
            reg_name.setForeground(QColor('#39c'))
            value_x = QStandardItem()
            # value_x.setTextAlignment(Qt.AlignCenter)
            value_dec = QStandardItem()
            # value_dec.setTextAlignment(Qt.AlignCenter)

            reg_name.setText(register)
            reg_name.setData(context_ptr)

            if context[register] is not None:
                if isinstance(context[register], int):
                    str_fmt = '0x{0:x}'
                    if self._emulatorctx_list.uppercase_hex:
                        str_fmt = '0x{0:X}'
                    value_x.setText(str_fmt.format(context[register]))
                    value_dec.setText('{0:d}'.format(context[register]))

            self._emulatorctx_model.appendRow([reg_name, value_x, value_dec])
            self._emulatorctx_list.resizeColumnToContents(0)
            self._emulatorctx_list.resizeColumnToContents(1)

    def _set_java_context(self, ptr, context):
        if self.indexOf(self._javactx_list) == -1:
            self.addTab(self._javactx_list, 'Java')
            self.show_context_tab('Java')
        else:
            self.show_context_tab('Java')

        for arg in context:
            _arg = QStandardItem()
            _arg.setText(arg)

            _class = QStandardItem()
            _class.setText(context[arg]['className'])
            if isinstance(context[arg]['handle'], str):
                _class.setForeground(Qt.lightGray)

            _value = QStandardItem()
            if 'arg' not in context[arg] or context[arg]['arg'] is None:
                _value.setText('null')
                _value.setForeground(Qt.gray)
            else:
                _value.setText(context[arg]['arg'])

            self._javactx_model.appendRow([_arg, _class, _value])
            self._javactx_list.resizeColumnToContents(0)
            self._javactx_list.resizeColumnToContents(1)

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_native_contextmenu(self, pos):
        index = self._nativectx_list.indexAt(pos).row()
        glbl_pt = self._nativectx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            # show contextmenu
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._nativectx_model.item(index, 1).text()))
            context_menu.addAction(
                'Jump to address', lambda: self._app_window.jump_to_address(
                    self._nativectx_model.item(index, 1).text()))
            context_menu.exec_(glbl_pt)

    def _on_emulator_contextmenu(self, pos):
        index = self._emulatorctx_list.indexAt(pos).row()
        glbl_pt = self._emulatorctx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            # show contextmenu
            context_menu.exec_(glbl_pt)

    def _on_java_contextmenu(self, pos):
        index = self._javactx_list.indexAt(pos).row()
        glbl_pt = self._javactx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            # show contextmenu
            context_menu.exec_(glbl_pt)

    def _on_context_changed(self, reg_name, reg_val):
        x_in = 0
        for c in reg_val:
            if c.lower() not in '1234567890abcdef':
                if c.lower() == 'x' and x_in == 0:
                    x_in += 1
                    continue

                self._app_window.dwarf.onLogToConsole.emit(
                    'error: invalid reg_value: ' + reg_val +
                    ' - expected dec/hex')
                return

        if isinstance(reg_val, str) and reg_val.startswith('0x'):
            try:
                reg_val = int(reg_val, 16)
            except ValueError:
                self._app_window.dwarf.onLogToConsole.emit(
                    'error: invalid reg_value: ' + reg_val +
                    ' - expected dec/hex')
                return
        try:
            reg_val = int(reg_val)
        except ValueError:
            self._app_window.dwarf.onLogToConsole.emit(
                'error: invalid reg_value: ' + reg_val + ' - expected dec/hex')
            return

        reg_val = hex(reg_val)
        was_found, find_result = self._nativectx_list.contains_text(
            reg_name, True, True, True)
        if was_found:
            if len(find_result) == 1:
                find_result = find_result[0]
                if self._nativectx_model.item(find_result[0],
                                              0).text() == reg_name:
                    str_fmt = '0x{0:x}'
                    if self._nativectx_list.uppercase_hex:
                        str_fmt = '0x{0:X}'

                    value_x = str_fmt.format(int(reg_val, 16))

                    value_dec = '{0:d}'.format(int(reg_val, 16))
                    self._nativectx_model.item(find_result[0],
                                               1).setText(value_x)
                    self._nativectx_model.item(find_result[0],
                                               2).setText(value_dec)
                    self._nativectx_model.item(find_result[0], 3).setText("")
Esempio n. 21
0
class ProcessList(QWidget):
    """ ProcessListWidget wich shows running Processes on Device
        Includes a Refresh Button to manually start refreshthread

        args:
            device needed

        Signals:
            onProcessSelected([pid, name]) - pid(int) name(str)
            onRefreshError(str)
    """

    onProcessSelected = pyqtSignal(list, name='onProcessSelected')
    onRefreshError = pyqtSignal(str, name='onRefreshError')

    def __init__(self, device, parent=None):
        super(ProcessList, self).__init__(parent=parent)

        # if not isinstance(device, frida.core.Device):
        #    print('No FridaDevice')
        #    return

        self._device = device

        self.process_list = DwarfListView()

        model = QStandardItemModel(0, 2, parent)
        model.setHeaderData(0, Qt.Horizontal, "PID")
        model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                            Qt.TextAlignmentRole)
        model.setHeaderData(1, Qt.Horizontal, "Name")

        self.process_list.doubleClicked.connect(self._on_item_clicked)

        v_box = QVBoxLayout()
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self.process_list)
        self.refresh_button = QPushButton('Refresh')
        self.refresh_button.clicked.connect(self._on_refresh_procs)
        self.refresh_button.setEnabled(False)
        v_box.addWidget(self.refresh_button)
        self.setLayout(v_box)

        self.process_list.setModel(model)
        self.process_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)

        self.procs_update_thread = ProcsThread(self, self._device)
        self.procs_update_thread.add_proc.connect(self._on_add_proc)
        self.procs_update_thread.is_error.connect(self._on_error)
        self.procs_update_thread.is_finished.connect(self._on_refresh_finished)
        self.procs_update_thread.device = self._device
        self.procs_update_thread.start()

    # ************************************************************************
    # **************************** Properties ********************************
    # ************************************************************************
    @property
    def device(self):
        """ Sets Device needs frida.core.device
        """
        return self._device

    @device.setter
    def device(self, value):
        self.set_device(value)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def clear(self):
        """ Clears the List
        """
        self.process_list.clear()

    def set_device(self, device):
        """ Set frida Device
        """
        if isinstance(device, frida.core.Device):
            self._device = device
            self.procs_update_thread.device = device
            self._on_refresh_procs()

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_item_clicked(self, model_index):
        model = self.process_list.model()

        index = model.itemFromIndex(model_index).row()

        if index != -1:
            sel_pid = self.process_list.get_item_text(index, 0)
            sel_name = self.process_list.get_item_text(index, 1)
            self.onProcessSelected.emit([int(sel_pid), sel_name])

    def _on_add_proc(self, item):
        model = self.process_list.model()
        pid = QStandardItem()
        pid.setText(str(item['pid']))
        pid.setTextAlignment(Qt.AlignCenter)
        name = QStandardItem()
        name.setText(item['name'])
        model.appendRow([pid, name])

    def _on_error(self, error_str):
        self.onRefreshError.emit(error_str)

    def _on_refresh_procs(self):
        if not self._device:
            return

        if self.procs_update_thread.isRunning():
            self.procs_update_thread.terminate()

        if not self.procs_update_thread.isRunning():
            self.clear()
            self.refresh_button.setEnabled(False)
            self.procs_update_thread.device = self._device
            self.procs_update_thread.start()

    def _on_refresh_finished(self):
        self.refresh_button.setEnabled(True)
Esempio n. 22
0
class HooksPanel(QWidget):
    """ HooksPanel

        Signals:
            onShowMemoryRequest(str) - ptr
            onHookChanged(str) - ptr
            onHookRemoved(str) - ptr
    """

    onShowMemoryRequest = pyqtSignal(str, name='onShowMemoryRequest')
    onHookChanged = pyqtSignal(str, name='onHookChanged')
    onHookRemoved = pyqtSignal(str, name='onHookRemoved')

    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(HooksPanel, self).__init__(parent=parent)

        self._app_window = parent

        if self._app_window.dwarf is None:
            print('HooksPanel created before Dwarf exists')
            return

        # connect to dwarf
        self._app_window.dwarf.onAddJavaHook.connect(self._on_add_hook)
        self._app_window.dwarf.onAddNativeHook.connect(self._on_add_hook)
        self._app_window.dwarf.onAddNativeOnLoadHook.connect(self._on_add_hook)
        self._app_window.dwarf.onHitNativeOnLoad.connect(
            self._on_hit_native_on_load)
        self._app_window.dwarf.onDeleteHook.connect(self._on_hook_deleted)

        self._hooks_list = DwarfListView()
        self._hooks_list.doubleClicked.connect(self._on_dblclicked)
        self._hooks_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._hooks_list.customContextMenuRequested.connect(
            self._on_contextmenu)
        self._hooks_model = QStandardItemModel(0, 5)

        self._hooks_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._hooks_model.setHeaderData(1, Qt.Horizontal, 'T')
        self._hooks_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                        Qt.TextAlignmentRole)
        self._hooks_model.setHeaderData(2, Qt.Horizontal, 'Input')
        self._hooks_model.setHeaderData(3, Qt.Horizontal, '{}')
        self._hooks_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter,
                                        Qt.TextAlignmentRole)
        self._hooks_model.setHeaderData(4, Qt.Horizontal, '<>')
        self._hooks_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter,
                                        Qt.TextAlignmentRole)

        self._hooks_list.setModel(self._hooks_model)

        self._hooks_list.header().setStretchLastSection(False)
        self._hooks_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._hooks_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._hooks_list.header().setSectionResizeMode(2, QHeaderView.Stretch)
        self._hooks_list.header().setSectionResizeMode(
            3, QHeaderView.ResizeToContents)
        self._hooks_list.header().setSectionResizeMode(
            4, QHeaderView.ResizeToContents)

        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self._hooks_list)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        self.btn1 = QPushButton(
            QIcon(utils.resource_path('assets/icons/plus.svg')), '')
        self.btn1.setFixedSize(20, 20)
        self.btn1.clicked.connect(self._on_additem_clicked)
        btn2 = QPushButton(QIcon(utils.resource_path('assets/icons/dash.svg')),
                           '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(utils.resource_path('assets/icons/trashcan.svg')), '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(self.btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)
        self.setLayout(v_box)

        self._bold_font = QFont(self._hooks_list.font())
        self._bold_font.setBold(True)

        shortcut_addnative = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_N),
                                       self._app_window, self._on_addnative)
        shortcut_addnative.setAutoRepeat(False)

        shortcut_addjava = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_J),
                                     self._app_window, self._on_addjava)
        shortcut_addjava.setAutoRepeat(False)

        shortcut_add_native_on_load = QShortcut(
            QKeySequence(Qt.CTRL + Qt.Key_O), self._app_window,
            self._on_add_native_on_load)
        shortcut_add_native_on_load.setAutoRepeat(False)

        # new menu
        self.new_menu = QMenu('New')
        self.new_menu.addAction('Native', self._on_addnative)
        self.new_menu.addAction('Java', self._on_addjava)
        self.new_menu.addAction('Module loading', self._on_add_native_on_load)
        if self._app_window.dwarf.java_available:
            self.new_menu.addAction('Java class loading',
                                    self._on_add_native_on_load)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def delete_items(self):
        """ Delete selected Items
        """
        index = self._hooks_list.selectionModel().currentIndex().row()
        if index != -1:
            self._on_deletehook(index)
            self._hooks_model.removeRow(index)

    def clear_list(self):
        """ Clear the List
        """
        # go through all items and tell it gets removed
        for item in range(self._hooks_model.rowCount()):
            if item:
                self._on_deletehook(item)

        if self._hooks_model.rowCount() > 0:
            # something was wrong it should be empty
            self._hooks_model.removeRows(0, self._hooks_model.rowCount())

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_add_hook(self, hook):
        type_ = QStandardItem()
        type_.setFont(self._bold_font)
        type_.setTextAlignment(Qt.AlignCenter)
        if hook.hook_type == Hook.HOOK_NATIVE:
            type_.setText('N')
            type_.setToolTip('Native hook')
        elif hook.hook_type == Hook.HOOK_JAVA:
            type_.setText('J')
            type_.setToolTip('Java hook')
        elif hook.hook_type == Hook.HOOK_ONLOAD:
            type_.setText('O')
            type_.setToolTip('On load hook')
        else:
            type_.setText('U')
            type_.setToolTip('Unknown Type')

        addr = QStandardItem()

        if hook.hook_type == Hook.HOOK_JAVA:
            parts = hook.get_input().split('.')
            addr.setText('.'.join(parts[:len(parts) - 1]))
        else:
            str_fmt = '0x{0:x}'
            if self._hooks_list.uppercase_hex:
                str_fmt = '0x{0:X}'
            # addr.setTextAlignment(Qt.AlignCenter)
            addr.setText(str_fmt.format(hook.get_ptr()))

        inp = QStandardItem()
        inp_text = hook.get_input()
        if hook.hook_type == Hook.HOOK_JAVA:
            parts = inp_text.split('.')
            inp_text = parts[len(parts) - 1]
        # if len(inp_text) > 15:
        #    inp_text = inp_text[:15] + '...'
        #    inp.setToolTip(hook.get_input())
        inp.setText(inp_text)
        inp.setData(hook.get_input(), Qt.UserRole + 2)
        inp.setToolTip(hook.get_input())

        logic = QStandardItem()
        logic.setTextAlignment(Qt.AlignCenter)
        logic.setFont(self._bold_font)
        if hook.logic and hook.logic != 'null' and hook.logic != 'undefined':
            logic.setText('ƒ')
            logic.setToolTip(hook.logic)
            logic.setData(hook.logic, Qt.UserRole + 2)

        condition = QStandardItem()
        condition.setTextAlignment(Qt.AlignCenter)
        condition.setFont(self._bold_font)
        if hook.condition and hook.condition != 'null' and hook.condition != 'undefined':
            condition.setText('ƒ')
            condition.setToolTip(hook.condition)
            condition.setData(hook.condition, Qt.UserRole + 2)

        self._hooks_model.appendRow([addr, type_, inp, logic, condition])

    def _on_hit_native_on_load(self, data):
        items = self._hooks_model.findItems(data[0], Qt.MatchExactly, 2)
        if len(items) > 0:
            self._hooks_model.item(items[0].row(), 0).setText(data[1])

    def _on_dblclicked(self, model_index):
        item = self._hooks_model.itemFromIndex(model_index)
        if model_index.column() == 3 and item.text() == 'ƒ':
            self._on_modify_logic(model_index.row())
        elif model_index.column() == 4 and item.text() == 'ƒ':
            self._on_modify_condition(model_index.row())
        else:
            self.onShowMemoryRequest.emit(
                self._hooks_model.item(model_index.row(), 0).text())

    def _on_contextmenu(self, pos):
        context_menu = QMenu(self)
        context_menu.addMenu(self.new_menu)
        context_menu.addSeparator()
        index = self._hooks_list.indexAt(pos).row()
        if index != -1:
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._hooks_model.item(index, 0).text()))
            context_menu.addAction(
                'Jump to address', lambda: self._app_window.jump_to_address(
                    self._hooks_model.item(index, 0).text()))
            context_menu.addSeparator()
            context_menu.addAction('Modify Logic',
                                   lambda: self._on_modify_logic(index))
            context_menu.addAction('Modify Condition',
                                   lambda: self._on_modify_condition(index))
            context_menu.addSeparator()
            context_menu.addAction('Delete Hook',
                                   lambda: self._on_deletehook(index))
        global_pt = self._hooks_list.mapToGlobal(pos)
        context_menu.exec(global_pt)

    def _on_modify_logic(self, num_row):
        item = self._hooks_model.item(num_row, 3)
        data = item.data(Qt.UserRole + 2)
        if data is None:
            data = ''
        ptr = self._hooks_model.item(num_row, 0).text()
        accept, input_ = InputMultilineDialog().input('Insert logic for %s' %
                                                      ptr,
                                                      input_content=data)
        if accept:
            what = utils.parse_ptr(ptr)
            if what == 0:
                what = self._hooks_model.item(num_row, 2).data(Qt.UserRole + 2)
            if self._app_window.dwarf.dwarf_api('setHookLogic',
                                                [what, input_]):
                item.setData(input_, Qt.UserRole + 2)
                if not item.text():
                    item.setText('ƒ')
                item.setToolTip(input_)
                self.onHookChanged.emit(ptr)

    def _on_modify_condition(self, num_row):
        item = self._hooks_model.item(num_row, 4)
        data = item.data(Qt.UserRole + 2)
        if data is None:
            data = ''
        ptr = self._hooks_model.item(num_row, 0).text()
        accept, input_ = InputDialog().input(self._app_window,
                                             'Insert condition for %s' % ptr,
                                             input_content=data)
        if accept:
            what = utils.parse_ptr(ptr)
            if what == 0:
                what = self._hooks_model.item(num_row, 2).data(Qt.UserRole + 2)
            if self._app_window.dwarf.dwarf_api('setHookCondition',
                                                [what, input_]):
                item.setData(input_, Qt.UserRole + 2)
                if not item.text():
                    item.setText('ƒ')
                item.setToolTip(input_)
                self.onHookChanged.emit(ptr)

    # + button
    def _on_additem_clicked(self):
        self.new_menu.exec_(QCursor.pos())

    # shortcuts/menu
    def _on_addnative(self):
        self._app_window.dwarf.hook_native()

    def _on_addjava(self):
        self._app_window.dwarf.hook_java()

    def _on_add_native_on_load(self):
        self._app_window.dwarf.hook_native_onload()

    def _on_deletehook(self, num_row):
        hook_type = self._hooks_model.item(num_row, 1).text()
        if hook_type == 'N':
            ptr = self._hooks_model.item(num_row, 0).text()
            ptr = utils.parse_ptr(ptr)
            self._app_window.dwarf.dwarf_api('deleteHook', ptr)
            self.onHookRemoved.emit(str(ptr))
        elif hook_type == 'J':
            input_ = self._hooks_model.item(num_row, 2).data(Qt.UserRole + 2)
            self._app_window.dwarf.dwarf_api('deleteHook', input_)
        elif hook_type == 'O':
            input_ = self._hooks_model.item(num_row, 2).data(Qt.UserRole + 2)
            self._app_window.dwarf.dwarf_api('deleteHook', input_)
        elif hook_type == 'U':
            ptr = self._hooks_model.item(num_row, 0).text()
            ptr = utils.parse_ptr(ptr)
            self._app_window.dwarf.dwarf_api('deleteHook', ptr)
            self.onHookRemoved.emit(str(ptr))

    def _on_hook_deleted(self, parts):
        _msg, _type, _val = parts

        additional = None

        if _type == 'java':
            _val = _val.split('.')
            str_frmt = '.'.join(_val[:-1])
            additional = _val[-1]
            item_index = 0
        elif _type == 'onload':
            str_frmt = _val
            item_index = 2
        else:
            _ptr = utils.parse_ptr(_val)
            if self._hooks_list._uppercase_hex:
                str_frmt = '0x{0:X}'.format(_ptr)
            else:
                str_frmt = '0x{0:x}'.format(_ptr)
            item_index = 0

        for _item in range(self._hooks_model.rowCount()):
            item = self._hooks_model.item(_item, item_index)

            if item is None:
                continue

            if str_frmt == item.text():
                if additional is not None:
                    if additional == self._hooks_model.item(_item, 2).text():
                        self._hooks_model.removeRow(_item)
                else:
                    self._hooks_model.removeRow(_item)
Esempio n. 23
0
class JavaInspector(QWidget):
    """ Java Class/Methods Lists
    """
    def __init__(self, parent=None):
        super(JavaInspector, self).__init__(parent)

        self._app_window = parent

        self._app_window.dwarf.onEnumerateJavaMethodsComplete.connect(
            self._on_method_enumeration_complete)
        self._app_window.dwarf.onEnumerateJavaClassesStart.connect(
            self._on_class_enumeration_start)
        self._app_window.dwarf.onEnumerateJavaClassesMatch.connect(
            self._on_class_enumeration_match)
        self._app_window.dwarf.onEnumerateJavaClassesComplete.connect(
            self._on_class_enumeration_complete)

        self._java_classes = DwarfListView(self)
        self._javaclass_model = QStandardItemModel(0, 1)
        self._javaclass_model.setHeaderData(0, Qt.Horizontal, 'Class')
        self._java_classes.setModel(self._javaclass_model)
        self._java_classes.selectionModel().selectionChanged.connect(
            self._class_clicked)
        self._java_classes.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._java_classes.setContextMenuPolicy(Qt.CustomContextMenu)
        self._java_classes.customContextMenuRequested.connect(
            self._on_class_contextmenu)
        self._java_classes.doubleClicked.connect(self._class_dblclicked)

        self._java_methods = DwarfListView(self)
        self._javamethod_model = QStandardItemModel(0, 1)
        self._javamethod_model.setHeaderData(0, Qt.Horizontal, 'Method')
        self._java_methods.setModel(self._javamethod_model)
        self._java_methods.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._java_methods.setContextMenuPolicy(Qt.CustomContextMenu)
        self._java_methods.customContextMenuRequested.connect(
            self._on_method_contextmenu)
        self._java_methods.doubleClicked.connect(self._method_dblclicked)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(0, 0, 0, 0)
        h_box.addWidget(self._java_classes)
        h_box.addWidget(self._java_methods)
        self.setLayout(h_box)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def update_classes(self):
        """ Refresh Classeslist
        """
        self._app_window.dwarf.dwarf_api('enumerateJavaClasses')

    def update_methods(self, class_name):
        """ Refresh Methodslist
        """
        if class_name:
            self._app_window.dwarf.dwarf_api('enumerateJavaMethods',
                                             class_name)

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _class_clicked(self):
        index = self._java_classes.selectionModel().currentIndex().row()
        _class = self._javaclass_model.item(index, 0)
        if _class is None:
            return

        self._app_window.dwarf.dwarf_api('enumerateJavaMethods', _class.text())

    def _on_class_enumeration_start(self):
        self._java_classes.clear()

    def _on_class_enumeration_match(self, java_class):
        _class_name = QStandardItem()
        _class_name.setText(java_class)
        self._javaclass_model.appendRow(_class_name)

    def _on_class_enumeration_complete(self):
        self._java_classes.sortByColumn(0, 0)

    def _on_method_enumeration_complete(self, data):
        self._java_methods.clear()
        _class, methods = data
        for method in methods:
            _method_name = QStandardItem()
            _method_name.setText(method)
            self._javamethod_model.appendRow(_method_name)

    def _class_dblclicked(self):
        """ Class DoubleClicked
        """
        index = self._java_classes.selectionModel().currentIndex().row()
        if index:
            class_item = self._javaclass_model.item(index, 0)
            if class_item:
                class_name = class_item.text()
                if class_name:
                    self._hook_class(class_name)

    def _method_dblclicked(self):
        """ Function DoubleClicked
        """
        class_index = self._java_classes.selectionModel().currentIndex().row()
        method_index = self._java_methods.selectionModel().currentIndex().row()
        if class_index and method_index:
            class_item = self._javaclass_model.item(class_index, 0)
            method_item = self._javamethod_model.item(method_index, 0)
            if class_item and method_item:
                class_name = class_item.text()
                method_name = method_item.text()
                if class_name and method_name:
                    self._app_window.dwarf.hook_java(class_name + '.' +
                                                     method_name)

    def _hook_class(self, class_name):
        if class_name:
            self._app_window.dwarf.hook_java(class_name)

    def _hook_class_functions(self, class_name):
        if class_name:
            self._app_window.dwarf.dwarf_api('hookAllJavaMethods', class_name)

    def _on_class_contextmenu(self, pos):
        """ Modules ContextMenu
        """
        index = self._java_classes.indexAt(pos).row()
        glbl_pt = self._java_classes.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Hook constructor', lambda: self._hook_class(
                    self._javaclass_model.item(index, 0).text()))
            context_menu.addAction(
                'Hook all methods', lambda: self._hook_class_functions(
                    self._javaclass_model.item(index, 0).text()))
            context_menu.addSeparator()

        context_menu.addAction('Refresh', self.update_classes)
        context_menu.exec_(glbl_pt)

    def _hook_method(self, method_name):
        class_index = self._java_classes.selectionModel().currentIndex().row()
        if class_index:
            class_item = self._javaclass_model.item(class_index, 0)
            if class_item:
                class_name = class_item.text()
                if class_name and method_name:
                    self._app_window.dwarf.hook_java(class_name + '.' +
                                                     method_name)

    def _cm_refresh_methods(self):
        index = self._java_classes.selectionModel().currentIndex().row()
        _class = self._javaclass_model.item(index, 0)
        if _class is None:
            return

        self.update_methods(_class.text())

    def _on_method_contextmenu(self, pos):
        """ Modules ContextMenu
        """
        index = self._java_methods.indexAt(pos).row()
        glbl_pt = self._java_methods.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Hook method', lambda: self._hook_method(
                    self._javamethod_model.item(index, 0).text()))
            context_menu.addSeparator()

        context_menu.addAction('Refresh', self._cm_refresh_methods)
        context_menu.exec_(glbl_pt)
Esempio n. 24
0
class WatchersPanel(QWidget):
    """ WatcherPanel

        Signals:
            onItemSelected(addr_str) - item dblclicked
            onItemAddClick

        Constants:
            MEMORY_ACCESS_READ = 1
            MEMORY_ACCESS_WRITE = 2
            MEMORY_ACCESS_EXECUTE = 4
            MEMORY_WATCH_SINGLESHOT = 8
    """
    MEMORY_ACCESS_READ = 1
    MEMORY_ACCESS_WRITE = 2
    MEMORY_ACCESS_EXECUTE = 4
    MEMORY_WATCH_SINGLESHOT = 8

    onItemDoubleClicked = pyqtSignal(int, name='onItemDoubleClicked')
    onItemAdded = pyqtSignal(int, name='onItemAdded')
    onItemRemoved = pyqtSignal(int, name='onItemRemoved')

    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(WatchersPanel, self).__init__(parent=parent)
        self._app_window = parent

        if self._app_window.dwarf is None:
            print('Watcherpanel created before Dwarf exists')
            return

        self._uppercase_hex = True
        self.setAutoFillBackground(True)

        # connect to dwarf
        self._app_window.dwarf.onWatcherAdded.connect(self._on_watcher_added)
        self._app_window.dwarf.onWatcherRemoved.connect(
            self._on_watcher_removed)

        # setup our model
        self._watchers_model = QStandardItemModel(0, 5)
        self._watchers_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._watchers_model.setHeaderData(1, Qt.Horizontal, 'R')
        self._watchers_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)
        self._watchers_model.setHeaderData(2, Qt.Horizontal, 'W')
        self._watchers_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)
        self._watchers_model.setHeaderData(3, Qt.Horizontal, 'X')
        self._watchers_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)
        self._watchers_model.setHeaderData(4, Qt.Horizontal, 'S')
        self._watchers_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter,
                                           Qt.TextAlignmentRole)

        # setup ui
        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        self.list_view = DwarfListView()
        self.list_view.setModel(self._watchers_model)
        self.list_view.header().setSectionResizeMode(0, QHeaderView.Stretch)
        self.list_view.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setSectionResizeMode(
            3, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setSectionResizeMode(
            4, QHeaderView.ResizeToContents | QHeaderView.Fixed)
        self.list_view.header().setStretchLastSection(False)
        self.list_view.doubleClicked.connect(self._on_item_dblclick)
        self.list_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.list_view.customContextMenuRequested.connect(self._on_contextmenu)

        v_box.addWidget(self.list_view)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        icon = QIcon()
        icon.addPixmap(QPixmap(utils.resource_path('assets/icons/plus.svg')))
        btn1 = QPushButton(icon, '')
        btn1.setFixedSize(20, 20)
        btn1.clicked.connect(self._on_additem_clicked)
        btn2 = QPushButton(
            QIcon(QPixmap(utils.resource_path('assets/icons/dash.svg'))), '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(QPixmap(utils.resource_path('assets/icons/trashcan.svg'))),
            '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)

        # create a centered dot icon
        _section_width = self.list_view.header().sectionSize(2)
        self._new_pixmap = QPixmap(_section_width, 20)
        self._new_pixmap.fill(Qt.transparent)
        painter = QPainter(self._new_pixmap)
        rect = QRect((_section_width * 0.5), 0, 20, 20)
        painter.setBrush(QColor('#666'))
        painter.setPen(QColor('#666'))
        painter.drawEllipse(rect)
        self._dot_icon = QIcon(self._new_pixmap)

        # shortcuts
        shortcut_add = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W),
                                 self._app_window, self._on_additem_clicked)
        shortcut_add.setAutoRepeat(False)

        self.setLayout(v_box)

    # ************************************************************************
    # **************************** Properties ********************************
    # ************************************************************************
    @property
    def uppercase_hex(self):
        """ Addresses displayed lower/upper-case
        """
        return self._uppercase_hex

    @uppercase_hex.setter
    def uppercase_hex(self, value):
        """ Addresses displayed lower/upper-case
            value - bool or str
                    'upper', 'lower'
        """
        if isinstance(value, bool):
            self._uppercase_hex = value
        elif isinstance(value, str):
            self._uppercase_hex = (value == 'upper')

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def do_addwatcher_dlg(self, ptr=None):  # pylint: disable=too-many-branches
        """ Shows AddWatcherDialog
        """
        watcher_dlg = AddWatcherDialog(self, ptr)
        if watcher_dlg.exec_() == QDialog.Accepted:
            mem_r = watcher_dlg.acc_read.isChecked()
            mem_w = watcher_dlg.acc_write.isChecked()
            mem_x = watcher_dlg.acc_execute.isChecked()
            mem_s = watcher_dlg.singleshot.isChecked()

            ptr = watcher_dlg.text_field.text()

            if ptr:
                if isinstance(ptr, str):
                    if ptr.startswith('0x') or ptr.startswith('#'):
                        ptr = utils.parse_ptr(ptr)
                    else:
                        try:
                            ptr = int(ptr, 10)
                        except ValueError:
                            pass

                    # int now?
                    if not isinstance(ptr, int):
                        try:
                            ptr = int(
                                self._app_window.dwarf.dwarf_api(
                                    'evaluatePtr', ptr), 16)
                        except ValueError:
                            ptr = 0

                        if ptr == 0:
                            return

                        if not self._app_window.dwarf.dwarf_api(
                                'isValidPointer', ptr):
                            return
                else:
                    return

                mem_val = 0
                if mem_r:
                    mem_val |= self.MEMORY_ACCESS_READ
                if mem_w:
                    mem_val |= self.MEMORY_ACCESS_WRITE
                if mem_x:
                    mem_val |= self.MEMORY_ACCESS_EXECUTE
                if mem_s:
                    mem_val |= self.MEMORY_WATCH_SINGLESHOT

                self.add_address(ptr, mem_val, from_api=False)

                # return [ptr, mem_val]

    def add_address(self, ptr, flags, from_api=False):
        """ Adds Address to display

            ptr - str or int
            flags - int
        """
        if isinstance(ptr, str):
            ptr = utils.parse_ptr(ptr)

        if not isinstance(flags, int):
            try:
                flags = int(flags, 10)
            except ValueError:
                flags = 3

        if not from_api:
            # function was called directly so add it to dwarf
            if not self._app_window.dwarf.is_address_watched(ptr):
                self._app_window.dwarf.dwarf_api('addWatcher', [ptr, flags])
                return

        # show header
        self.list_view.setHeaderHidden(False)

        # create items to add
        if self._uppercase_hex:
            str_frmt = '0x{0:X}'
        else:
            str_frmt = '0x{0:x}'

        addr = QStandardItem()
        addr.setText(str_frmt.format(ptr))

        read = QStandardItem()
        write = QStandardItem()
        execute = QStandardItem()
        singleshot = QStandardItem()

        if flags & self.MEMORY_ACCESS_READ:
            read.setIcon(self._dot_icon)
        if flags & self.MEMORY_ACCESS_WRITE:
            write.setIcon(self._dot_icon)
        if flags & self.MEMORY_ACCESS_EXECUTE:
            execute.setIcon(self._dot_icon)
        if flags & self.MEMORY_WATCH_SINGLESHOT:
            singleshot.setIcon(self._dot_icon)

        # add items as new row on top
        self._watchers_model.insertRow(
            0, [addr, read, write, execute, singleshot])

    def remove_address(self, ptr, from_api=False):
        """ Remove Address from List
        """
        if isinstance(ptr, str):
            ptr = utils.parse_ptr(ptr)

        if not from_api:
            # called somewhere so remove watcher in dwarf too
            self._app_window.dwarf.dwarf_api('removeWatcher', ptr)
            return

        str_frmt = ''
        if self._uppercase_hex:
            str_frmt = '0x{0:X}'.format(ptr)
        else:
            str_frmt = '0x{0:x}'.format(ptr)

        model = self.list_view.model()
        for item in range(model.rowCount()):
            if str_frmt == model.item(item).text():
                model.removeRow(item)

    def delete_items(self):
        """ Delete selected Items
        """
        model = self.list_view.model()

        index = self.list_view.selectionModel().currentIndex().row()
        if index != -1:
            ptr = model.item(index, 0).text()
            self.remove_address(ptr)

    def clear_list(self):
        """ Clear the List
        """
        model = self.list_view.model()

        # go through all items and tell it gets removed
        for item in range(model.rowCount()):
            ptr = model.item(item, 0).text()
            self.remove_address(ptr)

        if model.rowCount() > 0:
            # something was wrong it should be empty
            model.removeRows(0, model.rowCount())

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_contextmenu(self, pos):
        index = self.list_view.indexAt(pos).row()
        glbl_pt = self.list_view.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._watchers_model.item(index, 0).text()))
            context_menu.addAction(
                'Delete address', lambda: self.remove_address(
                    self._watchers_model.item(index, 0).text()))
            context_menu.addSeparator()

        context_menu.addAction('Add watcher',
                               lambda: self._on_additem_clicked())
        context_menu.exec_(glbl_pt)

    def _on_item_dblclick(self, model_index):
        row = self._watchers_model.itemFromIndex(model_index).row()
        if row != -1:
            ptr = self._watchers_model.item(row, 0).text()
            self.onItemDoubleClicked.emit(ptr)

    def _on_additem_clicked(self):
        if self._app_window.dwarf.pid == 0:
            return

        self.do_addwatcher_dlg()

    def _on_watcher_added(self, ptr, flags):
        """ Callback from Dwarf after Watcher is added
        """
        ptr = utils.parse_ptr(ptr)
        # add to watcherslist
        self.add_address(ptr, flags, from_api=True)
        self.onItemAdded.emit(ptr)

    def _on_watcher_removed(self, ptr):
        """ Callback from Dwarf after watcher is removed
        """
        ptr = utils.parse_ptr(ptr)
        # remove from list
        self.remove_address(ptr, from_api=True)
        self.onItemRemoved.emit(ptr)
Esempio n. 25
0
    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(ModulesPanel, self).__init__(parent)
        self._app_window = parent

        if self._app_window.dwarf is None:
            print('ModulesPanel created before Dwarf exists')
            return

        self._app_window.dwarf.onSetModules.connect(self.set_modules)

        self._uppercase_hex = True

        # setup models
        self.modules_list = None
        self.modules_model = QStandardItemModel(0, 4, self)
        self.modules_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self.modules_model.setHeaderData(1, Qt.Horizontal, 'Base')
        self.modules_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.modules_model.setHeaderData(2, Qt.Horizontal, 'Size')
        self.modules_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.modules_model.setHeaderData(3, Qt.Horizontal, 'Path')

        self.imports_list = None
        self.imports_model = QStandardItemModel(0, 4, self)
        self.imports_model.setHeaderData(0, Qt.Horizontal, 'Import')
        self.imports_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.imports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.imports_model.setHeaderData(2, Qt.Horizontal, 'Module')
        self.imports_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.imports_model.setHeaderData(3, Qt.Horizontal, 'Type')

        self.exports_list = None
        self.exports_model = QStandardItemModel(0, 3, self)
        self.exports_model.setHeaderData(0, Qt.Horizontal, 'Export')
        self.exports_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.exports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.exports_model.setHeaderData(2, Qt.Horizontal, 'Type')

        self.symbols_list = None
        self.symbols_model = QStandardItemModel(0, 3, self)
        self.symbols_model.setHeaderData(0, Qt.Horizontal, 'Export')
        self.symbols_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.symbols_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.symbols_model.setHeaderData(2, Qt.Horizontal, 'Type')

        # setup ui
        main_wrapper = QVBoxLayout()
        main_wrapper.setContentsMargins(0, 0, 0, 0)
        h_box = QHBoxLayout()
        self.modules_list = DwarfListView()
        self.modules_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.modules_list.customContextMenuRequested.connect(
            self._on_modules_contextmenu)
        self.modules_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.modules_list.clicked.connect(self._module_clicked)
        self.modules_list.doubleClicked.connect(self._module_dblclicked)
        self.modules_list.setModel(self.modules_model)
        self.modules_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.modules_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.modules_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        h_box.addWidget(self.modules_list)
        self.modules_list.selectionModel().selectionChanged.connect(
            self._module_clicked)

        hv_box = QVBoxLayout()
        self.imports_list = DwarfListView()
        self.imports_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.imports_list.customContextMenuRequested.connect(
            self._on_imports_contextmenu)
        self.imports_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.imports_list.doubleClicked.connect(self._import_dblclicked)
        self.imports_list.setModel(self.imports_model)
        self.imports_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.imports_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.imports_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.imports_list.setVisible(False)
        self.exports_list = DwarfListView()
        self.exports_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.exports_list.customContextMenuRequested.connect(
            self._on_exports_contextmenu)
        self.exports_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.exports_list.doubleClicked.connect(self._export_dblclicked)
        self.exports_list.setModel(self.exports_model)
        self.exports_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.exports_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.exports_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.exports_list.setVisible(False)
        self.symbols_list = DwarfListView()
        self.symbols_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.symbols_list.doubleClicked.connect(self._symbol_dblclicked)
        self.symbols_list.setModel(self.symbols_model)
        self.symbols_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.symbols_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.symbols_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.symbols_list.setVisible(False)
        hv_box.addWidget(self.imports_list)
        hv_box.addWidget(self.exports_list)
        hv_box.addWidget(self.symbols_list)
        h_box.addLayout(hv_box)
        main_wrapper.addLayout(h_box)
        self.setLayout(main_wrapper)
Esempio n. 26
0
class ListDialog(QDialog):
    def __init__(self,
                 parent=None,
                 setup_list_cb=None,
                 setup_list_cb_args=None,
                 double_click_to_accept=False,
                 checkable=False):
        super(ListDialog, self).__init__(parent)

        self.right_click_handler = None

        layout = QVBoxLayout(self)
        self.list = DwarfListView()  # QListWidget()

        self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        if double_click_to_accept:
            self.list.doubleClicked.connect(self.accept)

        if setup_list_cb is not None:
            setup_list_cb(self.list, setup_list_cb_args)

        layout.addWidget(self.list)
        if checkable:
            buttons = QHBoxLayout()
            select_all = QPushButton('select all')
            select_all.clicked.connect(self.select_all)
            buttons.addWidget(select_all)
            unselect_all = QPushButton('unselect all')
            unselect_all.clicked.connect(self.unselect_all)
            buttons.addWidget(unselect_all)
            ok = QPushButton('ok')
            ok.clicked.connect(self.accept)
            buttons.addWidget(ok)
            cancel = QPushButton('cancel')
            cancel.clicked.connect(self.close)
            buttons.addWidget(cancel)
            layout.addLayout(buttons)

    def get_checked_items(self):
        ret = []
        for i in range(0, self.list.count()):
            item = self.list.item(i)
            if item.checkState() == Qt.Checked:
                ret.append(item)
        return ret

    def select_all(self):
        for i in range(0, self.list.count()):
            item = self.list.item(i)
            item.setCheckState(Qt.Checked)

    def unselect_all(self):
        for i in range(0, self.list.count()):
            item = self.list.item(i)
            item.setCheckState(Qt.Unchecked)

    def keyPressEvent(self, event):
        super(ListDialog, self).keyPressEvent(event)
        if event.key() == Qt.Key_Return:
            self.accept()

    @staticmethod
    def build_and_show(setup_list_cb,
                       setup_list_cb_args,
                       double_click_to_accept=False,
                       checkable=False):
        dialog = ListDialog(setup_list_cb=setup_list_cb,
                            setup_list_cb_args=setup_list_cb_args,
                            double_click_to_accept=double_click_to_accept,
                            checkable=checkable)
        if dialog.list.count() > 0:
            result = dialog.exec_()
            if checkable:
                if result == QDialog.Accepted:
                    checked_items = dialog.get_checked_items()
                else:
                    checked_items = []
                return result == QDialog.Accepted, checked_items

            return result == QDialog.Accepted, dialog.list.selectedItems()
        return None