Beispiel #1
0
def isLikeLoadJmpTable(ea):
    insn_t = idautils.DecodeInstruction(ea)

    # 1) mov reg, off[reg*4]
    if hasDispl(insn_t, 1):
        base, scale, index, displ = getAddressParts(insn_t, 1)
        if base == 5 and scale == 2 and idc.isData(idc.GetFlags(displ)):
            # check if there is a table of valid code pointers
            ncases = 0
            bs = idaapi.get_many_bytes(displ, 4)
            if bs == None or len(bs) != 4:
                return False

            jmpaddress = struct.unpack('<I', bs)[0]
            while idc.isCode(idc.GetFlags(jmpaddress)):
                ncases += 1
                bs = idaapi.get_many_bytes(displ+ncases*4, 4)
                if bs == None or len(bs) != 4:
                    break
                jmpaddress = struct.unpack('<I', bs)[0]

            if ncases != 0:
                return True

    return False
Beispiel #2
0
def insertRelocatedSymbol(M, D, reloc_dest, offset, seg_offset, new_eas, itemsize=-1):
    pf = idc.GetFlags(reloc_dest)

    DS = D.symbols.add()
    DS.base_address = offset+seg_offset

    itemsize = int(itemsize)
    if itemsize == -1:
        itemsize = int(idc.ItemSize(offset))

    DEBUG("Offset: {0:x}, seg_offset: {1:x}\n".format(offset, seg_offset))
    DEBUG("Reloc Base Address: {0:x}\n".format(DS.base_address))
    DEBUG("Reloc offset: {0:x}\n".format(offset))
    DEBUG("Reloc size: {0:x}\n".format(itemsize))

    if idc.isCode(pf):
        DS.symbol_name = "sub_"+hex(reloc_dest)
        DS.symbol_size = itemsize
        DEBUG("Code Ref: {0:x}!\n".format(reloc_dest))

        if reloc_dest not in RECOVERED_EAS:
            new_eas.add(reloc_dest)

    elif idc.isData(pf):
        reloc_dest = handleDataRelocation(M, reloc_dest, new_eas)
        DS.symbol_name = "dta_"+hex(reloc_dest)
	DS.symbol_size = itemsize
        DEBUG("Data Ref!\n")
    else:
        reloc_dest = handleDataRelocation(M, reloc_dest, new_eas)
        DS.symbol_name = "dta_"+hex(reloc_dest)
	DS.symbol_size = itemsize
        DEBUG("UNKNOWN Ref, assuming data\n")
Beispiel #3
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
Beispiel #4
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
Beispiel #5
0
 def type_to_string(self, t):
     if idc.isCode(t):
         return "C"
     elif idc.isData(t):
         return "D"
     elif idc.isTail(t):
         return "T"
     elif idc.isUnknown(t):
         return "Ukn"
     else:
         return "Err"
Beispiel #6
0
    def renameDword(self):
        proc_addr = self._import_table.item(self._import_table.currentRow(), 3).text()
        proc_name = str(self._import_table.item(self._import_table.currentRow(), 2).text())
        renamed = 0
        if proc_addr:
            try:
                proc_addr = int(proc_addr, 16)
                proc_bin_str = " ".join([x.encode("hex") for x in struct.pack("<I", proc_addr)])
                next_dword = idc.FindBinary(idc.MinEA(), idc.SEARCH_DOWN | idc.SEARCH_NEXT, proc_bin_str)
                while next_dword != idc.BADADDR:
                    log.debug("Trying to fix-up 0x{:08x}".format(next_dword))
                    # DWORDs can be "inaccessible" for many reasons and it requires "breaking up" the data blobs
                    # and manually fixing them

                    # Reason 1: In a dword array in an unknown section
                    if idc.isUnknown(next_dword):
                        idc.MakeUnkn(next_dword, idc.DOUNK_EXPAND)
                        idc.MakeDword(next_dword)
                    # Reason 2: In a dword array in a data section
                    elif idc.isData(next_dword):
                        hd = idc.ItemHead(next_dword)
                        idc.MakeDword(hd)
                        idc.MakeDword(next_dword)
                    # Reason 3: In a dword array in a code section (validate via "dd <dword>,")
                    elif idc.isCode(next_dword) and idc.GetDisasm(next_dword).startswith("dd "):
                        hd = idc.ItemHead(next_dword)
                        idc.MakeDword(hd)
                        idc.MakeDword(next_dword)

                    # Only perform
                    if idc.Name(next_dword).startswith(("off_", "dword_")) or idc.Name(next_dword) == "":
                        success = idc.MakeNameEx(next_dword, proc_name, idc.SN_NOWARN | idc.SN_NON_AUTO)
                        i = 0
                        new_proc_name = proc_name
                        while not success and i < 10:
                            new_proc_name = "{}{}".format(proc_name, i)
                            success = idc.MakeNameEx(next_dword, new_proc_name, idc.SN_NOWARN | idc.SN_NON_AUTO)
                            i += 1
                        if success:
                            renamed += 1
                            item = self._import_table.item(self._import_table.currentRow(), 5)
                            item.setText("{}, {}".format(str(item.text()), new_proc_name))
                            log.debug("DWORD @ 0x{:08x} now has name {}".format(next_dword, new_proc_name))
                        else:
                            log.error("Unable to auto-rename successfully, terminating search")
                            break
                    else:
                        log.debug("Value at 0x{:08x} does not meet renaming requirements".format(next_dword))
                    next_dword = idc.FindBinary(next_dword + 4, idc.SEARCH_DOWN | idc.SEARCH_NEXT, proc_bin_str)
            except Exception, e:
                log.error("Error encountered: {}".format(e))
            log.debug("Renamed {:d} instances of {}".format(renamed, proc_name))
Beispiel #7
0
def isFwdExport(iname, ea):
    l = ea
    if l == idc.BADADDR:
        raise Exception("Cannot find addr for: " + iname)

    pf = idc.GetFlags(l)

    if not idc.isCode(pf) and idc.isData(pf):
        sz = idc.ItemSize(l)
        iname = idaapi.get_many_bytes(l, sz-1)
        return iname

    return None
Beispiel #8
0
def isFwdExport(iname, ea):
    l = ea
    if l == idc.BADADDR:
        raise Exception("Cannot find addr for: " + iname)

    pf = idc.GetFlags(l)

    if not idc.isCode(pf) and idc.isData(pf):
        sz = idc.ItemSize(l)
        iname = idaapi.get_many_bytes(l, sz-1)
        return iname

    return None
Beispiel #9
0
    def renameDword(self):
        proc_addr = self._import_table.item(self._import_table.currentRow(), 3).text()
        proc_name = str(self._import_table.item(self._import_table.currentRow(), 2).text())
        renamed = 0
        if proc_addr:
            try:
                proc_addr = int(proc_addr, 16)
                proc_bin_str = " ".join([x.encode("hex") for x in struct.pack("<I", proc_addr)])
                next_dword = idc.FindBinary(idc.MinEA(), idc.SEARCH_DOWN|idc.SEARCH_NEXT, proc_bin_str)
                while next_dword != idc.BADADDR:
                    log.debug("Trying to fix-up 0x{:08x}".format(next_dword))
                    # DWORDs can be "inaccessible" for many reasons and it requires "breaking up" the data blobs
                    # and manually fixing them

                    # Reason 1: In a dword array in an unknown section
                    if idc.isUnknown(next_dword):
                        idc.MakeUnkn(next_dword, idc.DOUNK_EXPAND)
                        idc.MakeDword(next_dword)
                    # Reason 2: In a dword array in a data section
                    elif idc.isData(next_dword):
                        hd = idc.ItemHead(next_dword)
                        idc.MakeDword(hd)
                        idc.MakeDword(next_dword)
                    # Reason 3: In a dword array in a code section (validate via "dd <dword>,")
                    elif idc.isCode(next_dword) and idc.GetDisasm(next_dword).startswith("dd "):
                        hd = idc.ItemHead(next_dword)
                        idc.MakeDword(hd)
                        idc.MakeDword(next_dword)

                    # Only perform
                    if idc.Name(next_dword).startswith(("off_", "dword_")) or idc.Name(next_dword) == "":
                        success = idc.MakeNameEx(next_dword, proc_name, idc.SN_NOWARN|idc.SN_NON_AUTO)
                        i = 0
                        new_proc_name = proc_name
                        while not success and i < 10:
                            new_proc_name = "{}{}".format(proc_name, i)
                            success = idc.MakeNameEx(next_dword, new_proc_name, idc.SN_NOWARN|idc.SN_NON_AUTO)
                            i += 1
                        if success:
                            renamed += 1
                            item = self._import_table.item(self._import_table.currentRow(), 5)
                            item.setText("{}, {}".format(str(item.text()), new_proc_name))
                            log.debug("DWORD @ 0x{:08x} now has name {}".format(next_dword, new_proc_name))
                        else:
                            log.error("Unable to auto-rename successfully, terminating search")
                            break
                    else: log.debug("Value at 0x{:08x} does not meet renaming requirements".format(next_dword))
                    next_dword = idc.FindBinary(next_dword+4, idc.SEARCH_DOWN|idc.SEARCH_NEXT, proc_bin_str)
            except Exception, e:
                log.error("Error encountered: {}".format(e))
            log.debug("Renamed {:d} instances of {}".format(renamed, proc_name))
Beispiel #10
0
 def getDisasm(self):
     """
     :return: transformed disassembly so that it's functional with the gcc assembler
     """
     disasm = self.getOrigDisasm()
     flags = idc.GetFlags(self.ea)
     if idc.isAlign(flags):
         disasm = self._convertAlignDisasm(disasm)
     elif idc.isData(flags) or idc.isUnknown(flags):
         disasm = self._convertData(disasm)
     elif idc.isCode(flags):
         disasm = self._convertCode(self.ea, disasm)
         # make code small case
         disasm = self._lowerCode(disasm)
     disasm = self._convertTabs(disasm)
     return disasm
Beispiel #11
0
def extendThumbFuncToLastPop(func_ea, lastInsn_ea, verbose=True):
    """
    Looks for another POP {..., PC}. Stops at the start of a new function, or at the start of
    labeled data. Otherwise, it makes sure the code is disassembled, and is thumb, and it extends the
    range of the function to the found POP {..., PC}.
    A corner case not accounted by this algorithm, is if the data is in the middle of code, but
    is jumped over.
    :param func_ea: addr to function to fix
    :param lastInsn_ea: address to the last instruction within the function, as registered in the IDB.
    :return: whether a fix ocurred or not
    """
    ea = lastPop_ea = lastInsn_ea
    while not idc.Name(ea) or not idc.isData(idc.GetFlags(ea)):
        if idc.GetReg(ea, 'T') == 0:
            idc.SetRegEx(ea, 'T', 1, idc.SR_user)

        # if idc.isData(idc.GetFlags(ea)):
        #     # if not thumb, make thumb
        #     idc.del_items(ea, 0, 2)
        #     idc.MakeCode(ea)

        if Instruction.isInsn(ea):
            insn = Instruction.Insn(ea)
            # update last POP {..., PC} detected
            if insn.itype == idaapi.ARM_pop and ((insn.getPushPopFlags() &
                                                  (1 << 15)) != 0):
                lastPop_ea = ea
            # stop condition, assuming no  PUSH {..., LR} in current function
            if insn.itype == idaapi.ARM_push and ((insn.getPushPopFlags() &
                                                   (1 << 14)) != 0):
                break

        ea += idaapi.get_item_size(ea)

    # extend last function to last pop detected
    if lastPop_ea != lastInsn_ea:
        if verbose:
            print('%07X: End -> %07X <%s>' %
                  (func_ea, lastPop_ea, Data.Data(lastPop_ea).getDisasm()))
        idc.SetFunctionEnd(func_ea, lastPop_ea + 2)
        return True
    return False
Beispiel #12
0
def insertRelocatedSymbol(M, D, reloc_dest, offset, seg_offset, new_eas):
    pf = idc.GetFlags(reloc_dest)

    DS = D.symbols.add()
    DS.base_address = offset + seg_offset

    if idc.isCode(pf):
        DS.symbol_name = "sub_" + hex(reloc_dest)
        DEBUG("Code Ref: {0:x}!\n".format(reloc_dest))

        if reloc_dest not in RECOVERED_EAS:
            new_eas.add(reloc_dest)

    elif idc.isData(pf):
        reloc_dest = handleDataRelocation(M, reloc_dest, new_eas)
        DS.symbol_name = "dta_" + hex(reloc_dest)
        DEBUG("Data Ref!\n")
    else:
        reloc_dest = handleDataRelocation(M, reloc_dest, new_eas)
        DS.symbol_name = "dta_" + hex(reloc_dest)
        DEBUG("UNKNOWN Ref, assuming data\n")
Beispiel #13
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.isStruct(flags):
         disasm = "INVALID"
     elif idc.isAlign(flags):
         disasm = idc.GetDisasm(self.ea)
     elif idc.isData(flags):
         disasm = self._getDataDisasm(self.ea)
     else:
         disasm = idc.GetDisasm(self.ea)
         disasm = self._filterComments(disasm)
         while '  ' in disasm:
             disasm = disasm.replace('  ', ' ')
     return disasm
Beispiel #14
0
def insertRelocatedSymbol(M, D, reloc_dest, offset, seg_offset, new_eas):
    pf = idc.GetFlags(reloc_dest)

    DS = D.symbols.add()
    DS.base_address = offset+seg_offset

    if idc.isCode(pf):
        DS.symbol_name = "sub_"+hex(reloc_dest)
        DEBUG("Code Ref: {0:x}!\n".format(reloc_dest))

        if reloc_dest not in RECOVERED_EAS:
            new_eas.add(reloc_dest)

    elif idc.isData(pf):
        reloc_dest = handleDataRelocation(M, reloc_dest, new_eas)
        DS.symbol_name = "dta_"+hex(reloc_dest)
        DEBUG("Data Ref!\n")
    else:
        reloc_dest = handleDataRelocation(M, reloc_dest, new_eas)
        DS.symbol_name = "dta_"+hex(reloc_dest)
        DEBUG("UNKNOWN Ref, assuming data\n")
Beispiel #15
0
 def getTypeName(self):
     # type: () -> str
     """
     :return: the type of the data item, if it's a struct/enum/const, the name of it.
     a number of stars can follow, indicating that it's a pointer.
     """
     type = idc.get_type(self.ea)
     flags = idc.GetFlags(self.ea)
     typeName = "INVALID"
     if idc.isCode(flags):
         typeName = "code"
     elif idc.isData(flags):
         if idc.is_byte(flags) and self.getSize() == 1:
             typeName = "u8"
         elif idc.is_word(flags) and self.getSize() == 2:
             typeName = "u16"
         elif idc.is_dword(flags) and self.getSize() == 4:
             if self.isPointer(self.getContent()):
                 typeName = "void*"
             else:
                 typeName = "u32"
         else:  # The weird case... an array. I don't know why it's weird. IDA doesn't like it!
             # It is assumed this is an array, but the type is unknown. Imply type based on disasm of first line!
             firstLineSplitDisasm = list(
                 filter(None, re.split('[ ,]', idc.GetDisasm(self.ea))))
             dataType = firstLineSplitDisasm[0]
             if dataType == "DCB":
                 typeName = "u8[%d]" % (self.getSize())
             if dataType == "DCW":
                 typeName = "u16[%d]" % (self.getSize() / 2)
             if dataType == "DCD":
                 if self.hasPointer():
                     typeName = "void*[%d]" % (self.getSize() / 4)
                 else:
                     typeName = "u32[%d]" % (self.getSize() / 4)
     elif idc.isUnknown(flags):
         typeName = "u8"
     elif idc.isStruct(flags):
         typeName = idc.GetStrucName
     return typeName
Beispiel #16
0
def processRelocationsInData(M, D, start, end, new_eas, seg_offset):

    if start == 0:
        start = 1

    i = idc.GetNextFixupEA(start-1)

    while i < end and i != idc.BADADDR:

        pointsto = idc.GetFixupTgtOff(i)
        fn = getFunctionName(i)
        DEBUG("{0:x} Found reloc to: {1:x}\n".format(i, pointsto))

        pf = idc.GetFlags(pointsto)

        DS = D.symbols.add()
        DS.base_address = i+seg_offset

        if idc.isCode(pf):

            DS.symbol_name = "sub_"+hex(pointsto)
            DEBUG("Code Ref!\n")

            if pointsto not in RECOVERED_EAS:
                new_eas.add(pointsto)

        elif idc.isData(pf):
            pointsto = handleDataRelocation(M, pointsto, new_eas)
            DS.symbol_name = "dta_"+hex(pointsto)
            DEBUG("Data Ref!\n")
        else:
            pointsto = handleDataRelocation(M, pointsto, new_eas)
            DS.symbol_name = "dta_"+hex(pointsto)
            DEBUG("UNKNOWN Ref, assuming data\n")


        i = idc.GetNextFixupEA(i)
Beispiel #17
0
def processRelocationsInData(M, D, start, end, new_eas, seg_offset):

    if start == 0:
        start = 1

    i = idc.GetNextFixupEA(start-1)

    while i < end and i != idc.BADADDR:

        pointsto = resolveRelocation(i)
        fn = getFunctionName(i)
        DEBUG("{0:x} Found reloc to: {1:x}\n".format(i, pointsto))

        if not isExternalReference(pointsto):
            pf = idc.GetFlags(pointsto)

            DS = D.symbols.add()
            DS.base_address = i+seg_offset

            if idc.isCode(pf):
                DS.symbol_name = "sub_"+hex(pointsto)
                DEBUG("Code Ref: {0:x}!\n".format(pointsto))

                if pointsto not in RECOVERED_EAS:
                    new_eas.add(pointsto)

            elif idc.isData(pf):
                pointsto = handleDataRelocation(M, pointsto, new_eas)
                DS.symbol_name = "dta_"+hex(pointsto)
                DEBUG("Data Ref!\n")
            else:
                pointsto = handleDataRelocation(M, pointsto, new_eas)
                DS.symbol_name = "dta_"+hex(pointsto)
                DEBUG("UNKNOWN Ref, assuming data\n")


        i = idc.GetNextFixupEA(i)
Beispiel #18
0
	def getsize(self):
		actual_ea = self.addr
		while (True):
			# first entry case
			f = idc.GetFlags(actual_ea)
			if (len(self.entries) == 0):
				if (not (idc.isRef(f) and (idc.hasName(f) or (f & FF_LABL)))):
					print("[-] Not an entry of vtable")
					return 0
			elif (idc.isRef(f) and (idc.hasName(f) or (f & FF_LABL))):
				# next vtable ?
				break
			if (not idc.hasValue(f) or not idc.isData(f)):
				break
			c = idc.Dword(actual_ea)
			if c:
				f = idc.GetFlags(c)
				if (not idc.hasValue(f) or not idc.isCode(f) or idc.Dword(c) == 0):
					break
			else:
				break
			self.entries.append(actual_ea)
			actual_ea += 4
		print("[+] Vtable %08X - %08X, methods : %d" % (self.addr, actual_ea, (actual_ea - self.addr) / 4))
Beispiel #19
0
def isData(ea):
    '''True if ea marked as data'''
    return idc.isData( idc.GetFlags(ea) )
Beispiel #20
0
    #print("// image 0x%x-0x%x" % (image_begin, image_end))
    print("// extract image: dd skip=$((0x%x)) count=$((0x%x-0x%x)) if=%s of=%s.data bs=1" % \
        (image_begin, image_end, image_begin, idaapi.get_input_file_path(), basename))

def print_section_list():
    for s in idautils.Segments():
        seg = idaapi.getseg(s)
        print("    {name:\"%s\", begin:0x%x, end:0x%x}," % (idc.SegName(s), idc.SegStart(s), idc.SegEnd(s)))

basename = os.path.splitext(idaapi.get_input_file_path())[0]
# basename = os.path.splitext(idaapi.get_root_filename())[0]

# undefine names
names = map(lambda x : x[0], idautils.Names())
names = filter(lambda x : idc.isData(idc.GetFlags(x)), names)

for n in names:
  idc.MakeUnknown(n, 1, 0)

with open(basename + ".cfg", "w") as out:
    prev = sys.stdout
    sys.stdout = out # comment to dump the json into console
    get_file_range()
    print ("{")
    print ("  segments:[")
    print_section_list()
    print ("  ],")
    print ("  cli:[")
    print ("    \"-parse\", \"%s.asm\"," % (basename))
    print ("    \"-save\",  \"%s.cico\"," % (basename))
Beispiel #21
0
end = MaxEA()
while cur_addr < end:
    cur_addr = idc.FindText(cur_addr, SEARCH_DOWN, 0, 0, "_fmode")
    if cur_addr == idc.BADADDR:
        break
    else:
        print hex(cur_addr), idc.GetDisasm(cur_addr)
        cur_addr = idc.NextHead(cur_addr)

#F这个参数需要先通过idc.GetFlags(ea)获取地址的内部标志表示形式,然后再传给idc.is*系列函数当参数

#判断IDA是否将其判定为代码
idc.isCode(F)

#判断IDA是否将其判定为数据
idc.isData(F)

#判断IDA是否将其判定为尾部
idc.isTail(F)

#判断IDA是否将其判定为未知(既不是数据,也不是代码)
idc.isUnknown(F)

#判断IDA是否将其判定为头部
idc.isHead(F)

#0x100001f77L mov     rbx, rsi
#True
ea = here()
print hex(ea), idc.GetDisasm(ea)
print idc.isCode(idc.GetFlags(ea))
Beispiel #22
0
def CountEdgeInBranch(func, parent, cur, stack):
    '''
    Calculate the total number of edges under branches
    @func       function address
    @parent     parent node address
    @cur        the address to start the search. This vuale is typically the starting address of BBL.
    @stack      stack of search address, avoid recusion loops
    '''
    global g_num_edge
    global g_off_set_random
    global g_size_ins_block

    # current pos must in func
    end = idc.GetFunctionAttr(func, idc.FUNCATTR_END)
    if cur < func:
        return

    # avoid recusion loops.
    if cur in stack:
        return
    stack.append(cur)

    ea = cur
    while ea < end and idaapi.BADADDR != ea:  #idaapi.BADADDR
        #print(hex(ea), idc.GetDisasm(ea))
        flag = idc.GetFlags(ea)
        if idc.isData(flag):
            ea += idc.ItemSize(ea)
            continue

        if not idc.isCode(flag):
            ea += 1
            continue

        # code
        # found a child node, stop
        if ea < end - g_size_ins_block and IsInstrumentIns(ea):
            g_num_edge += 1
            return

        asm = idc.GetDisasm(ea)
        if 0 == len(asm):
            ea += 1
            continue

        elif asm[:3] == 'ret':
            return

        # jmp jz jnz ja ......
        elif 'j' == asm[0]:  # and 'm' != idc.GetDisasm(ea)[1]:

            for xref in idautils.XrefsFrom(ea):  # idautils.ida_xref.XREF_ALL)
                if xref.type == 18 or xref.type == 19:  # 18 :'Code_Far_Jump', 19 : 'Code_Near_Jump',   please see XrefTypeName
                    CountEdgeInBranch(func, parent, xref.to, stack)

                elif xref.type == 20:  # 20 : 'Code_User'
                    print('******************************************')
                    print('Code_User', hex(parent), hex(ea), idc.GetDisasm(ea))

                elif xref.type == 21:  # 21 : 'Ordinary_Flow'
                    CountEdgeInBranch(func, parent, xref.to, stack)

            return

        else:
            ea += idc.ItemSize(ea)

    return
Beispiel #23
0
def FindChildNode2(func, bbl_heads, parent, cur, stack, num_call, write_head):
    '''
    Handle function which was instrumented by ratio.
    Find 1st layer instrumented child.
    Recusion when encounter jump instruction. Stop when found a child node.
    @func       function address
    @bbl_heads  all bbl heads of function.
    @parent     parent node address
    @cur        the address to start the search. This vuale is typically the starting address of BBL.
    @stack      stack of search address, avoid recusion loops
    @num_call   indicates how many call is contained in one edge.
    @write_head list
    '''
    global g_f
    global g_off_set_random
    global g_size_ins_block
    global g_off_random

    # num_call = 0 # don't count call in parent bbl
    num_mem = 0  # don't count call mem function in parent bbl

    # current pos must in func
    end = idc.GetFunctionAttr(func, idc.FUNCATTR_END)
    if cur < func:
        return

    # avoid recusion loops
    if cur in stack:
        return
    stack.append(cur)

    ea = cur
    while ea < end and idaapi.BADADDR != ea:  #idaapi.BADADDR
        #print(hex(ea), idc.GetDisasm(ea))
        flag = idc.GetFlags(ea)
        if idc.isData(flag):
            ea += idc.ItemSize(ea)
            continue

        if not idc.isCode(flag):
            ea += 1
            continue

        # code
        # found a child node, stop
        if ea < end - g_size_ins_block and IsInstrumentIns(ea):
            parent_id = idc.Dword(
                parent +
                g_off_random)  #(int)(idc.GetOpnd(parent, 1).strip('h'), 16)
            child_id = idc.Dword(
                ea + g_off_set_random +
                g_off_random)  #(int)(idc.GetOpnd(ea+0x13, 1).strip('h'), 16)
            #if len(g_dict_func_edge):
            if 1 == write_head[0]:  # found a child node, stop
                g_f.write(("%d %d\n") % (num_call, num_mem))
                write_head[0] = 0
                return

            if parent != ea + g_off_set_random:
                #g_f.write(("%d %d %d %d %d %d %d\n") % ( parent, ea+0x13, parent_id, child_id, (parent_id >> 1) ^ child_id, num_call, num_mem ))
                g_f.write(("%d %d %d %d %d ") %
                          (parent, ea + g_off_set_random, parent_id, child_id,
                           (parent_id >> 1) ^ child_id))
                write_head[0] = 1
            #return

        if ea in bbl_heads:
            pass

        mnem = idc.GetMnem(ea)  #asm = idc.GetDisasm(ea)
        if mnem[:3] == 'ret':  #asm[:3] == 'ret':
            if write_head[0]:  # found a child node, stop
                g_f.write(("%d %d\n") % (num_call, num_mem))
                write_head[0] = 0
            return

        # jmp jz jnz ja ......
        elif 'j' == mnem[
                0]:  # and 'm' != mnem[1]:   jmp dst addr has been instumented.

            if write_head[0]:  # found a child node, stop
                g_f.write(("%d %d\n") % (num_call, num_mem))
                write_head[0] = 0
                return

            for xref in idautils.XrefsFrom(ea):  # idautils.ida_xref.XREF_ALL)
                if xref.type == 18 or xref.type == 19:  # 18 :'Code_Far_Jump', 19 : 'Code_Near_Jump',   please see XrefTypeName
                    FindChildNode2(func, bbl_heads, parent, xref.to, stack,
                                   num_call, write_head)

                elif xref.type == 20:  # 20 : 'Code_User'
                    print('******************************************')
                    print('Code_User', hex(parent), hex(ea), idc.GetDisasm(ea))

                elif xref.type == 21:  # 21 : 'Ordinary_Flow'
                    FindChildNode2(func, bbl_heads, parent, xref.to, stack,
                                   num_call, write_head)

            return

        # call.  count call ins.
        elif mnem == 'call':  #asm.startswith('call'):
            to = 0
            for to in idautils.CodeRefsFrom(ea, False):
                fun_name = idc.GetFunctionName(to).lower()
                if IsSanFunc(fun_name):
                    continue
                if fun_name.find('alloc') >= 0 or fun_name.find('free') >= 0 \
                    or fun_name.find('create') >= 0 or fun_name.find('delete') >= 0 \
                    or fun_name.find('destroy') >= 0:
                    num_mem += 1
                break
            # only count instrumented function
            if idc.SegName(ea) == idc.SegName(to):
                if not IsSanFunc(fun_name) and IsInstrumentIns(to):
                    #if len(g_dict_func_edge):
                    #    num_call += g_dict_func_edge[to]
                    #else:
                    num_call += 1
            ea += idc.ItemSize(ea)
            continue

        else:
            ea += idc.ItemSize(ea)
            #ea += idc.DecodeInstruction(ea)
            #ea = idc.NextNotTail(ea)

    if write_head[0]:
        g_f.write(("%d %d\n") % (num_call, num_mem))
        write_head[0] = 0

    return
Beispiel #24
0
    def getContent(self, bin=False):
        """
        reads bytes at the EA of the data item and constructs its content representation based on its type
        :param bin: if True, array of bytes is always passed back
        """
        flags = idc.GetFlags(self.ea)
        output = -1

        if idc.isCode(flags):
            # an instruction is also data, its bytes are gathered and combined into one integer
            bytes = []
            for char in idc.get_bytes(self.ea, self.getSize()):
                bytes.append(ord(char))
            # either return one discrete instruction int, or an array of bytes representing it
            if bin:
                output = bytes
            else:
                output = self._combineBytes(bytes, self.getSize())[0]

        elif idc.isStruct(flags):
            pass
        elif idc.isData(flags):
            # normal case, build up a u8, u16, or u32
            if idc.is_data(flags) and (
                    idc.is_byte(flags) and self.getSize() == 1
                    or idc.is_word(flags) and self.getSize() == 2
                    or idc.is_dword(flags) and self.getSize() == 4):
                bytes = []
                for char in idc.get_bytes(self.ea, self.getSize()):
                    bytes.append(ord(char))
                # either return one discrete primitive, or the array of bytes representing it
                if bin:
                    output = bytes
                else:
                    output = self._combineBytes(bytes, self.getSize())[0]
            # The weird case... an array. I don't know why it's weird. IDA doesn't like it!
            else:
                # It is assumed this is an array, but the type is unknown. Imply type based on disasm of first line!
                firstLineSplitDisasm = list(
                    filter(None, re.split('[ ,]', idc.GetDisasm(self.ea))))
                dataType = firstLineSplitDisasm[0]
                elemsPerLine = len(
                    firstLineSplitDisasm
                ) - 1  # don't include type, ex: DCB 0, 4, 5, 0x02, 0

                # Grab all of the bytes in the array
                bytes = []
                for char in idc.get_bytes(self.ea, idc.get_item_size(self.ea)):
                    bytes.append(ord(char))

                # figure out datatype to convert the array to be of
                bytesPerElem = dataType == 'DCB' and 1 \
                               or dataType == 'DCW' and 2 \
                               or dataType == 'DCD' and 4 \
                               or 1  # if type unknown, just show it as a an array of bytes

                # create new array with correct type, or just return the bytes
                if bin:
                    output = bytes
                else:
                    output = self._combineBytes(bytes, bytesPerElem)
        elif idc.isUnknown(flags):
            # unknown data elements are always 1 byte in size!
            output = ord(idc.get_bytes(self.ea, 1))
            if bin: output = [output]
        return output
def IsData(addr):
    return idc.isData(idc.GetFlags(addr))
Beispiel #26
0
def isInternalCode(ea):

    pf = idc.GetFlags(ea)
    return idc.isCode(pf) and not idc.isData(pf)
Beispiel #27
0
 def isData(self):
     return idc.isData(idc.GetFlags(self.ea))
Beispiel #28
0
def isInternalCode(ea):

    pf = idc.GetFlags(ea)
    return idc.isCode(pf) and not idc.isData(pf)
Beispiel #29
0
def InsIsData(i):
    return idc.isData(idaapi.getFlags(i))
Beispiel #30
0
        YaCo.yaco.commit_cache()
    # save intermediate bases
    if debug:
        idc.SaveBase(idbname)

# save generator as global for all tests
# and prevent potential conflicts
_functions = sorted([k for k in idautils.Functions()])
_not_functions = sorted([j for j in  (set([k for k in idautils.Heads()]) - set(_functions))])
_codes = []
_datas = []
for ea in _not_functions:
    flags = idc.GetFlags(ea)
    if idc.isCode(flags) and not idaapi.isFunc(flags):
        _codes.append(ea)
    elif idc.isData(flags):
        _datas.append(ea)

def _get_next_from_list(list_from, predicate=None):
    for i in xrange(0, len(list_from)):
        ea = list_from[i]
        if not predicate or predicate(ea):
            del list_from[i]
            return ea
    raise BaseException(idaapi.BADADDR)
    

def get_next_function(predicate=None):
    return _get_next_from_list(_functions, predicate)

def get_next_not_function(predicate=None):
Beispiel #31
0
def address_is_code(address):
  pf = idc.GetFlags(address)
  return idc.isCode(pf) and not idc.isData(pf)
Beispiel #32
0
def address_is_data(address):
  pf = idc.GetFlags(address)
  return not idc.isCode(pf) and idc.isData(pf)
Beispiel #33
0
def isData(ea):
    '''True if ea marked as data'''
    return idc.isData(idc.GetFlags(ea))
Beispiel #34
0
 def is_data(self):
     """True if current object is data"""
     return idc.isData(self.flags)