예제 #1
0
    def __init__(self, app):
        super(DataPanel, self).__init__(app)

        self.app = app
        self.data = {}

        self.setOrientation(Qt.Horizontal)

        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.selectionModel().selectionChanged.connect(
            self.item_selected)
        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.have_context_menu = False
        self.hex_view.setVisible(False)
        self.addWidget(self.hex_view)
        #self.setStretchFactor(0, 8)
        self.setStretchFactor(1, 4)
        self.setStretchFactor(2, 4)
예제 #2
0
    def __init__(self, app, flags=None):
        super(QDebugPanel, self).__init__(flags)
        self.setDockOptions(QMainWindow.AnimatedDocks
                            | QMainWindow.AllowNestedDocks
                            | QMainWindow.AllowTabbedDocks)

        self.app = app
        self.q_settings = app.q_settings

        self.functions_list = DwarfListView()
        self.functions_list_model = QStandardItemModel(0, 1)
        self.functions_list_model.setHeaderData(0, Qt.Horizontal, '')
        self.functions_list.setModel(self.functions_list_model)
        self.functions_list.setHeaderHidden(True)
        self.functions_list.doubleClicked.connect(
            self._function_double_clicked)

        self.dock_functions_list = QDockWidget('Functions', self)
        self.dock_functions_list.setObjectName('functions')
        self.dock_functions_list.setWidget(self.functions_list)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_functions_list)
        self.resizeDocks([self.dock_functions_list], [100], Qt.Horizontal)
        self.app.debug_view_menu.addAction(
            self.dock_functions_list.toggleViewAction())

        self.memory_panel_range = None
        self.disassembly_panel_range = None

        screen_size = QtWidgets.QDesktopWidget().screenGeometry(-1)
        m_width = screen_size.width()

        self.memory_panel = HexEditor(self.app)
        self.memory_panel.debug_panel = self
        self.memory_panel.dataChanged.connect(self.on_memory_modified)

        self.disassembly_panel = DisassemblyView(self.app)
        self.disassembly_panel.debug_panel = self

        self.dock_memory_panel = QDockWidget('Memory', self)
        self.dock_memory_panel.setWidget(self.memory_panel)
        self.dock_memory_panel.setObjectName('memory')

        self.dock_disassembly_panel = QDockWidget('Disassembly', self)
        self.dock_disassembly_panel.setWidget(self.disassembly_panel)
        self.dock_disassembly_panel.setObjectName('disassembly')

        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_memory_panel,
                           Qt.Horizontal)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_disassembly_panel,
                           Qt.Horizontal)
        if m_width >= 1920:
            self.splitDockWidget(self.dock_memory_panel,
                                 self.dock_disassembly_panel, Qt.Horizontal)
        else:
            self.tabifyDockWidget(self.dock_memory_panel,
                                  self.dock_disassembly_panel)

        self.restoreUiState()
예제 #3
0
    def __init__(self, parent=None):
        super(ContextWidget, 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(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._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(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')
예제 #4
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

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

        self._recent_list_model = QStandardItemModel(0, 2)
        self._recent_list_model.setHeaderData(0, Qt.Horizontal, 'Type')
        self._recent_list_model.setHeaderData(1, Qt.Horizontal, 'Path')

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

        self._recent_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._recent_list.header().setSectionResizeMode(1, QHeaderView.Stretch)

        # 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()))
예제 #5
0
class DisassemblyPanel(QSplitter):
    def __init__(self, app):
        super(DisassemblyPanel, self).__init__()

        self.app = app

        self.functions_list = DwarfListView()
        self.functions_list_model = QStandardItemModel(0, 1)
        self.functions_list_model.setHeaderData(0, Qt.Horizontal, 'functions')
        self.functions_list.setModel(self.functions_list_model)
        self.addWidget(self.functions_list)
        self.functions_list.hide()
        self.functions_list.doubleClicked.connect(self._function_double_clicked)

        self.disasm_view = DisassemblyView(app)
        self.addWidget(self.disasm_view)

        self.setStretchFactor(0, 1)
        self.setStretchFactor(1, 5)

        self.update_functions()

    def disassemble(self, dwarf_range):
        self.disasm_view.disassemble(dwarf_range)

    def update_functions(self, functions_list=None):
        if functions_list is None:
            functions_list = {}
        self.functions_list_model.setRowCount(0)
        for module_info_base in self.app.dwarf.database.modules_info:
            module_info = self.app.dwarf.database.modules_info[module_info_base]
            if len(module_info.functions) > 0:
                self.functions_list.show()
                for function in module_info.functions:
                    functions_list[function.name] = function.address

        for function_name in sorted(functions_list.keys()):
            function_addr = functions_list[function_name]
            item = QStandardItem(function_name.replace('.', '_'))
            item.setData(function_addr, Qt.UserRole + 2)
            self.functions_list_model.appendRow([item])

        if self.functions_list_model.rowCount() > 0:
            self.functions_list.show()
        else:
            self.functions_list.hide()

    def _function_double_clicked(self, model_index):
        item = self.functions_list_model.itemFromIndex(model_index)
        address = item.data(Qt.UserRole + 2)
        self.disasm_view.read_memory(address)
예제 #6
0
파일: plugin.py 프로젝트: hazedic/r2dwarf
    def _on_ui_element_created(self, elem, widget):
        if elem == 'disassembly':
            self.disassembly_view = widget
            self.disassembly_view.run_default_disassembler = False
            self.disassembly_view.onDisassemble.connect(self._on_disassemble)

            r2_info = QSplitter()
            r2_info.setOrientation(Qt.Vertical)

            call_refs = DwarfListView()
            self.call_refs_model = QStandardItemModel(0, 3)
            self.call_refs_model.setHeaderData(0, Qt.Horizontal, 'call refs')
            self.call_refs_model.setHeaderData(1, Qt.Horizontal, '')
            self.call_refs_model.setHeaderData(2, Qt.Horizontal, '')
            call_refs.setModel(self.call_refs_model)

            code_xrefs = DwarfListView()
            self.code_xrefs_model = QStandardItemModel(0, 3)
            self.code_xrefs_model.setHeaderData(0, Qt.Horizontal, 'code xrefs')
            self.code_xrefs_model.setHeaderData(1, Qt.Horizontal, '')
            self.code_xrefs_model.setHeaderData(2, Qt.Horizontal, '')
            code_xrefs.setModel(self.code_xrefs_model)

            r2_info.addWidget(call_refs)
            r2_info.addWidget(code_xrefs)

            self.disassembly_view.insertWidget(0, r2_info)
            self.disassembly_view.setStretchFactor(0, 1)
            self.disassembly_view.setStretchFactor(1, 5)

            r2_menu = QMenu('r2')
            r2_menu.addAction('graph view', self.show_graph_view)
            r2_menu.addAction('decompile', self.show_decompiler_view)

            self.disassembly_view.disasm_view.menu_extra_menu.append(r2_menu)
예제 #7
0
class DataPanel(QSplitter):
    def __init__(self, app):
        super(DataPanel, self).__init__(app)

        self.app = app
        self.data = {}

        self.setOrientation(Qt.Horizontal)

        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)
예제 #8
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)
예제 #9
0
 def __init__(self, parent=None, file_path=None):
     super().__init__(parent=parent)
     h_box = QHBoxLayout(self)
     self._ident_titles = ['EI_MAG0', 'EI_MAG1', 'EI_MAG2', 'EI_MAG3', 'EI_CLASS', 'EI_DATA', 'EI_VERSION', 'EI_OSABI', 'EI_ABIVERSION', 'EI_PAD']
     self.elf_info = DwarfListView(self)
     self.elf_info.setRootIsDecorated(True)
     self.elf_info.setExpandsOnDoubleClick(True)
     self.elf_info.setContextMenuPolicy(Qt.CustomContextMenu)
     self.elf_info.customContextMenuRequested.connect(self._on_context_menu)
     h_box.addWidget(self.elf_info)
     self._elf_info_mdl = QStandardItemModel(0, 2)
     self._elf_info_mdl.setHeaderData(0, Qt.Horizontal, 'Name')
     self._elf_info_mdl.setHeaderData(1, Qt.Horizontal, 'Value')
     self.elf_info.setModel(self._elf_info_mdl)
     self.elf_info.doubleClicked.connect(self._on_dblclicked)
     self.title = "ELF Info"
     self._elf_file_path = None
     self.setLayout(h_box)
     if file_path:
         self.set_elf_file(file_path)
예제 #10
0
    def __init__(self, app):
        super(DisassemblyPanel, self).__init__()

        self.app = app

        self.functions_list = DwarfListView()
        self.functions_list_model = QStandardItemModel(0, 1)
        self.functions_list_model.setHeaderData(0, Qt.Horizontal, 'functions')
        self.functions_list.setModel(self.functions_list_model)
        self.addWidget(self.functions_list)
        self.functions_list.hide()
        self.functions_list.doubleClicked.connect(self._function_double_clicked)

        self.disasm_view = DisassemblyView(app)
        self.addWidget(self.disasm_view)

        self.setStretchFactor(0, 1)
        self.setStretchFactor(1, 5)

        self.update_functions()
예제 #11
0
    def __init__(self, device, parent=None):
        super(SpawnsList, self).__init__(parent=parent)

        self.break_at_start = False

        self._device = device

        self.spawn_list = DwarfListView()

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

        self.spawn_list.doubleClicked.connect(self._on_item_clicked)

        v_box = QVBoxLayout()
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self.spawn_list)

        break_spawn_start = QCheckBox('Break at spawn')
        break_spawn_start.stateChanged.connect(self._on_toggle_break_spawn)
        v_box.addWidget(break_spawn_start)

        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.spawn_list.setModel(model)
        self.spawn_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)

        self.spaw_update_thread = SpawnsThread(self, self._device)
        self.spaw_update_thread.add_spawn.connect(self._on_add_proc)
        self.spaw_update_thread.is_error.connect(self._on_error)
        self.spaw_update_thread.is_finished.connect(self._on_refresh_finished)
        self.spaw_update_thread.device = self._device
        self.spaw_update_thread.start()
예제 #12
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()
예제 #13
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)
예제 #14
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 = {}

        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)
예제 #15
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)
        btn1 = QPushButton(QIcon(utils.resource_path('assets/icons/plus.svg')),
                           '')
        btn1.setFixedSize(20, 20)
        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(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)
예제 #16
0
class SpawnsList(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(SpawnsList, self).__init__(parent=parent)

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

        self._device = device

        self.spawn_list = DwarfListView()

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

        self.spawn_list.doubleClicked.connect(self._on_item_clicked)

        v_box = QVBoxLayout()
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self.spawn_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.spawn_list.setModel(model)
        self.spawn_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)

        self.spaw_update_thread = SpawnsThread(self, self._device)
        self.spaw_update_thread.add_spawn.connect(self._on_add_proc)
        self.spaw_update_thread.is_error.connect(self._on_error)
        self.spaw_update_thread.is_finished.connect(self._on_refresh_finished)
        self.spaw_update_thread.device = self._device
        self.spaw_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.spawn_list.clear()

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

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

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

        if index != -1:
            sel_pid = self.spawn_list.get_item_text(index, 0)
            if model_index.column() == 0:
                sel_name = model.data(model_index, Qt.UserRole + 2)
            else:
                sel_name = self.spawn_list.get_item_text(index, 1)

            self.onProcessSelected.emit([sel_pid, sel_name])

    def _on_add_proc(self, item):
        model = self.spawn_list.model()
        name = QStandardItem()
        name.setText(item[0])
        name.setData(item[1], Qt.UserRole + 2)
        package = QStandardItem()
        package.setText(item[1])
        model.appendRow([name, package])

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

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

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

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

    def _on_refresh_finished(self):
        self.spawn_list.resizeColumnToContents(0)
        self.refresh_button.setEnabled(True)
예제 #17
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)
예제 #18
0
class SearchPanel(QWidget):
    """ SearchPanel
    """
    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._app_window.dwarf.onSetRanges.connect(self._on_setranges)

        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()
        self._app_window.dwarf.dwarf_api('updateRanges')

    # ************************************************************************
    # **************************** 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_double_clicked)

    def _on_setranges(self, ranges):
        """ Fills Rangelist with Data
        """
        if self._ranges_model.rowCount():
            return

        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_double_clicked(self, model_index):
        item = self._result_model.itemFromIndex(model_index)
        if item:
            self._app_window.jump_to_address(
                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

        status_message = 'searching...'

        if self._blocking_search:
            self.progress = utils.progress_dialog(status_message)
            self.progress.forceShow()

        self._app_window.show_progress(status_message)
        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
                    """
예제 #19
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._app_window.dwarf.onSetRanges.connect(self._on_setranges)

        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()
        self._app_window.dwarf.dwarf_api('updateRanges')
예제 #20
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.onAddJavaOnLoadHook.connect(self._on_add_hook)
        self._app_window.dwarf.onHitNativeOnLoad.connect(
            self._on_hit_native_on_load)
        self._app_window.dwarf.onHitJavaOnLoad.connect(
            self._on_hit_java_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_context_menu)
        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)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def delete_items(self):
        """ Delete selected Items
        """
        index = self._hooks_list.selectionModel().currentIndex().row()
        if index != -1:
            self._on_delete_hook(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()):
            self._on_delete_hook(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_NATIVE:
            type_.setText('N')
            type_.setToolTip('Native hook')
        elif hook.hook_type == HOOK_JAVA:
            type_.setText('J')
            type_.setToolTip('Java hook')
        elif hook.hook_type == 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_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_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[1]['module'], Qt.MatchExactly,
                                            2)
        if len(items) > 0:
            self._hooks_model.item(items[0].row(),
                                   0).setText(data[1]['moduleBase'])

    def _on_hit_java_on_load(self, data):
        items = self._hooks_model.findItems(data[0], Qt.MatchExactly, 2)
        if len(items) > 0:
            pass

    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_context_menu(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('Edit Logic',
                                   lambda: self._on_modify_logic(index))
            context_menu.addAction('Edit Condition',
                                   lambda: self._on_modify_condition(index))
            context_menu.addSeparator()
            context_menu.addAction('Delete Hook',
                                   lambda: self._on_delete_hook(index))

            if self._hooks_list.search_enabled:
                context_menu.addSeparator()
                context_menu.addAction('Search',
                                       self._hooks_list._on_cm_search)

        # show context menu
        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_.replace('\n', '')]):
                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_on_load()

    def _on_add_java_on_load(self):
        self._app_window.dwarf.hook_java_on_load()

    def _on_delete_hook(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' or _type == 'java_on_load':
            _val = _val.split('.')
            str_frmt = '.'.join(_val[:-1])
            additional = _val[-1]
            item_index = 0
        elif _type == 'native_on_load':
            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)
예제 #21
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.onAddJavaOnLoadHook.connect(self._on_add_hook)
        self._app_window.dwarf.onHitNativeOnLoad.connect(
            self._on_hit_native_on_load)
        self._app_window.dwarf.onHitJavaOnLoad.connect(
            self._on_hit_java_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_context_menu)
        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)
예제 #22
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)
        btn1 = QPushButton(QIcon(utils.resource_path('assets/icons/plus.svg')),
                           '')
        btn1.setFixedSize(20, 20)
        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(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.toPlainText()

            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)
        context_menu.addAction('Add watcher', self._on_additem_clicked)
        if index != -1:
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._watchers_model.item(index, 0).text()))
            context_menu.addAction(
                'Jump to address', lambda: self._app_window.jump_to_address(
                    self._watchers_model.item(index, 0).text()))
            context_menu.addAction(
                'Delete watcher', lambda: self.remove_address(
                    self._watchers_model.item(index, 0).text()))
        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)
예제 #23
0
class BookmarksPanel(QWidget):

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

    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 = {}

        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()):
            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):
        index = self._bookmarks_list.selectionModel().currentIndex().row()
        if index != -1:
            addr = self._bookmarks_model.item(index, 0).text()
            if addr:
                self.onShowMemoryRequest.emit(addr)

    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()
            if self._bookmarks_list.search_enabled:
                context_menu.addSeparator()
                context_menu.addAction('Search',
                                       self._bookmarks_list._on_cm_search)
                context_menu.addSeparator()
        context_menu.addAction('New', 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, _ = InputDialog.input_pointer(parent=self._app_window,
                                               input_content=ptr)
        else:
            if not isinstance(ptr, int):
                try:
                    if ptr.startswith('0x'):
                        ptr = int(ptr, 16)
                    else:
                        ptr = int(ptr)
                except ValueError:
                    ptr = 0

        if ptr > 0:
            ptr = hex(ptr)
            if self._bookmarks_list.uppercase_hex:
                ptr = ptr.upper().replace('0X', '0x')

            index = self._bookmarks_model.findItems(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' % ptr,
                                             input_content=note)
            if accept:
                if index < 0:
                    self.insert_bookmark(ptr, note)
                else:
                    item = self._bookmarks_model.item(index, 0)
                    item.setText(ptr)
                    item = self._bookmarks_model.item(index, 1)
                    item.setText(note)

                self.bookmarks[ptr] = note

    def insert_bookmark(self, ptr_as_hex, note):
        if self._bookmarks_list.uppercase_hex:
            ptr_as_hex = ptr_as_hex.upper().replace('0X', '0x')

        self._bookmarks_model.appendRow(
            [QStandardItem(ptr_as_hex),
             QStandardItem(note)])
        self._bookmarks_list.resizeColumnToContents(0)

    # shortcuts/menu
    def _on_delete_bookmark(self, index):
        ptr = self._bookmarks_model.item(index, 0).text()
        del self.bookmarks[ptr]

        self._bookmarks_model.removeRow(index)
예제 #24
0
class QDebugPanel(QMainWindow):
    def __init__(self, app, flags=None):
        super(QDebugPanel, self).__init__(flags)
        self.setDockOptions(QMainWindow.AnimatedDocks | QMainWindow.AllowNestedDocks)

        self.app = app
        self.q_settings = app.q_settings

        self.functions_list = DwarfListView()
        self.functions_list_model = QStandardItemModel(0, 1)
        self.functions_list_model.setHeaderData(0, Qt.Horizontal, '')
        self.functions_list.setModel(self.functions_list_model)
        self.functions_list.setHeaderHidden(True)
        self.functions_list.doubleClicked.connect(self._function_double_clicked)

        self.dock_functions_list = QDockWidget('Functions', self)
        self.dock_functions_list.setObjectName('functions')
        self.dock_functions_list.setWidget(self.functions_list)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_functions_list)
        self.app.debug_view_menu.addAction(self.dock_functions_list.toggleViewAction())

        self.memory_panel_range = None
        self.disassembly_panel_range = None

        screen_size = QtWidgets.QDesktopWidget().screenGeometry(-1)
        m_width = screen_size.width()

        self.memory_panel = HexEditor(self.app)
        self.memory_panel.debug_panel = self
        self.memory_panel.dataChanged.connect(self.on_memory_modified)

        self.disassembly_panel = DisassemblyView(self.app)
        self.disassembly_panel.debug_panel = self

        self.dock_memory_panel = QDockWidget('Memory', self)
        self.dock_memory_panel.setWidget(self.memory_panel)
        self.dock_memory_panel.setObjectName('memory')

        self.dock_disassembly_panel = QDockWidget('Disassembly', self)
        self.dock_disassembly_panel.setWidget(self.disassembly_panel)
        self.dock_disassembly_panel.setObjectName('disassembly')

        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_memory_panel)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_disassembly_panel)
        if m_width >= 1920:
            self.splitDockWidget(self.dock_memory_panel, self.dock_disassembly_panel, Qt.Horizontal)
        else:
            self.tabifyDockWidget(self.dock_memory_panel, self.dock_disassembly_panel)

        self.restoreUiState()

    def restoreUiState(self):
        ui_state = self.q_settings.value('dwarf_debug_ui_state')
        if ui_state:
            self.restoreGeometry(ui_state)
        window_state = self.q_settings.value('dwarf_debug_ui_window')
        if window_state:
            self.restoreState(window_state)

    def closeEvent(self, event):
        self.q_settings.setValue('dwarf_debug_ui_state', self.saveGeometry())
        self.q_settings.setValue('dwarf_debug_ui_window', self.saveState())

    def showEvent(self, event):
        main_width = self.size().width()
        new_widths = []
        new_widths.append(main_width * .1)
        new_widths.append(main_width * .4)
        new_widths.append(main_width * .5)
        self.resizeDocks([
            self.dock_functions_list, self.dock_memory_panel, self.dock_disassembly_panel
        ], new_widths, Qt.Horizontal)
        return super().showEvent(event)

    def update_functions(self, functions_list=None):
        if functions_list is None:
            functions_list = {}
        self.functions_list_model.setRowCount(0)
        for module_info_base in self.app.dwarf.database.modules_info:
            module_info = self.app.dwarf.database.modules_info[module_info_base]
            if len(module_info.functions) > 0:
                self.functions_list.show()
                for function in module_info.functions:
                    functions_list[function.name] = function.address

        for function_name in sorted(functions_list.keys()):
            function_addr = functions_list[function_name]
            item = QStandardItem(function_name.replace('.', '_'))
            item.setData(function_addr, Qt.UserRole + 2)
            self.functions_list_model.appendRow([item])

    def _function_double_clicked(self, model_index):
        item = self.functions_list_model.itemFromIndex(model_index)
        address = item.data(Qt.UserRole + 2)
        self.jump_to_address(address, view=DEBUG_VIEW_DISASSEMBLY)

    def on_context_setup(self):
        self.memory_panel.on_context_setup()

    def on_memory_modified(self, pos, length):
        data_pos = self.memory_panel.base + pos
        data = self.memory_panel.data[pos:pos + length]
        data = [data[0]]  # todo: strange js part

        if self.dwarf.dwarf_api('writeBytes', [data_pos, data]):
            pass
        else:
            utils.show_message_box('Failed to write Memory')

    def raise_memory_panel(self):
        self.dock_memory_panel.raise_()

    def raise_disassembly_panel(self):
        self.dock_disassembly_panel.raise_()

    def jump_to_address(self, address, view=DEBUG_VIEW_MEMORY):
        address = utils.parse_ptr(address)

        if view == DEBUG_VIEW_MEMORY:
            if self.memory_panel_range is not None:
                if self.is_address_in_view(view, address):
                    return

            self.memory_panel_range = \
                Range.build_or_get(self.app.dwarf, address, cb=lambda x: self._apply_range(address, view=view))
        elif view == DEBUG_VIEW_DISASSEMBLY:
            if self.disassembly_panel_range is not None:
                if self.is_address_in_view(view, address):
                    return

            self.disassembly_panel_range = \
                Range.build_or_get(self.app.dwarf, address, cb=lambda x: self._apply_range(address, view=view))

    def _apply_range(self, address, view=DEBUG_VIEW_MEMORY):
        self.update_functions()

        if view == DEBUG_VIEW_MEMORY:
            self.memory_panel.set_data(
                self.memory_panel_range.data, base=self.memory_panel_range.base, focus_address=address)
            if not self.dock_memory_panel.isVisible():
                self.dock_memory_panel.show()
            self.raise_memory_panel()

            if self.disassembly_panel_range is None:
                self.disassembly_panel_range = self.memory_panel_range
                self.disassembly_panel.apply_range(self.disassembly_panel_range)
        elif view == DEBUG_VIEW_DISASSEMBLY:
            self.disassembly_panel.apply_range(self.disassembly_panel_range)
            if not self.dock_disassembly_panel.isVisible():
                self.dock_disassembly_panel.show()
            self.raise_disassembly_panel()

            if self.memory_panel_range is None:
                self.memory_panel_range = self.disassembly_panel_range
                self.memory_panel.set_data(
                    self.memory_panel_range.data, base=self.memory_panel_range.base, focus_address=address)

    def is_address_in_view(self, view, address):
        if view == DEBUG_VIEW_MEMORY:
            if self.memory_panel_range is not None:
                ptr_exists = self.memory_panel.base <= address <= self.memory_panel.base + len(self.memory_panel.data)
                if ptr_exists:
                    self.memory_panel.caret.position = address - self.memory_panel.base
                    return True
        elif view == DEBUG_VIEW_DISASSEMBLY:
            if self.disassembly_panel_range is not None:
                line_index_for_address = self.disassembly_panel.get_line_for_address(address)
                if line_index_for_address >= 0:
                    self.disassembly_panel.verticalScrollBar().setValue(line_index_for_address)
                    return True
        return False

    def on_cm_jump_to_address(self, view=DEBUG_VIEW_MEMORY):
        ptr, _ = InputDialog.input_pointer(self.app)
        if ptr > 0:
            self.jump_to_address(ptr, view=view)

    def dump_data(self, address, _len):
        def _dump(dwarf_range):
            if address + _len > dwarf_range.tail:
                self.display_error('length is higher than range size')
            else:
                data = dwarf_range.data[address:address + _len]
                if data is not None:
                    from PyQt5.QtWidgets import QFileDialog
                    _file = QFileDialog.getSaveFileName(self.app)
                    with open(_file[0], 'wb') as f:
                        f.write(data)
        Range.build_or_get(self.app.dwarf, address, cb=_dump)
예제 #25
0
class ListDialog(DwarfDialog):
    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
예제 #26
0
class JavaExplorerPanel(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self._app_window = parent

        self._handle_history = []

        self._setup_ui()
        self._setup_models()

    def _setup_ui(self):
        self.setContentsMargins(0, 0, 0, 0)

        top_font = QFont()
        top_font.setBold(True)
        top_font.setPixelSize(19)

        # main wrapper
        main_wrapper = QVBoxLayout()
        main_wrapper.setContentsMargins(1, 1, 1, 1)

        # wrapwdgt
        wrap_wdgt = QWidget()
        self._top_class_name = QLabel(wrap_wdgt)
        self._top_class_name.setContentsMargins(10, 10, 10, 10)
        self._top_class_name.setAttribute(Qt.WA_TranslucentBackground,
                                          True)  # keep this
        self._top_class_name.setFont(top_font)
        self._top_class_name.setStyleSheet('color: #ef5350;')
        wrap_wdgt.setMaximumHeight(self._top_class_name.height() + 20)

        main_wrapper.addWidget(wrap_wdgt)

        # left list
        left_wrap_wdgt = QWidget()

        left_v_box = QVBoxLayout(left_wrap_wdgt)
        left_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('METHODS')
        font = methods_label.font()
        font.setBold(True)
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        left_v_box.addWidget(methods_label)

        self._methods_list = DwarfListView()
        left_v_box.addWidget(self._methods_list)

        # center list
        center_wrap_wdgt = QWidget()

        center_v_box = QVBoxLayout(center_wrap_wdgt)
        center_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('NATIVE FIELDS')
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        center_v_box.addWidget(methods_label)

        self._native_fields_list = DwarfListView()
        self._native_fields_list.doubleClicked.connect(
            self._on_native_field_dblclicked)
        center_v_box.addWidget(self._native_fields_list)

        # right list
        right_wrap_wdgt = QWidget()

        right_v_box = QVBoxLayout(right_wrap_wdgt)
        right_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('FIELDS')
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        right_v_box.addWidget(methods_label)

        self._fields_list = DwarfListView()
        self._fields_list.doubleClicked.connect(self._on_field_dblclicked)
        right_v_box.addWidget(self._fields_list)

        # main splitter
        main_splitter = QSplitter(Qt.Horizontal)
        main_splitter.setContentsMargins(0, 0, 0, 0)
        main_splitter.addWidget(left_wrap_wdgt)
        main_splitter.addWidget(center_wrap_wdgt)
        main_splitter.addWidget(right_wrap_wdgt)
        main_splitter.setSizes([250, 100, 100])

        main_wrapper.addWidget(main_splitter)
        main_wrapper.setSpacing(0)
        self.setLayout(main_wrapper)

    def _setup_models(self):
        # left list
        self._methods_model = QStandardItemModel(0, 3)
        self._methods_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self._methods_model.setHeaderData(1, Qt.Horizontal, 'Return')
        self._methods_model.setHeaderData(2, Qt.Horizontal, 'Arguments')
        self._methods_list.setModel(self._methods_model)
        self._methods_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._methods_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        # center list
        self._native_fields_model = QStandardItemModel(0, 2)
        self._native_fields_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self._native_fields_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._native_fields_list.setModel(self._native_fields_model)
        self._native_fields_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        # right list
        self._fields_model = QStandardItemModel(0, 2)
        self._fields_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self._fields_model.setHeaderData(1, Qt.Horizontal, 'Class')
        self._fields_list.setModel(self._fields_model)
        self._fields_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def _set_data(self, data):
        if 'class' not in data:
            return

        self._top_class_name.setText(data['class'])
        data = data['data']

        self._methods_list.clear()
        self._native_fields_list.clear()
        self._fields_list.clear()

        for key in data:
            ref = data[key]
            if ref['type'] == 'function':
                if not key.startswith('$'):
                    self._add_method(key, ref)
            elif ref['type'] == 'object':
                if ref['handle'] is not None:
                    if not key.startswith('$'):
                        self._add_field(key, ref['value'], ref['handle'],
                                        ref['handle_class'])
            else:
                if not key.startswith('$'):
                    self._add_field(key, ref['value'], is_native=True)

        self._methods_list.sortByColumn(0, 0)
        self._native_fields_list.sortByColumn(0, 0)
        self._fields_list.sortByColumn(0, 0)

    def _add_method(self, name, ref):
        ref_overloads = ref['overloads']
        for _, ref_overload in enumerate(ref_overloads):
            args = []

            if 'args' in ref_overload:
                for arg in ref_overload['args']:
                    if 'className' in arg:
                        args.append(arg['className'])

            self._methods_model.appendRow([
                QStandardItem(name),
                QStandardItem(ref_overload['return']['className']),
                QStandardItem('(%s)' % ', '.join(args)),
            ])

    def _add_field(self,
                   name,
                   value,
                   handle=None,
                   handle_class=None,
                   is_native=False):
        if handle:
            handle = {'handle': handle, 'handle_class': handle_class}
            handle_item = QStandardItem(name)
            handle_item.setData(handle, Qt.UserRole + 1)
        else:
            handle_item = QStandardItem(name)

        if not is_native:
            self._fields_model.appendRow(
                [handle_item, QStandardItem(str(value))])
        else:
            self._native_fields_model.appendRow(
                [handle_item, QStandardItem(str(value))])

    def _set_handle(self, handle):
        data = self._app_window.dwarf.dwarf_api('javaExplorer', handle)
        if not data:
            return
        self._handle_history.append({'handle': handle})
        self._set_data(data)

    def _set_handle_arg(self, arg):
        data = self._app_window.dwarf.dwarf_api('javaExplorer', arg)
        if not data:
            return
        self._handle_history.append({'handle': arg})
        self._set_data(data)

    def clear_panel(self):
        self._top_class_name.setText('')
        self._handle_history = []
        self._methods_list.clear()
        self._native_fields_list.clear()
        self._fields_list.clear()

    def _back(self):
        if len(self._handle_history) < 2:
            return
        self._handle_history.pop()
        data = self._handle_history.pop(len(self._handle_history) -
                                        1)['handle']
        if isinstance(data, int):
            self._set_handle_arg(data)
        else:
            self._set_handle(data)

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_field_dblclicked(self, _):
        field_row = self._fields_list.selectionModel().currentIndex().row()
        if field_row >= 0:
            field_handle = self._fields_model.item(field_row,
                                                   0).data(Qt.UserRole + 1)
            if field_handle:
                self._set_handle(field_handle)

    def _on_native_field_dblclicked(self, _):
        field_row = self._native_fields_list.selectionModel().currentIndex(
        ).row()
        if field_row:
            field_handle = self._native_fields_model.item(
                field_row, 0).data(Qt.UserRole + 1)
            if field_handle:
                self._set_handle(field_handle)

    def keyPressEvent(self, event):  # pylint: disable=invalid-name
        if event.key() == Qt.Key_Backspace:
            self._back()

        return super().keyPressEvent(event)
예제 #27
0
    def _setup_ui(self):
        self.setContentsMargins(0, 0, 0, 0)

        top_font = QFont()
        top_font.setBold(True)
        top_font.setPixelSize(19)

        # main wrapper
        main_wrapper = QVBoxLayout()
        main_wrapper.setContentsMargins(1, 1, 1, 1)

        # wrapwdgt
        wrap_wdgt = QWidget()
        self._top_class_name = QLabel(wrap_wdgt)
        self._top_class_name.setContentsMargins(10, 10, 10, 10)
        self._top_class_name.setAttribute(Qt.WA_TranslucentBackground,
                                          True)  # keep this
        self._top_class_name.setFont(top_font)
        self._top_class_name.setStyleSheet('color: #ef5350;')
        wrap_wdgt.setMaximumHeight(self._top_class_name.height() + 20)

        main_wrapper.addWidget(wrap_wdgt)

        # left list
        left_wrap_wdgt = QWidget()

        left_v_box = QVBoxLayout(left_wrap_wdgt)
        left_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('METHODS')
        font = methods_label.font()
        font.setBold(True)
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        left_v_box.addWidget(methods_label)

        self._methods_list = DwarfListView()
        left_v_box.addWidget(self._methods_list)

        # center list
        center_wrap_wdgt = QWidget()

        center_v_box = QVBoxLayout(center_wrap_wdgt)
        center_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('NATIVE FIELDS')
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        center_v_box.addWidget(methods_label)

        self._native_fields_list = DwarfListView()
        self._native_fields_list.doubleClicked.connect(
            self._on_native_field_dblclicked)
        center_v_box.addWidget(self._native_fields_list)

        # right list
        right_wrap_wdgt = QWidget()

        right_v_box = QVBoxLayout(right_wrap_wdgt)
        right_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('FIELDS')
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        right_v_box.addWidget(methods_label)

        self._fields_list = DwarfListView()
        self._fields_list.doubleClicked.connect(self._on_field_dblclicked)
        right_v_box.addWidget(self._fields_list)

        # main splitter
        main_splitter = QSplitter(Qt.Horizontal)
        main_splitter.setContentsMargins(0, 0, 0, 0)
        main_splitter.addWidget(left_wrap_wdgt)
        main_splitter.addWidget(center_wrap_wdgt)
        main_splitter.addWidget(right_wrap_wdgt)
        main_splitter.setSizes([250, 100, 100])

        main_wrapper.addWidget(main_splitter)
        main_wrapper.setSpacing(0)
        self.setLayout(main_wrapper)
예제 #28
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

        self._uc_user_arch = None
        self._uc_user_mode = None
        self._cs_user_arch = None
        self._cs_user_mode = None

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

        self._toolbar_container = QHBoxLayout()
        self._toolbar = QToolBar()
        self._toolbar.addAction('Start', self.handle_start)
        self._toolbar.addAction('Step', self.handle_step)
        self._toolbar.addAction('Step next call', self.handle_step_next_call)
        self._toolbar.addAction('Step next jump', self.handle_step_next_jump)
        self._toolbar.addAction('Stop', self.handle_stop)
        self._toolbar.addAction('Clear', self.handle_clear)
        self._toolbar.addAction('Options', self.handle_options)
        self._toolbar_container.addWidget(self._toolbar)

        selection_layout = QHBoxLayout()
        selection_layout.setAlignment(Qt.AlignRight)
        self.cpu_selection = QComboBox(self)
        for v in unicorn_const.__dict__:
            if 'UC_ARCH_' in v:
                self.cpu_selection.addItem('_'.join(v.split('_')[2:]).lower(),
                                           unicorn_const.__dict__[v])
        self.cpu_selection.activated[str].connect(self._on_cpu_selection)
        self.mode_selection = QComboBox(self)
        for v in unicorn_const.__dict__:
            if 'UC_MODE_' in v:
                self.mode_selection.addItem('_'.join(v.split('_')[2:]).lower(),
                                            unicorn_const.__dict__[v])
        self.mode_selection.activated[str].connect(self._on_mode_selection)
        selection_layout.addWidget(self.cpu_selection)
        selection_layout.addWidget(self.mode_selection)
        self._toolbar_container.addLayout(selection_layout)

        layout.addLayout(self._toolbar_container)

        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)

        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_model.setHeaderData(1, Qt.Horizontal, Qt.AlignLeft,
                                         Qt.TextAlignmentRole)
        self.ranges_list.setModel(self._ranges_model)
        self.tabs.addTab(self.ranges_list, 'Ranges')

        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)
        self.tabs.addTab(self._access_list, 'Access')

        layout.setSpacing(0)
        self.setLayout(layout)

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

        self.emulator.onEmulatorSetup.connect(self.on_emulator_setup)
        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 _on_cpu_selection(self, cpu):
        self._uc_user_arch = unicorn_const.__dict__['UC_ARCH_' + cpu.upper()]
        self._cs_user_arch = capstone.__dict__['CS_ARCH_' + cpu.upper()]
        self._uc_user_mode = unicorn_const.__dict__[
            'UC_MODE_' + self.mode_selection.itemText(
                self.mode_selection.currentIndex()).upper()]
        self._cs_user_mode = capstone.__dict__[
            'CS_MODE_' + self.mode_selection.itemText(
                self.mode_selection.currentIndex()).upper()]

    def _on_mode_selection(self, mode):
        self._uc_user_mode = unicorn_const.__dict__['UC_MODE_' + mode.upper()]
        self._cs_user_mode = capstone.__dict__['CS_MODE_' + mode.upper()]
        self._uc_user_arch = unicorn_const.__dict__[
            'UC_ARCH_' + self.cpu_selection.itemText(
                self.cpu_selection.currentIndex()).upper()]
        self._cs_user_arch = capstone.__dict__[
            'CS_ARCH_' + self.cpu_selection.itemText(
                self.cpu_selection.currentIndex()).upper()]

    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_clear(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.app.console_panel.show_console_tab('emulator')
            self.emulator.emulate(self.until_address,
                                  user_arch=self._uc_user_arch,
                                  user_mode=self._uc_user_mode,
                                  cs_arch=self._cs_user_arch,
                                  cs_mode=self._cs_user_mode)
            # if err > 0:
            #    self.until_address = 0
            #    self.console.log('cannot start emulator. err: %d' % err)
            #    return

    def handle_step(self):
        self.app.console_panel.show_console_tab('emulator')

        try:
            self.emulator.emulate(step_mode=STEP_MODE_SINGLE,
                                  user_arch=self._uc_user_arch,
                                  user_mode=self._uc_user_mode,
                                  cs_arch=self._cs_user_arch,
                                  cs_mode=self._cs_user_mode)
        except self.emulator.EmulatorAlreadyRunningError:
            self.console.log('Emulator already running')
        except self.emulator.EmulatorSetupFailedError as error:
            self.until_address = 0
            self.console.log(error)

    def handle_step_next_call(self):
        self.app.console_panel.show_console_tab('emulator')

        try:
            self.emulator.emulate(step_mode=STEP_MODE_FUNCTION,
                                  user_arch=self._uc_user_arch,
                                  user_mode=self._uc_user_mode,
                                  cs_arch=self._cs_user_arch,
                                  cs_mode=self._cs_user_mode)
        except self.emulator.EmulatorAlreadyRunningError:
            self.console.log('Emulator already running')
        except self.emulator.EmulatorSetupFailedError as error:
            self.until_address = 0
            self.console.log(error)

    def handle_step_next_jump(self):
        self.app.console_panel.show_console_tab('emulator')

        try:
            self.emulator.emulate(step_mode=STEP_MODE_JUMP,
                                  user_arch=self._uc_user_arch,
                                  user_mode=self._uc_user_mode,
                                  cs_arch=self._cs_user_arch,
                                  cs_mode=self._cs_user_mode)
        except self.emulator.EmulatorAlreadyRunningError:
            self.console.log('Emulator already running')
        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):
        # @PinkiePonkie why setting context here (which is triggered each instruction) and later, set it again
        # in emulator_stop? step = double hit in set_context, running emulation on more than 1 instruction
        # doesn't need spam of set_context
        # 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
            if len(self._require_register_result) == 1:
                res = 'jump = %s' % (hex(self._require_register_result[0]))
            else:
                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

                telescope = self.get_telescope(
                    self.emulator.uc.reg_read(
                        self._require_register_result[0]))
                if telescope is not None and telescope != 'None':
                    res += ' (' + telescope + ')'

                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 or instruction.is_call:
            self.assembly.add_instruction(None)
            self._require_register_result = [instruction.jump_address]
        else:
            # 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()

        if instruction.is_call:
            range_ = Range(Range.SOURCE_TARGET, self.app.dwarf)
            if range_.init_with_address(instruction.address,
                                        require_data=False) > 0:
                if range_.base > instruction.call_address > range_.tail:
                    if self.emulator.step_mode == STEP_MODE_NONE:
                        self.emulator.stop()
                    action = JumpOutsideTheBoxDialog.show_dialog(
                        self.app.dwarf)
                    if action == 0:
                        # step to jump
                        if self.emulator.step_mode != STEP_MODE_NONE:
                            self.handle_step()
                        else:
                            self.emulator.emulate(self.until_address,
                                                  user_arch=self._uc_user_arch,
                                                  user_mode=self._uc_user_mode,
                                                  cs_arch=self._cs_user_arch,
                                                  cs_mode=self._cs_user_mode)
                    if action == 1:
                        # step to next jump
                        if self.emulator.step_mode != STEP_MODE_NONE:
                            self.handle_step_next_jump()
                        else:
                            self.emulator.emulate(self.until_address,
                                                  user_arch=self._uc_user_arch,
                                                  user_mode=self._uc_user_mode,
                                                  cs_arch=self._cs_user_arch,
                                                  cs_mode=self._cs_user_mode)
                    elif action == 2:
                        # hook lr
                        hook_addr = instruction.address + instruction.size
                        if instruction.thumb:
                            hook_addr += 1
                        self.app.dwarf.hook_native(input_=hex(hook_addr))

    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()
        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:
                    if len(self._require_register_result) > 1:
                        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:
                telescope = self.get_telescope(value)
                if telescope is not None and telescope != 'None':
                    res += ' (' + telescope + ')'
                # invalidate
                self._require_register_result = None
                self.assembly._lines[len(self.assembly._lines) -
                                     row].string = res

    def get_telescope(self, address):
        try:
            size = self.app.dwarf.pointer_size
            telescope = self.emulator.uc.mem_read(address, size)
            try:
                for i in range(len(telescope)):
                    if int(telescope[i]) == 0x0 and i != 0:
                        st = telescope.decode('utf8')
                        return st
                st = telescope.decode('utf8')
                if len(st) != size:
                    return '0x%s' % telescope.hex()
                while True:
                    telescope = self.emulator.uc.mem_read(address + size, 1)
                    if int(telescope) == 0x0:
                        break
                    st += telescope.decode('utf8')
                    size += 1
                return st
            except:
                return '0x%s' % telescope.hex()
        except UcError as e:
            # read from js
            telescope = self.app.dwarf.dwarf_api('getAddressTs', address)
            if telescope is None:
                return None
            telescope = str(telescope[1]).replace('\n', ' ')
            if len(telescope) > 50:
                telescope = telescope[:50] + '...'
            return telescope

    def on_emulator_memory_range_mapped(self, data):
        address, size = data
        _address = QStandardItem()
        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_setup(self, data):
        user_arch = data[0]
        user_mode = data[1]
        if user_arch is not None and user_mode is not None:
            index = self.cpu_selection.findData(user_arch)
            self.cpu_selection.setCurrentIndex(index)
            index = self.mode_selection.findData(user_mode)
            self.mode_selection.setCurrentIndex(index)

    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
            if len(self._require_register_result) == 1:
                res = 'jump = %s' % (hex(self._require_register_result[0]))
            else:
                res = '%s = %s' % (self._require_register_result[1],
                                   hex(
                                       self.emulator.uc.reg_read(
                                           self._require_register_result[0])))
                telescope = self.get_telescope(
                    self.emulator.uc.reg_read(
                        self._require_register_result[0]))
                if telescope is not None and telescope != 'None':
                    res += ' (' + telescope + ')'

            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)
예제 #29
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
        sorted_regs = self.get_sort_order()

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

            value_x = QStandardItem()
            if context[register]['isValidPointer']:
                value_x.setForeground(Qt.red)
            # 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) > 50:
                            telescope_value = telescope_value[:50] + '...'

                        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__

        sorted_regs = self.get_sort_order()

        for register in sorted(context,
                               key=lambda x: sorted_regs[x]
                               if x in sorted_regs else len(sorted_regs)):
            if register.startswith('_') or register not in sorted_regs:
                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)

    def get_sort_order(self):
        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', 'cspr'
            ]
        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', 'cspr'
            ]
        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)}
        return sorted_regs

    # ************************************************************************
    # **************************** 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 value', 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("")
예제 #30
0
    def __init__(self, app, *__args):
        super().__init__(*__args)

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

        self._uc_user_arch = None
        self._uc_user_mode = None
        self._cs_user_arch = None
        self._cs_user_mode = None

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

        self._toolbar_container = QHBoxLayout()
        self._toolbar = QToolBar()
        self._toolbar.addAction('Start', self.handle_start)
        self._toolbar.addAction('Step', self.handle_step)
        self._toolbar.addAction('Step next call', self.handle_step_next_call)
        self._toolbar.addAction('Step next jump', self.handle_step_next_jump)
        self._toolbar.addAction('Stop', self.handle_stop)
        self._toolbar.addAction('Clear', self.handle_clear)
        self._toolbar.addAction('Options', self.handle_options)
        self._toolbar_container.addWidget(self._toolbar)

        selection_layout = QHBoxLayout()
        selection_layout.setAlignment(Qt.AlignRight)
        self.cpu_selection = QComboBox(self)
        for v in unicorn_const.__dict__:
            if 'UC_ARCH_' in v:
                self.cpu_selection.addItem('_'.join(v.split('_')[2:]).lower(),
                                           unicorn_const.__dict__[v])
        self.cpu_selection.activated[str].connect(self._on_cpu_selection)
        self.mode_selection = QComboBox(self)
        for v in unicorn_const.__dict__:
            if 'UC_MODE_' in v:
                self.mode_selection.addItem('_'.join(v.split('_')[2:]).lower(),
                                            unicorn_const.__dict__[v])
        self.mode_selection.activated[str].connect(self._on_mode_selection)
        selection_layout.addWidget(self.cpu_selection)
        selection_layout.addWidget(self.mode_selection)
        self._toolbar_container.addLayout(selection_layout)

        layout.addLayout(self._toolbar_container)

        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)

        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_model.setHeaderData(1, Qt.Horizontal, Qt.AlignLeft,
                                         Qt.TextAlignmentRole)
        self.ranges_list.setModel(self._ranges_model)
        self.tabs.addTab(self.ranges_list, 'Ranges')

        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)
        self.tabs.addTab(self._access_list, 'Access')

        layout.setSpacing(0)
        self.setLayout(layout)

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

        self.emulator.onEmulatorSetup.connect(self.on_emulator_setup)
        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