def main(): tid = get_guid_tid() for type_name, type_prefix, filepath in GUID_LIST: print('[*] scanning {}'.format(type_name)) fp = open(filepath, 'r') for line in fp.readlines(): line = line.strip() if line == "": continue guid, guid_name = line.split(' ') guid_name = type_prefix + guid_name binary_pattern = make_binary_pattern(guid) ea = 0 while True: ea = idc.find_binary( ea, ida_search.SEARCH_DOWN | ida_search.SEARCH_NEXT | ida_search.SEARCH_NOSHOW, binary_pattern) if ea == idaapi.BADADDR: break idc.del_items(ea, 16, 0) ida_bytes.create_struct(ea, ida_struct.get_struc_size(tid), tid) if idc.set_name(ea, guid_name, ida_name.SN_NOWARN) != 1: for i in range(0, 100): if idc.set_name(ea, guid_name + "_" + str(i), ida_name.SN_NOWARN) == 1: break else: print("[!] 0x{:X}: failed to apply {}".format( ea, guid_name)) print("[*] 0x{:X}: {}".format(ea, guid_name)) print("[*] finished")
def load(infos): for info in infos: ida_name.set_name(info['address'], info['name']) type = info.get('type', None) # TODO this code is kind of mashed together... not sure of the # right way. tid = ida_struct.get_struc_id(type) if type else BADADDR if type: ida_bytes.create_struct(info['address'], info['sz'], tid) ida_bytes.create_data( info['address'], info['flags'], info['sz'], tid)
def load(infos): for info in infos: ida_name.set_name(info['address'], info['name']) # TODO this code is kind of mashed together... not sure of the # right way. tid = ida_struct.get_struc_id( info['type']) if info['type'] else BADADDR if info['type']: print(info['type'], hex(tid)) ida_bytes.create_struct(info['address'], info['sz'], tid) ida_bytes.create_data(info['address'], info['flags'], info['sz'], tid)
def force_make_struct(ea, struct_name): sptr = get_sptr_by_name(struct_name) if sptr == BADADDR: return False s_size = ida_struct.get_struc_size(sptr) ida_bytes.del_items(ea, ida_bytes.DELIT_SIMPLE, s_size) return ida_bytes.create_struct(ea, s_size, sptr.id)
def force_make_struct(ea, struct_name): """@return: True on success, False on failure""" sid = idc.get_struc_id(struct_name) if sid == BADADDR: log.warn("Structure not found: %s", struct_name) return False size = idc.get_struc_size(sid) if not size: log.warn("Structure with zero size: %s", struct_name) return False if not ida_bytes.del_items(ea, ida_bytes.DELIT_SIMPLE, size): log.warn("Failed to delete structure items: %s", struct_name) return False return ida_bytes.create_struct(ea, size, sid)
def apply_struct(ea, size, sid): ida_bytes.del_items(ea, size, idc.DELIT_DELNAMES) ida_bytes.create_struct(ea, size, sid) return size
def update_vtable_struct( functions_ea, vtable_struct, class_name, this_type=None, get_next_func_callback=get_vtable_line, vtable_head=None, ignore_list=None, add_dummy_member=False, pure_virtual_name=None, parent_name=None, add_func_this=True, force_rename_vtable_head=False, # rename vtable head even if it is already named by IDA # if it's not named, then it will be renamed anyway ): # pylint: disable=too-many-arguments,too-many-locals,too-many-branches # TODO: refactor if this_type is None: this_type = utils.get_typeinf_ptr(class_name) if not add_func_this: this_type = None func_ea, next_func = get_next_func_callback( functions_ea, ignore_list=ignore_list, pure_virtual_name=pure_virtual_name, ) dummy_i = 1 offset = 0 while func_ea is not None: new_func_name, _ = update_func_name_with_class(func_ea, class_name) func_ptr = None if ida_hexrays.init_hexrays_plugin(): fix_userpurge(func_ea, idc.TINFO_DEFINITE) update_func_this(func_ea, this_type, idc.TINFO_DEFINITE) func_ptr = utils.get_typeinf_ptr(utils.get_func_tinfo(func_ea)) else: func_ptr = make_funcptr_pt(func_ea, this_type) # TODO: maybe try to get or guess type? if add_dummy_member: utils.add_to_struct(vtable_struct, "dummy_%d" % dummy_i, func_ptr) dummy_i += 1 offset += utils.WORD_LEN ptr_member = utils.add_to_struct( vtable_struct, new_func_name, func_ptr, offset, overwrite=True, is_offs=True ) if ptr_member is None: log.error( "Couldn't add %s(%s) to vtable struct 0x%X at offset 0x%X", new_func_name, str(func_ptr), vtable_struct.id, offset, ) offset += utils.WORD_LEN if not ida_xref.add_dref(ptr_member.id, func_ea, ida_xref.XREF_USER | ida_xref.dr_I): log.warn( "Couldn't create xref between member %s and func %s", ida_struct.get_member_name(ptr_member.id), idc.get_name(func_ea), ) func_ea, next_func = get_next_func_callback( next_func, ignore_list=ignore_list, pure_virtual_name=pure_virtual_name, ) vtable_size = ida_struct.get_struc_size(vtable_struct) if vtable_head is None: vtable_head = functions_ea # ida_bytes.del_items(vtable_head, ida_bytes.DELIT_SIMPLE, vtable_size) ida_bytes.create_struct(vtable_head, vtable_size, vtable_struct.id) if not idc.hasUserName(idc.get_full_flags(vtable_head)) or force_rename_vtable_head: if parent_name is None and this_type: parent = utils.deref_struct_from_tinfo(this_type) parent_name = ida_struct.get_struc_name(parent.id) if parent_name == class_name: parent_name = None idc.set_name( vtable_head, get_vtable_instance_name(class_name, parent_name), ida_name.SN_CHECK | ida_name.SN_FORCE, )
def load_file(f, neflags, format): f.seek(0) ida_idp.set_processor_type("metapc", ida_idp.SETPROC_LOADER) MGROUPStart = 0 magic = f.read(2) if magic == MZ_HEADER_MAGIC: f.seek(0x22) MGROUPStart = DW(f) * 16 f.seek(MGROUPStart) magic = f.read(2) headerSize = DW(f) segmentDataAlignment = DW(f) nextExeOff = DD(f) SegDataOff = DD(f) f.file2base(MGROUPStart, 0, SegDataOff, True) ida_segment.add_segm(0, 0, 0x50, "HEADER", "MODULE") f.seek(MGROUPStart + 2) headerSize = rnDW(f, "headerSize", MGROUPStart) segmentDataAlignment = rnDW(f, "segmentDataAlignment", MGROUPStart) nextExeOff = rnDD(f, "nextExeOff", MGROUPStart) SegDataOff = rnDD(f, "SegDataOff", MGROUPStart) ResDataOff = rnDD(f, "ResDataOff", MGROUPStart) flags = rnDW(f, "flags", MGROUPStart) version = rnDB(f, "version", MGROUPStart) revision = rnDB(f, "revision", MGROUPStart) AutoDataSegNo = rnDW(f, "AutoDataSegNo", MGROUPStart) HeapSize = rnDW(f, "HeapSize", MGROUPStart) StackSize = rnDW(f, "StackSize", MGROUPStart) StartProc = rnDD(f, "StartProc", MGROUPStart) LoadProc = rnDD(f, "LoadProc", MGROUPStart) FreeProc = rnDD(f, "FreeProc", MGROUPStart) nSegments = rnDW(f, "nSegments", MGROUPStart) pSegTable = rnDW(f, "pSegTable", MGROUPStart) cbResTab = rnDW(f, "cbResTab", MGROUPStart) pResTab = rnDW(f, "pResTab", MGROUPStart) cbEntTab = rnDW(f, "cbEntTab", MGROUPStart) pEntTab = rnDW(f, "pEntTab", MGROUPStart) cbNamTab = rnDW(f, "cbNamTab", MGROUPStart) pNamTab = rnDW(f, "pNamTab", MGROUPStart) cbStrTab = rnDW(f, "cbStrTab", MGROUPStart) pStrTab = rnDW(f, "pStrTab", MGROUPStart) cbNRNamTab = rnDW(f, "cbNRNamTab", MGROUPStart) pNRNamTab = rnDW(f, "pNRNamTab", MGROUPStart) ida_segment.add_segm(0, pSegTable, pSegTable + (nSegments * SEG_STRUCT_SIZE), "SEGTABLE", "MODULE") ida_segment.add_segm(0, pResTab, pResTab + cbResTab, "RESOURCES", "MODULE") ida_segment.add_segm(0, pEntTab, pEntTab + cbEntTab, "ENTTABLE", "MODULE") ida_segment.add_segm(0, pNamTab, pNamTab + cbNamTab, "ENTNAME", "MODULE") ida_segment.add_segm(0, pStrTab, pStrTab + cbStrTab, "IMPORTS", "MODULE") ida_segment.add_segm(0, pNRNamTab, pNRNamTab + cbNRNamTab, "NRENTNAME", "MODULE") #parse segtable segentsid = defSEGENT() base = SegDataOff // 16 importCount = 0 for i in range(nSegments): segEntStart = pSegTable + i * SEG_STRUCT_SIZE ida_bytes.create_struct(segEntStart, SEG_STRUCT_SIZE, segentsid) segStart = ida_bytes.get_word(segEntStart + 2) segLen = ida_bytes.get_word(segEntStart + 4) segImports = ida_bytes.get_word(segEntStart + 6) importCount += segImports f.file2base(MGROUPStart + SegDataOff + segStart * 16, SegDataOff + segStart * 16, SegDataOff + (segStart + segLen) * 16, True) segBase = (base + segStart) * 16 #segmentDef = ida_segment.segment_t() #segmentDef.start_ea = segBase #segmentDef.end_ea = (base+segStart+segLen)*16 #ida_segment.set_selector() print(base + segStart) ida_segment.add_segm(base + segStart, segBase, (base + segStart + segLen) * 16, "", "", 0) sel = ida_segment.find_selector(base + segStart) seg = ida_segment.getseg(segBase) ida_segment.set_segm_addressing(seg, 0) segtable[i] = seg segimportstable[i] = segImports if i + 1 == AutoDataSegNo: ida_segment.set_segm_name(seg, "DATA", 0) ida_segment.set_segm_class(seg, "DATA", 0) dataSel = sel else: ida_segment.set_segm_name(seg, "TEXT", 0) ida_segment.set_segm_class(seg, "CODE", 0) if AutoDataSegNo == 0: dataSel = sel ida_segregs.set_default_dataseg(dataSel) #parse enttable pENT = pEntTab currord = 1 while pENT < pEntTab + cbEntTab: bundleCount = ida_bytes.get_byte(pENT) bundleFlags = ida_bytes.get_byte(pENT + 1) if bundleCount == 0 and bundleFlags == 0: break pENT += 2 for i in range(bundleCount): if bundleFlags == 0xFF: ordFlags = ida_bytes.get_byte(pENT) if ordFlags & 0x80: toexport.append(currord) segNo = ida_bytes.get_byte(pENT + 3) segOff = ida_bytes.get_word(pENT + 4) enttable[currord] = (segtable[segNo - 1].start_ea // 16, segOff) pENT += 6 else: ordFlags = ida_bytes.get_byte(pENT) if ordFlags & 0x80: toexport.append(currord) segOff = ida_bytes.get_word(pENT + 1) enttable[currord] = (segtable[bundleFlags - 1].start_ea // 16, segOff) pENT += 3 currord += 1 modulename = readPASSTR(pNamTab) make_entry(StartProc, modulename + "_start") make_entry(LoadProc, modulename + "_load") make_entry(FreeProc, modulename + "_free") #export named ordinals namedordtable = loadExportsF(f) for i in toexport: if i in namedordtable: name = namedordtable[i] else: name = "Ordinal" + str(i) (base, off) = enttable[i] addr = base * 16 + off ida_entry.add_entry(i, addr, name, 1) #process imports ida_segment.add_segm(0xF000, 0xF0000, 0xF0000 + importCount * 2, "IMPORTS", "XTRN", 0) import_ea = 0xF0000 for seg in segtable: segend = segtable[seg].end_ea f.seek(MGROUPStart + segend) for i in range(segimportstable[seg]): count = DB(f) mode = DB(f) relocStart = DW(f) module = DW(f) proc = DW(f) if (module == 0xFFFF): (base, off) = enttable[proc] else: modulestr = readPASSTR(pStrTab + module) if (proc & 0x8000) != 0: # read by ord ordinal = proc & 0x7FFF procname = modulestr + "_Ordinal" + str(ordinal) if not modulestr in importedmodules: if os.path.isfile(modulestr + ".EXE"): importedmodules[modulestr] = loadExports( modulestr + ".EXE") else: filename = ida_kernwin.ask_file( 0, modulestr + ".EXE", "Select file to name exports") if filename is not None and os.path.isfile( filename): importedmodules[modulestr] = loadExports( filename) else: importedmodules[modulestr] = None if modulestr in importedmodules and ( importedmodules[modulestr] is not None ) and ordinal in importedmodules[modulestr]: procname = importedmodules[modulestr][ordinal] else: procname = readPASSTR(pStrTab + proc) ida_bytes.create_data(import_ea, ida_bytes.FF_WORD, 2, ida_idaapi.BADADDR) ida_name.force_name(import_ea, procname) ida_bytes.set_cmt(import_ea, "Imported from " + modulestr, 1) base = 0xF000 off = import_ea - 0xF0000 import_ea += 2 for xx in range(count): next = ida_bytes.get_word(segtable[seg].start_ea + relocStart) if mode == 0x20: ida_bytes.put_word(segtable[seg].start_ea + relocStart + 2, base) ida_bytes.put_word(segtable[seg].start_ea + relocStart, off) elif mode == 0x10: ida_bytes.put_word(segtable[seg].start_ea + relocStart, off) elif mode == 0x0: ida_bytes.put_word(segtable[seg].start_ea + relocStart, base) relocStart = next #print "import %d: seg %d mode %s count %d relocStart %s module %s proc %s" % (i, seg, hex(mode), count, hex(relocStart), modulestr, hex(proc)) return 1
if sid == idaapi.BADADDR: print("Structure {} does not exist".format(name)) i=0 lastea=0 names={} firstcmdid=0 for ea in references: nameptr=ida_bytes.get_dword(ea) cmdid=ida_bytes.get_word(ea+0xA) if firstcmdid==0: firstcmdid=cmdid name=get_string(nameptr) names[cmdid]=name ida_bytes.del_items(ea, ida_bytes.DELIT_DELNAMES,0x10) ida_bytes.create_struct(ea, 0x10, sid) print(f"EA:{hex(ea)} Name:{name} Cmdid:{hex(cmdid)}") #idc.set_cmt(ea, str(i),0) i+=1 lastea=ea create_cmdptr() sid = ida_struct.get_struc_id("cmd_ptr") ssize = ida_struct.get_struc_size(sid) eas=search_ea("FC 3A 00 00","",None,startea-0x3000,lastea) sea=None for ea in eas: cmdid=ida_bytes.get_dword(ea+8) if cmdid==0x3AFD: sea=ea break
def update_vtable_struct( functions_ea, vtable_struct, class_name, this_type=None, get_next_func_callback=get_vtable_line, vtable_head=None, ignore_list=None, add_dummy_member=False, pure_virtual_name=None, parent_name=None, add_func_this=True, ): is_first_member = True if this_type is None: this_type = utils.get_typeinf_ptr(class_name) if not add_func_this: this_type = None func, next_func = get_next_func_callback( functions_ea, ignore_list=ignore_list, pure_virtual_name=pure_virtual_name ) dummy_i = 1 while func is not None: new_func_name, is_name_changed = update_func_name_with_class(func, class_name) func_ptr = None if ida_hexrays.init_hexrays_plugin(): if is_name_changed: func_type = update_func_this(func, this_type) else: func_type = update_func_this(func, None) if func_type is not None: func_ptr = utils.get_typeinf_ptr(func_type) else: func_ptr = make_funcptr_pt(func, this_type) if add_dummy_member: utils.add_to_struct(vtable_struct, f"dummy_{dummy_i}", func_ptr) dummy_i += 1 if is_first_member: # We did an hack for vtables contained in union vtable with one dummy member ptr_member = utils.add_to_struct( vtable_struct, new_func_name, func_ptr, 0, overwrite=True ) is_first_member = False else: ptr_member = utils.add_to_struct( vtable_struct, new_func_name, func_ptr, is_offset=True ) if ptr_member is None: logging.exception( "Couldn't add %s(%s) to %d", new_func_name, str(func_ptr), vtable_struct.id, ) ida_xref.add_dref(ptr_member.id, func, ida_xref.XREF_USER | ida_xref.dr_I) func, next_func = get_next_func_callback( next_func, ignore_list=ignore_list, pure_virtual_name=pure_virtual_name ) vtable_size = ida_struct.get_struc_size(vtable_struct) if vtable_head is None: vtable_head = functions_ea ida_bytes.del_items(vtable_head, ida_bytes.DELIT_SIMPLE, vtable_size) ida_bytes.create_struct(vtable_head, vtable_size, vtable_struct.id) if parent_name is None and this_type: parent = utils.deref_struct_from_tinfo(this_type) parent_name = ida_struct.get_struc_name(parent.id) if parent_name == class_name: parent_name = None utils.set_name_retry(vtable_head, get_vtable_instance_name(class_name, parent_name))