def fixupSysctlSet(): ''' fixupSysctlSet: Fixes up the '__sysctl_set' segment, ensures the targets are actually 'sysctl_oid' structures and adds the correct function type to the handler. ''' segm = idaapi.get_segm_by_name("__DATA:__sysctl_set") if not segm: segm = idaapi.get_segm_by_name("__sysctl_set") if not segm: print "Could not find kernel __sysctl_set section" return segea = segm.startEA segend = segm.endEA sid = get_struc_id("sysctl_oid") ssize = get_struc_size(sid) stru = get_struc(sid) if ssize == 0: print "Could not load information about 'sysctl_oid' struct" return # clear whole range of sysctl_set segment idaapi.do_unknown_range(segea, segend - segea, DOUNK_DELNAMES) # idapython oldschool - we work with the structure offset oid_handler = get_member_by_name(stru, "oid_handler") # loop through sysctl_set segment while segea < segend: # Ensure pointer is a pointer idaapi.op_offset(segea, 0, idaapi.REF_OFF32, 0xffffffff, 0, 0) ptr = idc.Dword(segea) # Mark structure as sysctl_oid structure idaapi.do_unknown_range(ptr, ssize, DOUNK_DELNAMES) x = doStruct(ptr, ssize, sid) handler = idc.Dword(ptr + oid_handler.soff) # We have to support ARM THUMB code addr = handler & 0xFFFFFFFE # Set correct function type for oid_handler idc.SetType( addr, "int *oid_handler(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);" ) segea += 4
def fixupSysctlSet(): ''' fixupSysctlSet: Fixes up the '__sysctl_set' segment, ensures the targets are actually 'sysctl_oid' structures and adds the correct function type to the handler. ''' segm = idaapi.get_segm_by_name("__DATA:__sysctl_set") if not segm: segm = idaapi.get_segm_by_name("__sysctl_set") if not segm: print "Could not find kernel __sysctl_set section" return segea = segm.startEA segend = segm.endEA sid = get_struc_id("sysctl_oid") ssize = get_struc_size(sid) stru = get_struc(sid) if ssize == 0: print "Could not load information about 'sysctl_oid' struct" return # clear whole range of sysctl_set segment idaapi.do_unknown_range(segea, segend-segea, DOUNK_DELNAMES) # idapython oldschool - we work with the structure offset oid_handler = get_member_by_name(stru, "oid_handler") # loop through sysctl_set segment while segea < segend: # Ensure pointer is a pointer idaapi.op_offset(segea, 0, idaapi.REF_OFF32, 0xffffffff, 0, 0) ptr = idc.Dword(segea) # Mark structure as sysctl_oid structure idaapi.do_unknown_range(ptr, ssize, DOUNK_DELNAMES) x = doStruct(ptr, ssize, sid) handler = idc.Dword(ptr + oid_handler.soff) # We have to support ARM THUMB code addr = handler & 0xFFFFFFFE # Set correct function type for oid_handler idc.SetType(addr, "int *oid_handler(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);") segea += 4
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 __init__(self): self.sym_file_path = idc.AskFile(0, "*.map;*.txt", "open symbol file") self.sym_file = None self.seg = idaapi.get_segm_by_name(".text") if self.seg is None: self.seg = idaapi.getnseg(0) self.base = self.seg.startEA
def __init__(self, dotnet_version): self.dotnet_version = dotnet_version self.imagebase = idaapi.get_imagebase() self.module_header_struct = idaapi.get_segm_by_name(".rdata").start_ea self.nb_custom_modules = idaapi.get_dword(self.module_header_struct + \ dotnet_versions_offsets[self.dotnet_version]\ ["nbCustomModules"])
def search_ea(sig, segment="", callback=None): eas = [] if segment != "": seg = idaapi.get_segm_by_name(segment) if not seg: return ea, maxea = seg.startEA, seg.endEA count = 0 while ea != idaapi.BADADDR: ea = idaapi.find_binary(ea, maxea, sig, 16, idaapi.SEARCH_DOWN) if ea != idaapi.BADADDR: count = count + 1 if callback != None: callback(ea) else: eas.append(ea) ea += 2 else: for seg in Segments(): ea = SegStart(seg) maxea = SegEnd(ea) count = 0 while ea != idaapi.BADADDR: ea = idaapi.find_binary(ea, maxea, sig, 16, idaapi.SEARCH_DOWN) if ea != idaapi.BADADDR: count = count + 1 if callback != None: callback(ea) else: eas.append(ea) ea += 2 return eas
def __init__(self, ea=UseCurrentAddress, name=None, index=None): """Wrapper around IDA segments. There are 3 ways to get a segment - by name, ea or index. Only use one. Args: ea - address in the segment name - name of the segment index - index of the segment """ if sum((ea not in (self.UseCurrentAddress, None), name is not None, index is not None,)) > 1: raise ValueError( "Expected only one (ea, name or index). Got (ea={!r}, name={!r}, index={!r})".format(ea, name, index)) elif name is not None: seg = idaapi.get_segm_by_name(name) elif index is not None: seg = idaapi.getnseg(index) elif ea == self.UseCurrentAddress: seg = idaapi.getseg(idc.here()) elif ea is None: raise ValueError("`None` is not a valid address. To use the current screen ea, " "use `Function(ea=Function.UseCurrentAddress)` or supply no `ea`.") else: seg = idaapi.getseg(ea) self._segment = seg
def find_tablegroups(segname=".data"): ''' Returns a list of (start, end) ea pairs for the vtable groups in 'segname' ''' # 设置计数的返回值 # count = 0 seg = idaapi.get_segm_by_name(segname) ea = seg.startEA vtbs = [] # print hex(seg.endEA) while ea < seg.endEA: # 记录之前ea的值 prev_ea = ea ea, ptr = read_ea(ea) if ptr == 0: continue # 检测是否为方法 if isFunction(ptr): # print hex(ea) # 如果是off开头,则可以确认为虚表 # if is_vtb_begin(prev_ea): ea, vtb = store_segVtb(prev_ea) # 空的列表则不添加 if vtb.get('vtb_func_lists') == []: continue vtbs.append(vtb) # count = count + 1 # if count==4: # break # pprint(vtbs) return vtbs
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 by_name(name): '''Return the segment with the given `name`.''' res = utils.string.to(name) seg = idaapi.get_segm_by_name(res) if seg is None: raise E.SegmentNotFoundError(u"{:s}.by_name({!r}) : Unable to locate the segment with the specified name.".format(__name__, name)) return seg
def main(): global cfgTree cfgTree = CFGTree() seg = idaapi.get_segm_by_name("__text") # Loop from segment start to end func_ea = seg.startEA # Get a function at the start of the segment (if any) func = idaapi.get_func(func_ea) if func is None: # No function there, try to get the next one func = idaapi.get_next_func(func_ea) seg_start = seg.startEA seg_end = seg.end_ea while func is not None and func.start_ea < seg_end: funcea = func.start_ea fflags = idc.get_func_flags(funcea) if (fflags & idc.FUNC_LIB) or (fflags & idc.FUNC_THUNK): continue # print("Function %s at 0x%x" % (idc.get_func_name(funcea), funcea)) flow = idaapi.FlowChart(idaapi.get_func(funcea), flags=idaapi.FC_PREDS) construct_cfg(flow, funcea, seg_start, seg_end) func = idaapi.get_next_func(funcea) cfgTree.print_deepest_path()
def renamer_init(): renamed = 0 gopclntab = idaapi.get_segm_by_name('.gopclntab') if gopclntab is not None: # Skip unimportant header and goto section size addr = gopclntab.startEA + 8 size, addr_size = create_pointer(addr) addr += addr_size # Unsure if this end is correct early_end = addr + (size * addr_size * 2) while addr < early_end: func_offset, addr_size = create_pointer(addr) name_offset, addr_size = create_pointer(addr + addr_size) addr += addr_size * 2 func_name_addr = Dword(name_offset + gopclntab.startEA + addr_size) + gopclntab.startEA func_name = GetString(func_name_addr) MakeStr(func_name_addr, func_name_addr + len(func_name)) appended = clean_func_name = clean_function_name(func_name) debug( 'Going to remap function at 0x%x with %s - cleaned up as %s' % (func_offset, func_name, clean_func_name)) if idaapi.get_func_name(func_offset) is not None: if MakeName(func_offset, clean_func_name): renamed += 1 else: error('clean_func_name error %s' % clean_func_name) return renamed
def find_func_by_name(name): text_seg = idaapi.get_segm_by_name('.text') for addr in Functions(text_seg.startEA, text_seg.endEA): if name == idaapi.get_func_name(addr): return idaapi.get_func(addr) return None
def get_seg(seg_names): seg = None for seg_name in seg_names: seg = idaapi.get_segm_by_name(seg_name) if seg: return seg return seg
def _get_seg(possible_seg_names): seg = None for seg_name in possible_seg_names: seg = idaapi.get_segm_by_name(seg_name) if seg: return seg return seg
def by_name(name): '''Return the segment with the given `name`.''' s = idaapi.get_segm_by_name(name) if s is None: raise E.SegmentNotFoundError( "{:s}.by_name({!r}) : Unable to locate the segment with the specified name." .format(__name__, name)) return s
def check_if_segm_exists(self): segm = idaapi.get_segm_by_name(self.config.entropy['segm_name']) if segm: self.config.entropy['segm_exists'] = True self.config.entropy['segm_addr'] = segm.start_ea else: self.config.entropy['segm_exists'] = False self.config.entropy['segm_addr'] = None
def stringRecoveryB(): #for exe _rodata_name = "_rodata" if not idaapi.get_segm_by_name(".rodata"): _rodata_name = "_rdata" userfunc = getUserFunctions(False) for func in userfunc: addr_list = [] inst = func while inst < find_func_end(func): addr_list += [inst] inst = find_code(inst, SEARCH_DOWN) for i in range(len(addr_list) - 2): if print_insn_mnem(addr_list[i]) == "lea" and print_insn_mnem( addr_list[i + 1]) == "mov" and print_insn_mnem( addr_list[i + 2]) == "mov": if "qword ptr [" in print_operand( addr_list[i + 1], 0) and "qword ptr [" in print_operand( addr_list[i + 2], 0): if get_operand_value(addr_list[i + 2], 0) - get_operand_value( addr_list[i + 1], 0) == 8: Addr = get_operand_value(addr_list[i], 1) Len = get_operand_value(addr_list[i + 2], 1) seg_name = idaapi.get_visible_segm_name( idaapi.getseg(Addr)) if seg_name == _rodata_name: if get_wide_byte(Addr + Len) != 0: MyMakeStr(Addr, Len) #print hex(Addr), Len elif print_operand(addr_list[i + 1], 0) == "eax" and print_operand( addr_list[i + 2], 1) == "eax": Addr = get_operand_value(addr_list[i], 1) Len = get_operand_value(addr_list[i + 1], 1) seg_name = idaapi.get_visible_segm_name( idaapi.getseg(Addr)) if seg_name == _rodata_name: if get_wide_byte(Addr + Len) == 0: Len += 1 MyMakeStr(Addr, Len) #print hex(addr_list[i]), hex(Addr), Len if print_insn_mnem(addr_list[i]) == "lea": if "ref_" in print_operand(addr_list[i], 1) or "off_" in print_operand( addr_list[i], 1): Addr = get_operand_value(addr_list[i], 1) seg_name = idaapi.get_visible_segm_name( idaapi.getseg(Addr)) if seg_name == _rodata_name or seg_name == "_data_rel_ro": Len = get_qword(Addr + 8) Cmt = get_string(get_qword(Addr), Len) if Cmt != "": #print hex(addr_list[i]),Len,get_string(get_qword(Addr),Len) MakeRptCmt(addr_list[i], Cmt)
def find_segment(seg_name): text_segment = idaapi.get_segm_by_name(seg_name).start_ea if text_segment == BADADDR: text_segment = FirstSeg() if text_segment == BADADDR: return BADADDR return text_segment
def go_buildid(): # TODO: work only for windows textstart = idaapi.get_segm_by_name(".text").startEA buildid = GetManyBytes(textstart, 0x3c) if buildid.startswith("\xff Go build ID: \""): MakeStr(textstart, textstart + 0x3c) return buildid[1:-1] else: return None
def set_hypercalls_name(): global g_TableEntrySize StartAddress = idaapi.get_segm_by_name( "CONST" ).start_ea # usually start of CONST segment, but it will can change in future print("Address of HvCallTable is ", hex(StartAddress)) hvCallCount = get_hypercall_count(StartAddress) hv_table_count = len(g_hvcalls_dict) if hvCallCount > len(g_hvcalls_dict): print( "Warning! Hypercall's count is more then size of table with list of known hypercalls. Some hypercalls will be undefined. " ) add_hypercall_stats_enum(hvCallCount) check_hvix_os_version(hvCallCount) idc.set_name(StartAddress, str('HvCallTable'), SN_NOWARN) # Working with first element manually HvCallReserved00 = idc.get_qword(StartAddress) ida_bytes.del_items(HvCallReserved00, 0, 1) idc.create_insn(HvCallReserved00) idc.add_func(HvCallReserved00) idc.set_name(HvCallReserved00, str('HvCallReserved00'), SN_NOWARN) for j in range(0, 6): idc.create_data(StartAddress + 8 + j * 2, FF_WORD, 2, ida_idaapi.BADADDR) j = j + 1 idc.create_data(StartAddress + 8 + j * 2, FF_DWORD, 4, ida_idaapi.BADADDR) idc.op_enum(StartAddress + 8 + j * 2, 0, g_hv_stats, 0) # Next elements for i in range(1, hvCallCount + 1): hvCallAddress = idc.get_qword(StartAddress + i * g_TableEntrySize) if hvCallAddress != HvCallReserved00: idc.create_insn(hvCallAddress) idc.add_func(hvCallAddress) if i < hv_table_count: idc.set_name(hvCallAddress, g_hvcalls_dict[i], SN_NOWARN) else: hvcall_name = "HvCallUknown" + hex(i) idc.set_name(hvCallAddress, hvcall_name, SN_NOWARN) for j in range(0, 6): dw_addr = idc.create_data( StartAddress + i * g_TableEntrySize + 8 + j * 2, FF_WORD, 2, ida_idaapi.BADADDR) j = j + 1 idc.create_data(StartAddress + i * g_TableEntrySize + 8 + j * 2, FF_DWORD, 4, ida_idaapi.BADADDR) idc.op_enum(StartAddress + i * g_TableEntrySize + 8 + j * 2, 0, g_hv_stats, 0)
def seg_by_name(self, name): ida_seg = idaapi.get_segm_by_name(name) if ida_seg is None: return None perms = 0 perms |= SEG_PROT_R if ida_seg.perm & idaapi.SEGPERM_READ else 0 perms |= SEG_PROT_W if ida_seg.perm & idaapi.SEGPERM_WRITE else 0 perms |= SEG_PROT_X if ida_seg.perm & idaapi.SEGPERM_EXEC else 0 return self.angrdbg_mod.Segment(name, ida_seg.start_ea, ida_seg.end_ea, perms)
def get_idata(self): #return tuple(start_addr, end_addr) ida_seg = idaapi.get_segm_by_name(".idata") if ida_seg is None: addr = None def cb(ea, name, i): addr = ea idaapi.enum_import_names(0, cb) ida_seg = idaapi.seg_by_addr(addr) return (ida_seg.start_ea, ida_seg.end_ea)
def by_name(name): '''Return the segment with the given `name`.''' res = utils.string.to(name) seg = idaapi.get_segm_by_name(res) if seg is None: raise E.SegmentNotFoundError( u"{:s}.by_name({!r}) : Unable to locate the segment with the specified name." .format(__name__, name)) return seg
def create(offset, size, name, **kwds): '''Create a segment at /offset/ and /size/ and name it /name/ /bits/ can be used to specify the bit size of the segment /comb/ can be used to specify any flags (idaapi.sc*) /align/ can be used to specify paragraph alignment (idaapi.sa*) /org/ specifies the origin of the segment (must be paragraph aligned due to ida) ''' s = idaapi.get_segm_by_name(name) if s is not None: logging.fatal( "segment.create(%x, %x, %r, %r) : a segment with the specified name already exists : %s", offset, size, name, kwds, name) return None bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset). abits()) # FIXME: use disassembler default bit length instead of 32 if bits == 16: ## create a selector with the requested origin org = kwds.get('org', 0) if org & 0xf > 0: logging.fatal( "segment.create(%x, %x, %r, %r) : origin (.org) is not aligned to the size of a paragraph (0x10):%x", offset, size, name, kwds, org) return None para = offset / 16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para - kwds.get('org', 0) / 16) & 0xffffffff) else: ## auto-create a selector for everything else sel = idaapi.setup_selector( kwds['selector'] ) if 'selector' in kwds else idaapi.find_free_selector() # create segment. ripped from idc s = idaapi.segment_t() s.startEA = offset s.endEA = offset + size s.sel = sel s.bitness = {16: 0, 32: 1, 64: 2}[bits] s.comb = kwds.get('comb', idaapi.scPub) # public s.align = kwds.get('align', idaapi.saRelByte) # paragraphs res = idaapi.add_segm_ex(s, name, "", idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_SPARSE) if res == 0: logging.warn( "segment.create(%x, %x, %r, %r) : unable to add a new segment", offset, size, name, kwds) res = idaapi.del_selector(sel) #assert res != 0 return None return s
def find_sig(segment, sig, callback): seg = idaapi.get_segm_by_name(segment) if not seg: return ea, maxea = seg.start_ea, seg.end_ea while ea != idaapi.BADADDR: ea = idaapi.find_binary(ea, maxea, sig, 16, idaapi.SEARCH_DOWN) if ea != idaapi.BADADDR: callback(ea) ea += 4
def get_heap_base(self, address=None): if not address: segm = idaapi.get_segm_by_name("[heap]") # same as mp_->sbrk_base if segm: return segm.start_ea else: heap_addr = self.heap_for_ptr(address) heap_addr = heap_addr + sizeof(self.heap_info_s) + sizeof( self.malloc_state_s) return round_up(heap_addr, self.malloc_alignment) return None
def find_gopclntab(self): found = False try: ea = idaapi.get_segm_by_name(".gopclntab").startEA found = True except: ea = MinEA() ea = FindBinary(ea, SEARCH_DOWN, self.header) if ea!=0xffffffffffffffff: found = True return (found, ea)
def find_1337babes(): res = [] ea = idaapi.get_segm_by_name('.text').startEA while True: found_addr = FindBinary(ea, SEARCH_NEXT|SEARCH_DOWN, "BE BA 37 13") if found_addr != 0xFFFFFFFFFFFFFFFF: res.append(found_addr) ea = found_addr else: break return res
def __init__(self): self.text = get_segm_by_name(".text") self.data = get_segm_by_name(".data") self.rdata = get_segm_by_name(".rdata") # try to use rdata if there actually is an rdata segment, otherwise just use data if self.rdata is not None: self.valid_ranges = [(self.rdata.startEA, self.rdata.endEA), (self.data.startEA, self.data.endEA)] else: self.valid_ranges = [(self.data.startEA, self.data.endEA)] # self.x64 = (idaapi.getseg(here()).bitness == 2) # if self.x64: # self.PTR_TYPE = FF_QWRD # self.REF_OFF = REF_OFF64 # self.PTR_SIZE = 8 # self.get_ptr = get_64bit # else: self.PTR_TYPE = FF_DWRD self.REF_OFF = REF_OFF32 self.PTR_SIZE = 4 self.get_ptr = get_32bit
def _lookup_segments(self): """ Looks up __TEXT:__cstring, __TEXT:__text, __DATA:__const """ self.cstring_seg = get_segm_by_name(CSTRING_SEGNAME) if type(self.cstring_seg) == type(None): print "[!] Error looking up %s" % CSTRING_SEGNAME return False self.text_seg = get_segm_by_name(TEXT_SEGNAME) if type(self.text_seg) == type(None): print "[!] Error looking up %s" % TEXT_SEGNAME return False self.data_seg = get_segm_by_name(DATA_SEGNAME) if type(self.data_seg) == type(None): print "[!] Error looking up %s" % DATA_SEGNAME return False return True
def relocate_bootblock(): bootblk_start = 0xF000 << 4 bootblk_end = 0x10000 << 4 bootblk_baseparagraph = 0xF000 bootblk_size = 0x10000 # 64 Kbyte idaapi.add_segm(bootblk_baseparagraph, bootblk_start, bootblk_end, "BOOTBLK", "CODE") bootblk = idaapi.get_segm_by_name("BOOTBLK") idaapi.set_segm_addressing(bootblk, 16) bootblk_addr = get_bootblock_start_address() print("Found bootblock at {0} addr!".format(hex(bootblk_addr))) relocate_segment(bootblk_addr, bootblk_start, bootblk_size)
def obtain_segment_data(segname): """ Given a segment name, return the bytes within the segment. :param segname: Name of the segment :return: Data from the specified segment. """ seg = idaapi.get_segm_by_name(segname) if seg: return _read_bytes(seg.startEA, seg.endEA) return None
def find_section(name): sec = idaapi.get_segm_by_name(name) S = 0 E = 0 if sec is not None: S = sec.startEA E = sec.endEA print "found %s (%x - %x)" % (name, S, E) return S, E
def strings_init(): strings_added = 0 retry = [] text_seg = idaapi.get_segm_by_name('.text') # 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 Functions(text_seg.startEA, text_seg.endEA): name = GetFunctionName(addr) end_addr = Chunks(addr).next()[1] if (end_addr < addr): error('Unable to find good end for the function %s' % name) pass debug('Found function %s starting/ending @ 0x%x 0x%x' % (name, addr, end_addr)) while addr <= end_addr: if is_string_load(addr): if 'rodata' not in idaapi.get_segm_name( addr) and 'text' not in idaapi.get_segm_name(addr): debug('Should a string be in the %s section?' % idaapi.get_segm_name(addr)) string_addr = GetOperandValue(addr, 1) addr_3 = FindCode(FindCode(addr, SEARCH_DOWN), SEARCH_DOWN) string_len = GetOperandValue(addr_3, 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 = FindCode(addr_3, SEARCH_DOWN) else: addr = FindCode(addr, 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: 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 rebuild_functions_from_prologues(): segm = idaapi.get_segm_by_name("__text") seg_start = segm.startEA seg_end = segm.endEA print ("Segment Address : 0x%08x-0x%08x"%(seg_start, seg_end)) cursor = seg_start while cursor < seg_end: #print ("Cursor Offset : 0x%08x"%cursor) #cursor = idaapi.find_not_func(cursor, 0x1) #print Byte(cursor) if (Byte(cursor) == 0x55 and Byte(cursor+1) == 0x48 and Byte(cursor+2) == 0x89): idc.MakeFunction(cursor) cursor += 1
def create(offset, size, name, **kwds): '''Create a segment at /offset/ and /size/ and name it /name/ /bits/ can be used to specify the bit size of the segment /comb/ can be used to specify any flags (idaapi.sc*) /align/ can be used to specify paragraph alignment (idaapi.sa*) /org/ specifies the origin of the segment (must be paragraph aligned due to ida) ''' s = idaapi.get_segm_by_name(name) if s is not None: logging.fatal("segment.create(%x, %x, %r, %r) : a segment with the specified name already exists : %s", offset, size, name, kwds, name) return None bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).abits()) # FIXME: use disassembler default bit length instead of 32 if bits == 16: ## create a selector with the requested origin org = kwds.get('org',0) if org&0xf > 0: logging.fatal("segment.create(%x, %x, %r, %r) : origin (.org) is not aligned to the size of a paragraph (0x10):%x", offset, size, name, kwds, org) return None para = offset/16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para-kwds.get('org',0)/16)&0xffffffff) else: ## auto-create a selector for everything else sel = idaapi.setup_selector(kwds['selector']) if 'selector' in kwds else idaapi.find_free_selector() # create segment. ripped from idc s = idaapi.segment_t() s.startEA = offset s.endEA = offset+size s.sel = sel s.bitness = {16:0,32:1,64:2}[bits] s.comb = kwds.get('comb', idaapi.scPub) # public s.align = kwds.get('align', idaapi.saRelByte) # paragraphs res = idaapi.add_segm_ex(s, name, "", idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_SPARSE) if res == 0: logging.warn("segment.create(%x, %x, %r, %r) : unable to add a new segment", offset, size, name, kwds) res = idaapi.del_selector(sel) #assert res != 0 return None return s
def activate(self, ctx): print 'Starting Swift demangling' seg = idaapi.get_segm_by_name('.plt'); # if seg == None: # print 'Segment .plt was not found, exiting' # return count = 0 for funcea in Functions(seg.startEA, seg.endEA): func_name = GetFunctionName(funcea)[1:] demangled_output = self.demangle(func_name).split(' ---> ') name = demangled_output[0].strip() demangled_name = demangled_output[1].strip() if name == demangled_name: continue count += 1 self.comment_xrefs(funcea, demangled_name) print 'Successfully demangled %d functions' % count
def findAllKEXT(): """ findAllKEXT: Finds all KEXT contained in the kernelcache file. The mach-o headers will be converted into the appropiate structs, the new sections will be defined and the name and version number of the KEXT are extracted. In the end a window is shown that shows all contained KEXT. """ # Ask the user if he wants to add all the KEXT sections # to the IDA database. answer = idc.AskYN(0, """Do you want to add all the KEXT sections to the IDA database? If this was already done before or there was already code or data in the same place in the IDA database, IDA might react very slow, crash or just stop to work.""") # KEXT cache starts behind the __LINKEDIT segment # NOTE: IDA calls the segment __LINKEDIT_hidden linkedit = idaapi.get_segm_by_name("__LINKEDIT_hidden") if not linkedit: print "[-] cannot find KEXTCACHE: __LINKEDIT segment not found" return kextcache = idaapi.get_next_seg(linkedit.endEA) if not kextcache: print "[-] cannot find KEXTCACHE: __LINKEDIT not followed by any segment" return dummyName = idaapi.get_segm_name(kextcache) if dummyName != "__text": print "[-] cannot find KEXTCACHE: __LINKEDIT not followed by __text segment" return if answer == 1: # Destroy everything in the kextcache area idaapi.do_unknown_range(kextcache.startEA, kextcache.endEA-kextcache.startEA, DOUNK_DELNAMES) startEA = kextcache.startEA kextlist = [] while True: sig = idc.Dword(startEA) if sig != 0xfeedface: "[-] expected the next KEXT but did not find correct signature" break seg_lc = None sections = [] added = 0 next = forceStruct(startEA, "mach_header") ncmds = get_member_from_struct(startEA, "mach_header", "ncmds") for i in range(ncmds): lc_addr = next cmd = get_member_from_struct(next, "load_command", "cmd") if cmd == 1: seg_lc = next next = forceStruct(seg_lc, "segment_command") nsecs = get_member_from_struct(seg_lc, "segment_command", "nsects") for j in range(nsecs): section = next next = forceStruct(section, "section") # Get basic information about segment (needed for ALL the code below) secStart = get_member_from_struct(section, "section", "addr") secEnd = secStart + get_member_from_struct(section, "section", "size") secname = idc.GetString(section) # We should tell IDA about what this section is s = idaapi.segment_t() s.startEA = secStart s.endEA = secEnd s.sel = idaapi.setup_selector(0) if secname == "__text": s.bitness = 0 else: s.bitness = 1 s.align = get_member_from_struct(section, "section", "align") s.comb = 0 # ??? if secname == "__text" or secname == "stubs": sclass = "CODE" elif secname == "__bss": sclass = "BSS" else: sclass = "DATA" if len(sections) == 0: sec = {} sec["name"] = "MACH-O HEADER" sec["start"] = "%08X" % (startEA) sec["end"] = "%08X" % (secStart-1) sections.append(sec) sec = {} sec["name"] = secname sec["start"] = "%08X" % (secStart) sec["end"] = "%08X" % (secEnd-1) sections.append(sec) if answer == 1: # Destroy everything inside the segment idaapi.do_unknown_range(secStart, secEnd-secStart, DOUNK_DELNAMES) # Ensure that the whole section is undefined idaapi.add_segm_ex(s, secname, sclass, idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_QUIET) if secname == "__text": idc.SetRegEx(secStart, "T", 1, 0) # special handling of constructor and destructor if secname == "__constructor" or secname == "__destructor": for z in range(secStart, secEnd, 4): idc.OpOffEx(z, -1, REF_OFF32, 0xFFFFFFFF, 0, 0) # We have to check for __data section because we want # to find the kmod_info structure if secname != "__data": continue kextName = None for z in range(secStart, secEnd, 4): k = z # We assume that all KEXT name start with "com." kextNameSig = idc.Dword(k) if kextNameSig == 0x2e6d6f63: forceStruct(k-12, "kmod_info") kextName = idc.GetString(k) kextVersion = idc.GetString(k+64) #print "-> %s - version: %s" % (kextName, kextVersion) dic = {} dic["addr"] = "%08X" % (startEA) dic["name"] = kextName dic["version"] = kextVersion kextlist.append(dic) added = 1 break if kextName == None: print "ERROR COULD NOT FIND NAME" elif cmd == 0x1b: next = forceStruct(lc_addr, "uuid_command") elif cmd == 0x2: next = forceStruct(lc_addr, "symtab_command") #print "Found symbol table KEXT at %08x" % (startEA) else: print "Unknown load command %08x" % (cmd) if added: kextlist[len(kextlist)-1]["sections"] = sections next = lc_addr + get_member_from_struct(lc_addr, "load_command", "cmdsize") if seg_lc == None: startEA += 4 while idc.Dword(startEA) != 0xfeedface: startEA += 4 continue startEA = get_member_from_struct(seg_lc, "segment_command", "vmaddr") startEA += get_member_from_struct(seg_lc, "segment_command", "vmsize") c = MySelectionDialog("Retrieved KEXT", [ ["Address", 10], [ "Name", 65 ], ["Version", 65] ], formatKEXTresults(kextlist)) selected_row = c.Show(True) if selected_row >= 0: sel = kextlist[selected_row] c = MySelectionDialog("Sections inside " + sel["name"], [ ["Name", 16], [ "Start", 10 ], ["End", 10] ], formatSECTIONresults(sel["sections"])) selected_row = c.Show(True) if selected_row >= 0: sel = sel["sections"][selected_row] idc.Jump(int(sel["start"], 16))
def new(offset, size, name, **kwds): """Create a segment at `offset` with `size` and name it according to `name`. The keyword `bits` can be used to specify the bit size of the segment The keyword `comb` can be used to specify any flags (idaapi.sc*) The keyword `align` can be used to specify paragraph alignment (idaapi.sa*) The keyword `org` specifies the origin of the segment (must be paragraph aligned due to ida) """ res = utils.string.to(name) # find the segment according to the name specified by the user seg = idaapi.get_segm_by_name(res) if seg is not None: raise E.DuplicateItemError(u"{:s}.new({:#x}, {:+#x}, \"{:s}\"{:s}) : A segment with the specified name (\"{:s}\") already exists.".format(__name__, offset, size, utils.string.escape(name, '"'), u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', utils.string.escape(name, '"'))) # FIXME: use disassembler default bit length instead of 32 bits = kwds.get( 'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).abits()) ## create a selector with the requested origin if bits == 16: org = kwds.get('org',0) if org & 0xf > 0: raise E.InvalidTypeOrValueError(u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : The specified origin ({:#x}) is not aligned to the size of a paragraph (0x10).".format(__name__, offset, size, name, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', org)) para = offset/16 sel = idaapi.allocate_selector(para) idaapi.set_selector(sel, (para-kwds.get('org',0)/16)&0xffffffff) ## if the user specified a selector, then use it elif 'sel' in kwds or 'selector' in kwds: sel = kwds.get('sel', kwds.get('selector', idaapi.find_free_selector())) ## choose the paragraph size defined by the user elif 'para' in kwds or 'paragraphs' in kwds: para = kwds.get('paragraph', kwds.get('para', 1)) sel = idaapi.setup_selector(para) ## find a selector that is 1 paragraph size, elif idaapi.get_selector_qty(): sel = idaapi.find_selector(1) # otherwise find a free one and set it. else: sel = idaapi.find_free_selector() idaapi.set_selector(sel, 1) # populate the segment_t using code ripped from the idc module seg = idaapi.segment_t() seg.startEA = offset seg.endEA = offset+size seg.sel = sel seg.bitness = {16:0,32:1,64:2}[bits] seg.comb = kwds.get('comb', idaapi.scPub) # public seg.align = kwds.get('align', idaapi.saRelByte) # paragraphs # now we can add our segment_t to the database res = utils.string.to(name) ok = idaapi.add_segm_ex(seg, res, "", idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_SPARSE) if not ok: ok = idaapi.del_selector(sel) if not ok: logging.warn(u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to delete the created selector ({:#x}) for the new segment.".format(__name__, offset, size, name, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '', sel)) raise E.DisassemblerError(u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to add a new segment.".format(__name__, offset, size, name, u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '')) return seg
def byName(name): '''Return the segment_t with the given /name/''' s = idaapi.get_segm_by_name(name) if s is None: raise Exception, "segment.byName(%r):unable to locate segment"% name return s
def test_read(ea): args = walk_stack(ea, 3) arg_dict = {} for x in args: arg_dict[x[1]] = trace_arg(x[0]) arg_dict['nbytes'] = hex2int(arg_dict['nbytes']) arg_dict['buf'] = calculate_buffer_size(arg_dict['buf']) if arg_dict['buf'] < arg_dict['nbytes']: return True, hex(ea), arg_dict else: return False, hex(ea), arg_dict ### Populate BSS <Hail Chris Eagle> start = idaapi.get_segm_by_name(".bss").startEA end = idaapi.get_segm_by_name(".bss").endEA item = idc.NextHead(start - 1, end) bss = {} while item != BADADDR: next = idc.NextHead(item, end) if next != BADADDR: bss[idc.Name(item)] = next - item else: bss[idc.Name(item)] = end - item item = next ### Populate Functions functions = {} for x in idautils.Functions(): functions[idc.GetFunctionName(x)] = x
# 8A 89 B0 D5 04 10 mov cl, key[ecx] # ^ key offset key_offset = struct.unpack("<I", idaapi.get_many_bytes(addr + 2, 4))[0] elif idaapi.get_many_bytes(addr, 1) == "\x6B": # 6B C2 33 imul eax, edx, 51 # ^ key length key_len = idaapi.get_byte(addr + 2) elif idaapi.get_many_bytes(addr, 3) == "\x8B\x04\xDD": # 8B 04 DD C0 DE 06 10 mov eax, packed_strings_list[ebx*8] # ^ address of string list struct_base = struct.unpack("<I", idaapi.get_many_bytes(addr + 3, 4))[0] print "[*] Decoding function : 0x{:08x}".format(int(decoding_func.startEA)) print "[*] Encoded string list base : 0x{:08x}".format(struct_base) data_seg = idaapi.get_segm_by_name(".data") xor_key = idaapi.get_many_bytes(key_offset, key_len) index = 0 while True: addr = struct_base + index * 8 data_ptr, size = struct.unpack("<II", idaapi.get_many_bytes(addr, 8)) if data_ptr < data_seg.startEA or data_ptr > data_seg.endEA: # We don't know how many strings there are so we stop when the pointer # to the data doesn't make sense. break data = idaapi.get_many_bytes(data_ptr, size) decrypted_string = "".join( [chr(ord(data[i]) ^ ord(xor_key[i % len(xor_key)])) for i in range(size)]