def define(ea): if CompleteObjectLocator.isDefined(ea): return if not CompleteObjectLocator.isValid(ea): raise RttiError( "%08X: doesn't look like a correct CompleteObjectLocator" % (ea)) # Ensure referenced structs are defined. # An exception will be thrown if something goes wrong. tdPtr = idaapi.get_full_long(ea + 12) td = TypeDescriptor(tdPtr) chdPtr = idaapi.get_full_long(ea + 16) chd = ClassHierarchyDescriptor(chdPtr) strid = idaapi.get_struc_id('_s__RTTICompleteObjectLocator') size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) if chd.isMultipleInheritance: if chd.isVirtualInheritance: print '%08X: Cannot handle virtual inheritance yet.' % (ea) else: # '??_R4' + td.baseMangledName + '6B' + baseClassTd.baseMangledName + '@' # '??_7' + ... print '%08X: Cannot handle multiple inheritance yet.' % (ea) else: idaapi.set_name(ea, '??_R4' + td.baseMangledName + '6B@', 0)
def make_xref(from_ea, to_ea, xref_constructor, xref_size): """Force the data at `from_ea` to reference the data at `to_ea`.""" if not idc.GetFlags(to_ea) or is_invalid_ea(to_ea): DEBUG(" Not making reference (A) from {:x} to {:x}".format(from_ea, to_ea)) return make_head(from_ea) if is_code(from_ea): _CREFS_FROM[from_ea].add(to_ea) _CREFS_TO[to_ea].add(from_ea) else: _DREFS_FROM[from_ea].add(to_ea) _DREFS_TO[to_ea].add(from_ea) # If we can't make a head, then it probably means that we're at the # end of the binary, e.g. the last thing in the `.extern` segment. if not make_head(from_ea + xref_size): assert idc.BADADDR == idc.SegStart(from_ea + xref_size) idaapi.do_unknown_range(from_ea, xref_size, idc.DOUNK_EXPAND) xref_constructor(from_ea) if not is_code_by_flags(from_ea): idc.add_dref(from_ea, to_ea, idc.XREF_USER|idc.dr_O) else: DEBUG(" Not making reference (B) from {:x} to {:x}".format(from_ea, to_ea))
def chendo(address, end, search, struct): while address < end: address = idaapi.find_binary(address, end, search, 0x10, SEARCH_DOWN) idaapi.do_unknown_range(address, 0xB0, 0) idaapi.create_struct(address, 0xB0, struct) address += 0x8
def __init__(self, ea, vtable): do_unknown_range(ea, self.size, DOUNK_DELNAMES) if doStruct(ea, self.size, self.tid): # Get adress of type descriptor from CompleteLocator print "Complete Object Locator at: 0x%x" % ea offset = get_member_by_name(self.struc, "pTypeDescriptor").soff typeDescriptor = get_32bit(ea + offset) + u.x64_imagebase() print "Looking for type Descriptor at: 0x%x" % typeDescriptor rtd = RTTITypeDescriptor(typeDescriptor) if rtd.class_name: print "Type Descriptor at: 0x%x" % typeDescriptor offset = get_member_by_name(self.struc, "pClassDescriptor").soff classHierarchyDes = get_32bit(ea + offset) + u.x64_imagebase() rchd = RTTIClassHierarchyDescriptor(classHierarchyDes) # filter out None entries rchd.bases = filter(lambda x: x, rchd.bases) className = strip(rtd.class_name) classes[className] = [strip(b) for b in rchd.bases] vtables[className] = vtable MakeNameEx(vtable, "vtable__" + className, SN_NOWARN) else: # if the RTTITypeDescriptor doesn't have a valid name for us to # read, then this wasn't a valid RTTICompleteObjectLocator MakeUnknown(ea, self.size, DOUNK_SIMPLE)
def make_xref(from_ea, to_ea, xref_constructor, xref_size): """Force the data at `from_ea` to reference the data at `to_ea`.""" if not idc.GetFlags(to_ea) or is_invalid_ea(to_ea): DEBUG(" Not making reference (A) from {:x} to {:x}".format( from_ea, to_ea)) return make_head(from_ea) if is_code(from_ea): _CREFS_FROM[from_ea].add(to_ea) _CREFS_TO[to_ea].add(from_ea) else: _DREFS_FROM[from_ea].add(to_ea) _DREFS_TO[to_ea].add(from_ea) # If we can't make a head, then it probably means that we're at the # end of the binary, e.g. the last thing in the `.extern` segment. if not make_head(from_ea + xref_size): assert idc.BADADDR == idc.SegStart(from_ea + xref_size) idaapi.do_unknown_range(from_ea, xref_size, idc.DOUNK_EXPAND) xref_constructor(from_ea) if not is_code_by_flags(from_ea): idc.add_dref(from_ea, to_ea, idc.XREF_USER | idc.dr_O) else: DEBUG(" Not making reference (B) from {:x} to {:x}".format( from_ea, to_ea))
def define(ea): if BaseClassDescriptor.isDefined(ea): return td = TypeDescriptor(BaseClassDescriptor.__typeDescriptorPtr(ea)) attrs = BaseClassDescriptor.__attributes(ea) if attrs != 0 and attrs != 0x40: print "%08X: Suspicious attributes value: %08X" % (ea, attrs) # raise RttiError('%08X: Suspicious attributes value: %08X' % (ea, attrs)) isV2 = (attrs & 0x40) != 0 if isV2: strid = idaapi.get_struc_id("_s__RTTIBaseClassDescriptor2") else: strid = idaapi.get_struc_id("_s__RTTIBaseClassDescriptor") size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) pmd = BaseClassDescriptor.__where(ea) name = "??_R1" name += mangleNumber(pmd.mdisp) name += mangleNumber(pmd.pdisp) name += mangleNumber(pmd.vdisp) name += mangleNumber(attrs) name += td.baseMangledName + "8" idaapi.set_name(ea, name, 0) if isV2: ClassHierarchyDescriptor.define(BaseClassDescriptor.__v2ChdPtr(ea))
def define(ea): if CompleteObjectLocator.isDefined(ea): return if not CompleteObjectLocator.isValid(ea): raise RttiError("%08X: doesn't look like a correct CompleteObjectLocator" % (ea)) # Ensure referenced structs are defined. # An exception will be thrown if something goes wrong. tdPtr = idaapi.get_full_long(ea + 12) td = TypeDescriptor(tdPtr) chdPtr = idaapi.get_full_long(ea + 16) chd = ClassHierarchyDescriptor(chdPtr) strid = idaapi.get_struc_id("_s__RTTICompleteObjectLocator") size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) if chd.isMultipleInheritance: if chd.isVirtualInheritance: print "%08X: Cannot handle virtual inheritance yet." % (ea) else: # '??_R4' + td.baseMangledName + '6B' + baseClassTd.baseMangledName + '@' # '??_7' + ... print "%08X: Cannot handle multiple inheritance yet." % (ea) else: idaapi.set_name(ea, "??_R4" + td.baseMangledName + "6B@", 0)
def __init__(self, ea, vtable): filepath = GetIdbPath()[:-4] fp = open(r"{filepath}.txt".format(filepath=filepath), 'a') # fp.write(filepath) print "Create file" do_unknown_range(ea, self.size, DOUNK_DELNAMES) if doStruct(ea, self.size, self.tid): # Get adress of type descriptor from CompleteLocator # print "Complete Object Locator at: 0x%x" % ea offset = get_member_by_name(self.struc, "pTypeDescriptor").soff typeDescriptor = get_32bit(ea + offset) + u.x64_imagebase() # print "Looking for type Descriptor at: 0x%x" % typeDescriptor rtd = RTTITypeDescriptor(typeDescriptor) if rtd.class_name: # print "Type Descriptor at: 0x%x" % typeDescriptor offset = get_member_by_name(self.struc, "pClassDescriptor").soff classHierarchyDes = get_32bit(ea + offset) + u.x64_imagebase() rchd = RTTIClassHierarchyDescriptor(classHierarchyDes) # filter out None entries rchd.bases = filter(lambda x: x, rchd.bases) classes[strip(rtd.class_name)] = [strip(b) for b in rchd.bases] MakeNameEx(vtable, "vtable__" + strip(rtd.class_name), SN_NOWARN) tempStr = hex(vtable).rstrip('L') + '\t' + strip( rtd.class_name) + '\t' + str(GuessType( Dword(vtable + 4))) + '\n' if ('std' not in tempStr[:15] and 'ATL' not in tempStr[:15]): fp.write(tempStr) else: # if the RTTITypeDescriptor doesn't have a valid name for us to # read, then this wasn't a valid RTTICompleteObjectLocator MakeUnknown(ea, self.size, DOUNK_SIMPLE) fp.close()
def define(ea): if BaseClassDescriptor.isDefined(ea): return td = TypeDescriptor(BaseClassDescriptor.__typeDescriptorPtr(ea)) attrs = BaseClassDescriptor.__attributes(ea) if attrs != 0 and attrs != 0x40: print '%08X: Suspicious attributes value: %08X' % (ea, attrs) # raise RttiError('%08X: Suspicious attributes value: %08X' % (ea, attrs)) isV2 = (attrs & 0x40) != 0 if isV2: strid = idaapi.get_struc_id('_s__RTTIBaseClassDescriptor2') else: strid = idaapi.get_struc_id('_s__RTTIBaseClassDescriptor') size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) pmd = BaseClassDescriptor.__where(ea) name = '??_R1' name += mangleNumber(pmd.mdisp) name += mangleNumber(pmd.pdisp) name += mangleNumber(pmd.vdisp) name += mangleNumber(attrs) name += td.baseMangledName + '8' idaapi.set_name(ea, name, 0) if isV2: ClassHierarchyDescriptor.define(BaseClassDescriptor.__v2ChdPtr(ea))
def make_code(start, end): for i in range((end - start) / 4): addr = start + (i * 4) if not idc.isCode(idc.GetFlags(addr)): idaapi.do_unknown_range(addr, 4, 0) idaapi.auto_make_code(addr) idc.MakeCode(addr) return
def Chendo(address, members): for (size, name) in members: flags = idaapi.get_flags_by_size(size) idaapi.do_unknown_range(address, size, 0) if name == '': idc.make_array(address, size) else: idaapi.create_data(address, flags, size, BADNODE) idc.set_cmt(address, name, False) address += size
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 define(ea): if TypeDescriptor.isDefined(ea): return if not TypeDescriptor.isValid(ea): raise RttiError("%08X: This doesn't look like a TypeDescriptor." % ea) # FIXME: 64-bit compatibility mangledName = getAsciiz(ea + 8) # Define data in DB structLength = 8 + len(mangledName) + 1 idaapi.do_unknown_range(ea, structLength, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, structLength, idaapi.get_struc_id("_TypeDescriptor")) idaapi.set_name(ea, TypeDescriptor.makeName(ea), 0)
def forceStruct(ea, name): """ forceStruct: ea, name Does all the necessary things to force IDA to convert the memory starting at address 'ea' into a struct of type 'name'. Returns the address after the struct. """ sid = idaapi.get_struc_id(name) ssize = idaapi.get_struc_size(sid) idaapi.do_unknown_range(ea, ssize, DOUNK_DELNAMES) x = idaapi.doStruct(ea, ssize, sid) return ea + ssize
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 define(ea, count): # TODO: sanity checks idaapi.do_unknown_range(ea, count * 4, idaapi.DOUNK_DELNAMES) idaapi.doDwrd(ea, 4) idaapi.do_data_ex(ea, idaapi.getFlags(ea), count * 4, idaapi.BADADDR) # TODO: rewrite into idaapi calls idc.SetArrayFormat(ea, idc.AP_INDEX | idc.AP_IDXDEC, 1, 0) # Entry 0 describes the class itself => I can find out the class name. bcd = BaseClassDescriptor(idaapi.get_full_long(ea)) idaapi.set_name(ea, "??_R2" + bcd.typeDescriptor.baseMangledName + "8", 0) i = 1 while i < count: bcd = BaseClassDescriptor(idaapi.get_full_long(ea + i * 4)) i += 1
def define(ea): if ClassHierarchyDescriptor.isDefined(ea): return if not ClassHierarchyDescriptor.isValid(ea): raise RttiError("%08X: Doesn't look like a correct ClassHierarchyDescriptor" % ea) strid = idaapi.get_struc_id("_s__RTTIClassHierarchyDescriptor") size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) bca = BaseClassArray( ClassHierarchyDescriptor.__baseClassArrayPtr(ea), ClassHierarchyDescriptor.__baseClassCount(ea) ) # Entry 0 describes the class itself => I can find out the class name. idaapi.set_name(ea, "??_R3" + bca[0].typeDescriptor.baseMangledName + "8", 0)
def znullptr(address, end, search, struct): magic = idaapi.find_binary(address, end, search, 0x10, idc.SEARCH_DOWN) pattern = '%02X %02X %02X %02X FF FF FF FF' % (magic & 0xFF, ((magic >> 0x8) & 0xFF), ((magic >> 0x10) & 0xFF), ((magic >> 0x18) & 0xFF)) sysvec = idaapi.find_binary(address, cvar.inf.maxEA, pattern, 0x10, idc.SEARCH_UP) - 0x60 idaapi.set_name(sysvec, 'sysentvec', SN_NOCHECK | SN_NOWARN | SN_FORCE) sysent = idaapi.get_qword(sysvec + 0x8) idaapi.set_name(sysent, 'sv_table', SN_NOCHECK | SN_NOWARN | SN_FORCE) sysnames = idaapi.get_qword(sysvec + 0xD0) idaapi.set_name(sysnames, 'sv_syscallnames', SN_NOCHECK | SN_NOWARN | SN_FORCE) # Get the list of syscalls offset = idaapi.find_binary(address, cvar.inf.maxEA, '73 79 73 63 61 6C 6C 00 65 78 69 74 00', 0x10, SEARCH_DOWN) numsyscalls = idaapi.get_qword(sysvec) for entry in xrange(numsyscalls): initial = sysnames + (entry * 0x8) idc.create_data(initial, FF_QWORD, 0x8, BADNODE) offset = idaapi.get_qword(initial) length = idaapi.get_max_strlit_length(offset, STRTYPE_C) name = idaapi.get_strlit_contents(offset, length, STRTYPE_C) sysentoffset = sysent + 0x8 + (entry * 0x30) idaapi.do_unknown_range(sysentoffset - 0x8, 0x30, 0) idaapi.create_struct(sysentoffset - 0x8, 0x30, struct) idc.set_cmt(sysentoffset - 0x8, '#%i' % entry, False) if '{' in name: continue # Rename the functions function = idaapi.get_qword(sysentoffset) idaapi.set_name(function, name.replace('#', 'sys_'), SN_NOCHECK | SN_NOWARN | SN_FORCE)
def define(ea, count): # TODO: sanity checks idaapi.do_unknown_range(ea, count * 4, idaapi.DOUNK_DELNAMES) idaapi.doDwrd(ea, 4) idaapi.do_data_ex(ea, idaapi.getFlags(ea), count * 4, idaapi.BADADDR) # TODO: rewrite into idaapi calls idc.SetArrayFormat(ea, idc.AP_INDEX | idc.AP_IDXDEC, 1, 0) # Entry 0 describes the class itself => I can find out the class name. bcd = BaseClassDescriptor(idaapi.get_full_long(ea)) idaapi.set_name(ea, '??_R2' + bcd.typeDescriptor.baseMangledName + '8', 0) i = 1 while i < count: bcd = BaseClassDescriptor(idaapi.get_full_long(ea + i * 4)) i += 1
def define(ea): if ClassHierarchyDescriptor.isDefined(ea): return if not ClassHierarchyDescriptor.isValid(ea): raise RttiError( "%08X: Doesn't look like a correct ClassHierarchyDescriptor" % ea) strid = idaapi.get_struc_id('_s__RTTIClassHierarchyDescriptor') size = idaapi.get_struc_size(strid) idaapi.do_unknown_range(ea, size, idaapi.DOUNK_DELNAMES) idaapi.doStruct(ea, size, strid) bca = BaseClassArray(ClassHierarchyDescriptor.__baseClassArrayPtr(ea), ClassHierarchyDescriptor.__baseClassCount(ea)) # Entry 0 describes the class itself => I can find out the class name. idaapi.set_name(ea, '??_R3' + bca[0].typeDescriptor.baseMangledName + '8', 0)
def __init__(self, ea): name = ea + get_member_by_name(self.struc, "name").soff strlen = u.get_strlen(name) if strlen is None: # not a real vtable return self.size = self.size + strlen mangled = get_ascii_contents(name, strlen, 0) if mangled is None: # not a real function name return print "Mangled: " + mangled demangled = demangle_name('??_R0' + mangled[1:], 0) if demangled: do_unknown_range(ea, self.size, DOUNK_DELNAMES) if doStruct(ea, self.size, self.tid): print " Made td at 0x%x: %s" % (ea, demangled) self.class_name = demangled return print " FAIL :(" return
def __init__(self, ea): print "Processing Class Hierarchy Descriptor at 0x%x" % ea do_unknown_range(ea, get_struc_size(self.tid), DOUNK_DELNAMES) if doStruct(ea, get_struc_size(self.tid), self.tid): baseClasses = get_32bit(ea + get_member_by_name( self.struc, "pBaseClassArray").soff) + u.x64_imagebase() nb_classes = get_32bit( ea + get_member_by_name(self.struc, "numBaseClasses").soff) print "Baseclasses array at 0x%x" % baseClasses # Skip the first base class as it is itself (could check) self.bases = [] for i in range(1, nb_classes): baseClass = get_32bit(baseClasses + i * 4) + u.x64_imagebase() print "base class 0x%x" % baseClass doDwrd(baseClasses + i * 4, 4) op_offset(baseClasses + i * 4, -1, u.REF_OFF | REFINFO_RVA, -1, 0, 0) doStruct(baseClass, RTTIBaseClassDescriptor.size, RTTIBaseClassDescriptor.tid) typeDescriptor = get_32bit(baseClass) + u.x64_imagebase() self.bases.append( RTTITypeDescriptor(typeDescriptor).class_name)
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))
pc = triton.getSymbolicRegisterValue(triton.REG.RIP) rax_ast = triton.buildSymbolicRegister(triton.REG.RAX) rax_ast = triton.getFullAst(rax_ast) rax_ast = triton.simplify(rax_ast, True) start = time.time() print("[+] computing Arybo representation...") e = atools.tritonast2arybo(rax_ast, use_exprs=True, use_esf=False) print("[+] got Arybo expression, evalute it...") e = aexprs.eval_expr(e, use_esf=False) end = time.time() diff = end - start print("[*] Arybo evaluation computed in %0.4fs" % diff) app = e.vectorial_decomp([rdi.v]) exp = atools.identify(app, "rdi") print("[*] Identified expression: rax = %s" % aexprs.prettyprint(exp)) asm = easm.asm_binary(exp, ("rax", 64), {"rdi": ("rdi", 64)}, "x86_64-unknown-unknwon") print("[*] Assembled expression: %s" % asm.encode("hex")) func_size = func.endEA - 1 - func.startEA if len(asm) > func_size: printf("[-] Final assembly does not fit in the original function!") asm_nop = asm + "\x90" * (func_size - len(asm)) func_start = int(func.startEA) func_end = int(func.endEA) idaapi.patch_many_bytes(func_start, asm_nop) idaapi.do_unknown_range(func_start, func_end, 0) idaapi.auto_make_code(func_start) idaapi.auto_make_proc(func_start)
def make_data(self, object_version, address): size = 0 try: size = object_version.get_size() except KeyError: pass flags = None try: flags = object_version.get_object_flags() except KeyError: pass if size == 0: idc.MakeUnkn(address, idc.DOUNK_EXPAND) else: if flags is not None: if idc.isASCII(flags): try: str_type = object_version.get_string_type() YaToolIDATools.check_and_set_str_type(str_type) except KeyError: pass idc.MakeStr(address, address + size) idc.SetFlags(address, flags) if idc.isStruct(flags): found = False for xref_offset_operand, xref_id_attr in object_version.get_xrefed_id_map( ).iteritems(): (xref_offset, xref_operand) = xref_offset_operand for xref_hash, xref_attrs in xref_id_attr: if xref_hash in self.struc_ids: struc_id = self.struc_ids[xref_hash] if DEBUG_EXPORTER: logger.debug( "making unknown from 0x%08X to 0x%08X" % (address, address + size)) idaapi.do_unknown_range( address, size, idc.DOUNK_DELNAMES) # idc.MakeUnkn(address, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # for i in xrange(1, size): # MakeName(address + i, "") # idc.MakeUnkn(address + i, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # idc.MakeStructEx uses idaapi.doStruct (but asks for name while # we already have the struc id) if DEBUG_EXPORTER: logger.debug( "Making struc at %s : %s (sizeof(%s)=0x%08X, size=0x%08X, flags=0x%08X" % (self.yatools.address_to_hex_string( address), self.yatools.address_to_hex_string( struc_id), idaapi.get_struc_name(struc_id), idc.GetStrucSize(struc_id), size, flags)) idc.SetCharPrm(idc.INF_AUTO, True) idc.Wait() if idaapi.doStruct(address, size, struc_id) == 0: if DEBUG_EXPORTER: logger.warning("Making struc failed") idc.SetCharPrm(idc.INF_AUTO, False) # idc.SetFlags(address, flags) found = True else: logger.error( "bad struc flags : idc.isStruct is true but no xref available for object %s" % self.hash_provider.hash_to_string( object_version.get_id())) if not found: logger.error( "bad struc flags : idc.isStruct is true " "but no struc available for object %s (%s)" % (self.hash_provider.hash_to_string( object_version.get_id()), object_version.get_name())) else: idc.MakeData(address, flags & (idc.DT_TYPE | idc.MS_0TYPE), size, 0) else: idc.MakeData(address, idc.FF_BYTE, size, 0) self.make_name(object_version, address, False) self.set_type(object_version, address)