def getSegName(seg, segm): count = 0 h = '' while (idaapi.get_segm_name(seg, 0) + h) in segm.keys(): count += 1 h = str(count) name = idaapi.get_segm_name(seg, 0) + h return name
def strings_init(): strings_added = 0 retry = [] text_seg = get_text_seg() if text_seg is None: 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 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 segm_added(self, segm): if idaapi.get_segm_name(segm) == 'HEADER': self.base_address = segm.startEA self.is_iOS12 = is_iOS_12(self.base_address) if idaapi.get_segm_name(segm) == '__thread_starts': self.relocs_address = segm.startEA self.relocs_size = segm.endEA-segm.startEA if idaapi.get_segm_name(segm) == '__kmod_info': self.is_kernelcache = True if self.is_iOS12 and self.relocs_address is not None: print 'iOS12 kernelcache detected!' print 'let\'s fix relocs' fix_relocs(self.base_address, self.relocs_address, self.relocs_size) return 0
def getAddressDetails(self, address): # FIXME: look for nearest .text, then get prev segm = get_prev_seg(address) moduleName = get_segm_name(segm) moduleBase = segm.startEA offset = address - moduleBase return (offset, moduleName)
def segm_added(self, s): self._send_event(SegmAddedEvent(idaapi.get_segm_name(s), idaapi.get_segm_class(s), s.start_ea, s.end_ea, s.orgbase, s.align, s.comb, s.perm, s.bitness, s.flags)) return 0
def list_segments(self): """ Return the list of segments in the current binary and their characteristics """ self.segments = list() self.segments_idx = list() for n in xrange(get_segm_qty()): seg = getnseg(n) if not seg: continue # For some linux binaries # Ida does not recognize the segment # permissions (usually for plt) if seg.perm == 0: continue segentry = SegmentEntry( name = idaapi.get_segm_name(seg), start = seg.startEA, end = seg.endEA, size = seg.size(), r = (seg.perm & idaapi.SEGPERM_READ) >> 2, w = (seg.perm & idaapi.SEGPERM_WRITE) >> 1, x = (seg.perm & idaapi.SEGPERM_EXEC), segclass = idaapi.get_segm_class(seg) ) self.segments.append(segentry) self.segments_idx.append(n) return self.segments
def create_string(addr, string_len): if idaapi.get_segm_name(addr) is None: debug( 'Cannot load a string which has no segment - not creating string @ 0x%02x' % addr) return False 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 GetStringType(addr) is not None and GetString(addr) is not None and len( GetString(addr)) != string_len: debug('It appears that there is already a string present @ 0x%x' % addr) MakeUnknown(addr, string_len, DOUNK_SIMPLE) if GetString(addr) is None and MakeStr(addr, addr + string_len): return True else: # If something is already partially analyzed (incorrectly) we need to MakeUnknown it MakeUnknown(addr, string_len, DOUNK_SIMPLE) if MakeStr(addr, addr + string_len): return True debug('Unable to make a string @ 0x%x with length of %d' % (addr, string_len)) return False
def pointer_renamer(): renamed = 0 text_seg = get_text_seg() if text_seg is None: debug('Failed to get text segment') return renamed for addr in Functions(text_seg.startEA, text_seg.endEA): name = 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 != BADADDR: if 'rodata' in idaapi.get_segm_name(data_ref): # Only rename things that are currently listed as an offset; eg. off_9120B0 if 'off_' in GetTrueName(data_ref): if MakeName(data_ref, ('%s_ptr' % name)): renamed += 1 else: error( 'error attempting to name pointer @ 0x%02x for %s' % (data_ref, name)) data_ref = idaapi.get_next_dref_to(addr, data_ref) return renamed
def __init__(self, seg): self.content = None self.segclass = idaapi.get_segm_class(seg) self.name = idaapi.get_segm_name(seg) self.content = function.functions_node(seg.startEA, seg.endEA)
def dump_binary(path): max_addr = 0 # Check if we have a buggy IDA or not try: idaapi.get_many_bytes_ex(0, 1) except TypeError: buggy = True else: buggy = False if buggy: f = idaapi.qfile_t() try: f.open(path, 'wb+') except TypeError: # Another ugly hack for IDA 6/7 compat (unicode strings) f.open(str(path), 'wb+') segments = [idaapi.getnseg(x) for x in range(idaapi.get_segm_qty())] # no need for IDA 7 compat, it's not buggy max_addr = segments[-1].endEA if max_addr > 200 * 1024 * 1024: askyn = idaapi.ask_yn if hasattr(idaapi, "ask_yn") else idaapi.askyn_c if askyn( idaapi.ASKBTN_NO, "Dump file is over 200MB," " do you want to dump it anyway ?") != idaapi.ASKBTN_YES: return None idaapi.base2file(f.get_fp(), 0, 0, max_addr) f.close() return [("dump", 0, max_addr, 0, max_addr)] else: sections = [] current_offset = 0 with open(path, 'wb+') as f: # over all segments for n in range(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) if hasattr(seg, "start_ea"): start_ea = seg.start_ea else: start_ea = seg.startEA if hasattr(seg, "end_ea"): end_ea = seg.end_ea else: end_ea = seg.endEA size = end_ea - start_ea # Only works with fixed IDAPython. f.write(idaapi.get_many_bytes_ex(start_ea, size)[0]) sections.append((idaapi.get_segm_name(seg), start_ea, size, current_offset, size)) current_offset += size dump_log.debug(repr(sections)) return sections
def extract_file_section_names(): """extract section names IDA must load resource sections for this to be complete - '-R' from console - Check 'Load resource sections' when opening binary in IDA manually """ for seg in capa.features.extractors.ida.helpers.get_segments( skip_header_segments=True): yield Section(idaapi.get_segm_name(seg)), seg.start_ea
def code_segments_iter(): """Iterates over the possible code sections within an input binary.""" for i in range(idaapi.get_segm_qty()): seg = idaapi.getnseg(i) if not seg: continue seg_class = idaapi.get_segm_class(seg) if seg_class != "CODE": continue seg_name = idaapi.get_segm_name(seg.startEA) yield seg.startEA, seg.endEA, seg_name
def output_segments(out): """Dump binary segmentation.""" info = idaapi.get_inf_structure() size = "r32" if info.is_32bit else "r64" out.writelines(('(', info.get_proc_name()[1], ' ', size, ' (')) for seg in idautils.Segments(): out.write("\n({} {} {:d} ({:#x} {:d}))".format( idaapi.get_segm_name(seg), "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data", idaapi.get_fileregion_offset(seg), seg, idaapi.getseg(seg).size())) out.write("))\n")
def ida_iter_segments(): seg = idaapi.get_first_seg() while seg: # TODO: CRITICAL!! Figure out how to calculate segment file size yield SegmentTuple(name=idaapi.get_segm_name(seg), perm=seg.perm, startEA=seg.startEA, endEA=seg.endEA, offset=ida_loader.get_fileregion_offset( seg.startEA)) seg = idaapi.get_next_seg(seg.startEA)
def imp_cb(self, ea, name, ord1): """Callback passed to idaapi.enum_import_name in buildImportDictionary(). Sets the name of the PE segment in which the import table resides, and inserts current import in dictionary of imported APIS""" if self.firstImport: self.imports_segment_name = idaapi.get_segm_name(ea) self.firstImport = False demangled_name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN)) if not demangled_name: self.import_dict[ea] = (name, self.curr_mod_name) else: self.import_dict[ea] = (demangled_name, self.curr_mod_name) return True
def is_string_load(addr): patterns = [] # Check for first parts instruction and what it is loading -- also ignore function pointers we may have renamed if (GetMnem(addr) != 'mov' and GetMnem(addr) != 'lea') and ( GetOpType(addr, 1) != 2 or GetOpType(addr, 1) != 5) or GetOpnd( addr, 1)[-4:] == '_ptr': return False # Validate that the string offset actually exists inside the binary if idaapi.get_segm_name(GetOperandValue(addr, 1)) is None: return False # Could be unk_, asc_, 'offset ', XXXXh, ignored ones are loc_ or inside [] if GetOpnd(addr, 0) in VALID_REGS and not ('[' in GetOpnd( addr, 1) or 'loc_' in GetOpnd(addr, 1)) and ( ('offset ' in GetOpnd(addr, 1) or 'h' in GetOpnd(addr, 1)) or ('unk' == GetOpnd(addr, 1)[:3])): from_reg = GetOpnd(addr, 0) # Check for second part addr_2 = FindCode(addr, SEARCH_DOWN) try: dest_reg = GetOpnd(addr_2, 0)[GetOpnd(addr_2, 0).index('[') + 1:GetOpnd(addr_2, 0).index('[') + 4] except ValueError: return False if GetMnem(addr_2) == 'mov' and dest_reg in VALID_DEST and ( '[%s' % dest_reg) in GetOpnd(addr_2, 0) and GetOpnd( addr_2, 1) == from_reg: # Check for last part, could be improved addr_3 = FindCode(addr_2, SEARCH_DOWN) # GetOpType 1 is a register, potentially we can just check that GetOpType returned 5? if GetMnem(addr_3) == 'mov' and ( ('[%s+' % dest_reg) in GetOpnd(addr_3, 0) or GetOpnd( addr_3, 0) in VALID_DEST) and 'offset ' not in GetOpnd( addr_3, 1) and 'dword ptr ds' not in GetOpnd( addr_3, 1) and GetOpType(addr_3, 1) != 1 and GetOpType( addr_3, 1) != 2 and GetOpType(addr_3, 1) != 4: try: dumb_int_test = GetOperandValue(addr_3, 1) if dumb_int_test > 0 and dumb_int_test < sys.maxsize: return True except ValueError: return False return False
def dump_loader_info(output_filename): """Dump information for BAP's loader into output_filename.""" from idautils import Segments import idc idaapi.autoWait() with open(output_filename, 'w+') as out: info = idaapi.get_inf_structure() size = "r32" if info.is_32bit else "r64" out.write("(%s %s (" % (info.get_proc_name()[1], size)) for seg in Segments(): out.write("\n(%s %s %d (0x%X %d))" % ( idaapi.get_segm_name(seg), "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data", idaapi.get_fileregion_offset(seg), seg, idaapi.getseg(seg).size())) out.write("))\n")
def dump_binary(path): max_addr = 0 # Check if we have a buggy IDA or not try: idaapi.get_many_bytes_ex(0, 1) except TypeError: buggy = True else: buggy = False if buggy: f = idaapi.qfile_t() f.open(path, 'wb+') segments = [idaapi.getnseg(x) for x in range(idaapi.get_segm_qty())] max_addr = segments.endEA # no need for IDA 7 compat, it's not buggy if max_addr > 200 * 1024 * 1024: if idaapi.ask_yn( idaapi.ASKBTN_NO, "Dump file is over 200MB," " do you want to dump it anyway ?") != idaapi.ASKBTN_YES: return None idaapi.base2file(f.get_fp(), 0, 0, max_addr) f.close() return [("dump", 0, max_addr, 0, max_addr)] else: sections = [] current_offset = 0 with open(path, 'wb+') as f: # over all segments for n in range(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) start_ea = seg.start_ea if hasattr(seg, "start_ea") else seg.startEA end_ea = seg.end_ea if hasattr(seg, "end_ea") else seg.endEA size = end_ea - start_ea # print "Start: %x, end: %x, size: %x" % (start, end, end-start) # Only works with fixed IDAPython. f.write(idaapi.get_many_bytes_ex(start_ea, size)[0]) sections.append((idaapi.get_segm_name(seg), start_ea, size, current_offset, size)) current_offset += size dump_log.debug(repr(sections)) return sections
def get_info_about_call(call_addr, call_arg, stack_ptr, current_function=False): one_row = [] call_addr_str = '{:08X}'.format(call_addr) #when print current function, then add " <ip>" if current_function: call_addr_str += " <ip>" #"Call Address" column one_row.append(call_addr_str) #"Call Argument", column one_row.append(call_arg) function_name, call_offset_in_function, _, _ = get_func_name_and_call_offset( call_addr) #when print current function, then add " <curr fun>" if current_function: function_name += " <curr fun>" #"Function name" column one_row.append(function_name) #when print current function, then add " <curr pos>" if current_function: call_offset_in_function += " <curr pos>" #Function offset" column one_row.append(call_offset_in_function) #"Segment" columns one_row.append(idaapi.get_segm_name(idaapi.getseg(call_addr))) #"Stack pointer" column one_row.append(" 0x{:X}".format(stack_ptr)) return one_row
def run_yara_on_segment(rule_text, name=None, start_ea=None, callback_func=_yara_callback): ''' Description: Applies yara rule to the bytes in the specified segment and returns raw results. Segments may be specified by name or start EA, but one or the other is required. Clears the matches each time to prevent duplicates. Input: name - The name of the target segment start_ea - The start EA of the target segment callback_func - A pointer to the callback function for YARA's matching to use Output: Returns a list of YARA's match results with items (location, description) ''' global _YARA_MATCHES, FROM_FILE _YARA_MATCHES = [] FROM_FILE = False if name is None and start_ea is None: raise Exception( "Either a segment name or start EA are required to YARA scan a specific segment." ) rule = yara.compile(source=rule_text) found_segment = False for seg in map(idaapi.getseg, idautils.Segments()): if seg.startEA == start_ea or idaapi.get_segm_name( seg.startEA) == name: found_segment = True for bites in _read_bytes(seg.startEA, seg.endEA): rule.match(data=bites, callback=callback_func) if not found_segment: append_debug("Failed to find segment \"" + name + "\"") return _YARA_MATCHES
def get_sreg_base_x64(name): sdb = idaapi.dbg_get_thread_sreg_base(idc.GetCurrentThreadId(), int(getattr(cpu, name))) if not sdb: for n in xrange(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) sgname = idaapi.get_segm_name(seg, 0) if sgname.startswith('TIB['): _sdb = seg.startEA + 0x1000 sdb_self = int( base64.b16encode( idaapi.dbg_read_memory(_sdb + 0x30, 8)[::-1]), 16) if (sdb_self == _sdb): sdb = _sdb print("\nwarning: the segname:%s is zero,I give %016x" % (name, sdb)) break if not sdb: print( "\n\nwarning: the segname:%s is zero, U need set it by yourself\n" % (name)) return sdb
def get_offset_name(ea): # Try and get the function name try: func = get_func(ea) name = idaapi.get_ea_name(func.start_ea) name = demangle(name, 0x60) # MNG_NOTYPE | MNG_NORETTYPE if name: offset = ea - func.start_ea if offset: return '{}+{:X}'.format(name, offset) return name except exceptions.SarkNoFunction: pass # If that failed, use the segment name instead. segment = idaapi.getseg(ea) name = idaapi.get_segm_name(segment) offset_format = '{{:0{}X}}'.format(get_native_size() * 2) ea_text = offset_format.format(ea) if name: return '{}:{}'.format(name, ea_text) # Nothing found, simply return the address return ea_text
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 get_segments(): seg_names = [] for seg in idautils.Segments(): st = ida_segment.getseg(seg) seg_names.append(idaapi.get_segm_name(st)) return seg_names
def writeMem(binfile, regs): segm = {} for n in xrange(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) if seg: count = 0 h = '' while (idaapi.get_segm_name(seg, 0) + h) in segm.keys(): count += 1 h = str(count) name = idaapi.get_segm_name(seg, 0) + h address = seg.startEA length = seg.endEA - seg.startEA db_data = idaapi.dbg_read_memory(address, length) if db_data: print('ok ', name, seg.flags, length, 'bytes', length / 1024, 'kb') segm[name] = [address, length, db_data] else: print('faild', name, seg.flags, length, 'bytes', length / 1024, 'kb') pass nameoffset_p = 0 dataoffset_p = 0 all_ab_name = 0 register_names = { 16: 'rax', 24: 'rcx', 32: 'rdx', 40: 'rbx', 48: 'rsp', 56: 'rbp', 64: 'rsi', 72: 'rdi', 80: 'r8', 88: 'r9', 96: 'r10', 104: 'r11', 112: 'r12', 120: 'r13', 128: 'r14', 136: 'r15', 144: 'cc_op', 152: 'cc_dep1', 160: 'cc_dep2', 168: 'cc_ndep', 176: 'd', 184: 'rip', 192: 'ac', 200: 'id', 208: 'fs', 216: 'sseround', 224: 'ymm0', 256: 'ymm1', 288: 'ymm2', 320: 'ymm3', 352: 'ymm4', 384: 'ymm5', 416: 'ymm6', 448: 'ymm7', 480: 'ymm8', 512: 'ymm9', 544: 'ymm10', 576: 'ymm11', 608: 'ymm12', 640: 'ymm13', 672: 'ymm14', 704: 'ymm15', 736: 'ymm16', 768: 'ftop', 776: 'mm0', 784: "mm1", 792: "mm2", 800: "mm3", 808: "mm4", 816: "mm5", 824: "mm6", 832: "mm7", 840: 'fptag', 848: 'fpround', 856: 'fc3210', 864: 'emnote', 872: 'cmstart', 880: 'cmlen', 888: 'nraddr', 904: 'gs', 912: 'ip_at_syscall' } registers = { 'rax': (16, 8), 'eax': (16, 4), 'ax': (16, 2), 'al': (16, 1), 'ah': (17, 1), 'rcx': (24, 8), 'ecx': (24, 4), 'cx': (24, 2), 'cl': (24, 1), 'ch': (25, 1), 'rdx': (32, 8), 'edx': (32, 4), 'dx': (32, 2), 'dl': (32, 1), 'dh': (33, 1), 'rbx': (40, 8), 'ebx': (40, 4), 'bx': (40, 2), 'bl': (40, 1), 'bh': (41, 1), 'rsp': (48, 8), 'sp': (48, 8), 'esp': (48, 4), 'rbp': (56, 8), 'bp': (56, 8), 'ebp': (56, 4), 'rsi': (64, 8), 'esi': (64, 4), 'si': (64, 2), 'sil': (64, 1), 'sih': (65, 1), 'rdi': (72, 8), 'edi': (72, 4), 'di': (72, 2), 'dil': (72, 1), 'dih': (73, 1), 'r8': (80, 8), 'r9': (88, 8), 'r10': (96, 8), 'r11': (104, 8), 'r12': (112, 8), 'r13': (120, 8), 'r14': (128, 8), 'r15': (136, 8), 'cc_op': (144, 8), 'cc_dep1': (152, 8), 'cc_dep2': (160, 8), 'cc_ndep': (168, 8), 'd': (176, 8), 'dflag': (176, 8), 'rip': (184, 8), 'ip': (184, 8), 'pc': (184, 8), 'ac': (192, 8), 'acflag': (192, 8), 'id': (200, 8), 'idflag': (200, 8), 'fs': (208, 8), 'fs_const': (208, 8), 'sseround': (216, 8), 'ymm0': (224, 32), 'xmm0': (224, 16), 'ymm1': (256, 32), 'xmm1': (256, 16), 'ymm2': (288, 32), 'xmm2': (288, 16), 'ymm3': (320, 32), 'xmm3': (320, 16), 'ymm4': (352, 32), 'xmm4': (352, 16), 'ymm5': (384, 32), 'xmm5': (384, 16), 'ymm6': (416, 32), 'xmm6': (416, 16), 'ymm7': (448, 32), 'xmm7': (448, 16), 'ymm8': (480, 32), 'xmm8': (480, 16), 'ymm9': (512, 32), 'xmm9': (512, 16), 'ymm10': (544, 32), 'xmm10': (544, 16), 'ymm11': (576, 32), 'xmm11': (576, 16), 'ymm12': (608, 32), 'xmm12': (608, 16), 'ymm13': (640, 32), 'xmm13': (640, 16), 'ymm14': (672, 32), 'xmm14': (672, 16), 'ymm15': (704, 32), 'xmm15': (704, 16), 'ymm16': (736, 32), 'xmm16': (736, 16), 'ftop': (768, 4), 'fpreg': (776, 64), 'fpu_regs': (776, 64), 'mm0': (776, 8), 'mm1': (784, 8), 'mm2': (792, 8), 'mm3': (800, 8), 'mm4': (808, 8), 'mm5': (816, 8), 'mm6': (824, 8), 'mm7': (832, 8), 'fptag': (840, 8), 'fpu_tags': (840, 8), 'fpround': (848, 8), 'fc3210': (856, 8), 'emnote': (864, 4), 'cmstart': (872, 8), 'cmlen': (880, 8), 'nraddr': (888, 8), 'gs': (904, 8), 'gs_const': (904, 8), 'ip_at_syscall': (912, 8) } for regAddress in regs: INT = regs[regAddress] regName = register_names[regAddress] size = registers[regName][1] if size == 1: db_data = struct.pack("<B", INT) elif size == 2: db_data = struct.pack("<H", INT) elif size == 4: db_data = struct.pack("<I", INT) elif size == 8: db_data = struct.pack("<Q", INT) elif size == 16: db_data = struct.pack("<QQ", int(INT & 0xffffffffffffffff), int(INT >> 64)) elif size == 32: db_data = struct.pack("<QQQQ", INT & 0xffffffffffffffff, (INT >> 64) & 0xffffffffffffffff, (INT >> 128) & 0xffffffffffffffff, INT >> 192) else: continue segm['registers' + str(regAddress)] = [regAddress, len(db_data), db_data] for name in segm: address, length, db_data = segm[name] ab_name = (name + '\x00').encode('utf-8') all_ab_name += len(ab_name) for name in segm: address, length, db_data = segm[name] ab_name = (name + '\x00').encode('utf-8') nameoffset = len(segm) * 32 + nameoffset_p dataoffset = len(segm) * 32 + all_ab_name + dataoffset_p db1 = struct.pack("<Q", nameoffset) db2 = struct.pack("<Q", address) db3 = struct.pack("<Q", length) db4 = struct.pack("<Q", dataoffset) binfile.write(db1) binfile.write(db2) binfile.write(db3) binfile.write(db4) nameoffset_p += len(ab_name) dataoffset_p += length for name in segm: address, length, db_data = segm[name] ab_name = (name + '\x00').encode('utf-8') binfile.write(ab_name) for name in segm: address, length, db_data = segm[name] binfile.write(db_data)
def run_yara_on_segments(rule_text, names=None, excluded_names=None, start_eas=None, excluded_eas=None, callback_func=_yara_callback): ''' Description: Applies yara rule to the bytes in the specified segments and returns raw results. Segemnts may be specified by name or start EA, but one or the other is required. Alternatively, names or start EAs may be provided to exclude. In this case all other segments will be scanned. Clears the matches each time to prevent duplicates. Input: names - The names of the target segments excluded_names - The names of the excluded segments start_eas - The start EAs of the target segments excluded_eas - The start EAs of the excluded segments callback_func - A pointer to the callback function for YARA's matching to use Output: Returns a list of YARA's match results with items (location, description) ''' global _YARA_MATCHES, FROM_FILE _YARA_MATCHES = [] FROM_FILE = False if names is None and excluded_names is None and start_eas is None and excluded_eas is None: raise Exception( "Either segment names, start EAs, excluded names, or excluded EAs are required to YARA scan by segment." ) if (names and excluded_names) or (start_eas and excluded_eas): raise Exception( "Do not specify names and excluded names or start eas and excluded eas." ) results = [] if names: for name in names: results.extend( run_yara_on_segment(rule_text, name=name, callback_func=callback_func)) elif start_eas: for start_ea in start_eas: results.extend( run_yara_on_segment(rule_text, start_ea=start_ea, callback_func=callback_func)) else: segs_eas = list(idautils.Segments()) if excluded_names: for seg_ea in segs_eas: seg_name = idaapi.get_segm_name(seg_ea) if seg_name not in excluded_names: results.extend( run_yara_on_segment(rule_text, name=seg_name, callback_func=callback_func)) elif excluded_eas: for seg_ea in segs_eas: if seg_ea not in excluded_eas: results.extend( run_yara_on_segment(rule_text, start_ea=seg_ea, callback_func=callback_func)) _YARA_MATCHES = results # For conformity sake, make sure _YARA_MATCHES is set with all results return _YARA_MATCHES
def get_segm_name(ea: int) -> Optional[str]: return idaapi.get_segm_name(idaapi.getseg(ea))
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 # for easy testing if __name__ == "__main__": print("[+] find_interesting():") for seg in idautils.Segments(): st = ida_segment.getseg(seg) name = idaapi.get_segm_name(st) if name == "iBoot" or name == "SecureROM" or name == "iBEC" \ or name == "BootRom" or name == "LLB": segm_start = st.start_ea segm_end = idc.get_segm_attr(segm_start, idc.SEGATTR_END) find_interesting(segm_start, segm_end) break # ida_pro.qexit() # EOF
def writeMem(self, binfile): regs = self.getRegs() segm = self.init_segm_mem() for n in xrange(idaapi.get_segm_qty()): seg = idaapi.getnseg(n) if seg: count = 0 h = '' while (idaapi.get_segm_name(seg, 0) + h) in segm.keys(): count += 1 h = str(count) name = idaapi.get_segm_name(seg, 0) + h address = seg.startEA length = seg.endEA - seg.startEA db_data = idaapi.dbg_read_memory(address, length) if db_data: print('ok ', name, seg.flags, length, 'bytes', length / 1024, 'kb') segm[name] = [address, length, db_data] else: print('faild', name, seg.flags, length, 'bytes', length / 1024, 'kb') pass nameoffset_p = 0 dataoffset_p = 0 all_ab_name = 0 for regAddress in regs: INT = regs[regAddress] regName = self.register_names[regAddress] size = self.registers[regName][1] try: if size == 1: db_data = struct.pack("<B", INT) elif size == 2: db_data = struct.pack("<H", INT) elif size == 4: db_data = struct.pack("<I", INT) elif size == 8: db_data = struct.pack("<Q", INT) elif size == 16: db_data = struct.pack("<QQ", int(INT & 0xffffffffffffffff), int(INT >> 64)) elif size == 32: db_data = struct.pack("<QQQQ", INT & 0xffffffffffffffff, (INT >> 64) & 0xffffffffffffffff, (INT >> 128) & 0xffffffffffffffff, INT >> 192) else: continue segm['registers' + str(regAddress)] = [regAddress, len(db_data), db_data] print(" (%-10s : %-5d) (%-x) (%d)" % (regName, regAddress, (INT), len(db_data))) except Exception as e: print("--------- error:", e, regName, hex(INT), size, "--------- ") for name in segm: address, length, db_data = segm[name] ab_name = (name + '\x00').encode('utf-8') all_ab_name += len(ab_name) for name in segm: address, length, db_data = segm[name] ab_name = (name + '\x00').encode('utf-8') nameoffset = len(segm) * 32 + nameoffset_p dataoffset = len(segm) * 32 + all_ab_name + dataoffset_p db1 = struct.pack("<Q", nameoffset) db2 = struct.pack("<Q", address) db3 = struct.pack("<Q", length) db4 = struct.pack("<Q", dataoffset) binfile.write(db1) binfile.write(db2) binfile.write(db3) binfile.write(db4) nameoffset_p += len(ab_name) dataoffset_p += length for name in segm: address, length, db_data = segm[name] ab_name = (name + '\x00').encode('utf-8') binfile.write(ab_name) for name in segm: address, length, db_data = segm[name] binfile.write(db_data)
def name(self): return idaapi.get_segm_name(self.segment)
def getSegmentName(self, ea): return idaapi.get_segm_name(ea)
def name(self): return idaapi.get_segm_name(self.segment_t)