def make_offsets(segname): segea = idc.SegByBase(idc.SegByName(segname)) segend = idc.SegEnd(segea) while segea < segend: idc.OpOffset(segea, 0) ptr = idc.Dword(segea) idc.OpOffset(ptr, 0) segea += 4
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 define_functions(): # The function first searches for all user defined functions, reads # the opcodes and searches for that opcodes in the rest of the file. # # You can extend this by adding more disassembled instructions that # make you believe are function prologues. # # Obviously not any PUSH is a function start, this is only a filter # against erroneously defined functions. So if you define a function # that starts with other instruction (and you think there could be # other functions that start with that instruction), just add it here. prologues = ["STMFD", "push", "PUSH", "mov", "MOV"] print "Finding all signatures" #ea= 0 ea = 0x11800000 #ea = 0x10000000 opcodes = set() if idc.SegStart(ea) == 0xFFFFFFFF: print "Wrong segment address set!" return for funcea in idautils.Functions(idc.SegStart(ea), idc.SegEnd(ea)): # Get the opcode start_opcode = idc.Dword(funcea) # Get the disassembled text dis_text = idc.GetDisasm(funcea) we_like_it = False # Filter possible errors on manually defined functions for prologue in prologues: if prologue in dis_text: we_like_it = True # If it passes the filter, add the opcode to the search list. if we_like_it: opcodes.add(start_opcode) print "# different opcodes: %x" % (len(opcodes)) while len(opcodes) > 0: # Search for this opcode in the rest of the file opcode_bin = opcodes.pop() opcode_str = " ".join( x.encode("hex") for x in struct.pack("<L", opcode_bin)) print "Searching for " + opcode_str matches = find_all(opcode_str) for matchea in matches: # If the opcode is found in a non-function if not idc.GetFunctionName(matchea): # Try to make code and function print "Function at " + hex(matchea) idc.MakeCode(matchea) idc.MakeFunction(matchea) print "We're done!"
def nextCompressedData(ea, end_ea=None): if not end_ea: end_ea = idc.SegEnd(ea) while ea < end_ea: if mt.getLZ77CompressedSize(ea) >= 0: return ea ea += 1 return -1
def recover_frame_entries(seg_ea): if seg_ea == idc.BADADDR: return DEBUG("Recover entries from section : {}".format(idc.SegName(seg_ea))) ea = idc.SegStart(seg_ea) end_ea = idc.SegEnd(seg_ea) while ea != idc.BADADDR and ea < end_ea: ea = format_entries(ea)
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 get_list_of_functions(self): '''Get all functions list.''' seg_ea = idc.BeginEA() functions_list = {} for func_ea in idautils.Functions(idc.SegStart(seg_ea), idc.SegEnd(seg_ea)): function_name = self.maybe_demangle(idc.GetFunctionName(func_ea)) functions_list[function_name] = func_ea return functions_list
def get_functions(): ''' enumerate the functions in the currently loaded module. Yields: int: address of the function. ''' startea = idc.BeginEA() for fva in idautils.Functions(idc.SegStart(startea), idc.SegEnd(startea)): yield fva
def setBPs(self): """ Set breakpoints on all CALL and RET instructions in all of the executable sections. """ for seg_ea in idautils.Segments(): for head in idautils.Heads(seg_ea, idc.SegEnd(seg_ea)): if idc.isCode(idc.GetFlags(head)): # Add BP if instruction is a CALL if is_call(head): self.addBP(head)
def apply_everywhere(): hr_remove() for segea in idautils.Segments(): for funcea in idautils.Functions(segea, idc.SegEnd(segea)): print("Handling %s" % idc.GetFunctionName(funcea)) try: cfunc = ida_hexrays.decompile(funcea) apply_on_fn(cfunc) except ida_hexrays.DecompilationFailure as e: print("Failed to decompile!") hr_install()
def analyse_subroutines(): """Goes through all the subroutines that IDA's initial auto analysis discovers.""" log.info("Analysing subroutines") exported_eas = find_exported_eas() log.info("IDA identified {} exported functions".format(len(exported_eas))) subs = set() sub_eas = set() # Work list. sub_eas.update(exported_eas) # Get all subroutines that IDA recognised. for seg_ea in idautils.Segments(): min_ea, max_ea = idc.SegStart(seg_ea), idc.SegEnd(seg_ea) sub_eas.update(idautils.Functions(min_ea, max_ea)) log.info("IDA identified {} functions".format(len(sub_eas))) bad_sub_eas = set() for sub_ea in sub_eas: if has_segment_type(sub_ea, idc.SEG_CODE): sub = program.get_subroutine(sub_ea) # Mark `ea` as a subroutine. # Iteratively analyse the blocks in subroutines. This may discover new # subroutines because our block analysis can be more aggressive than what # IDA finds. while len(sub_eas): sub_ea = sub_eas.pop() if not has_segment_type(sub_ea, idc.SEG_CODE): log.warning( "Not analysing subroutine at non-code address {:08x}".format( sub_ea)) continue sub = program.get_subroutine(sub_ea) if sub in subs: log.debug("Skipping {:08x}; already analysed.".format(sub_ea)) continue subs.add(sub) if idc.hasName(sub_ea): sub.name = idc.GetFunctionName(sub_ea) # Mark this subroutine as exported. if sub_ea in exported_eas: sub.visibility = program.Subroutine.VISIBILITY_EXPORTED analyse_subroutine(sub) sub_eas.update(get_called_subroutines(sub)) return subs
def main(): objc_data_seg = idc.SegByBase(idc.SegByName('__objc_data')) if objc_data_seg == idc.BADADDR: print 'Cannot locate objc_data segment' return ea = objc_data_seg while ea < idc.SegEnd(objc_data_seg): objc_class = ObjcClass(ea) objc_class.dump() ea = ea + 0x14
def get_sections(): """Get section names and start/end addrs from IDA database """ sections = {} for ea in idautils.Segments(): curr = {} curr["start"] = idc.SegStart(ea) curr["end"] = idc.SegEnd(ea) sections[idc.SegName(ea)] = curr return sections
def promptForRange(self): #check if a range has already been selected - if so skip prompt start = idc.SelStart() if start != idc.BADADDR: self.logger.info('Processing range 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) self.params.startAddr = start self.params.endAddr = idc.SelEnd() else: self.logger.info('Processing current segment only') self.params.startAddr = idc.SegStart(idc.here()) self.params.endAddr = idc.SegEnd(idc.here())
def getBinary(self): result = b"" segment_starts = [ea for ea in idautils.Segments()] offsets = [] start_len = 0 for start in segment_starts: end = idc.SegEnd(start) result += idc.get_bytes(start, end - start) offsets.append((start, start_len, len(result))) start_len = len(result) return result
def update_mapping(self): pass self.fun_mapping = { idc.GetFunctionName(x): (idaapi.get_func(x).startEA, idaapi.get_func(x).endEA - 1) for x in idautils.Functions() } self.seg_mapping = { idc.SegName(x): (idc.SegStart(x), idc.SegEnd(x)) for x in idautils.Segments() }
def recordText(self): for seg_ea in idautils.Segments(): print('seg: %s' % idc.SegName(seg_ea)) if idc.SegName(seg_ea) == '.text': start = idc.SegStart(seg_ea) end = idc.SegEnd(seg_ea) print('text at 0x%x - 0x%x' % (start, end)) gdbProt.Evalx( 'SendGDBMonitor("@cgc.recordText(0x%x, 0x%x)");' % (start, end)) break
def _process_offsets_section(segstart, next_offset): """Process all the offsets in a __got section.""" for offset, ea in idau.ReadWords(segstart, idc.SegEnd(segstart), addresses=True): if not offset_name_target(idau.get_ea_name(ea)): # This is not a previously named offset. if idau.is_mapped(offset, value=False): _process_offset(offset, ea, next_offset) else: _log(-1, 'Offset {:#x} at address {:#x} is unmapped', offset, ea)
def __init__(self, fmt='[+] srch (IDB/binary searching utils)'): """ This module is responsible for printing disassemblies and necessary compoents of disassemblies """ super(srch, self).__init__(fmt) self.registerCommand(self, self.nextarm, "nextarm", "<search_ea> [ui=True]") self.registerCommand(self, self.nextascii, "nextascii", "<search_ea> [ui=True]") self.registerCommand(self, self.nextfakeinst, "nextfakeinst", "<search_ea> [ui=True]") self.registerCommand(self, self.nextname, "nextname", "<search_ea> [ui=True]") self.registerCommand(self, self.nextknown, "nextknown", "<search_ea> [ui=True]") self.registerCommand(self, self.nextbin, "nextbin", "<search_ea> [ui=True]") self.registerCommand(self, self.nextred, "nextred", "<search_ea> [ui=True]") self.registerCommand(self, self.nextimmref, "nextimmref", "<search_ea> [ui=True]") # figure out the very last ea reachable self.end_ea = 0 for seg in idautils.Segments(): if idc.SegEnd(seg) > self.end_ea: self.end_ea = idc.SegEnd(seg)
def get_instruction_dictionary(ea): insts = dict() for func in idautils.Functions(idc.SegStart(ea), idc.SegEnd(ea)): f_end = FindFuncEnd(func) for head in Heads(func, f_end): if not isCode(GetFlags(head)): continue mnem = GetMnem(head) if mnem not in insts: insts[mnem] = list() insts[mnem].append(head) return insts
def make_offsets(segname): ''' change the segment's data value into offset by class name ''' segea = idc.SegByBase(idc.SegByName(segname)) segend = idc.SegEnd(segea) while segea < segend: idc.OpOffset(segea, 0) ptr = idc.Dword(segea) idc.OpOffset(ptr, 0) segea += 4
def _get_memory(self): result = "" segment_starts = [ea for ea in idautils.Segments()] offsets = [] start_len = 0 for start in segment_starts: end = idc.SegEnd(start) for ea in lrange(start, end): result += chr(idc.Byte(ea)) offsets.append((start, start_len, len(result))) start_len = len(result) return result, offsets
def _process_const_section_for_vtables(segstart, metaclass_info, found_vtable): """Process a __const section to search for virtual method tables.""" segend = idc.SegEnd(segstart) addr = segstart while addr < segend: possible, length = vtable.vtable_length(addr, segend, scan=True) if possible: metaclass = _get_vtable_metaclass(addr, metaclass_info) if metaclass: _log(4, 'Vtable at address {:#x} has metaclass {:#x}', addr, metaclass) found_vtable(metaclass, addr, length) addr += length * idau.WORD_SIZE
def getSegsInfo(): ''' Returns a list of all segments in the form: (name, segstart, segend) ''' segments = list(idautils.Segments()) res = [] for s in segments: res.append((idc.SegName(s), idc.SegStart(s), idc.SegEnd(s))) return res
def processCode(self): if (self.params.startAddr==idc.BADADDR) and (self.params.endAddr==idc.BADADDR): self.logger.info('Processing current segment only') #self.processAllSegments() self.params.startAddr = idc.SegStart(idc.here()) self.params.endAddr = idc.SegEnd(idc.here()) else: self.logger.info('Processing range 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) if self.params.searchDwordArray: self.lookForDwordArray(self.params.startAddr, self.params.endAddr) if self.params.searchPushArgs: self.lookForOpArgs(self.params.startAddr, self.params.endAddr)
def get_import_module_name(address): global module_names global idata_seg_start global idata_seg_end segment_eas = list(idautils.Segments()) # This hasn't been initialized yet... # if module_names is None: module_names = list() for idata_seg_start in segment_eas: print "Going through segment %08X" % idata_seg_start segment = idaapi.getseg(idata_seg_start) if segment.type != idaapi.SEG_XTRN: continue print "Found idata segment" idata_seg_end = idc.SegEnd(idata_seg_start) parse = re.compile('.*Imports\s+from\s+([\w\d]+\.[\w\d]+).*', re.IGNORECASE) # save the address/module name combinations we discover # modules = list() # Scan the .idata segment looking for the imports from # string and get the address ranges where it applies # for head in idautils.Heads(idata_seg_start, idata_seg_end): for line_id in range(100): line = idc.LineA(head, line_id) if line and 'imports from' in line.lower(): res = parse.match(line) if res: print 'Found import line [%s][%s]' % (line, res.group(1)) modules.append((head, res.group(1).lower())) modules.append((idata_seg_end, None)) for idx in range(len(modules) - 1): mod = modules[idx] module_names.append(((mod[0], modules[idx + 1][0]), mod[1])) for addr_range, module_name in module_names: if addr_range[0] <= address < addr_range[1]: return module_name return None
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 processAllSegments(self): for seg in idautils.Segments(): if using_ida7api: segStart = idc.get_segm_start(seg) segEnd = idc.get_segm_end(seg) else: segStart = idc.SegStart(seg) segEnd = idc.SegEnd(seg) if self.params.searchPushArgs: self.lookForOpArgs(segStart, segEnd) if self.params.searchDwordArray: self.lookForDwordArray(segStart, segEnd)
def iter_lines(): """ Iterate through all line addresses in the IDB Yields addresses of all lines. """ for ea in idautils.Segments(): seg_start = idc.SegStart(ea) seg_end = idc.SegEnd(ea) cur_addr = seg_start while (cur_addr < seg_end) and (cur_addr != idaapi.BADADDR): yield cur_addr cur_addr = idc.NextHead(cur_addr)
def walk_datas(): for seg_start in idautils.Segments(): seg_end = idc.SegEnd(seg_start) for ea in ya.get_all_items(seg_start, seg_end): flags = idc.GetFlags(ea) func = idaapi.get_func(ea) if idaapi.isFunc(flags) or (func and idc.isCode(flags)): # function continue if not func and idc.isCode(flags): # code continue yield ea