def is_ELF_thunk_by_structure(ea): """Try to manually identify an ELF thunk by its structure.""" from util import * global _INVALID_THUNK_ADDR inst = None for i in range(4): # 1 is good enough for x86, 4 for aarch64. inst, _ = decode_instruction(ea) if not inst: break # elif is_direct_jump(inst): # ea = get_direct_branch_target(inst) # inst = None if is_indirect_jump(inst) or is_direct_jump(inst): target_ea = get_reference_target(inst.ea) if not is_invalid_ea(target_ea): seg_name = idc.get_segm_name(target_ea).lower() if ".got" in seg_name or ".plt" in seg_name: target_ea = get_reference_target(target_ea) seg_name = idc.get_segm_name(target_ea).lower() if "extern" == seg_name: return True, target_ea ea = inst.ea + inst.size return _INVALID_THUNK_ADDR
def calc_pe_size(self, image_base): # Blind guess at PE size based on contigious segments size = idc.get_segm_end(image_base) - image_base prev = idc.get_segm_start(image_base) offset = idc.get_next_seg(image_base) if offset == ida_idaapi.BADADDR: size = 0 # Size based on contigious segments by address while offset != ida_idaapi.BADADDR and idc.get_segm_end( prev) == offset: size += idc.get_segm_end(offset) - offset prev = offset offset = idc.get_next_seg(offset) if size <= 0x1000: name = idc.get_segm_name(image_base) prev = idc.get_segm_start(image_base) offset = idc.get_next_seg(image_base) start = offset # Size based on contigious segments by name while offset != ida_idaapi.BADADDR and idc.get_segm_name( prev) == name: prev = offset offset = idc.get_next_seg(offset) size = idc.get_segm_end(offset) - start self.ret = size return self.ret
def fromDataToFunc(ea, deep): if deep > 5: print('No Xref function is found ' + hex(ea)) return [] funcs = [] refs = idautils.DataRefsTo(ea) for r in refs: if idc.get_segm_name(r) == '.text': funcs.append(idc.get_func_attr(r, idc.FUNCATTR_START)) elif idc.get_segm_name(r) == '.data' or idc.get_segm_name(r) == '.bss': # orign = r # r = r-1 cnt = 1 while not idc.get_name(r): r -= 1 cnt += 1 if cnt > 100: print('cannot find a real label in .data' + hex(ea)) break if cnt < 100: funcs = funcs + fromDataToFunc(r, deep + 1) else: print("Ref in Seg {} at Addr {}".format(idc.get_segm_name(r), r)) if not funcs: print('No Xref function is found ' + hex(ea)) return funcs
def parse_strings(): strings_added = 0 retry = [] text_seg = common.get_text_seg() if text_seg is None: common._debug('Failed to get text segment') return strings_added # This may be inherently flawed as it will only search for defined functions # and as of IDA Pro 6.95 it fails to autoanalyze many GO functions, currently # this works well since we redefine/find (almost) all the functions prior to # this being used. Could be worth a strategy rethink later one or on diff archs for addr in idautils.Functions(text_seg.startEA, text_seg.endEA): name = idc.GetFunctionName(addr) end_addr = idautils.Chunks(addr).next()[1] if (end_addr < addr): common._error('Unable to find good end for the function %s' % name) pass common._debug('Found function %s starting/ending @ 0x%x 0x%x' % (name, addr, end_addr)) while addr <= end_addr: if parse_str_ptr(addr): strings_added += 1 addr = idc.FindCode(addr, idaapi.SEARCH_DOWN) elif is_string_patt(addr): if 'rodata' not in idc.get_segm_name( addr) and 'text' not in idc.get_segm_name(addr): common._debug('Should a string be in the %s section?' % idc.get_segm_name(addr)) string_addr = idc.GetOperandValue(addr, 1) addr_3 = idc.FindCode(idc.FindCode(addr, idaapi.SEARCH_DOWN), idaapi.SEARCH_DOWN) string_len = idc.GetOperandValue(addr_3, 1) if string_len > 1: if create_string(string_addr, string_len): if create_offset(addr): strings_added += 1 else: # There appears to be something odd that goes on with IDA making some strings, always works # the second time, so lets just force a retry... retry.append((addr, string_addr, string_len)) # Skip the extra mov lines since we know it won't be a load on any of them addr = idc.FindCode(addr_3, idaapi.SEARCH_DOWN) else: addr = idc.FindCode(addr, idaapi.SEARCH_DOWN) for instr_addr, string_addr, string_len in retry: if create_string(string_addr, string_len): if create_offset(instr_addr): strings_added += 1 else: common._error( 'Unable to make a string @ 0x%x with length of %d for usage in function @ 0x%x' % (string_addr, string_len, instr_addr)) return strings_added
def BL(self, bl_addr): # OSMetaClass::OSMetaClass(this, className, superclass, classSize) X0, X1, X3 = (self.regs[n] for n in ('X0', 'X1', 'X3')) if (X0 and X1 and X3 and idc.get_segm_name(X1).endswith("__cstring") and idc.get_segm_name(X0)): found_metaclass(X0, idc.get_strlit_contents(X1))
def is_ELF_thunk_by_structure(ea): """Try to manually identify an ELF thunk by its structure.""" from util import * global _INVALID_THUNK_ADDR seg_name = idc.get_segm_name(ea).lower() if ".plt" not in seg_name: return _INVALID_THUNK_ADDR inst, _ = decode_instruction(ea) if not inst or not (is_indirect_jump(inst) or is_direct_jump(inst)): return _INVALID_THUNK_ADDR target_ea = get_reference_target(inst.ea) if is_invalid_ea(target_ea): return _INVALID_THUNK_ADDR seg_name = idc.get_segm_name(target_ea).lower() if ".got" in seg_name or ".plt" in seg_name: target_ea = get_reference_target(target_ea) seg_name = idc.get_segm_name(target_ea).lower() if "extern" == seg_name: return True, target_ea return _INVALID_THUNK_ADDR
def find_pe(self, cursor=False): """Search IDB for possible MZ/PE headers""" info = idaapi.get_inf_structure() mz_headers = [] # Check current cursor for MZ/PE? if cursor: # Get IDA cursor address addr = idc.here() # Get segment and end address s = idaapi.getseg(addr) e = idc.get_segm_end(addr) # Check for MZ magic if ida_bytes.get_word(addr) == 0x5a4d: # Ensure the PE header is in the segment e_lfanew = ida_bytes.get_dword(addr + 0x3c) if addr + e_lfanew + 1 < e: # Check for PE magic if ida_bytes.get_word(addr + e_lfanew) == 0x4550: # Found possible MZ/PE header mz_headers.append([addr, idc.get_segm_name(addr), info.is_64bit()]) self.ret = mz_headers return self.ret # Search all segments for seg in idautils.Segments(): s = idc.get_segm_start(seg) e = idc.get_segm_end(seg) addr = s while True: # Find first byte of MZ header addr = ida_bytes.find_byte(addr, e-addr, 0x4d, 0) if addr == ida_idaapi.BADADDR or addr >= e: break # Check for MZ magic if ida_bytes.get_word(addr) == 0x5a4d: # Ensure the PE header is in the segment e_lfanew = ida_bytes.get_dword(addr + 0x3c) if addr + e_lfanew + 1 < e: # Check for PE magic if ida_bytes.get_word(addr + e_lfanew) == 0x4550: # Found possible MZ/PE header mz_headers.append([addr, idc.get_segm_name(s), info.is_64bit()]) # Resume search from next address addr += 1 self.ret = mz_headers return self.ret
def on_BL(addr, reg): X0, X1, X3 = reg['X0'], reg['X1'], reg['X3'] if not (X0 and X1 and X3): return _log(5, 'Have call to {:#x}({:#x}, {:#x}, ?, {:#x})', addr, X0, X1, X3) # OSMetaClass::OSMetaClass(this, className, superclass, classSize) if not idc.get_segm_name(X1).endswith( "__TEXT.__cstring") or not idc.get_segm_name(X0): return found_metaclass(X0, ida_bytes.get_strlit_contents(X1), X3, reg['X2'] or None)
def get_global_seg_start(self, segs_name): global_seg_start = {} for seg in idautils.Segments(): if idc.get_segm_name(seg) in segs_name: global_seg_start[idc.get_segm_name(seg)] = seg if not '.roooodata' in global_seg_start: start, _ = self.add_rodata_segment() global_seg_start['.roooodata'] = start self.global_seg_start = global_seg_start return global_seg_start
def getSegAddr(): textStart=0 textEnd=0 end = 0 for seg in idautils.Segments(): if (idc.get_segm_name(seg)).lower()=='.text' or (idc.get_segm_name(seg)).lower()=='text': textStart=idc.get_segm_start(seg) textEnd=idc.get_segm_end(seg) tmp = idc.get_segm_end(seg) if end < tmp: end = tmp return textStart,textEnd,end
def bin_info(self, node_title, chunk_addr, chunk, with_size=True): line = idaapi.COLSTR("%s " % node_title, idaapi.SCOLOR_NUMBER) line += idaapi.COLSTR("0x%x\n\n" % chunk_addr, idaapi.SCOLOR_INSN) chunk_info = "" if with_size: chunk_info += "size: 0x%x\n" % chunk.size chunk_info += "fd: 0x%x - %s\nbk: 0x%x - %s" % (chunk.fd, \ idc.get_segm_name(chunk.fd), chunk.bk, idc.get_segm_name(chunk.bk)) line += idaapi.COLSTR(chunk_info, idaapi.SCOLOR_DEFAULT) return line
def getSegAddr(): textStart = [] textEnd = [] for seg in idautils.Segments(): if (idc.get_segm_name(seg)).lower() == '.text' or ( idc.get_segm_name(seg)).lower() == 'text': tempStart = idc.get_segm_start(seg) tempEnd = idc.get_segm_end(seg) textStart.append(tempStart) textEnd.append(tempEnd) return min(textStart), max(textEnd)
def append_segment(segment_name): """ Add a new segment to the IDB file and return its starting address. Information about function arguments will be stored here. Only works if the segment name is not used yet. This does not affect the original binary. Arguments: segment_name -- the name of the segment to be added """ for segment in idautils.Segments(): if idc.get_segm_name(segment) == segment_name: g_logger.warning('Segment ' + segment_name + ' already exists') return idc.get_segm_start(segment) new_segment_start = get_end_of_last_segment() g_logger.debug('Adding new segment at 0x%08x' % new_segment_start) if not idc.AddSeg(new_segment_start, (new_segment_start + NEW_SEGMENT_SIZE), 0, 1, 0, idaapi.scPub) == 1: raise FailedToAppendSegmentException('Could not add segment') # set new segment's attributes if not idc.set_segm_name(new_segment_start, segment_name): raise FailedToAppendSegmentException('Could not rename segment') if not idc.set_segm_class(new_segment_start, 'DATA'): raise FailedToAppendSegmentException('Could not set segment class') if not idc.set_segm_alignment(new_segment_start, idc.saRelPara): raise FailedToAppendSegmentException('Could not align segment') if not idc.set_segm_addressing(new_segment_start, 1): # 1 -- 32 bit raise FailedToAppendSegmentException( 'Could not set segment addressing') return new_segment_start
def initialize_segments(): """Rename the kernelcache segments in IDA according to the __PRELINK_INFO data. Rename the kernelcache segments based on the contents of the __PRELINK_INFO dictionary. Segments are renamed according to the scheme '[<kext>:]<segment>.<section>', where '<kext>' is the bundle identifier if the segment is part of a kernel extension. The special region containing the Mach-O header is renamed '[<kext>:]<segment>.HEADER'. """ # First rename the kernel segments. _log(1, 'Renaming kernel segments') kernel_skip = [ '__PRELINK_TEXT', '__PLK_TEXT_EXEC', '__PRELINK_DATA', '__PLK_DATA_CONST' ] _initialize_segments_in_kext(None, kernel.base, skip=kernel_skip) # Process each kext identified by the __PRELINK_INFO. In the new kernelcache format 12-merged, # the _PrelinkExecutableLoadAddr key is missing for all kexts, so no extra segment renaming # takes place. prelink_info_dicts = kernel.prelink_info['_PrelinkInfoDictionary'] for kext_prelink_info in prelink_info_dicts: kext = kext_prelink_info.get('CFBundleIdentifier', None) mach_header = kext_prelink_info.get('_PrelinkExecutableLoadAddr', None) if kext is not None and mach_header is not None: orig_kext = idc.get_segm_name(mach_header).split(':', 1)[0] if '.kpi.' not in kext and orig_kext != kext: _log(0, 'Renaming kext {} -> {}', orig_kext, kext) _log(1, 'Renaming segments in {}', kext) _initialize_segments_in_kext(kext, mach_header)
def get_segments_memory(self): memory = b"" step_size = self.entropy_cfg['step_size'] segments = OrderedDict() for ea in filter(self.segment_filter, idautils.Segments()): seg_name = idc.get_segm_name(ea) segm = idaapi.get_segm_by_name(seg_name) data = idaapi.get_bytes(segm.start_ea, segm.size()) assert len(data) == segm.size() start_offset = len(memory) end_offset = (start_offset+len(data)) seg_info = { 'segm': segm, 'entropy': entropy(data), 'offsets': [ start_offset , end_offset ], 'chart_offsets': [ start_offset // step_size, end_offset // step_size ] } segments[seg_name] = seg_info memory += data self.data = memory self.data_size = len(memory) self.segments = segments
def get_header_idb(): """get file header from idb""" if idc.get_segm_name(0) == "HEADER": header = bytearray( [idc.get_wide_byte(ea) for ea in range(0, idc.get_segm_end(0))]) return header return bytearray(b"")
def find_all_segments(self, segment_names): segments = {name: None for name in segment_names} for seg_va in Segments(): seg_name = get_segm_name(seg_va) if seg_name in segment_names: segments[seg_name] = (seg_va, get_segm_end(seg_va)) return segments
def method_list(ea): if not ea: return count = ida_bytes.get_dword(ea + 4) name = idc.get_segm_name(ea) first = ea + 8 def post14format(addr): for _ in range(3): data = ida_bytes.get_bytes(addr, 4) offset, = struct.unpack('<i', data) yield addr + offset addr += 4 is14 = name and (name.endswith(':__objc_const_ax') or name.endswith(':__objc_methlist')) for i in range(count): if is14: # iOS 14 yield Post14Method(*post14format(first + i * 12)) else: ea_method_t = first + i * Objc2Method.length data = ida_bytes.get_bytes(ea_method_t, Objc2Method.length) yield Objc2Method(data)
def parse_func_pointer(): renamed = 0 for segea in idautils.Segments(): for addr in idautils.Functions(segea, idc.SegEnd(segea)): #for addr in idautils.Functions(text_seg.startEA, text_seg.endEA): name = idc.GetFunctionName(addr) # Look at data xrefs to the function - find the pointer that is located in .rodata data_ref = idaapi.get_first_dref_to(addr) while data_ref != idc.BADADDR: if 'rodata' in idc.get_segm_name(data_ref): # Only rename things that are currently listed as an offset; eg. off_9120B0 if 'off_' in idc.GetTrueName(data_ref): if idc.MakeNameEx(data_ref, ('%s_ptr' % name), flags=idaapi.SN_FORCE): idaapi.autoWait() renamed += 1 else: common._error( 'Failed to name pointer @ 0x%02x for %s' % (data_ref, name)) data_ref = idaapi.get_next_dref_to(addr, data_ref) common._info("\nRename %d function pointers.\n" % renamed)
def get_value_type(ea): addr_type = T_VALUE if not idaapi.is_loaded(ea): return addr_type segm_name = idc.get_segm_name(ea) segm = idaapi.getseg(ea) flags = idc.get_full_flags(ea) is_code = idc.is_code(flags) if "stack" in segm_name.lower() or \ (dbg.stack_segm and dbg.stack_segm.start_ea == segm.start_ea): addr_type = T_STACK elif "heap" in segm_name.lower(): addr_type = T_HEAP elif not is_code and segm.perm & idaapi.SEGPERM_READ and \ segm.perm & idaapi.SEGPERM_WRITE and \ segm.perm & idaapi.SEGPERM_EXEC: addr_type = T_RWX elif is_code or \ (segm.perm & idaapi.SEGPERM_READ and segm.perm & idaapi.SEGPERM_EXEC): addr_type = T_CODE elif segm.perm & idaapi.SEGPERM_READ and \ segm.perm & idaapi.SEGPERM_WRITE: addr_type = T_DATA elif segm.perm & idaapi.SEGPERM_READ: addr_type = T_RODATA return addr_type
def get_data_refs(self): xrefs = list(idautils.XrefsTo(self.addr)) return len([ x for x in xrefs if (x.type == idautils.ida_xref.dr_O and 'data' in idc.get_segm_name(x.frm).lower()) ])
def __init__(self, show_extra_fields): self.addr = None self.flags = None self.show_extra_fields = show_extra_fields self.names = [ 'Name', 'Address', 'Segment', 'Length', 'Locals', 'Arguments' ] self.handlers = { 0: lambda: None, 1: lambda: self.fmt(self.addr), 2: lambda: '{}'.format(idc.get_segm_name(self.addr)), 3: lambda: self.fmt(idc.get_func_attr(self.addr, idc.FUNCATTR_END) - self.addr), 4: lambda: self.fmt(idc.get_func_attr(self.addr, idc.FUNCATTR_FRSIZE)), 5: lambda: self.fmt(idc.get_func_attr(self.addr, idc.FUNCATTR_ARGSIZE)) } if self.show_extra_fields: self.names.extend(['R', 'F', 'L', 'S', 'B', 'T', '=']) # TODO: add Lumina column info self.handlers.update({ 6: lambda: self.is_true(not self.flags & idc.FUNC_NORET, 'R'), 7: lambda: self.is_true(self.flags & idc.FUNC_FAR, 'F'), 8: lambda: self.is_true(self.flags & idc.FUNC_LIB, 'L'), 9: lambda: self.is_true(self.flags & idc.FUNC_STATIC, 'S'), 10: lambda: self.is_true(self.flags & idc.FUNC_FRAME, 'B'), 11: lambda: self.is_true(idc.get_type(self.addr), 'T'), 12: lambda: self.is_true(self.flags & idc.FUNC_BOTTOMBP, '=') })
def is_external_segment(ea): """Returns `True` if the segment containing `ea` looks to be solely containing external references.""" global _NOT_EXTERNAL_SEGMENTS seg_ea = idc.get_segm_start(ea) if seg_ea in _NOT_EXTERNAL_SEGMENTS: return False if seg_ea in _EXTERNAL_SEGMENTS: return True if is_external_segment_by_flags(ea): _EXTERNAL_SEGMENTS.add(seg_ea) return True ext_types = [] seg_name = idc.get_segm_name(seg_ea).lower() if IS_ELF: if ".got" in seg_name or ".plt" in seg_name: _EXTERNAL_SEGMENTS.add(seg_ea) return True elif IS_PE: if ".idata" == seg_name: # Import table. _EXTERNAL_SEGMENTS.add(seg_ea) return True _NOT_EXTERNAL_SEGMENTS.add(seg_ea) return False
def main(): for segstart, segend, segname in enum_segments(): if segname not in ('.rdata', 'UPX1'): continue print(segname) for src, dst, size in find_pointers(segstart, segend): if idc.get_segm_name(dst) not in (".text", "UPX0"): continue if is_code(dst): continue print("new function pointer: 0x%x -> 0x%x" % (src, dst)) ida_auto.auto_make_code(dst) ida_auto.auto_make_proc(dst) ida_bytes.del_items(src, size) ida_bytes.create_data(src, idc.FF_QWORD if size == 8 else idc.FF_DWORD, size, idc.BADADDR) # this doesn't seem to always work :-( idc.op_plain_offset(src, -1, 0) ida_name.set_name(src, "j_%s_%x" % (src, dst))
def segment_contains_external_function_pointers(seg_ea): """Returns `True` if a segment contains pointers to external functions.""" try: seg_name = idc.get_segm_name(seg_ea) return seg_name.lower() in (".idata", ".plt.got") except: return False
def is_destructor_segment(ea): """Returns `True` if the segment containing `ea` belongs to global destructor section""" seg_ea = idc.get_segm_start(ea) seg_name = idc.get_segm_name(seg_ea).lower() if seg_name in [".fini_array", ".dtor"]: return True return False
def translate_ea(offset): for s in idautils.Segments(): if idc.get_segm_name(s) == ".text": return offset + s print('translate_ea fails..') return None
def translate_ea_to_offset(ea): for s in idautils.Segments(): if idc.get_segm_name(s) == ".text": return ea - s print('translate_ea_to_offset fails...') return None
def is_external_segment(ea): """Returns `True` if the segment containing `ea` looks to be solely containing external references.""" global _NOT_EXTERNAL_SEGMENTS seg_ea = idc.get_segm_start(ea) if seg_ea in _NOT_EXTERNAL_SEGMENTS: return False if seg_ea in _EXTERNAL_SEGMENTS: return True if is_external_segment_by_flags(ea): _EXTERNAL_SEGMENTS.add(seg_ea) return True ext_types = [] seg_name = idc.get_segm_name(seg_ea).lower() if IS_ELF: if ".got" in seg_name or ".plt" in seg_name: _EXTERNAL_SEGMENTS.add(seg_ea) return True elif IS_PE: if ".idata" == seg_name: # Import table. _EXTERNAL_SEGMENTS.add(seg_ea) return True _NOT_EXTERNAL_SEGMENTS.add(seg_ea) return False
def segment_contains_external_function_pointers(seg_ea): """Returns `True` if a segment contains pointers to external functions.""" try: seg_name = idc.get_segm_name(seg_ea) return seg_name.lower() in (".idata", ".plt.got") except: return False
def get_all_func(): num = 0 content = [] for func in idautils.Functions(): seg_perm = idc.get_segm_attr(func,SEGATTR_PERM) # 段属性 if(5 !=seg_perm): continue seg_name = idc.get_segm_name(func) # 段名 if(".plt" == seg_name): continue func_name = idc.get_func_name(func) # 函数名 func_flags = hex(idc.get_func_attr(func,FUNCATTR_FLAGS))# 函数信息 func_head = hex(idc.get_func_attr(func,FUNCATTR_START)) # 函数头 func_end = hex(idc.get_func_attr(func,FUNCATTR_END)) # 函数尾 l = [] l.append(num) l.append(seg_name) l.append(seg_perm) l.append(func_name) l.append(func_flags) l.append(func_head) l.append(func_end) content.append(l) num += 1 #print(l) return content
def is_destructor_segment(ea): """Returns `True` if the segment containing `ea` belongs to global destructor section""" seg_ea = idc.get_segm_start(ea) seg_name = idc.get_segm_name(seg_ea).lower() if seg_name in [".fini_array", ".dtor"]: return True return False
def create_string(addr, string_len): # if idaapi.get_segm_name(addr) is None: if idc.get_segm_name(addr) is None: common._debug( 'Cannot load a string which has no segment - not creating string @ 0x%02x' % addr) return False common._debug('Found string load @ 0x%x with length of %d' % (addr, string_len)) # This may be overly aggressive if we found the wrong area... if idc.GetStringType(addr) is not None and idc.GetString( addr) is not None and len(idc.GetString(addr)) != string_len: common._debug( 'It appears that there is already a string present @ 0x%x' % addr) idc.MakeUnknown(addr, string_len, idc.DOUNK_SIMPLE) idaapi.autoWait() if idc.GetString(addr) is None and idc.MakeStr(addr, addr + string_len): idaapi.autoWait() return True else: # If something is already partially analyzed (incorrectly) we need to MakeUnknown it idc.MakeUnknown(addr, string_len, idc.DOUNK_SIMPLE) idaapi.autoWait() if idc.MakeStr(addr, addr + string_len): idaapi.autoWait() return True common._debug('Unable to make a string @ 0x%x with length of %d' % (addr, string_len)) return False
def recover_frame_entries(seg_ea): if seg_ea == idc.BADADDR: return DEBUG("Recover entries from section : {}".format(idc.get_segm_name(seg_ea))) ea = idc.get_segm_start(seg_ea) end_ea = idc.get_segm_end(seg_ea) while ea != idc.BADADDR and ea < end_ea: ea = format_entries(ea)
def recover_exception_table(): """ Recover the CIE and FDE entries from the segment .eh_frame """ seg_eas = [ea for ea in idautils.Segments() if not is_invalid_ea(ea)] for seg_ea in seg_eas: seg_name = idc.get_segm_name(seg_ea) if seg_name in [".eh_frame", "__eh_frame"]: recover_frame_entries(seg_ea) break
def main(): print("[*] loading crypto constants") for const in non_sparse_consts: const["byte_array"] = convert_to_byte_array(const) for start in idautils.Segments(): print("[*] searching for crypto constants in %s" % idc.get_segm_name(start)) ea = start while ea < idc.get_segm_end(start): bbbb = list(struct.unpack("BBBB", idc.get_bytes(ea, 4))) for const in non_sparse_consts: if bbbb != const["byte_array"][:4]: continue if map(lambda x:ord(x), idc.get_bytes(ea, len(const["byte_array"]))) == const["byte_array"]: print(("0x%0" + str(digits) + "X: found const array %s (used in %s)") % (ea, const["name"], const["algorithm"])) idc.set_name(ea, const["name"]) if const["size"] == "B": idc.create_byte(ea) elif const["size"] == "L": idc.create_dword(ea) elif const["size"] == "Q": idc.create_qword(ea) idc.make_array(ea, len(const["array"])) ea += len(const["byte_array"]) - 4 break ea += 4 ea = start if idc.get_segm_attr(ea, idc.SEGATTR_TYPE) == 2: while ea < idc.get_segm_end(start): d = ida_bytes.get_dword(ea) for const in sparse_consts: if d != const["array"][0]: continue tmp = ea + 4 for val in const["array"][1:]: for i in range(8): if ida_bytes.get_dword(tmp + i) == val: tmp = tmp + i + 4 break else: break else: print(("0x%0" + str(digits) + "X: found sparse constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(idc.prev_head(ea), 0) if cmt: idc.set_cmt(idc.prev_head(ea), cmt + ' ' + const["name"], 0) else: idc.set_cmt(idc.prev_head(ea), const["name"], 0) ea = tmp break ea += 1 print("[*] finished")
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) or \ (idc.get_segm_name(ea) == "LOAD"): return True try: idc.get_segm_attr(idc.get_segm_start(ea), idc.SEGATTR_TYPE) return False # If we get here, then it must be a valid ea! except: return True
def get_destructor_segment(): """Returns the start address of the global destructor section""" for seg_ea in idautils.Segments(): seg_name = idc.get_segm_name(seg_ea).lower() if seg_name in [".fini_array", ".dtor"]: return seg_ea;
def is_tls_segment(ea): try: seg_name = idc.get_segm_name(ea) return seg_name in (".tbss", ".tdata", ".tls") except: return False