Example #1
0
    def _markImmCompares(self):
        """
        Marks the immediate compares within the current function
        """
        self.output_window.append("Marking all immediate compares...")
        self.table_label.setText("Immediate compares within current function")

        INS_COLOR = 0x2020c0

        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Address", "Disassembly"))
        self.table.clearContents()
        self.table.setRowCount(0)

        idx = 0
        for cmp_ea, dis in self.ba.find_imm_compares():

            self.table.insertRow(idx)

            addr_item = QTableWidgetItem("%x" % cmp_ea)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            dis_item = cw.NumQTableWidgetItem("%s" % dis)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, dis_item)

            misc.set_ins_color(cmp_ea, INS_COLOR)
            idx += 1
Example #2
0
    def _markImmCompares(self):
        """
        Marks the immediate compares within the current function
        """
        self.output_window.append("Marking all immediate compares...")
        self.table_label.setText("Immediate compares within current function")

        INS_COLOR = 0x2020c0

        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Address", "Disassembly"))
        self.table.clearContents()
        self.table.setRowCount(0)

        idx = 0
        for cmp_ea, dis in self.ba.find_imm_compares():

            self.table.insertRow(idx)

            addr_item = QTableWidgetItem("%x" % cmp_ea)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            dis_item =  cw.NumQTableWidgetItem("%s" % dis)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, dis_item)

            misc.set_ins_color(cmp_ea, INS_COLOR)
            idx += 1
Example #3
0
    def _bbTableDoubleClicked(self, row, col):
        """
        This overrides the callback for table's double click
        set in the CustomWidget object.
        Apparently if there is an exception it falls back to
        the original callback... Not sure why this behaviour.
        NOTE: This is kind of nasty.
        :return: None
        """
        it = self.table.item(row, col).text()

        try:
            idx = int(it)   # decimal
            bb_path = self.ba.cache.bb_paths[idx]

            col = QtGui.QColorDialog.getColor()
            if col.isValid():
                # IDA works with BGR (annoying)
                ida_color = misc.pyside_to_ida_color(col.name())
                misc.paint_basic_blocks(bb_path, ida_color)

            else:
                print '[x] Invalid QColor'

            return

        except IndexError:
            # Address value (does not contain [A-F]) is interpreted as index
            return

        except ValueError:
            # Address value (containing [A-F]) f***s up int()
            return
Example #4
0
    def import_data(self, bb_color = 0x581414):
        """
        Pretty straightforward, isn't it? ;)
        @return: dictionary d[tid] = [bb_ea, ...]
        """
        filename = AskFile(1, "*.*", "File to import addresses from?")

        # Rebase
        image_base = self.get_image_base(filename)
        ida_base = get_imagebase()  # idaapi
        delta = image_base - ida_base

        if delta:
            # IDA would go ahead with the rebasing process
            # even if the delta is zero. This avoids it.
            rebase_program(delta, MSF_FIXONCE)

        # Parse basic blocks from file
        trace_dict = self.file_parser(filename)

        for addr_list in trace_dict.values():
            for _, v_ea in addr_list:
                misc.paint_basic_blocks(v_ea, bb_color)

        return trace_dict
Example #5
0
    def import_data(self, bb_color=0x581414):
        """
        Pretty straightforward, isn't it? ;)
        @return: dictionary d[tid] = [bb_ea, ...]
        """
        filename = AskFile(1, "*.*", "File to import addresses from?")

        # Rebase
        image_base = self.get_image_base(filename)
        ida_base = get_imagebase()  # idaapi
        delta = image_base - ida_base

        if delta:
            # IDA would go ahead with the rebasing process
            # even if the delta is zero. This avoids it.
            rebase_program(delta, MSF_FIXONCE)

        # Parse basic blocks from file
        trace_dict = self.file_parser(filename)

        for addr_list in trace_dict.values():
            for _, v_ea in addr_list:
                misc.paint_basic_blocks(v_ea, bb_color)

        return trace_dict
Example #6
0
    def _bbTableDoubleClicked(self, row, col):
        """
        This overrides the callback for table's double click
        set in the CustomWidget object.
        Apparently if there is an exception it falls back to
        the original callback... Not sure why this behaviour.
        NOTE: This is kind of nasty.
        :return: None
        """
        it = self.table.item(row, col).text()

        try:
            idx = int(it)   # decimal
            bb_path = self.ba.cache.bb_paths[idx]

            col = QtGui.QColorDialog.getColor()
            if col.isValid():
                # IDA works with BGR (annoying)
                ida_color = misc.pyside_to_ida_color(col.name())
                misc.paint_basic_blocks(bb_path, ida_color)

            else:
                print '[x] Invalid QColor'

            return

        except IndexError:
            # Address value (does not contain [A-F]) is interpreted as index
            return

        except ValueError:
            # Address value (containing [A-F]) f***s up int()
            return
Example #7
0
    def _showImportTrace(self, restrict=True):
        """
        This is the GUI part of the PIN trace import functionality
        """
        self._console_output("Importing PIN trace information from file...")

        # Color for the basic blocks hit during the trace
        col = QtGui.QColorDialog.getColor()
        if col.isValid():
            # IDA works with BGR (annoying)
            ida_color = misc.pyside_to_ida_color(col.name())

        else:
            # Probably closed the QColorDialog
            self._console_output(
                "[!] Problem getting color for trace. Aborting.")
            return

        try:
            imported_info_dict = self.ie.ti.import_data(ida_color)

        except:
            self._console_output("[!] Problem importing from file", err=True)
            self._console_output(traceback.format_exc(), err=True)
            return

        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(
            ('Thread ID', 'From', 'To', 'From (name)', 'To (name)'))
        self.table_label.setText("Imported information from PIN trace")
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        # TODO: This could be better in a QTree or maybe adding
        # a dropdown to select the thread id...
        idx = 0
        for tid, call_list in imported_info_dict.iteritems():
            self._console_output("Processing Thread ID %d" % tid)

            for u_ea, v_ea in call_list:

                self.table.insertRow(idx)
                tid_item = QTableWidgetItem("%d" % tid)
                u_item = QTableWidgetItem("%x" % u_ea)
                u_item.setFlags(u_item.flags() ^ QtCore.Qt.ItemIsEditable)
                v_item = QTableWidgetItem("%x" % v_ea)
                v_item.setFlags(v_item.flags() ^ QtCore.Qt.ItemIsEditable)
                from_item = QTableWidgetItem(misc.get_function_name(u_ea))
                to_item = QTableWidgetItem(misc.get_function_name(v_ea))

                self.table.setItem(idx, 0, tid_item)
                self.table.setItem(idx, 1, u_item)
                self.table.setItem(idx, 2, v_item)
                self.table.setItem(idx, 3, from_item)
                self.table.setItem(idx, 4, to_item)

                idx += 1
    def _showImportTrace(self):
        """
        This is the GUI part of the PIN trace import functionality
        """
        self._console_output("Importing PIN trace information from file...")

        # Color for the basic blocks hit during the trace
        col = QtGui.QColorDialog.getColor()
        if col.isValid():
            # IDA works with BGR (annoying)
            ida_color = misc.pyside_to_ida_color(col.name())

        else:
            # Probably closed the QColorDialog
            self._console_output("[!] Problem getting color for trace. Aborting.")
            return

        try:
            imported_info_dict = self.ie.ti.import_data(ida_color)

        except:
            self._console_output("[!] Problem importing from file", err = True)
            self._console_output(traceback.format_exc(), err = True)
            return

        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(
            ('Thread ID', 'From', 'To', 'From (name)', 'To (name)'))
        self.table_label.setText("Imported information from PIN trace")
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        # TODO: This could be better in a QTree or maybe adding
        # a dropdown to select the thread id...
        idx = 0
        for tid, call_list in imported_info_dict.iteritems():
            self._console_output("Processing Thread ID %d" % tid)

            for u_ea, v_ea in call_list:

                self.table.insertRow(idx)
                tid_item = QTableWidgetItem("%d" % tid)
                u_item = QTableWidgetItem("%x" % u_ea)
                u_item.setFlags(u_item.flags() ^ QtCore.Qt.ItemIsEditable)
                v_item = QTableWidgetItem("%x" % v_ea)
                v_item.setFlags(v_item.flags() ^ QtCore.Qt.ItemIsEditable)
                from_item = QTableWidgetItem(misc.get_function_name(u_ea))
                to_item = QTableWidgetItem(misc.get_function_name(v_ea))

                self.table.setItem(idx, 0, tid_item)
                self.table.setItem(idx, 1, u_item)
                self.table.setItem(idx, 2, v_item)
                self.table.setItem(idx, 3, from_item)
                self.table.setItem(idx, 4, to_item)

                idx += 1
Example #9
0
    def calls_in_function(self, unique = True):
        """
        Find calls within current function
        Execution transfer like jmp sub_xxx included
        @return: a list of tuples [(addr, dis)]
        """

        callees = []

        for addr, dis in misc.iter_disasm():
            if is_call_insn(addr) or misc.is_external_jmp(addr):
                if dis not in callees:
                    callees.append((addr, dis))

        return callees
    def _showStringXrefs(self):
        """
        Displays string references in a table
        Optionally Shannon's misc.entropy as well
        """

        # Retrieve some config values
        show_misc_entropy = self.config.calculate_entropy
        show_unique_s = self.config.display_unique_strings

        self._console_output("Calculating string references...")

        self.ba.calculate_strings_list()
        s_ref_list = self.ba.get_string_references()

        # Found any references at all?
        nrows = len(s_ref_list)
        if not nrows:
            self._console_output("[!] No string references found", err=True)
            return

        if show_misc_entropy:
            self.table.setColumnCount(3)
            self.table.setHorizontalHeaderLabels(
                ("Address", "String", "Entropy"))

        else:
            self.table.setColumnCount(2)
            self.table.setHorizontalHeaderLabels(("Address", "String"))

        self.table_label.setText("String references in current function")
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill the table
        displayed_strings = []

        idx = 0
        for (addr, s) in s_ref_list:
            if show_unique_s and s in displayed_strings:
                continue

            displayed_strings.append(s)

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%08x" % addr)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            string_item = QTableWidgetItem(s.decode('utf-8'))
            string_item.setFlags(string_item.flags()
                                 ^ QtCore.Qt.ItemIsEditable)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, string_item)

            if show_misc_entropy:
                misc_entropy_item = cw.NumQTableWidgetItem("%.4f" %
                                                           misc.entropy(s))
                self.table.setItem(idx, 2, misc_entropy_item)

            idx += 1
Example #11
0
    def _showConnectedIO(self):
        """
        Shows a list of functions dealing with IO and
        connected to the current function
        """
        self._console_output("Calculating file & network IO...")
        io_list = self.ba.input_to_function()

        if not io_list:
            self._console_output("[!] No (obvious) IO connecting \
                to this function", err = True)
            return

        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Caller", "Name"))

        self.table_label.setText("Connected IO")
        self.table.clearContents()
        self.table.setRowCount(0)

        for idx, caller in enumerate(io_list):
            self.table.insertRow(idx)

            addr_item = QTableWidgetItem("%08x" % caller)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            name_item = QTableWidgetItem("%s" % misc.get_function_name(caller))

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, name_item)
Example #12
0
    def _showConnectedIO(self):
        """
        Shows a list of functions dealing with IO and
        connected to the current function
        """
        self._console_output("Calculating file & network IO...")
        io_list = self.ba.input_to_function()

        if not io_list:
            self._console_output("[!] No (obvious) IO connecting to this function", err = True)
            return

        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Caller", "Name"))

        self.table_label.setText("Connected IO")
        self.table.clearContents()
        self.table.setRowCount(0)

        for idx, caller in enumerate(io_list):
            self.table.insertRow(idx)

            addr_item = QTableWidgetItem("%08x" % caller)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            name_item = QTableWidgetItem("%s" % misc.get_function_name(caller))

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, name_item)
Example #13
0
    def _showBannedFunctions(self):
        """
        Points to functions banned by Microsoft being used.
        """
        self._console_output("Looking for banned functions...")

        deep_search_f = self.config.deep_dangerous_functions

        if deep_search_f:
            self._console_output("Performing a deep search (based on function name)")

        banned_refs_dict = self.vd.find_banned_functions(deep_search_f)

        if not banned_refs_dict:
            self._console_output("[!] No banned functions found", err = True)
            return

        self.tree_label.setText("Functions banned by Microsoft")
        self.tree.clear()
        self.tree.setHeaderLabels(("Banned function", "References", "Name"))

        for f_name, refs in banned_refs_dict.iteritems():
            bf_item = QTreeWidgetItem(self.tree)
            bf_item.setText(0, f_name)

            for ref_addr in refs:
                ref_item = QTreeWidgetItem(bf_item)
                ref_item.setText(1, "%x" %ref_addr)
                ref_name = misc.get_function_name(ref_addr)
                ref_item.setText(2, ref_name)

        # Display all items expanded initially
        self.tree.expandAll()
Example #14
0
    def get_dangerous_functions(self):
        """
        Gets a list of functions calling
        dangerous ones
        @returns: a *set* of func_addr's
        """
        # TODO: use a centralized list for the dangerous functions?
        # TODO: this whole process must be O(mfg).
        bad_funcs = set([])

        dangerous_funcs = ["wcsncpy", "strcpy", "_strcpy", "_strcpy_0",
                           "strncpy", "_strncpy", "_strncpy_0",
                           "memmove", "memcpy", "_memcpy", "_memcpy_0"]

        # Loop from start to end within the current segment
        for func_name in dangerous_funcs:
            func_addr = LocByName(func_name)

            if func_addr == BADADDR:
                continue

            # find all code references to the function
            for ref in CodeRefsTo(func_addr, True):
                func_addr = misc.function_boundaries(ref)[0]
                bad_funcs.add(func_addr)

        return bad_funcs
    def _showBannedFunctions(self):
        """
        Points to functions banned by Microsoft being used.
        """
        self._console_output("Looking for banned functions...")

        deep_search_f = self.config.deep_dangerous_functions

        if deep_search_f:
            self._console_output("Performing a deep search \
                (based on function name)")

        banned_refs_dict = self.vd.find_banned_functions(deep_search_f)

        if not banned_refs_dict:
            self._console_output("[!] No banned functions found", err = True)
            return

        self.tree_label.setText("Functions banned by Microsoft")
        self.tree.clear()
        self.tree.setHeaderLabels(("Banned function", "References", "Name"))

        for f_name, refs in banned_refs_dict.iteritems():
            bf_item = QTreeWidgetItem(self.tree)
            bf_item.setText(0, f_name)

            for ref_addr in refs:
                ref_item = QTreeWidgetItem(bf_item)
                ref_item.setText(1, "%x" % ref_addr)
                ref_name = misc.get_function_name(ref_addr)
                ref_item.setText(2, ref_name)

        # Display all items expanded initially
        self.tree.expandAll()
    def _showStringXrefs(self):
        """
        Displays string references in a table
        Optionally Shannon's misc.entropy as well
        """

        # Retrieve some config values
        show_misc_entropy = self.config.calculate_entropy
        show_unique_s = self.config.display_unique_strings

        self._console_output("Calculating string references...")

        self.ba.calculate_strings_list()
        s_ref_list = self.ba.get_string_references()

        # Found any references at all?
        nr_rows = len(s_ref_list)
        if not nr_rows:
            self._console_output("[!] No string references found", err = True)
            return

        if show_misc_entropy:
            self.table.setColumnCount(3)
            self.table.setHorizontalHeaderLabels(
                ("Address", "String", "Entropy"))

        else:
            self.table.setColumnCount(2)
            self.table.setHorizontalHeaderLabels(("Address", "String"))

        self.table_label.setText("String references in current function")
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill the table
        displayed_strings = []

        idx = 0
        for (addr, s) in s_ref_list:
            if show_unique_s and s in displayed_strings:
                continue

            displayed_strings.append(s)

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%08x" % addr)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            string_item = QTableWidgetItem(s.decode('utf-8'))
            string_item.setFlags(string_item.flags() ^ QtCore.Qt.ItemIsEditable)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, string_item)

            if show_misc_entropy:
                misc_entropy_item = cw.NumQTableWidgetItem("%.4f" % misc.entropy(s))
                self.table.setItem(idx, 2, misc_entropy_item)

            idx += 1
Example #17
0
    def __init__(self):

        print "= Loading vulnerability detection module..."

        # Since this is pretty demanded information
        # let's calculate it here
        self.im = misc.importManager()
        self.ii = IntegerIssues()
        self.cache = VulnDetectionCache()
Example #18
0
    def __init__(self):

        print "= Loading vulnerability detection module..."

        # Since this is pretty demanded information
        # let's calculate it here
        self.im = misc.importManager()
        self.ii = IntegerIssues()
        self.cache = VulnDetectionCache()
Example #19
0
    def _showDangerousConnections(self):
        """
        Shows connections graphs between functions calling IO
        and the ones calling dangerous APIs
        """
        self._console_output("Calculating dangerous connections...")
        try:
            conn_graphs = self.ba.get_all_dangerous_connections()
        except Exception as e:
            print "[!] Error in get_all_dangerous_connections()", e
            return

        if not conn_graphs:
            self._console_output("[!] No (obvious) dangerous connections",
                                 err=True)
            return

        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(
            ("IO Caller", "Dangerous Functions", "Shortest Path Length", "u",
             "v"))

        self.table_label.setText("Dangerous Connections")
        self.table.clearContents()
        self.table.setRowCount(0)

        for idx, c in enumerate(conn_graphs):
            self.table.insertRow(idx)

            u, v, sp_len = c  # tuple unpacking
            io_item = QTableWidgetItem("%s" % misc.get_function_name(u))
            df_item = QTableWidgetItem("%s" % misc.get_function_name(v))
            sp_item = QTableWidgetItem("%d" % sp_len)
            ioa_item = QTableWidgetItem("%x" % u)
            ioa_item.setFlags(ioa_item.flags() ^ QtCore.Qt.ItemIsEditable)
            dfa_item = QTableWidgetItem("%x" % v)
            dfa_item.setFlags(dfa_item.flags() ^ QtCore.Qt.ItemIsEditable)

            self.table.setItem(idx, 0, io_item)
            self.table.setItem(idx, 1, df_item)
            self.table.setItem(idx, 2, sp_item)
            self.table.setItem(idx, 3, ioa_item)
            self.table.setItem(idx, 4, dfa_item)
Example #20
0
    def __init__(self):
        """
        A bunch of more or less useful binary analysis
        routines. Not necessarily related to security stuff.
        """
        self.name = "BinaryAnalysis"
        self.im = misc.importManager()
        self.cache = BinaryAnalysisCache()
        self.config = JConfig()

        print "= Loading binary analysis module..."
    def _showDangerousConnections(self):
        """
        Shows connections graphs between functions calling IO
        and the ones calling dangerous APIs
        """
        self._console_output("Calculating dangerous connections...")
        try:
            conn_graphs = self.ba.get_all_dangerous_connections()
        except Exception as e:
            print "[!] Error in get_all_dangerous_connections()", e
            return

        if not conn_graphs:
            self._console_output("[!] No (obvious) dangerous connections", err = True)
            return

        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(
            ("IO Caller", "Dangerous Functions", "Shortest Path Length", "u", "v"))

        self.table_label.setText("Dangerous Connections")
        self.table.clearContents()
        self.table.setRowCount(0)

        for idx, c in enumerate(conn_graphs):
            self.table.insertRow(idx)

            u, v, sp_len = c    # tuple unpacking
            io_item = QTableWidgetItem("%s" % misc.get_function_name(u))
            df_item = QTableWidgetItem("%s" % misc.get_function_name(v))
            sp_item = QTableWidgetItem("%d" % sp_len)
            ioa_item = QTableWidgetItem("%x" % u)
            ioa_item.setFlags(ioa_item.flags() ^ QtCore.Qt.ItemIsEditable)
            dfa_item = QTableWidgetItem("%x" % v)
            dfa_item.setFlags(dfa_item.flags() ^ QtCore.Qt.ItemIsEditable)

            self.table.setItem(idx, 0, io_item)
            self.table.setItem(idx, 1, df_item)
            self.table.setItem(idx, 2, sp_item)
            self.table.setItem(idx, 3, ioa_item)
            self.table.setItem(idx, 4, dfa_item)
Example #22
0
    def find_imm_compares(self):
        """
        Find all immediate compares in the current function.
        Very useful when debugging parsers, for example.
        @return: list of tuples [(address, disassembly),...]
        """
        cmp_addr = []

        for addr, dis in misc.iter_disasm():
            if "cmp" in dis:
                if GetOpType(addr, 1) == o_imm: # 5: immediate value
                    cmp_addr.append((addr, dis))

        return cmp_addr
Example #23
0
    def comments_in_function(self):
        """
        Searches the current function for IDA generated annotations
        Useful when dealing with large functions doing lots of logging
        @return: a list of tuples [(addr, comment)]
        """
        comments = []

        for addr, dis in misc.iter_disasm():
            comm = Comment(addr)
            # Comment returns None if no comment
            if comm:
                comments.append((addr, comm))

        return comments
Example #24
0
    def _showAllFunctions(self):
        """
        Populates the functions list.
        From this it is possible to select endpoints to
        create a ConnectGraph for example
        """
        self._console_output("Displaying all known functions...")

        current_ea, _ = misc.function_boundaries()

        func_list = self.ba.get_all_functions()
        if not func_list:
            return

        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Address", "Name"))

        self.table_label.setText("Functions in current binary")
        self.table.clearContents()
        self.table.setRowCount(0)

        # Current table index
        c_idx = 0

        for idx, (f_ea, f_name) in enumerate(func_list):
            self.table.insertRow(idx)

            addr_item = QTableWidgetItem("%08x" % f_ea)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            name_item = QTableWidgetItem("%s" % f_name)

            if f_ea == current_ea:
                # current_ea_item = addr_item
                c_idx = idx

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, name_item)

        # Conveniently scroll to the current EA
        self.table.scrollToItem(
            # current_ea_item,
            self.table.item(c_idx, 0),
            QtGui.QAbstractItemView.PositionAtTop
            )
Example #25
0
    def _showAllFunctions(self):
        """
        Populates the functions list.
        From this it is possible to select endpoints to
        create a ConnectGraph for example
        """
        self._console_output("Displaying all known functions...")

        current_ea, _ = misc.function_boundaries()

        func_list = self.ba.get_all_functions()
        if not func_list:
            return

        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Address", "Name"))

        self.table_label.setText("Functions in current binary")
        self.table.clearContents()
        self.table.setRowCount(0)

        # Current table index
        c_idx = 0

        for idx, (f_ea, f_name) in enumerate(func_list):
            self.table.insertRow(idx)

            addr_item = QTableWidgetItem("%08x" % f_ea)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            name_item = QTableWidgetItem("%s" % f_name)

            if f_ea == current_ea:
                current_ea_item = addr_item
                c_idx = idx

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, name_item)

        # Conveniently scroll to the current EA
        self.table.scrollToItem(
            #current_ea_item,
            self.table.item(c_idx, 0),
            QtGui.QAbstractItemView.PositionAtTop
            )
Example #26
0
    def export_current_function(self):
        """
        Exports the current function code, ascii hex encoded
        This is useful to import into tools like miasm and alike
        """
        # TODO: Reading one byte at a time must be EXTREMELY INEFFICIENT!!! o.O

        begin, end = misc.function_boundaries()

        try:
            filename = AskFile(1, "function_bytes.txt", "File to save the code?")
            code_s = ''.join(["%02x" % get_byte(x) for x in xrange(begin, end)])
            with open(filename, 'w') as f:
                f.write(code_s)

            return True

        except:
            return False
    def _commentsInThisFunction(self):
        """
        Shows all comments within the current function
        """
        show_unique_c = self.config.display_unique_comments

        msg = "Searching comments within function '" + \
            misc.get_function_name() + "'"
        self._console_output(msg)

        comment_list = self.ba.comments_in_function()

        # Found any comment at all?
        nr_rows = len(comment_list)
        if not nr_rows:
            self._console_output("[!] No comments found", err = True)
            return

        self.table.setColumnCount(2)
        self.table_label.setText("Comments within current function")
        self.table.setHorizontalHeaderLabels(("Address", "Comments"))
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        displayed_comments = []

        idx = 0
        for (addr, comment) in comment_list:
            if show_unique_c and comment in displayed_comments:
                continue

            displayed_comments.append(comment)

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%08x" % addr)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            comment_item = QTableWidgetItem(comment)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, comment_item)

            idx += 1
Example #28
0
    def _commentsInThisFunction(self):
        """
        Shows all comments within the current function
        """
        show_unique_c = self.config.display_unique_comments

        msg = "Searching comments within function '" + \
            misc.get_function_name() + "'"
        self._console_output(msg)

        comment_list = self.ba.comments_in_function()

        # Found any comment at all?
        nrows = len(comment_list)
        if not nrows:
            self._console_output("[!] No comments found", err = True)
            return

        self.table.setColumnCount(2)
        self.table_label.setText("Comments within current function")
        self.table.setHorizontalHeaderLabels(("Address", "Comments"))
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        displayed_comments = []

        idx = 0
        for (addr, comment) in comment_list:
            if show_unique_c and comment in displayed_comments:
                continue

            displayed_comments.append(comment)

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%08x" % addr)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            comment_item = QTableWidgetItem(comment)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, comment_item)

            idx += 1
Example #29
0
    def _callsInThisFunction(self):
        """
        Shows all calls within the current function
        """
        msg = "Calls within function '" + misc.get_function_name()
        self._console_output(msg)

        show_unique_calls = self.config.display_unique_calls
        callee_list = self.ba.calls_in_function()

        nrows = len(callee_list)
        if not nrows:
            self._console_output("[!] No calls found", err = True)
            return

        self.table_label.setText("Calls within current function")
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Address", "Callee"))
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        shown_calls = []

        idx = 0
        for (addr, callee) in callee_list:

            if show_unique_calls and callee in shown_calls:
                continue

            shown_calls.append(callee)

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%08x" % addr)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            callee_item =  QTableWidgetItem(callee)
            callee_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, callee_item)

            idx += 1
Example #30
0
    def _callsInThisFunction(self):
        """
        Shows all calls within the current function
        """
        msg = "Calls within function '" + misc.get_function_name()
        self._console_output(msg)

        show_unique_calls = self.config.display_unique_calls
        callee_list = self.ba.calls_in_function()

        nrows = len(callee_list)
        if not nrows:
            self._console_output("[!] No calls found", err = True)
            return

        self.table_label.setText("Calls within current function")
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(("Address", "Callee"))
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        shown_calls = []

        idx = 0
        for (addr, callee) in callee_list:

            if show_unique_calls and callee in shown_calls:
                continue

            shown_calls.append(callee)

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%08x" % addr)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            callee_item = QTableWidgetItem(callee)
            callee_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, callee_item)

            idx += 1
Example #31
0
    def find_imm_compares(self):
        """
        Find all immediate compares in the current function.
        Very useful when debugging parsers, for example.
        @return: list of tuples [(address, disassembly),...]
        """
        cmp_addr = []

        for addr, dis in misc.iter_disasm():
            if "cmp" in dis:
                if GetOpType(addr, 1) == o_imm:  # 5: immediate value
                    # If this is ASCII, display for convenience
                    v = GetOperandValue(addr, 1)
                    if v > 0x20 and v <0x7F:
                        msg = "{0} ({1})".format(addr, chr(v))
                    else:
                        msg = dis
                    cmp_addr.append((addr, msg))

        return cmp_addr
Example #32
0
    def export_current_function(self):
        """
        Exports the current function code, ascii hex encoded
        This is useful to import into tools like miasm and alike
        """
        # TODO: Reading one byte at a time must be EXTREMELY INEFFICIENT!!! o.O

        begin, end = misc.function_boundaries()

        try:
            filename = AskFile(1, "function_bytes.txt",
                               "File to save the code?")
            code_s = ''.join(
                ["%02x" % get_byte(x) for x in xrange(begin, end)])
            with open(filename, 'w') as f:
                f.write(code_s)

            return True

        except:
            return False
Example #33
0
    def get_dangerous_args(self, ea):
        """
        Find the dangerous function arguments
        Ex. "call strncpy" find the third push,
        which should correspond to the size argument
        @returns: list of arguments (may be empty)
        """
        dang_name = GetOpnd(ea, 0)
        dang_arg_idx = 0
        #x86_64_regs = ['rdi', 'rsi', 'rdx', 'rcx', 'r8', 'r9'] # System V AMD64 ABI
        x86_64_regs = ['rcx', 'rdx', 'r8', 'r9'] # Microsoft x64

        # TODO: the algo as a whole is flaky...
        # which paths are being considered?
        for pat, arg_idx in self.dangerous_patterns.iteritems():
            if pat in dang_name:
                dang_arg_idx = arg_idx

        if misc.is_64bit():
            return x86_64_regs[:dang_arg_idx]

        prev_addr = ea
        dang_args = []
        while dang_arg_idx > 0:
            pi = DecodePreviousInstruction(prev_addr)

            # DecodePreviousInstruction returns None if we try
            # to decode past the beginning of the function
            if not pi:
                return []

            if pi.get_canon_mnem() == 'push':
                dang_arg_idx -= 1
                push_op = GetOpnd(pi.ea, 0)
                dang_args.append(push_op)

            prev_addr = pi.ea

        return dang_args
Example #34
0
    def get_dangerous_args(self, ea):
        """
        Find the dangerous function arguments
        Ex. "call strncpy" find the third push,
        which should correspond to the size argument
        @returns: list of arguments (may be empty)
        """

        # TODO: x86 only at the moment, x64 at least
        # TODO: the algo as a whole is flaky...
        # which paths are being considered?
        if misc.is_64bit():
            raise NotImplementedError

        prev_addr = ea
        dang_args = []
        dang_name = GetOpnd(ea, 0)
        dang_arg_idx = 0

        for pat, arg_idx in self.dangerous_patterns.iteritems():
            if pat in dang_name:
                dang_arg_idx = arg_idx

        while dang_arg_idx > 0:
            pi = DecodePreviousInstruction(prev_addr)

            # DecodePreviousInstruction returns None if we try
            # to decode past the beginning of the function
            if not pi:
                return []

            if pi.get_canon_mnem() == 'push':
                dang_arg_idx -= 1
                push_op = GetOpnd(pi.ea, 0)
                dang_args.append(push_op)

            prev_addr = pi.ea

        return dang_args
Example #35
0
    def input_to_function(self, ea = None):
        """
        Gets all functions calling IO (net & file) whose downgraph
        is connected to the specified function
        If none is specified, then use current function
        @returns: a list of f_ea's (io callers)
        """
        connected_input_list = []

        if not ea:
            # Called without arguments
            # Use current function
            ea = misc.function_boundaries()[0]

        io_list = self.locate_file_io().keys() + self.locate_net_io().keys()

        for caller_ea in io_list:
            cg = self.get_connect_graph(caller_ea, ea)
            if cg:
                connected_input_list.append(caller_ea)

        return connected_input_list
Example #36
0
    def get_dangerous_args(self, ea):
        """
        Find the dangerous function arguments
        Ex. "call strncpy" find the third push,
        which should correspond to the size argument
        @returns: list of arguments (may be empty)
        """

        # TODO: x86 only at the moment, x64 at least
        # TODO: the algo as a whole is flaky...
        # which paths are being considered?
        if misc.is_64bit():
            raise NotImplementedError

        prev_addr = ea
        dang_args = []
        dang_name = GetOpnd(ea, 0)
        dang_arg_idx = 0

        for pat, arg_idx in self.dangerous_patterns.iteritems():
            if pat in dang_name:
                dang_arg_idx = arg_idx

        while dang_arg_idx > 0:
            pi = DecodePreviousInstruction(prev_addr)

            # DecodePreviousInstruction returns None if we try
            # to decode past the beginning of the function
            if not pi:
                return []

            if pi.get_canon_mnem() == 'push':
                dang_arg_idx -= 1
                push_op = GetOpnd(pi.ea, 0)
                dang_args.append(push_op)

            prev_addr = pi.ea

        return dang_args
Example #37
0
    def _showIntegerIssues(self):
        """
        This is the GUI part of the integer issues functionality
        """
        self._console_output("Looking for integer issues (comparisons)")

        try:
            integer_issues_ins = self.ii.search_integer_issues()

        except NotImplementedError:
            self._console_output("[!] x86_64 not implemented yet", err=True)
            return

        # Is there any integer issues at all?
        nrows = len(integer_issues_ins)
        if not nrows:
            self._console_output("[-] No integer issues found.")
            return

        self.table.setColumnCount(3)
        self.table_label.setText("Possible integer issues")
        self.table.setHorizontalHeaderLabels(
            ('Address', 'Function name', 'Notes'))
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        for idx, ins_ea in enumerate(integer_issues_ins):

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%x" % ins_ea)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            name_item = QTableWidgetItem(misc.get_function_name(ins_ea))
            mnem_item = QTableWidgetItem("")  # placeholder

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, name_item)
            self.table.setItem(idx, 2, mnem_item)
    def _showIntegerIssues(self):
        """
        This is the GUI part of the integer issues functionality
        """
        self._console_output("Looking for integer issues (comparisons)")

        try:
            integer_issues_ins = self.ii.search_integer_issues()

        except NotImplementedError:
            self._console_output("[!] x86_64 not implemented yet", err = True)
            return

        # Is there any integer issues at all?
        nrows = len(integer_issues_ins)
        if not nrows:
            self._console_output("[-] No integer issues found.")
            return

        self.table.setColumnCount(3)
        self.table_label.setText("Possible integer issues")
        self.table.setHorizontalHeaderLabels(
            ('Address', 'Function name', 'Notes'))
        self.table.clearContents()
        self.table.setRowCount(0)

        # Fill with contents
        for idx, ins_ea in enumerate(integer_issues_ins):

            self.table.insertRow(idx)
            addr_item = QTableWidgetItem("%x" % ins_ea)
            addr_item.setFlags(addr_item.flags() ^ QtCore.Qt.ItemIsEditable)
            name_item = QTableWidgetItem(misc.get_function_name(ins_ea))
            mnem_item = QTableWidgetItem("")  # placeholder

            self.table.setItem(idx, 0, addr_item)
            self.table.setItem(idx, 1, name_item)
            self.table.setItem(idx, 2, mnem_item)