def analyze_init_array(): print('analyze_init_array') seg = idc.SegByName('.init_array') addr = idc.SegByBase(seg) seg_st = idc.GetSegmentAttr(addr, idc.SEGATTR_START) seg_en = idc.GetSegmentAttr(addr, idc.SEGATTR_END) print(' .init_array = %08X - %08X' % (seg_st, seg_en)) if addr == idc.BADADDR: return while addr < seg_en: funcaddr = idc.Dword(addr) if funcaddr > 0: name = idc.Name(funcaddr) if name is None or name.startswith('sub_'): idc.MakeName(funcaddr, 'INIT_%X' % funcaddr) print(' %08X: %s' % (funcaddr, idc.Name(funcaddr))) addr += 4 return seg_st
def dump_binary(fname): max_addr = 0 # Check if we have a buggy IDA or not try: idaapi.get_many_bytes_ex(0, 1) except TypeError: buggy = True else: buggy = False if buggy: f = idaapi.qfile_t() f.open(fname, 'wb+') segments = [x for x in idautils.Segments()] max_addr = idc.GetSegmentAttr(segments[-1], idc.SEGATTR_END) # TODO check max_addr to see if it's sane to write such a big file idaapi.base2file(f.get_fp(), 0, 0, max_addr) f.close() else: with open(fname, 'wb+') as f: # over all segments for s in idautils.Segments(): start = idc.GetSegmentAttr(s, idc.SEGATTR_START) end = idc.GetSegmentAttr(s, idc.SEGATTR_END) # print "Start: %x, end: %x, size: %x" % (start, end, end-start) max_addr = max(max_addr, end) f.seek(start, 0) # Only works with fixed IDAPython. f.write(idaapi.get_many_bytes_ex(start, end - start)[0]) dump_log.debug("section[dump] = 0, 0x%x, 0, 0x%x", max_addr, max_addr)
def segment_bytes(self, val): """ Will obtain segment bytes for the segment in which EA is contained or by segment name. This will be on demand and segment bytes will be cached if they have not already been obtained :param string|int val: either the name of a segment or an EA within a segment :return string: bytes which are contained with the segment """ if isinstance(val, str): seg_start = idaapi.get_segm_by_name(val).startEA if seg_start is None: raise AssertionError( "could not find segment for {}".format(val)) elif isinstance(val, numbers.Number): seg_start = idc.GetSegmentAttr(val, idc.SEGATTR_START) seg_bytes = self.segments.get(seg_start) if seg_bytes is None: seg_end = idc.GetSegmentAttr(seg_start, idc.SEGATTR_END) seg_bytes = self._get_segment_bytes(seg_start, seg_end) self.segments[seg_start] = seg_bytes return seg_bytes
def get_f5_comments(self): cmts = [] for seg in idautils.Segments(): ea = idc.SegStart(seg) if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) != idaapi.SEG_CODE: continue seg_name = idc.SegName(seg) end = idc.SegEnd(seg) while ea < end: if ea != idc.BADADDR and idc.GetFunctionFlags( ea) != 0xffffffff: try: cfunc = idaapi.decompile(ea) for tl, citem in cfunc.user_cmts.items(): current_cmt = [ "%s:%-16X" % (seg_name, tl.ea), 'F5', idc.GetDisasm(tl.ea), citem.c_str() ] # F5 comments cmts.append(current_cmt) self.n += 1 except idaapi.DecompilationFailure: pass finally: ea = idc.GetFunctionAttr(ea, idc.FUNCATTR_END) else: ea = idc.next_head(ea, end) return cmts
def is_code(ea): if is_invalid_ea(ea): return False seg_ea = idc.SegStart(ea) seg_type = idc.GetSegmentAttr(seg_ea, idc.SEGATTR_TYPE) return seg_type == idc.SEG_CODE
def resolve_unknown_functions(): proc_name = get_proc_name() if proc_name.startswith("mips"): prolog_pattern = FUNCTION_PROLOGS.get(proc_name, "BAD ARCH") elif proc_name.startswith("ARM"): prolog_pattern = FUNCTION_PROLOGS.get(proc_name, "BAD ARCH") else: # TODO: support another arch return ea = get_start_ea(idaapi.SEG_CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() cur_seg_end = idc.SegEnd(ea) while ea != idc.BADADDR: if ea < cur_seg_end and idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == idaapi.SEG_CODE: if idc.GetFunctionFlags(ea) == -1: # not function raw_data_hex = read_addr(ea) if re.match(prolog_pattern, raw_data_hex.decode('hex')): idc.MakeFunction(ea) ea = ea + 4 else: ea = idc.NextSeg(ea) cur_seg_end = idc.SegEnd(ea)
def is_64_bit(ea): '''Returns True if the ea is in a 64 bit segment, false otherwise''' seg_ea = get_current_segment(ea) if seg_ea: return idc.GetSegmentAttr(seg_ea, idc.SEGATTR_BITNESS) == 2 else: return False # Assume things are 32-bit if all else fails.
def codeify(self, ea=idc.BADADDR): func_count = 0 code_count = 0 if ea == idc.BADADDR: ea = self.get_start_ea(self.CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() print "\nLooking for undefined code starting at: %s:0x%X" % ( idc.SegName(ea), ea) if self.get_start_ea(self.DATA) == idc.BADADDR: print "WARNING: No data segments defined! I don't know where the code segment ends and the data segment begins." while ea != idc.BADADDR: try: if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == self.CODE: if idc.GetFunctionName(ea) != '': ea = idc.FindFuncEnd(ea) continue else: if idc.MakeFunction(ea): func_count += 1 elif idc.MakeCode(ea): code_count += 1 except: pass ea = idc.NextAddr(ea) print "Created %d new functions and %d new code blocks\n" % ( func_count, code_count)
def codeify(self, ea=idc.BADADDR): func_count = 0 code_count = 0 if ea == idc.BADADDR: ea = self.get_start_ea(self.CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() self.say("\nLooking for undefined code starting at: %s:0x%X" % (idc.SegName(ea), ea)) while ea != idc.BADADDR: try: if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == self.CODE: if idc.GetFunctionName(ea) != '': ea = idc.FindFuncEnd(ea) continue else: if idc.MakeFunction(ea): func_count += 1 elif idc.MakeCode(ea): code_count += 1 except: pass ea = idc.NextAddr(ea) self.say("Created %d new functions and %d new code blocks\n" % (func_count, code_count))
def has_segment_type(ea, expected_seg_type): """Returns true if the segment containing `ea` has the type `seg_type`.""" seg = idc.SegStart(ea) if seg == idc.BADADDR: return False seg_type = idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) return seg_type == expected_seg_type
def GetROSections(): seg_addrs_readonly = [] for seg in idautils.Segments(): seg_start_ea = idc.SegStart(seg) seg_end_ea = idc.SegEnd(seg) flags = idc.GetSegmentAttr(seg, idc.SEGATTR_PERM) if flags & 6: # Flags 4 means read-only seg_addrs_readonly.append([seg_start_ea, seg_end_ea]) return seg_addrs_readonly
def processDataSegments(M, new_eas): for n in xrange(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) ea = seg.startEA segtype = idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) if segtype in [idc.SEG_DATA, idc.SEG_BSS]: start = idc.SegStart(ea) end = idc.SegEnd(ea) addDataSegment(M, start, end, new_eas)
def is_external_segment_by_flags(ea): try: seg_ea = idc.SegStart(ea) seg_type = idc.GetSegmentAttr(seg_ea, idc.SEGATTR_TYPE) if seg_type == idc.SEG_XTRN: _EXTERNAL_SEGMENTS.add(seg_ea) return True else: return False except: return False
def getx86CodeSize(ea=None): ''' For a given EA, finds the code size. Returns 16 for-16bit, 32 for 32-bit, or 64 for 64-bit. If no EA is given, searches through all segments for a code segment to use. ''' if ea is None: for seg in idautils.Segments(): if idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) == idc.SEG_CODE: ea = seg break if ea is None: raise RuntimeError('Could not find code segment to use for getx86CodeSize') bitness = idc.GetSegmentAttr(ea, idc.SEGATTR_BITNESS) if bitness == 0: return 16 elif bitness == 1: return 32 elif bitness == 2: return 64 raise RuntimeError('Bad bitness')
def is_invalid_ea(ea): """Returns `True` if `ea` is not valid, i.e. it doesn't point into any valid segment.""" if idc.BADADDR == ea: return True try: idc.GetSegmentAttr(idc.SegStart(ea), idc.SEGATTR_TYPE) return False # If we get here, then it must be a valid ea! except: return True
def isExternalReference(ea): # see if this is in an internal or external code ref ext_types = [idc.SEG_XTRN] seg = idc.SegStart(ea) if seg == idc.BADADDR: raise Exception("Could not get segment addr for: {0:x}\n".format(ea)) segtype = idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) if segtype in ext_types: return True return False
def is_external_segment_by_flags(ea): """Returns `True` if IDA believes that `ea` belongs to an external segment.""" try: seg_ea = idc.SegStart(ea) seg_type = idc.GetSegmentAttr(seg_ea, idc.SEGATTR_TYPE) if seg_type == idc.SEG_XTRN: _EXTERNAL_SEGMENTS.add(seg_ea) return True else: return False except: return False
def load_til(path_to_til): if not ida_typeinf.load_til(path_to_til, os.path.dirname(path_to_til)): raise Exception("load_til('%s') has failed" % (path_to_til)) # Fix UINTN to be the actual word size if we can determine it idc.Til2Idb(-1, "UINTN") entry = idc.GetEntryPoint(idc.GetEntryOrdinal(0)) if entry != idc.BADADDR: typedef = "typedef UINT" + str(16 << idc.GetSegmentAttr(entry, idc.SEGATTR_BITNESS)) + " UINTN;" for i in range(0, idc.GetMaxLocalType()): if idc.GetLocalTypeName(i) == "UINTN": idc.SetLocalType(idc.SetLocalType(i, "", 0), typedef, 0)
def get_start_ea(self, attr): ea = idc.BADADDR seg = idc.FirstSeg() while seg != idc.BADADDR: if idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) == attr: ea = seg break else: seg = idc.NextSeg(seg) return ea
def get_data_section(self): ea = idc.BADADDR seg = idc.FirstSeg() while seg != idc.BADADDR: if ea == idc.BADADDR and idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) == 2: ea = seg stop = idc.SegEnd(seg) seg = idc.NextSeg(seg) return (ea, stop)
def analyse_data(pointer_size): """Go through the data sections and look for possible tables of code pointers.""" log.info("Analysing the data section for simple code refs") for seg_ea in idautils.Segments(): seg_type = idc.GetSegmentAttr(seg_ea, idc.SEGATTR_TYPE) if seg_type != idc.SEG_DATA: continue min_ea, max_ea = idc.SegStart(seg_ea), idc.SegEnd(seg_ea) if 8 == pointer_size: scan_data_for_code_refs(min_ea, max_ea, idc.Qword, 8) scan_data_for_code_refs(min_ea, max_ea, idc.Dword, 4)
def _get_segments(self, attr): segments = [] start = idc.BADADDR end = idc.BADADDR seg = idc.FirstSeg() while seg != idc.BADADDR: if idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) == attr: start = idc.SegStart(seg) end = idc.SegEnd(seg) segments.append((start, end)) seg = idc.NextSeg(seg) return segments
def isExternalReference(ea): # see if this is in an internal or external code ref DEBUG("Testing {0:x} for externality\n".format(ea)) ext_types = [idc.SEG_XTRN] seg = idc.SegStart(ea) if seg == idc.BADADDR: DEBUG("WARNING: Could not get segment addr for: {0:x}\n".format(ea)) return False segtype = idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) if segtype in ext_types: return True return False
def find_default_function_heads(): """Loop through every function, to discover the heads of all blocks that IDA recognizes. This will populate some global sets in `flow.py` that will help distinguish block heads.""" func_heads = set() for seg_ea in idautils.Segments(): seg_type = idc.GetSegmentAttr(seg_ea, idc.SEGATTR_TYPE) if seg_type != idc.SEG_CODE: continue for func_ea in idautils.Functions(seg_ea, idc.SegEnd(seg_ea)): if is_code_by_flags(func_ea): func_heads.add(func_ea) return func_heads
def find_ret_addrs(s): s_addr = s addrs = [] s_start = s_addr s_end = idc.GetSegmentAttr(s_start, SEGATTR_END) while (s_addr < s_end): d = Dword(s_addr) if ret_addr(d): addrs.append(s_addr) s_addr += 4 return addrs
def get_architecture_name(self): """Fetch the name to be used to identify the architecture.""" # Get the addressing mode of the first segment in the IDB and # set it to describe the module in the database. # This would need to be rethought for the cases where addressing # might change withing a module. # bitness = idc.GetSegmentAttr( list(idautils.Segments())[0], idc.SEGATTR_BITNESS) if bitness == 0: bitness = 16 elif bitness == 1: bitness = 32 elif bitness == 2: bitness = 64 return '%s-%d' % (self.arch_name, bitness)
def main(): base_addr = 0 ea = 0 idc.MakeFunction(ea) # heuristic while (true): mnemonic = idc.GetMnem(ea) if "LDR" in mnemonic: base_str = idc.GetOpnd(ea, 1) base_addr = int(base_str.split("=")[1], 16) break ea += 4 print("[+] rebasing to address 0x%x" % (base_addr)) idc.rebase_program(base_addr, idc.MSF_FIXONCE) idaapi.autoWait() segment_start = base_addr segment_end = idc.GetSegmentAttr(segment_start, idc.SEGATTR_END) ea = segment_start print("[+] searching and defining functions") while ea != idc.BADADDR: ea = idc.FindBinary(ea, idc.SEARCH_DOWN, "BF A9", 16) if ea != idc.BADADDR: ea = ea - 2 if (ea % 4) == 0 and idc.GetFlags(ea) < 0x200: # print("[+] defining a function at 0x%x" % (ea)) idc.MakeFunction(ea) ea = ea + 4 idc.AnalyzeArea(segment_start, segment_end) idaapi.autoWait()
def init_arch(self): if hasattr(idaapi, 'get_inf_structure'): info = idaapi.get_inf_structure() else: info = idaapi.cvar.inf bitness = idc.GetSegmentAttr( list(idautils.Segments())[0], idc.SEGATTR_BITNESS) if bitness == 0: bitness = 16 elif bitness == 1: bitness = 32 elif bitness == 2: bitness = 64 print bitness if info.procName == 'metapc': if bitness == 64: self.arch = X64() elif bitness == 32: self.arch = X86() else: print 'TODO: implement many architecture :)' return
def bottom(ea): return idc.GetSegmentAttr(ea, idc.SEGATTR_END)
def top(ea): return idc.GetSegmentAttr(ea, idc.SEGATTR_START)