Exemple #1
0
def make_head(ea):
    flags = idc.GetFlags(ea)
    if not idc.isHead(flags):
        idc.SetFlags(ea, flags | idc.FF_DATA)
        idaapi.autoWait()
        return is_head(ea)
    return True
Exemple #2
0
def make_xref(from_ea, to_ea, xref_constructor, xref_size):
    """Force the data at `from_ea` to reference the data at `to_ea`."""
    if not idc.GetFlags(to_ea) or is_invalid_ea(to_ea):
        DEBUG("  Not making reference (A) from {:x} to {:x}".format(
            from_ea, to_ea))
        return

    make_head(from_ea)

    if is_code(from_ea):
        _CREFS_FROM[from_ea].add(to_ea)
        _CREFS_TO[to_ea].add(from_ea)
    else:
        _DREFS_FROM[from_ea].add(to_ea)
        _DREFS_TO[to_ea].add(from_ea)

    # If we can't make a head, then it probably means that we're at the
    # end of the binary, e.g. the last thing in the `.extern` segment.
    if not make_head(from_ea + xref_size):
        assert idc.BADADDR == idc.SegStart(from_ea + xref_size)

    idaapi.do_unknown_range(from_ea, xref_size, idc.DOUNK_EXPAND)
    xref_constructor(from_ea)
    if not is_code_by_flags(from_ea):
        idc.add_dref(from_ea, to_ea, idc.XREF_USER | idc.dr_O)
    else:
        DEBUG("  Not making reference (B) from {:x} to {:x}".format(
            from_ea, to_ea))
Exemple #3
0
def make_array(ea, size):
    if ea != idc.BADADDR and ea != 0:
        flags = idc.GetFlags(ea)
        if not idc.isByte(flags) or idc.ItemSize(ea) != 1:
            idc.MakeUnknown(ea, 1, idc.DOUNK_SIMPLE)
            idc.MakeByte(ea)
        idc.MakeArray(ea, size)
    def getSize(self, withPool=False):
        """
        Computes the size of the function the first time this is called, and caches that computation for later
        Parsed Comment commands:
            <endpool> specifies the last element in the pool. That element's size is included in the pool.
                      to specify a function has no pool at all, put the comment command at its last instruction.
        :param withPool: (bool) somewhat of a heuristic. Computes the pool size as simply the amount of bytes since
                         the function's code portion finished (endEA) until a new code head is detected
        :return:  Returns the size of the Function in bytes: EndEA - StartEA (if no pool selected, otherwise + pool)
        """
        if not withPool: return self.func.end_ea - self.func.start_ea
        head = self.func.end_ea

        # check if the function is set to have no pool
        instSize = self.isThumb() and 2 or 4
        endCmt = idc.Comment(self.func.end_ea - instSize)
        if endCmt and '<endpool>' in endCmt:
            return self.func.end_ea - self.func.start_ea

        while not idc.isCode(idc.GetFlags(head)):
            # manual pool computation, trust and assume that this is the last element in the pool!
            if idc.Comment(head) and '<endpool>' in idc.Comment(head):
                head += idc.get_item_size(head)
                break
            # advance to next data element
            head += idc.get_item_size(head)

        return head - self.func.start_ea
Exemple #5
0
    def yacheck_apply_struct(self):
        addrs = yaunit.load('apply_struct')
        for k in range(-1, 4):
            # retrieve struct id
            addr = addrs[k + 1]
            sid = idc.GetStrucIdByName('apply_struct_%x' % (k + 1))
            self.assertNotEqual(sid, idaapi.BADADDR)

            # begin to check if something is applied
            flags = idaapi.get_flags_novalue(addr)
            self.assertTrue(idaapi.isStroff(flags, 1))
            ti = idaapi.opinfo_t()
            flags = idc.GetFlags(addr)
            self.assertTrue(idaapi.get_opinfo(addr, 1, flags, ti))

            # apply struct only
            if k == -1:
                # check struct is applied
                self.assertEqual(ti.path.ids[0], sid)
                continue

            # check union is selected & applied at target address
            uid = idc.GetStrucIdByName('apply_union_%x' % (k + 1))
            self.assertNotEqual(uid, idaapi.BADADDR)
            fid = idc.GetMemberId(uid, k)
            self.assertNotEqual(fid, -1)

            # check union is applied
            self.assertEqual([x for x in ti.path.ids if x], [sid, fid])
Exemple #6
0
    def post_analysis_stuff(self, results):
        if results.has_formula():
            self.action_selector.addItem(self.parent.HIGHLIGHT_CODE)
            self.action_selector.addItem(self.parent.GRAPH_DEPENDENCY)
            self.formula_area.setText(self.parent.results.formula)
        if results.has_values():
            self.action_selector.addItem(self.parent.DISASS_UNKNOWN_TARGET)
        self.action_selector.setEnabled(True)
        self.action_button.setEnabled(True)

        report = HTMLReport()
        report.add_title("Results", size=3)
        report.add_table_header(["address", "assertion", "status", "values"])
        addr = make_cell("%x" % results.target)
        status = make_cell(results.get_status(),
                           color=results.color,
                           bold=True)
        vals = ""
        for value in results.values:
            flag = idc.GetFlags(value)
            typ = self.type_to_string(flag)
            vals += "%x type:%s seg:%s fun:%s<br/>" % (
                value, typ, idc.SegName(value), idc.GetFunctionName(value))
        report.add_table_line([
            addr,
            make_cell(cgi.escape(results.query)), status,
            make_cell(vals)
        ])
        report.end_table()
        data = report.generate()
        self.result_area.setHtml(data)
Exemple #7
0
 def heatmap_trace(self):
     try:
         index = self.traces_tab.currentIndex()
         trace = self.core.traces[self.id_map[index]]
         if self.heatmaped:
             self.heatmap_button.setText("Heatmap")
             color = lambda x: 0xffffff
         else:
             self.heatmap_button.setText("Heatmap undo")
             self.heatmap_button.setFlat(True)
             hit_map = trace.address_hit_count
             color_map = self.compute_step_map(set(hit_map.values()))
             print color_map
             color = lambda x: color_map[hit_map[x]]
         for inst in trace.instrs.values():
             if idc.isCode(idc.GetFlags(inst.address)):
                 c = color(inst.address)
                 idc.SetColor(inst.address, idc.CIC_ITEM, c)
         if not self.heatmaped:
             self.heatmap_button.setFlat(False)
             self.heatmaped = True
         else:
             self.heatmaped = False
     except KeyError:
         print "No trace found"
Exemple #8
0
def crefs_from(ea, only_one=False, check_fixup=True):
    flags = idc.GetFlags(ea)
    if not idc.isCode(flags):
        return

    fixup_ea = idc.BADADDR
    seen = False
    has_one = only_one
    if check_fixup:
        fixup_ea = idc.GetFixupTgtOff(ea)
        if not is_invalid_ea(fixup_ea) and is_code(fixup_ea):
            seen = only_one
            has_one = True
            yield fixup_ea

        if has_one and _stop_looking_for_xrefs(ea):
            return

    for target_ea in _xref_generator(ea, idaapi.get_first_cref_from,
                                     idaapi.get_next_cref_from):
        if target_ea != fixup_ea and not is_invalid_ea(target_ea):
            seen = only_one
            yield target_ea
            if seen:
                return

    if not seen and ea in _CREFS_FROM:
        for target_ea in _CREFS_FROM[ea]:
            seen = only_one
            yield target_ea
            if seen:
                return
Exemple #9
0
    def disassemble_from_trace(self):
        try:
            index = self.traces_tab.currentIndex()
            trace = self.core.traces[self.id_map[index]]

            self.disassemble_button.setFlat(True)
            found_match = False
            for k, inst in trace.instrs.items():
                if k in trace.metas:
                    for name, arg1, arg2 in trace.metas[k]:
                        if name == "wave":
                            self.parent.log("LOG", "Wave n°%d encountered at (%s,%x) stop.." % (arg1, k, inst.address))
                            prev_inst = trace.instrs[k-1]
                            idc.MakeComm(prev_inst.address, "Jump into Wave %d" % arg1)
                            self.disassemble_button.setFlat(False)
                            return
                # TODO: Check that the address is in the address space of the program
                if not idc.isCode(idc.GetFlags(inst.address)):
                    found_match = True
                    # TODO: Add an xref with the previous instruction
                    self.parent.log("LOG", "Addr:%x not decoded as an instruction" % inst.address)
                    if idc.MakeCode(inst.address) == 0:
                        self.parent.log("ERROR", "Fail to decode at:%x" % inst.address)
                    else:
                        idaapi.autoWait()
                        self.parent.log("SUCCESS", "Instruction decoded at:%x" % inst.address)

            if not found_match:
                self.parent.log("LOG", "All instruction are already decoded")
            self.disassemble_button.setFlat(False)
        except KeyError:
            print "No trace found to use"
Exemple #10
0
    def getOrigDisasm(self):
        # type: () -> str
        """
        Gets the original disassembly without any further applied transformations
        However, the formatting is different from the original and is more convenient
        for parsing
        :return: the disassembly
        """
        flags = idc.GetFlags(self.ea)
        if idc.isCode(flags):
            disasm = idc.GetDisasm(self.ea)
            disasm = self._filterComments(disasm)
            disasm = disasm.replace('  ', ' ')
        elif idc.isStruct(flags):
            disasm = self._getStructDisasm()
            # disasm = "INVALID"
        elif idc.isAlign(flags):
            disasm = idc.GetDisasm(self.ea)
            disasm = self._convertAlignDisasm(disasm)
        elif idc.isASCII(flags):
            content = self.getContent()
            numNewLines = content.count(0x0A)
            if numNewLines > 1:
                disasm = '.ascii "'
            else:
                disasm = '.asciz "'
            for i in range(len(content)):
                if content[i] == 0x00:
                    disasm += '"'
                elif chr(content[i]) == '"':
                    disasm += '\\\"'
                elif chr(content[i]) == '\\':
                    disasm += '\\\\'
                elif content[i] == 0x0A:
                    disasm += '\\n'
                    numNewLines -= 1
                    if numNewLines > 1:
                        disasm += '"\n\t.ascii "'
                    elif numNewLines == 1:
                        disasm += '"\n\t.asciz "'
                elif chr(content[i]) == ' ':
                    disasm += ' '
                elif not chr(content[i]).isspace():
                    disasm += chr(content[i])
                else:
                    # TODO [INVALID] arm-none-eabi doesn't recognize \xXX? \x seems to become a byte.
                    disasm += '\\x%02X' % content[i]
        elif idc.isData(flags):
            disasm = self._getDataDisasm()
        else:
            disasm = idc.GetDisasm(self.ea)
            disasm = self._filterComments(disasm)
            disasm = disasm.replace('  ', ' ')

        # parse force command
        if '<force>' in self.getComment():
            comment = self.getComment()
            disasm = comment[comment.index('<force> ') + len('<force> '):]
        return disasm
Exemple #11
0
def _process_stubs_section(segstart, make_thunk, next_stub):
    """Process all the functions in a __stubs section."""
    segend = idc.SegEnd(segstart)
    # We'll go through each address and check if it has a reference. If it does, it is likely a
    # stub. As long as the address doesn't already have a stub name, process it.
    for ea in idau.Addresses(segstart, segend, step=1):
        if idc.isRef(idc.GetFlags(ea)) and not stub_name_target(idau.get_ea_name(ea)):
            _process_possible_stub(ea, make_thunk, next_stub)
Exemple #12
0
 def decode_here_clicked(self):
     inst = idc.here()
     if not idc.isCode(idc.GetFlags(inst)):
         print "Not code instruction"
     else:
         raw = idc.GetManyBytes(inst, idc.NextHead(inst) - inst)
         s = to_hex(raw)
         self.decode_ir(s)
Exemple #13
0
def make_code(start, end):
  for i in range((end - start) / 4):
    addr = start + (i * 4)
    if not idc.isCode(idc.GetFlags(addr)):
      idaapi.do_unknown_range(addr, 4, 0)
      idaapi.auto_make_code(addr)
      idc.MakeCode(addr)
  return
Exemple #14
0
def valid_oreans_macro_entry(address):
    if idc.isCode(
            idc.GetFlags(address)) and get_mnemonic(address) == ENTRY_MNEM:
        jump_location_address = get_jump_destination(address)
        if (jump_location_address >= OREANS_SEGMENT.startEA) and (
                jump_location_address <= OREANS_SEGMENT.endEA):
            return True
    return False
Exemple #15
0
def get_function_xrefs_at_ea(base_address, ea, function_xrefs, minSegAddress, maxSegAddress):
    # TODO: we should look at the operand number
    xrefCode = idc.Rfirst0(ea)
    # code xref
    while xrefCode != idc.BADADDR:
        if (idc.GetFlags(xrefCode) & idc.FF_FUNC) == idc.FF_FUNC:
            function_xrefs[ea - base_address] = GetItemContaining(xrefCode)
        xrefCode = idc.Rnext0(ea, xrefCode)
Exemple #16
0
def scan_data_for_code_refs(begin_ea, end_ea, read_func, read_size):
    """Read in 4- or 8-byte chunks of data, and try to see if they look like
  pointers into the code."""
    global POSSIBLE_CODE_REFS
    for ea in xrange(begin_ea, end_ea, read_size):
        qword = read_func(ea)
        if idc.isCode(idc.GetFlags(qword)):
            POSSIBLE_CODE_REFS.add(qword)
Exemple #17
0
def read_bytes_slowly(start, end):
    bytestr = []
    for i in xrange(start, end):
        if idc.hasValue(idc.GetFlags(i)):
            bt = idc.Byte(i)
            bytestr.append(chr(bt))
        else:
            bytestr.append("\x00")
    return "".join(bytestr)
Exemple #18
0
    def is_end_of_flow(self, instruction):
        """Return whether the last instruction processed end the flow."""

        next_addr = instruction.ip + idc.ItemSize(instruction.ip)
        next_addr_flags = idc.GetFlags(next_addr)
        if idc.isCode(next_addr_flags) and idc.isFlow(next_addr_flags):
            return False

        return True
Exemple #19
0
	def have_string(self, operand):
		if operand[0] != 'a':
			return False

		loc_addr = idc.LocByName(operand)
		if idc.GetString(loc_addr) != '' and idc.isData(idc.GetFlags(loc_addr)):
			return True
		else:
			return False
Exemple #20
0
 def disassemble_new_targets(self, enabled):
     for value in self.results.values:
         flag = idc.GetFlags(value)
         if not idc.isCode(flag) and idc.isUnknown(flag):
             res = idc.MakeCode(value)
             if res == 0:
                 print "Try disassemble at:" + hex(value) + " KO"
                 #TODO: Rollback ?
             else:
                 print "Try disassemble at:" + hex(value) + " Success !"
Exemple #21
0
 def setBPs(self):
     """
     Set breakpoints on all CALL and RET instructions in all of the executable sections.
     """
     for seg_ea in idautils.Segments():
         for head in idautils.Heads(seg_ea, idc.SegEnd(seg_ea)):
             if idc.isCode(idc.GetFlags(head)):
                 # Add BP if instruction is a CALL
                 if is_call(head):
                     self.addBP(head)
 def _isFunctionPointer(self, firstLineSplitDisasm):
     """
     Identifies the construct 'DCD <funcName>' as a function pointer entry!
     The function Name is checked in the database for confirmation!
     This actually extend to none-identified functions, because it only checks if the location is valid code.
     :param firstLineSplitDisasm: list of space and comma split operands in the instruction. ['DCD', 'sub_DEADBEEF+1']
     :return:
     """
     return len(firstLineSplitDisasm) >= 2 and firstLineSplitDisasm[0] == 'DCD' \
            and idc.isCode(idc.GetFlags(idc.get_name_ea(0, firstLineSplitDisasm[1])))
 def fix_code(start_address, end_address):
     # Todo: There might be some data in the range of codes.
     offset = start_address
     while offset <= end_address:
         offset = idc.NextAddr(offset)
         flags = idc.GetFlags(offset)
         if not idc.isCode(flags):
             # Todo: Check should use MakeCode or MakeFunction
             # idc.MakeCode(offset)
             idc.MakeFunction(offset)
Exemple #24
0
 def compute_nb_instr(self):
     #return 1000
     count = 0
     start, stop = self.seg_mapping[
         ".text"]  #TODO: Iterate all segs writable
     current = start
     while current <= stop:
         if idc.isCode(idc.GetFlags(current)):
             count += 1
         current = idc.NextHead(current, stop)
     return count
Exemple #25
0
    def make_function(self, object_version, address):
        #
        # call the architecture dependent plugin  ###########
        #
        self.arch_plugin.make_function_prehook(object_version, address)

        flags = object_version.get_object_flags()
        size = object_version.get_size()
        # create function if not already exist

        current_flags = idc.GetFlags(address)
        # if ea is func
        func = idaapi.get_func(address)
        if not idaapi.isFunc(current_flags) or (func is not None and
                                                (func.startEA != address)):
            logger.debug(
                "MakeFunction at 0x%08X : flags=0x%08X, current_flags=0x%08X" %
                (address, flags, current_flags))

            if func is not None:
                logger.debug(
                    "                                       "
                    "func.startEA[0x%08X]!=address func.endEA[0x%08X]!=(address+size[0x%08X])  "
                    % (func.startEA, func.endEA, size))
            if not idc.MakeFunction(address):
                if not idc.isLoaded(address):
                    logger.error(
                        "Failed at idc.MakeFunction at 0x%08X : data not loaded"
                        % address)
                else:
                    logger.error("Failed at idc.MakeFunction at 0x%08X" %
                                 address)
                    self.clear_function(object_version, address)
                    if not idc.MakeFunction(address):
                        logger.error("Failed at idc.MakeFunction at 0x%08X" %
                                     address)

                        #             idc.MakeUnknown(address, size, DOUNK_SIMPLE)
            if idc.AnalyzeArea(address, address + 1) != 1:
                logger.error("[0x%08X] idc.AnalyzeArea failed" % address)

                #             if(idc.AnalyzeArea(address, address+size) != 1):
                #                 logger.error("[0x%08X] idc.AnalyzeArea failed" % address)
                #             if(address == 0x0000000000411558):
                #                 raise Exception()
        if flags is not None:
            idc.SetFunctionFlags(address, flags)

        self.set_type(object_version, address)

        #
        # call the architecture dependent plugin  ###########
        #
        self.arch_plugin.make_function_posthook(object_version, address)
Exemple #26
0
 def getBlocks(self, function_offset):
     blocks = []
     function_chart = idaapi.FlowChart(idaapi.get_func(function_offset))
     for block in function_chart:
         extracted_block = []
         for instruction in idautils.Heads(block.startEA, block.endEA):
             if idc.isCode(idc.GetFlags(instruction)):
                 extracted_block.append(instruction)
         if extracted_block:
             blocks.append(extracted_block)
     return sorted(blocks)
Exemple #27
0
 def load_symbols_from_ida(self):
     for ea, name in idautils.Names():
         flag = idc.GetFlags(ea)
         if not idc.hasUserName(flag):
             continue
         seg_ea = idc.SegStart(ea)
         seg_name = idc.SegName(ea)
         if seg_name not in self.sections:
             continue
         sym_type = 'function' if idc.isCode(flag) else 'object'
         self.symbols[name] = (seg_name, ea - seg_ea, sym_type)
 def yacheck_reference_views(self):
     eas = yaunit.load('reference_views')
     idx = 0
     for ea in eas:
         (operand, is_num, reference) = tests[idx]
         idx += 1
         ti = idaapi.opinfo_t()
         f = idc.GetFlags(ea)
         self.assertTrue(idaapi.get_opinfo(ea, operand, f, ti))
         self.assertTrue(ti.ri.type())
         self.assertEqual(ti.ri.base, reference)
Exemple #29
0
def find_function_ends(location, end_mnem_bytes=None):
    """
    Description:
        Identifies all possible function ends before the next function or Align.

    Input:
        location - The EA to search after
        end_mnem_bytes - Try to end functions on a particular instruction
                         Instructions are entered as space separated bytes (i.e. 'C2' for 'retn')
                         The specified pattern will be used first, then the defaults will be used
                         If no pattern is specified, the defaults will be used, which prefers 'retn'

    Output:
        ends - A list of function end EAs sorted: end_mnem_bytes, retn, jmp
    """
    # foreach target bytes:
    #  step instructions down
    #  if instruction matches the target bytes, add to the corresponding output list
    #  if we hit a function or an align, quit
    # return ends in the order:
    #  end_nmem_bytes
    #  retn
    #  jmp
    #  others, sorted ascending

    max_location = None
    ea = location
    while max_location is None:
        ea = idc.NextHead(ea)
        if idaapi.get_func(ea) or idc.isAlign(idc.GetFlags(ea)):
            max_location = ea
        elif ea == idc.BADADDR:
            max_location = idaapi.getseg(location).endEA
    max_location = min(max_location, idaapi.getseg(location).endEA)

    targets = ['C3', 'C2', 'E9', 'EA', 'EB']
    if end_mnem_bytes:
        targets.insert(0, end_mnem_bytes)

    ends = {}
    for target in targets:
        function_ends = []
        ea = find_binary_instruction_start(location, idc.SEARCH_DOWN, target, max_location=max_location)
        while ea != idc.BADADDR:
            if ea > max_location:
                break
            else:
                function_ends.append(ea)
            ea = find_binary_instruction_start(ea + 11, idc.SEARCH_DOWN, target, max_location=max_location)
        ends[target] = function_ends

    return [end + idc.ItemSize(end) for end in
            ((ends[end_mnem_bytes] if end_mnem_bytes else []) + sorted(ends['C3'] + ends['C2']) +
             sorted(itertools.chain.from_iterable(ends[target] for target in targets[-3:])))]
Exemple #30
0
 def compute_nb_instr(self):
     return 0  # FIXME: by iterating all segments
     count = 0
     start, stop = self.seg_mapping[
         ".text"]  # TODO: Iterate all executable segs
     current = start
     while current <= stop:
         if idc.isCode(idc.GetFlags(current)):
             count += 1
         current = idc.NextHead(current, stop)
     return count