def cleanStart(analyzer, scs, undef=False): """Clean the selected code segments, and re-analyzer them using the gathered metadata until now. Args: analyzer (instance): analyzer instance to be used scs (list): list of (sark) code segments to work on undef (bool, optional): True iff should undefine the code segments (False by default) """ for sc in scs: if undef: analyzer.logger.info("Undefining code segment: 0x%x - 0x%x", sc.start_ea, sc.end_ea) sark.data.undefine(sc.start_ea, sc.end_ea) if analyzer.switch_identifier.hasSwithTables(sc): analyzer.logger.info( "Marking all known switch tables in the segment") analyzer.switch_identifier.markSwitchTables(sc) else: analyzer.logger.debug("No known switch tables in the segment") if analyzer.fptr_identifier.hasKnownFptrs(): analyzer.logger.info("Marking all known fptr functions") analyzer.fptr_identifier.makePointedFunctions() else: analyzer.logger.debug("No known fptr functions") for sc in scs: analyzer.logger.info("Re-Analyzing code segment: 0x%x - 0x%x", sc.start_ea, sc.end_ea) idc.plan_and_wait(sc.start_ea, sc.end_ea) idaapi.auto_wait()
def try_make_function(function_start, function_end=idc.BADADDR, target_location=None, require_term=True, end_mnem_bytes=None): """ Description: Given a function location, attempt to create a function. If function creation fails, delete any partially created functions. If function creation succeeds, ensure all of the function's bytes are analyzed as code. Input: function_start - The start_ea of the function to create function_end - The end_ea of the function to create. IDA will calculate if not provided. target_location - If provided, fail function creation if it does not include this EA require_term - If provided, fail function creation if the last instruction is not a ret or jmp end_mnem_bytes - If provided, fail function creation if the last instruction is not the provided bytes Instructions are entered as space separated bytes (i.e. '55' for 'push ebp') Output: Returns a tuple (function_start, function_end) for the created function if successful, None otherwise """ if function_start <= function_end: if idc.add_func(function_start, function_end): logger.debug('Created a function 0x%X - 0x%X.' % (function_start, function_end)) if require_term: last_mnem_ea = idc.get_item_head( idaapi.get_func(function_start).end_ea - 1) last_mnem = idc.print_insn_mnem(last_mnem_ea) if (end_mnem_bytes is None and 'ret' not in last_mnem and 'jmp' not in last_mnem) or \ (end_mnem_bytes and idc.get_bytes(last_mnem_ea, idc.get_item_size(last_mnem_ea)).encode('hex').upper() != end_mnem_bytes.upper()): idc.del_func(function_start) logger.debug( 'Deleted function at 0x%X - the function didn\'t end with the correct mnem/bytes.' % function_start) return if target_location is not None: if function_start <= target_location < idaapi.get_func( function_start).end_ea: idc.plan_and_wait(function_start, idaapi.get_func(function_start).end_ea) return function_start, function_end else: idc.del_func(function_start) logger.debug( 'Deleted function at 0x%X - the function didn\'t contain the target location.' % function_start) return else: logger.debug( 'Tried to create a function 0x%X - 0x%X, but IDA wouldn\'t do it.' % (function_start, function_end)) else: logger.debug('The end address was not greater than the start address!')
def _convert_address_to_function(func): """Convert an address that IDA has classified incorrectly into a proper function.""" # If everything goes wrong, we'll try to restore this function. orig = idc.first_func_chunk(func) # If the address is not code, let's undefine whatever it is. if not ida_bytes.is_code(ida_bytes.get_full_flags(func)): if not is_mapped(func): # Well, that's awkward. return False item = ida_bytes.get_item_head(func) itemend = ida_bytes.get_item_end(func) if item != idc.BADADDR: _log(1, 'Undefining item {:#x} - {:#x}', item, itemend) ida_bytes.del_items(item, ida_bytes.DELIT_EXPAND) idc.create_insn(func) # Give IDA a chance to analyze the new code or else we won't be able to create a # function. #ida_auto.auto_wait() autoanalyze() idc.plan_and_wait(item, itemend) else: # Just try removing the chunk from its current function. IDA can add it to another function # automatically, so make sure it's removed from all functions by doing it in loop until it # fails. for i in range(1024): if not idc.remove_fchunk(func, func): break # Now try making a function. if ida_funcs.add_func(func) != 0: return True # This is a stubborn chunk. Try recording the list of chunks, deleting the original function, # creating the new function, then re-creating the original function. if orig != idc.BADADDR: chunks = list(idautils.Chunks(orig)) if ida_funcs.del_func(orig) != 0: # Ok, now let's create the new function, and recreate the original. if ida_funcs.add_func(func) != 0: if ida_funcs.add_func(orig) != 0: # Ok, so we created the functions! Now, if any of the original chunks are not # contained in a function, we'll abort and undo. if all(idaapi.get_func(start) for start, end in chunks): return True # Try to undo the damage. for start, _ in chunks: ida_funcs.del_func(start) # Everything we've tried so far has failed. If there was originally a function, try to restore # it. if orig != idc.BADADDR: _log(0, 'Trying to restore original function {:#x}', orig) ida_funcs.add_func(orig) return False
def convertRegion(analyzer, start_ea, end_ea): """Convert (Cancel) a given code region (change it's code type). Args: analyzer (instance): analyzer instance to be used start_ea (int): effective start address of the region end_ea (int): effective end address of the region """ wanted_code_type = analyzer.codeType(end_ea) analyzer.logger.info("Converting code region of type %d to %d: 0x%x - 0x%x (%d bytes)", analyzer.codeType(start_ea), wanted_code_type, start_ea, end_ea, end_ea - start_ea) # Make sure it will be treated as code ida_bytes.del_items(start_ea, 0, end_ea - start_ea) # manually set the wanted value over the entire region analyzer.setCodeType(start_ea, end_ea, wanted_code_type) # now reanalyze the new section idc.plan_and_wait(analyzer.alignTransitionAddress(start_ea, wanted_code_type), end_ea)
def origFun(self, ip): print('look for fun having ip 0x%x' % ip) fun = self.getFun(ip) if fun is None: simicsString = gdbProt.Evalx( 'SendGDBMonitor("@cgc.getSO(0x%x)");' % ip) print('No function found. Check load for: %s' % simicsString) if ':' in simicsString: sofile, start_end = str(simicsString).rsplit(':', 1) print('sofile is %s start_end is %s' % (sofile, start_end)) if '-' not in start_end: print('Bad response from getSO: %s' % simicsString) return root_prefix = self.getRootPrefix(sofile) full = os.path.join(root_prefix, sofile[1:]) sopath = self.getFunPath(full) start, end = start_end.split('-') start = int(start, 16) end = int(end, 16) self.add(sopath, start) fun = self.getFun(ip) print('start 0x%x end 0x%x' % (start, end)) #idaapi.analyze_area(start, end) idc.plan_and_wait(start, end) for fun in sorted(self.funs): if fun >= start and fun <= end: name = str(self.funs[fun]['name']) nea = idaapi.get_name_ea(idaapi.BADADDR, name) if nea != idaapi.BADADDR: name = name + '_so' idc.set_name(int(fun), name, idc.SN_CHECK) print('made name for 0x%x %s' % (int(fun), name)) for fun in self.funs: if fun >= start and fun <= end: #print('fun 0x%x name <%s>' % (fun, name)) idaversion.add_func(fun, idaapi.BADADDR) elif fun is not None: print('Do one fun 0x%x' % fun) for i in range(self.funs[fun]['start'], self.funs[fun]['end']): idaversion.del_items(i, 1) idaapi.auto_mark_range(self.funs[fun]['start'], self.funs[fun]['end'], 25) idaapi.autoWait() return fun return None
def resizeRegion(analyzer, start_ea, end_ea, new_start_ea, new_end_ea): """Resize a given code region, according to the new dimensions. Args: analyzer (instance): analyzer instance to be used start_ea (int): effective start address of the original region end_ea (int): effective end address of the original region new_start_ea (int): effective start address for the new region new_end_ea (int): effective end address for the new region """ analyzer.logger.info( "Resizing code region of type %d: 0x%x (0x%x) - 0x%x (0x%x)", analyzer.codeType(start_ea), new_start_ea, start_ea, end_ea, new_end_ea) code_type_before = analyzer.codeType(min(start_ea, new_start_ea) - 1) code_type_middle = analyzer.codeType(start_ea) code_type_after = analyzer.codeType(max(end_ea, new_end_ea)) # Make sure it will be treated as code fix_regions = [] if new_start_ea < start_ea: fix_regions.append((new_start_ea, start_ea)) elif new_start_ea != start_ea: fix_regions.append((start_ea, new_start_ea)) if end_ea < new_end_ea: fix_regions.append((end_ea, new_end_ea)) elif end_ea != new_end_ea: fix_regions.append((new_end_ea, end_ea)) # Make the changed parts unknown, before re-analyzing them for region_start, region_end in fix_regions: ida_bytes.del_items(region_start, 0, region_end - region_start) # manually set the wanted value over the entire region if start_ea < new_start_ea: analyzer.setCodeType(start_ea, new_start_ea, code_type_before) elif start_ea != new_start_ea: analyzer.setCodeType(new_start_ea, start_ea, code_type_middle) if end_ea < new_end_ea: analyzer.setCodeType(end_ea, new_end_ea, code_type_middle) elif end_ea != new_end_ea: analyzer.setCodeType(new_end_ea, end_ea, code_type_after) # now reanalyze the new section for region_start, region_end in fix_regions: idc.plan_and_wait(region_start, region_end)
def add_rodata_segment(self): last_seg_end = idc.get_first_seg() # print(hex(last_seg_end)) for s in idautils.Segments(): start = idc.get_segm_start(s) end = idc.get_segm_end(s) if int(start) != int(last_seg_end): # found idaapi.add_segm(0, last_seg_end, start, "roooodata", "CONST") print("Adding segment from 0x%x to 0x%x" % (last_seg_end, start)) print("OK") break else: last_seg_end = end idc.plan_and_wait(ida_ida.inf_get_min_ea(), ida_ida.inf_get_max_ea()) # idc.plan_and_wait(idc.MinEA(), idc.MaxEA()) self.start = last_seg_end self.end = start return last_seg_end, start
# for Link Time Optimized binaries we look for LDR instructions whose src operand # begins with "=" to differentiate from non LTO binaries # for non LTO binaries, we patch the ADRP/ADRL instructions that reference the selrefs if (idc.print_insn_mnem(x.frm) == "ADRP" or idc.print_insn_mnem(x.frm) == "ADRL" or (idc.print_insn_mnem(x.frm)[:3] == "LDR" and idc.print_operand(x.frm, 1)[0] == "=")): selRefsXrefs[selRef].append(x.frm) else: selRefsXrefs[selRef].append(x.frm) # run analyzer objc2_analyzer.Objc2Analyzer() baseAddr = idc.get_inf_attr(idc.INF_MIN_EA) endAddr = idc.get_inf_attr(idc.INF_MAX_EA) idc.plan_and_wait(baseAddr, endAddr) #start tests print("objc2_analyzer_test: TESTING COMMENTS") msgSendXrefs = list( idautils.XrefsTo(idc.get_name_ea_simple("_objc_msgSend"))) # IDA gets the xrefs in places we are not interested # we rely on objc2_analyzer's new xrefs to help our testing if arch == "ARM": i = 0 while i < len(msgSendXrefs): if idc.print_insn_mnem(msgSendXrefs[i].frm) != "BLX": del (msgSendXrefs[i]) continue i += 1
def load_file(fd, neflags, format): global prologues global br_flag size = 0 base_addr = 0 ea = 0 nfunc = 0 idaapi.set_processor_type("arm", ida_idp.SETPROC_LOADER_NON_FATAL) idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT if (neflags & idaapi.NEF_RELOAD) != 0: return 1 fd.seek(0, idaapi.SEEK_END) size = fd.tell() segm = idaapi.segment_t() segm.bitness = 2 # 64-bit segm.start_ea = 0 segm.end_ea = size if br_flag == false: idaapi.add_segm_ex(segm, "iBoot", "CODE", idaapi.ADDSEG_OR_DIE) else: idaapi.add_segm_ex(segm, "SecureROM", "CODE", idaapi.ADDSEG_OR_DIE) fd.seek(0) fd.file2base(0, 0, size, false) idaapi.add_entry(0, 0, "start", 1) ida_funcs.add_func(ea) print("[+] Marked as code") # heuristic while (true): mnemonic = idc.print_insn_mnem(ea) if "LDR" in mnemonic: base_str = idc.print_operand(ea, 1) base_addr = int(base_str.split("=")[1], 16) break ea += 4 print("[+] Rebasing to address 0x%x" % (base_addr)) idaapi.rebase_program(base_addr, idc.MSF_NOFIX) segment_start = base_addr segment_end = idc.get_segm_attr(segment_start, idc.SEGATTR_END) ea = segment_start print("[+] Searching and defining functions") for prologue in prologues: while ea != ida_idaapi.BADADDR: ea = ida_search.find_binary(ea, segment_end, prologue, 16, ida_search.SEARCH_DOWN) if ea != ida_idaapi.BADADDR: if len(prologue) < 8: ea = ea - 2 if (ea % 4) == 0 and ida_bytes.get_full_flags(ea) < 0x200: # print("[+] Defining a function at 0x%x" % (ea)) ida_funcs.add_func(ea) nfunc = nfunc + 1 ea = ea + 4 idc.plan_and_wait(segment_start, segment_end) print("[+] Identified %d new functions" % (nfunc)) print("[+] Looking for interesting functions") find_interesting(segment_start, segment_end) return 1
def dataScan(analyzer, scs): """Scan the code segments for orphan data blobs that represent analysis errors. Args: analyzer (instance): analyzer instance to be used scs (list): list of (sark) code segments """ # First Scan - unreffed data chunks inside functions ==> should be converted to code for sc in scs: first_line = None end_line = None for line in sc.lines: # After the first, the rest of the lines should have 0 crefs if first_line is not None and ((not line.is_data) or len(list(line.drefs_to)) > 0 or len(list(line.crefs_to)) > 0): end_line = line # we only care about data lines with a single cref from the previous line elif first_line is None and ( (not line.is_data) or len(list(line.drefs_to)) > 0 or len(list(line.crefs_to)) != 1 or sark.Line(list(line.crefs_to)[0]).next != line): end_line = line # don't mark switch entries elif analyzer.switch_identifier.isSwitchEntry(line.start_ea): end_line = line # Finally, check if it could be a function of some type elif first_line is None: first_line = line continue # Found an adjacent suitable line else: continue # Now check if we found something (end_line is always != None at this point) if first_line is not None and end_line is not None: chunk_start = first_line.start_ea chunk_end = end_line.start_ea # check that we can deduce anything on this current code type if not analyzer.supportedCodeType( analyzer.codeType(chunk_start)): continue # check that the chunk before us is not the end of a function if analyzer.func_classifier.predictFunctionEnd(chunk_start): # shouldn't really happen, do nothing in this case pass # data chunk in the middle of a function, and not at it's end - convert it to code else: analyzer.logger.debug( "In-Function data chunk at: 0x%x - 0x%x (%d)", chunk_start, chunk_end, chunk_end - chunk_start) ida_bytes.del_items(chunk_start, 0, chunk_end - chunk_start) idc.create_insn(chunk_start) # reset the vars first_line = None end_line = None # Second scan - unreffed data chunks outside of functions ==> new functions, possibly of different code type size_limit = analyzer.func_classifier.functionStartSize() analyzer.logger.debug("Size limit for data scan is: %d", size_limit) conversion_candidates = [] # recon pass for sc in scs: first_line = None end_line = None for line in sc.lines: # we only care about data lines without xrefs if (not line.is_data) or len(list(line.crefs_to)) > 0 or len( list(line.drefs_to)) > 0: end_line = line # check if it's big enough for the classifier elif line.size < size_limit: end_line = line # check if it looks like a string elif analyzer.str_identifier.isLocalAsciiString(line.start_ea, check_refs=False): analyzer.str_identifier.defineAsciiString(line.start_ea) end_line = line # make sure it isn't a switch entry elif analyzer.switch_identifier.isSwitchEntry(line.start_ea): end_line = line # Finally, check if it could be a function of some type elif first_line is None: first_line = line continue # Found an adjacent suitable line else: continue # Now check if we found something (end_line is always != None at this point) if first_line is not None and end_line is not None: chunk_start = first_line.start_ea chunk_end = end_line.start_ea guess_code_type = analyzer.func_classifier.predictFunctionStartType( chunk_start) original_code_type = analyzer.codeType(chunk_start) analyzer.logger.debug( "Found a data chunk at: 0x%x - 0x%x (%d), (Type %d, Local type %d)", chunk_start, chunk_end, chunk_end - chunk_start, guess_code_type, original_code_type) # Check if this is the beginning of a function if analyzer.func_classifier.predictFunctionStart( chunk_start, guess_code_type): conversion_candidates.append( (chunk_start, chunk_end, guess_code_type, original_code_type)) # reset the vars first_line = None end_line = None # conversion pass for chunk_start, chunk_end, guess_code_type, original_code_type in conversion_candidates: analyzer.logger.info( "Found an isolated data chunk at: 0x%x - 0x%x (%d), (Type %d, Local type %d)", chunk_start, chunk_end, chunk_end - chunk_start, guess_code_type, original_code_type) ida_bytes.del_items(chunk_start, 0, chunk_end - chunk_start) if original_code_type != guess_code_type: analyzer.setCodeType(chunk_start, chunk_end, guess_code_type) idc.plan_and_wait(chunk_start, chunk_end) ida_funcs.add_func(chunk_start)
def run(self): try: logger.debug('Starting up') dlg = StructTyperWidget() dlg.setStructs(loadStructs()) oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtWidgets.QDialog.Accepted: regPrefix = dlg.getRegPrefix() sid = None struc = None if dlg.ui.rb_useStackFrame.isChecked(): ea = idc.here() if using_ida7api: sid = idc.get_frame_id(ea) else: sid = idc.GetFrame(ea) struc = idaapi.get_frame(ea) logger.debug('Dialog result: accepted stack frame') if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError( 'Failed to get sid for stack frame at 0x%x' % ea) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError( 'Failed to get struc_t for stack frame at 0x%x' % ea) if using_ida7api: pass else: #need the actual pointer value, not the swig wrapped struc_t struc = long(struc.this) else: structName = dlg.getActiveStruct() if structName is None: print("No struct selected. Bailing out") return logger.debug('Dialog result: accepted %s "%s"', type(structName), structName) if using_ida7api: sid = idc.get_struc_id(structName) else: sid = idc.GetStrucIdByName(structName) if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for %s' % structName) tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) if using_ida7api: struc = idaapi.get_struc(tid) else: struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) foundMembers = self.processStruct(regPrefix, struc, sid) if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0): #reanalyze current function if we're analyzing a stack frame & found some func pointers if using_ida7api: funcstart = idc.get_func_attr(idc.here(), idc.FUNCATTR_START) funcend = idc.get_func_attr(idc.here(), idc.FUNCATTR_END) else: funcstart = idc.GetFunctionAttr( idc.here(), idc.FUNCATTR_START) funcend = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END) if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR): if using_ida7api: idc.plan_and_wait(funcstart, funcend) else: idc.AnalyzeArea(funcstart, funcend) elif res == QtWidgets.QDialog.Rejected: logger.info('Dialog result: canceled by user') else: logger.debug('Unknown result') raise RuntimeError('Dialog unknown result') except Exception, err: logger.exception("Exception caught: %s", str(err))
def run(self): try: logger.debug('Starting up') dlg = StructTyperWidget() dlg.setStructs(loadStructs()) oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtWidgets.QDialog.Accepted: regPrefix = dlg.getRegPrefix() sid = None struc = None if dlg.ui.rb_useStackFrame.isChecked(): ea = idc.here() if using_ida7api: sid = idc.get_frame_id(ea) else: sid = idc.GetFrame(ea) struc = idaapi.get_frame(ea) logger.debug('Dialog result: accepted stack frame') if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for stack frame at 0x%x' % ea) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for stack frame at 0x%x' % ea) if using_ida7api: pass else: #need the actual pointer value, not the swig wrapped struc_t struc= long(struc.this) else: structName = dlg.getActiveStruct() if structName is None: print("No struct selected. Bailing out") return logger.debug('Dialog result: accepted %s "%s"', type(structName), structName) if using_ida7api: sid = idc.get_struc_id(structName) else: sid = idc.GetStrucIdByName(structName) if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for %s' % structName) tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) if using_ida7api: struc = idaapi.get_struc(tid) else: struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) foundMembers = self.processStruct(regPrefix, struc, sid) if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0): #reanalyze current function if we're analyzing a stack frame & found some func pointers if using_ida7api: funcstart = idc.get_func_attr(idc.here(), idc.FUNCATTR_START) funcend = idc.get_func_attr(idc.here(), idc.FUNCATTR_END) else: funcstart = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_START) funcend = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END) if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR): if using_ida7api: idc.plan_and_wait(funcstart, funcend) else: idc.AnalyzeArea(funcstart, funcend) elif res == QtWidgets.QDialog.Rejected: logger.info('Dialog result: canceled by user') else: logger.debug('Unknown result') raise RuntimeError('Dialog unknown result') except Exception, err: logger.exception("Exception caught: %s", str(err))
def load_file(fd, flags, format): ea = 0 size = 0 fd.seek(0x200) search = fd.read(0x10) print("[sephelper]: starting...") if segbit == 1: print("[sephelper]: detected a 32bit SEPROM !") idaapi.set_processor_type("arm:armv7-m", idaapi.SETPROC_LOADER_NON_FATAL) idaapi.get_inf_structure().lflags |= idaapi.LFLG_PC_FLAT else: print("[sephelper]: detected a 64bit SEPROM !") idaapi.set_processor_type("arm", idaapi.SETPROC_LOADER_NON_FATAL) idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT if (flags & idaapi.NEF_RELOAD) != 0: return 1 fd.seek(0x0, idaapi.SEEK_END) size = fd.tell() segm = idaapi.segment_t() segm.bitness = segbit segm.start_ea = 0x0 segm.end_ea = size idaapi.add_segm_ex(segm, "SEPROM", "CODE", idaapi.ADDSEG_OR_DIE) fd.seek(0x0) fd.file2base(0x0, 0x0, size, False) print("[sephelper]: adding entry point...") idaapi.add_entry(0x0, 0x0, "_start", 1) ida_funcs.add_func(ea) print("[sephelper]: base_addr = 0x%x" % base_addr) idaapi.rebase_program(base_addr, idc.MSF_NOFIX) print("[sephelper]: analyzing...") ea = base_addr segment_end = idc.get_segm_attr(base_addr, idc.SEGATTR_END) hexcode = ["BF A9", "BD A9"] # there is not PAC on SEPROM if segbit == 1: hexcode = ["03 AF", "02 AF", "01 AF"] for prologue in hexcode: while ea != idc.BADADDR: ea = ida_search.find_binary(ea, segment_end, prologue, 0x10, ida_search.SEARCH_DOWN) if ea != idc.BADADDR: ea = ea - 0x2 if (ea % 0x4) == 0 and ida_bytes.get_full_flags(ea) < 0x200: # print("[sephelper]: function added = 0x%x" % ea) ida_funcs.add_func(ea) ea = ea + 0x4 idc.plan_and_wait(base_addr, segment_end) print('[sephelper]: finding some functions...') find_function(segm.start_ea, segment_end) print('[sephelper]: done !') return 1