示例#1
0
    def render_img(self, buffers, addr, mouse_offs):
        colors = []
        head = ida_idaapi.BADADDR
        tail = ida_idaapi.BADADDR
        goffs = 0

        for mapped, buf in buffers:
            if mapped:
                if mouse_offs is not None:
                    if self.switch == 0:  # data
                        head = get_item_head(addr + mouse_offs)
                        tail = get_item_end(addr + mouse_offs)
                    else:  # code
                        f = get_func(addr + mouse_offs)
                        if f:
                            head = f.startEA
                            tail = f.endEA

                for pos in xrange(len(buf)):
                    c = ord(buf[pos]) & 0xFF

                    highlight = False
                    if mouse_offs is not None:

                        if addr + pos + goffs >= head and addr + pos + goffs < tail:
                            highlight = True
                    if highlight:
                        colors.append((True, qRgb(c, 0xFF, self.hl_color)))
                    else:
                        colors.append((True, qRgb(c, 0, 0)))
            else:
                for pos in xrange(len(buf)):
                    colors.append((False, 0))
            goffs += len(buf)
        return colors
示例#2
0
    def on_process_buffer(self, buffers, addr, size, mouse_offs):
        colors = []
        goffs = 0

        if mouse_offs is not None:
            head = get_item_head(addr + mouse_offs)
            tail = get_item_end(addr + mouse_offs)

        for mapped, buf in buffers:
            if mapped:
                for i in range(len(buf)):
                    c = buf[i]
                    if addr + i + goffs >= head and addr + i + goffs < tail:
                        col = self.red[1]
                    else:
                        col = self.colormap[int(
                            c / (0xff / (len(self.colormap) - 1)))]

                    colors.append((True, col))
            else:
                for i in range(len(buf)):
                    if addr + i + goffs >= head and addr + i + goffs < tail:
                        colors.append((False, self.red[0]))
                    else:
                        colors.append((False, None))

            goffs += len(buf)

        return colors
示例#3
0
    def on_get_annotations(self, address, size, mouse_offs):
        caption = "  Mov instructions:"
        spaces = 40 * '-'

        cursor_ea = address + mouse_offs
        head = get_item_head(cursor_ea)

        ann = [
            (head, self.ptrcol,
             "%X:  %s" % (head,
                          generate_disasm_line(
                              head, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS)),
             self.ptrcol), (None, None, "", None),
            (None, None, caption, self.colormap[0])
        ]
        if len(self.annotations):
            i = 0
            offs = self._get_selection_offs()
            ann_cnt = len(self.annotations)
            for x in xrange(offs, ann_cnt):
                _, acc, ea = self.annotations[x]
                textcol = self.txtcol
                ann.append((ea, self.insn_colors[acc], "   %X:  %s" %
                            (ea,
                             generate_disasm_line(
                                 ea, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS)),
                            self.insn_colors[acc]))
                i += 1
                if i > self.threshold:
                    ann.append((None, None, "  <%d more not shown>" %
                                (len(self.annotations) - i), self.colormap[0]))
                    break
        return ann
示例#4
0
    def render_img(self, buffers, addr, mouse_offs):
        colors = []
        cols = [qRgb(0xDC, 0xDC, 0xDC), qRgb(0x00, 0x00, 0x00)]
        colidx = 0
        goffs = 0

        for mapped, buf in buffers:
            if mapped:
                start = ea = addr + goffs
                end = start + len(buf)

                head = get_item_head(start)
                sz = get_item_size(head)
                if head < start:
                    sz -= (start - head)
                while ea < end:
                    for i in xrange(sz):
                        colors.append((True, copy(cols[colidx])))

                    colidx = ((colidx + 1) & sz != 0)
                    if ea + sz > end:
                        sz = ea + sz - end
                    ea += sz
                    sz = get_item_size(ea)
            else:
                for i in xrange(len(buf)):
                    colors.append((False, 0))
            goffs += len(buf)
        return colors
示例#5
0
    def mouseMoveEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()
        within_graph = (x >= self.rect_x
                        and x < self.rect_x + self.rect_x_width)
        """(sx1, sy1), (sx2, sy2) = self.slider_coords
        on_slider = (x >= sx1 and x< sx2 and y>= sy1 and y < sy2)"""

        update_state = self.is_dragging_graph or within_graph

        if self.is_dragging_graph:
            # zoom
            if self.key == Qt.Key_Control:
                self.set_zoom_delta(-1 if y > self.prev_mouse_y else 1)

            # width
            elif self.key == Qt.Key_X:
                if not self.lock_width:
                    self.set_width_delta(-1 if y > self.prev_mouse_y else 1)

            elif self.key == Qt.Key_H:
                if not self.lock_width:
                    less = y > self.prev_mouse_y
                    delta = -16 if less else 16
                    self.set_pixel_qty_per_line((self.get_pixel_qty_per_line()
                                                 & 0xFFFFFFF0) + delta)

            # scrolling (offset)
            elif y != self.prev_mouse_y:
                # offset (fine)
                delta = y - self.prev_mouse_y

                # offset (coarse)
                if self.key != Qt.Key_Shift:
                    delta *= self.get_pixel_qty_per_line()

                self.set_offset_delta(delta)

        elif within_graph:
            self._update_mouse_coords(event.pos())
            self.mouseOffs = self._get_offs_by_pos(event.pos())

            if self.link_pixel and self.highlight_cursor:
                highlight_item(
                    ida_bytes.get_item_head(self.get_cursor_address()))
            elif self.highlight_cursor:
                unhighlight_item()

            self.setToolTip(
                self.fm.on_get_tooltip(self.get_address(),
                                       self.get_pixel_qty(), self.mouseOffs))

        if update_state:
            self.prev_mouse_y = y
            self.x = x
            self.statechanged.emit()
            self.repaint()

        return
示例#6
0
    def get_tooltip(self, addr, mouse_offs):
        tooltip = '%X: ' % (addr + mouse_offs)

        if self.switch == 0:
            tooltip += '%s' % get_name(get_item_head(addr + mouse_offs))
        else:
            f = get_func(addr + mouse_offs)
            if f:
                tooltip += '%s' % get_func_name(f.startEA)
        return tooltip
示例#7
0
    def mouseMoveEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()
        within_graph = (x >= self.rect_x
                        and x < self.rect_x + self.rect_x_width)

        if within_graph:
            if event.buttons() == Qt.NoButton:
                self._update_mouse_coords(event.pos())
                self.mouseOffs = self._get_offs_by_pos(event.pos())

                if self.link_pixel and self.highlight_cursor:
                    highlight_item(
                        ida_bytes.get_item_head(self.get_cursor_address()))
                elif self.highlight_cursor:
                    unhighlight_item()

                self.setToolTip(
                    self.fm.on_get_tooltip(self.get_address(),
                                           self.get_pixels_total(),
                                           self.mouseOffs))

            # zoom
            elif self.key == Qt.Key_Control:
                self.set_zoom_delta(-1 if y > self.prev_mouse_y else 1)

            # width
            elif self.key == Qt.Key_X:
                if not self.lock_width:
                    self.set_width_delta(-1 if y > self.prev_mouse_y else 1)

            elif self.key == Qt.Key_H:
                if not self.lock_width:
                    less = y > self.prev_mouse_y
                    delta = -16 if less else 16
                    self.set_width((self.get_width() & 0xFFFFFFF0) + delta)

            # scrolling (offset)
            elif y != self.prev_mouse_y:
                # offset (fine)
                delta = y - self.prev_mouse_y

                # offset (coarse)
                if self.key != Qt.Key_Shift:
                    delta *= self.get_width()

                self.set_offset_delta(delta)

            self.prev_mouse_y = y
            self.x = x
            self.statechanged.emit()
            self.repaint()
        return
示例#8
0
    def _has_code(self):
        """
        Checks if any address in the changed data area has code in it

        :return: (int) address of the code start, or None.
        """
        for i in xrange(self.data):
            maybe_start_of_item = ida_bytes.get_item_head(self.address + i)
            if ida_bytes.is_code(
                    ida_bytes.get_full_flags(maybe_start_of_item)):
                return self.address + i
        return None
示例#9
0
 def on_get_annotations(self, address, size, mouse_offs):
     item_ea = get_item_head(address + mouse_offs)
     cursor_ea = address + mouse_offs
     name = get_name(item_ea)
     if len(name):
         name = "(%s)" % name
     else:
         name = ""
     ann = [
         (item_ea, self.red[0], "Item: %X" % (item_ea), self.colormap[-1]),
         (None, None,
          "  Size: %d %s" % (get_item_size(get_item_head(cursor_ea)), name),
          self.colormap[-3]),
         (cursor_ea, self.colormap[-1], "Cursor: %X" % (cursor_ea),
          self.colormap[-1]),
         (None, None, "  %s" % generate_disasm_line(
             cursor_ea, GENDSM_FORCE_CODE | GENDSM_REMOVE_TAGS),
          self.colormap[-3]),
         (None, None, "  Value: %02X" % get_byte(cursor_ea),
          self.colormap[-3]),
     ]
     return ann
示例#10
0
def _convert_address_to_function(func):
    """Convert an address that IDA has classified incorrectly into a proper function."""
    # If everything goes wrong, we'll try to restore this function.
    orig = idc.first_func_chunk(func)
    # If the address is not code, let's undefine whatever it is.
    if not ida_bytes.is_code(ida_bytes.get_full_flags(func)):
        if not is_mapped(func):
            # Well, that's awkward.
            return False
        item = ida_bytes.get_item_head(func)
        itemend = ida_bytes.get_item_end(func)
        if item != idc.BADADDR:
            _log(1, 'Undefining item {:#x} - {:#x}', item, itemend)
            ida_bytes.del_items(item, ida_bytes.DELIT_EXPAND)
            idc.create_insn(func)
            # Give IDA a chance to analyze the new code or else we won't be able to create a
            # function.
            #ida_auto.auto_wait()
            autoanalyze()
            idc.plan_and_wait(item, itemend)
    else:
        # Just try removing the chunk from its current function. IDA can add it to another function
        # automatically, so make sure it's removed from all functions by doing it in loop until it
        # fails.
        for i in range(1024):
            if not idc.remove_fchunk(func, func):
                break
    # Now try making a function.
    if ida_funcs.add_func(func) != 0:
        return True
    # This is a stubborn chunk. Try recording the list of chunks, deleting the original function,
    # creating the new function, then re-creating the original function.
    if orig != idc.BADADDR:
        chunks = list(idautils.Chunks(orig))
        if ida_funcs.del_func(orig) != 0:
            # Ok, now let's create the new function, and recreate the original.
            if ida_funcs.add_func(func) != 0:
                if ida_funcs.add_func(orig) != 0:
                    # Ok, so we created the functions! Now, if any of the original chunks are not
                    # contained in a function, we'll abort and undo.
                    if all(idaapi.get_func(start) for start, end in chunks):
                        return True
            # Try to undo the damage.
            for start, _ in chunks:
                ida_funcs.del_func(start)
    # Everything we've tried so far has failed. If there was originally a function, try to restore
    # it.
    if orig != idc.BADADDR:
        _log(0, 'Trying to restore original function {:#x}', orig)
        ida_funcs.add_func(orig)
    return False
示例#11
0
    def _ins2color(self, addr):
        col = _len = 0
        acc = -1

        head = get_item_head(addr)
        if can_decode(head):
            f = get_full_flags(head)
            if is_code(f):
                _len = decode_insn(self.insn, head)
                if _len:
                    if self.insn.itype in [ida_allins.NN_mov
                                           ]:  # TODO: add more instructions
                        if self.insn.Op1.type in [o_mem, o_phrase, o_displ]:
                            acc = ACC_WRITE
                            col = self.insn_colors[acc]
                        elif self.insn.Op2.type in [o_mem, o_phrase, o_displ]:
                            acc = ACC_READ
                            col = self.insn_colors[acc]
                        else:
                            acc = -1

        return (col, _len, acc)
示例#12
0
    def get_conflict(self):
        """

        :return: None if there's no conflict, empty string if there's no change, data if there's a change.
        """
        # TODO: Fill docstring, plus, make the function return 0,1,2 and save the current data by itself.
        code_address = self._has_code()
        if code_address:
            return 'Code: 0x%x' % code_address

        num_of_elements = self._get_num_of_elements()

        data_undefined = True
        for i in xrange(self.data):
            ea_flags = ida_bytes.get_full_flags(self.address + i)
            if ea_flags & 0x400:  # Data defined
                data_undefined = False
        if data_undefined:
            return None  # No conflict

        # Iterate over all local data, and check if there's any conflict with the type
        conflict = ''
        for i in xrange(num_of_elements):
            current_address = self.address + (
                i * self.TYPE_TO_SIZE[self.data_type])
            current_address = ida_bytes.get_item_head(current_address)
            ea_flags = ida_bytes.get_full_flags(current_address)
            if not ida_bytes.is_data(ea_flags):
                conflict += 'unknown at 0x%x\n' % current_address
                continue
            current_data_type = ea_flags & ida_bytes.DT_TYPE
            if self.data_type != current_data_type:  # Different data
                conflict += '%s at 0x%x\n' % (
                    self.TYPE_TO_NAME[current_data_type], current_address)
        if conflict:
            return conflict

        # TODO: Deal with the case it's just multiple type definitions in the area?
        return ''  # No difference
示例#13
0
    def on_process_buffer(self, buffers, addr, size, mouse_offs):
        colors = []
        head = BADADDR
        tail = BADADDR
        goffs = 0

        for mapped, buf in buffers:
            if mapped:
                if mouse_offs is not None:
                    if self.switch == 0: # data
                        head = get_item_head(addr + mouse_offs)
                        tail = get_item_end(addr + mouse_offs)
                    else: # code
                        f = get_func(addr + mouse_offs)
                        if f:
                            head = f.startEA
                            tail = f.endEA

                for pos in xrange(len(buf)):
                    c = ord(buf[pos]) & 0xFF
                    
                    highlight = False
                    if mouse_offs is not None:
                        if addr + pos + goffs >= head and addr + pos + goffs < tail:
                            highlight = True
                    if self.last_sel:
                        lhead, lsize = self.last_sel
                        if addr + pos + goffs >= lhead and addr + pos + goffs < lhead+lsize:
                            highlight = True
                    if highlight:
                        colors.append((True, qRgb(c, 0xFF, self.hl_color)))
                    else:
                        colors.append((True, qRgb(c, 0, 0)))
            else:
                for pos in xrange(len(buf)):
                    colors.append((False, None))
            goffs += len(buf)
        return colors
示例#14
0
    def get_conflict(self):
        """

        :return: None if there's no conflict, empty string if there's no change, data if there's a change.
        """
        # TODO: Fill docstring, plus, make the function return 0,1,2 and save the current data by itself.
        conflicts = ""
        conflict_flag = False
        for i in xrange(self.data):
            current_address = self.address + i
            head_address = ida_bytes.get_item_head(current_address)
            if ida_bytes.is_code(ida_bytes.get_full_flags(head_address)):
                conflict_flag = True
            ea_flags = ida_bytes.get_full_flags(head_address)
            if not ida_bytes.is_data(ea_flags):
                continue
            conflict_flag = True
            conflicts += '%s at 0x%x\n' % (
                self.TYPE_TO_NAME[ea_flags & ida_bytes.DT_TYPE], head_address)

        if conflict_flag:
            return conflicts
        return None
示例#15
0
def _invent_var_type(ea, seg_ref, min_size=1):
    """Try to invent a variable type. This will basically be an array of bytes
    that spans what we need. We will, however, try to be slightly smarter and
    look for cross-references in the range, and when possible, use their types."""
    seg = find_segment_containing_ea(ea, seg_ref)
    if not seg:
        return ea, None

    head_ea = ida_bytes.get_item_head(ea)
    if head_ea < ea:
        head_seg = find_segment_containing_ea(head_ea, seg_ref)
        if head_seg != seg:
            return ea, None
        return _invent_var_type(head_ea, seg_ref, ea - head_ea)

    min_size = max(min_size, ida_bytes.get_item_size(ea))
    next_ea = ida_bytes.next_head(ea + 1, seg.end_ea)
    next_seg = find_segment_containing_ea(next_ea, seg_ref)

    arr = ArrayType()
    arr.set_element_type(IntegerType(1, False))

    if not next_seg or next_seg != seg:
        arr.set_num_elements(min_size)
        return ea, arr

    min_size = min(min_size, next_ea - ea)

    # TODO(pag): Go and do a better job, e.g. find pointers inside of the global.
    # i = 0
    # while i < min_size:
    #   for ref_ea in xref_generator(ea + i, seg_ref):
    #     break
    #   i += 1

    arr.set_num_elements(min_size)
    return ea, arr
示例#16
0
    def render_img(self, buf, addr, mouse_offs):
        colors = []
        start = addr
        end = start + len(buf)
        ea = start
        col1 = qRgb(0xDC, 0xDC, 0xDC)
        col2 = qRgb(0x00, 0x00, 0x00)
        cols = [col1, col2]

        pos = 0
        head = get_item_head(start)
        sz = get_item_size(start)
        if head < start:
            sz -= (start - head)
        while ea < end:
            for i in xrange(sz):
                colors.append(copy(cols[pos]))

            pos = (pos + 1) % len(cols)
            if ea + sz > end:
                sz = ea + sz - end
            ea += sz
            sz = get_item_size(ea)
        return colors
示例#17
0
def lines(start=None, end=None, reverse=False, max_steps=None):
    """
    Iterates through instructions within the start address and end addresses.

    :param start: Address of the starting instruction. (starts at beginning if not defined)
    :param end: Address of the end instruction.
    :param reverse: Iterates up if true.
    :param max_steps: Maximum number of steps to iterate.
    :yields: instructions addresses
    """
    max_ea = idaapi.cvar.inf.maxEA
    min_ea = idaapi.cvar.inf.minEA

    # Normalize start and end addresses.
    if reverse:
        if start is None:
            start = max_ea - 1
        if end is None:
            end = 0
        start = max(start, end)
    else:
        if start is None:
            start = min_ea
        if end is None:
            end = max_ea + 1
        start = min(start, end)

    steps = 0
    func = ida_bytes.prev_head if reverse else ida_bytes.next_head
    ea = ida_bytes.get_item_head(start)
    while ea != idc.BADADDR:
        yield ea
        ea = func(ea, end)
        steps += 1
        if max_steps and steps >= max_steps:
            break
示例#18
0
 def _get_item_info(self, ea):
     head = get_item_head(ea)
     name = get_name(head)
     size = get_item_size(head)
     return (head, name, size)
示例#19
0
 def _is_string(self, ea):
     head = get_item_head(ea)
     flags = get_flags(head)
     return is_strlit(flags)