def handle_dll_calls(self): dll_call_count = ida_bytes.get_dword(self.E_info_entry_ea + self.dll_call_count_offset) dll_call_lib_names_ea = ida_bytes.get_dword( self.E_info_entry_ea + self.dll_call_lib_names_offset) dll_call_func_names_ea = ida_bytes.get_dword( self.E_info_entry_ea + self.dll_call_func_names_offset) self.dll_calls = Dll_calls(dll_call_lib_names_ea, dll_call_func_names_ea, dll_call_count) ida_auto.auto_wait() ea = ida_name.get_name_ea(idaapi.BADADDR, "j__krnl_MCallDllCmd") code_fref_eas = [] fref_ea = ida_xref.get_first_fcref_to(ea) while fref_ea != idaapi.BADADDR: code_fref_eas.append(fref_ea) fref_ea = ida_xref.get_next_cref_to(ea, fref_ea) for ref_ea in code_fref_eas: #get prev mov instruction prev_ins_ea = idaapi.get_item_head(ref_ea - 1) ins = ida_lines.generate_disasm_line(prev_ins_ea, ida_lines.GENDSM_REMOVE_TAGS) if (ins.startswith("mov eax,")): index = ida_bytes.get_dword(prev_ins_ea + 1) cmt = self.dll_calls[index] ida_bytes.set_cmt(ref_ea, cmt, False)
def set_repeated_comment(address, repeated_comment): assert type(repeated_comment) == str if is_function_start(address): pfn = ida_funcs.get_func(address) ida_funcs.set_func_cmt(pfn, repeated_comment, 1) else: ida_bytes.set_cmt(address, repeated_comment, 1)
def run(self, arg=0): print("running") ea = idc.get_screen_ea() if idc.GetOpType(ea, 1) != 5: # Immediate return value = idc.GetOperandValue(ea, 1) & 0xffffffff ida_bytes.set_cmt(ea, windows_ioctl_decode(value), 1) return
def restore_x(unique_name=None, start=None): ea = ida_kernwin.get_screen_ea() # signature if not unique_name: if not start: seg = ida_segment.getseg(ea) start = seg.start_ea sig_bytes = ida_bytes.get_bytes(start, SIGNATURE_SIZE) sig_hash = hashlib.md5(sig_bytes).hexdigest() unique_name = sig_hash if not start: seg = ida_segment.getseg(ea) start = seg.start_ea if MD5_hash_data_file and os.path.isfile(MD5_hash_data_file): with open(MD5_hash_data_file, "rb") as ifile: received_data = pickle.loads(ifile.read()) saved_data = received_data print("dumpDyn::restore\n\ Name: {}\n\ Restore address: {}\n".format(unique_name, hex(start))) # (start_addr, end_addr, names, comms, bpts, funcs) if unique_name in saved_data: current_data = saved_data[unique_name] # restore names names = current_data[2] for name in names: # names: (rel_addr, name, is_code) ida_name.set_name(start + name[0], name[1]) flags = ida_bytes.get_flags(start + name[0]) if name[2] and not ida_bytes.is_code(flags): ida_auto.auto_make_code(start + name[0]) # restore comments # comms: (rel_addr, TYPE, comment) comms = current_data[3] for comm in comms: # 0:MakeComm and 1:MakeRptCmt ida_bytes.set_cmt(start + comm[0], comm[2], comm[1]) # restore breakpoints # bpts: (rel_addr, size, type) bpts = current_data[4] for bpt in bpts: ida_dbg.add_bpt(start + bpt[0], bpt[1], bpt[2]) # restore functions funcs_addr = current_data[5] for addr in funcs_addr: ida_auto.auto_make_proc(start + addr) # make code & func
def make_rpt(): """ Inserting a comment """ ida_bytes.set_cmt( comment["address"], comment["data"].encode( 'ascii', 'replace'), 1)
def rcomment(self, value): """ Setter which allow to set the value of the repeatable comment. :param value: The comment to set. :type value: :class:`str` """ if value is None: value = "" ida_bytes.set_cmt(self.ea, value, 1)
def load_struc(struc: StructureData, p: int, path: str) -> int: """ Load the given structure into the current IDA Pro at the given offset. Example:: load_struc(sections[0].data, 0x0, 'foo-section') Args: struc (wasm.Structure): the structure to load. p (int): the effective address at which to load. path (str): the namespaced name of the given structure. Returns: int: the next offset following the loaded structure. """ for field in get_fields(struc): # build names like: `sections:2:payload:entries:0:module_str` name = path + ':' + field.name # recurse into nested structures if is_struc(field.value): p = load_struc(cast(StructureData, field.value), p, name) # recurse into lists of structures elif (isinstance(field.value, list) and len(field.value) > 0 and is_struc(field.value[0])): for i, v in enumerate(field.value): p = load_struc(v, p, name + ':' + str(i)) # emit primitive types else: # add annotations like follows: # # imports:002D sections:2:payload:entries:0:module_len <--- Add line prior to element. # imports:002D db 3 ;; 0x3 <--- Render element for human. # imports:002E sections:2:payload:entries:0:module_str # imports:002E db 0x65 ;; e ;; env <--- Pull out strings and lists nicely. # imports:002F db 0x6E ;; n # imports:0030 db 0x76 ;; v # add line prior to element ida_lines.update_extra_cmt(p, ida_lines.E_PREV + 0, name) # if primitive integer element, set it as such if isinstance(field.value, int): MakeN(p, field.size) # add comment containing human-readable representation ida_bytes.set_cmt(p, format_value(name, field.value), 0) p += field.size return p
def import_line_comments(comments, sections): """ Import line comments :param comments: Dict containing line comments :param sections: Dict containing section info """ for addr, comment in comments.items(): addr = adjust_addr(sections, int(addr)) ida_bytes.set_cmt(addr, comment, 0)
def main(): for segstart, segend, segname in enum_segments(): for head in idautils.Heads(segstart, segend): if not is_code(head): continue # pattern: # # lea rax, unk_6BDF88 # mov [rsp+0], rax # mov qword ptr [rsp+8], 40h if ida_ua.ua_mnem(head) != "lea": continue next_head = ida_bytes.next_head(head, idc.BADADDR) if ida_ua.ua_mnem(next_head) != "mov": continue next_head2 = ida_bytes.next_head(next_head, idc.BADADDR) if ida_ua.ua_mnem(next_head2) != "mov": continue dst = idc.get_operand_value(head, 1) if idc.get_segm_name(dst) not in (".rdata", "UPX1"): continue size = idc.get_operand_value(next_head2, 1) if size > 0x100: continue if size <= 2: continue buf = ida_bytes.get_bytes(dst, size) if not buf: continue if b"\x00" in buf: continue try: s = buf.decode("ascii") except UnicodeDecodeError: continue print("string pointer: 0x%x -> 0x%x: %s" % (head, dst, s)) ida_bytes.del_items(dst, 1) ida_bytes.create_data(dst, idc.FF_BYTE, 1, idc.BADADDR) ida_bytes.set_cmt(dst, s, True) ida_name.set_name(dst, "s_%x" % (dst))
def add_comments(info_for_pcs, selections): for pc, info in info_for_pcs.items(): comment = ida_bytes.get_cmt(pc, 0) if (not comment): comment = "" if (selections['add_tids'] and selections['add_seqs']): label_portion = "(seq #, thread ID) = {}".format(sorted(list(info))) elif (selections['add_tids']): label_portion = "thread ID = {}".format(sorted(list(info))) else: label_portion = "seq # = {}".format(sorted(list(info))) if (comment == ""): comment = label_portion else: comment = comment + ", " + label_portion ida_bytes.set_cmt(pc, comment, 0)
def main(): for segstart, segend, segname in enum_segments(): if segname not in ('.rdata', 'UPX1' ): continue for src, dst, psize in find_pointers(segstart, segend): if idc.get_segm_name(dst) not in (".rdata", "UPX0"): continue if psize == 8: size = ida_bytes.get_qword(src + 0x8) else: size = ida_bytes.get_dword(src + 0x4) if size > 0x100: continue if size <= 2: continue buf = ida_bytes.get_bytes(dst, size) if not buf: continue if b"\x00" in buf: continue try: s = buf.decode("ascii") except UnicodeDecodeError: continue print("string pointer: 0x%x -> 0x%x: %s" % (src, dst, s)) ida_bytes.del_items(src, 1) ida_bytes.set_cmt(dst, s, True) # pointer ida_bytes.del_items(src, psize) ida_bytes.create_data(src, idc.FF_QWORD if size == 8 else idc.FF_DWORD, psize, idc.BADADDR) # this doesn't seem to always work :-( idc.op_plain_offset(src, -1, 0) ida_name.set_name(src, "s_%x" % (src)) ida_bytes.set_cmt(src, s, True) # size ida_bytes.del_items(src + psize, psize) ida_bytes.create_data(src + psize, idc.FF_QWORD if size == 8 else idc.FF_DWORD, psize, idc.BADADDR)
def set_ida_comment(addr, cmt, decompiled=False): func = ida_funcs.get_func(addr) if not func: l.info(f"No function found at {addr}") return False rpt = 1 # function comment if addr == func.start_ea: idc.set_func_cmt(addr, cmt, rpt) return True # a comment in decompilation elif decompiled: try: cfunc = idaapi.decompile(addr) except Exception: ida_bytes.set_cmt(addr, cmt, rpt) return True eamap = cfunc.get_eamap() decomp_obj_addr = eamap[addr][0].ea tl = idaapi.treeloc_t() # try to set a comment using the cfunc obj and normal address for a in [addr, decomp_obj_addr]: tl.ea = a for itp in range(idaapi.ITP_SEMI, idaapi.ITP_COLON): tl.itp = itp cfunc.set_user_cmt(tl, cmt) cfunc.save_user_cmts() cfunc.refresh_func_ctext() # attempt to set until it does not fail (orphan itself) if not cfunc.has_orphan_cmts(): cfunc.save_user_cmts() return True cfunc.del_orphan_cmts() return False # a comment in disassembly else: ida_bytes.set_cmt(addr, cmt, rpt) return True
def write_reg_info(index: dict): """Write register info as line comment at instruction pointed to by the program counter and change focus to that location :param index: _index.json JSON data """ cmt = "" for reg, val in index["regs"].items(): cmt += f"{reg.ljust(6)} : {hex(val)}\n" progctr = get_pc_by_arch(index) if progctr is None: raise ArchNotSupportedError( "Architecture not fully supported, skipping register status comment" ) ida_bytes.set_cmt(progctr, cmt, 0) ida_kernwin.jumpto(progctr)
def main(): filename, _ = QFileDialog.getOpenFileName(None, "Open file", ".", "CSV Files(*.csv)") if filename == "": return processes = set() input_file = open(filename, "r") reader = csv.reader(input_file) next(reader, None) for row in reader: processes.add((row[0], int(row[1]))) input_file.close() selected_pid = ProcessSelectDialog.selectProcess(processes) # N.B.: 0 is a valid process ID if (None == selected_pid): return semantic_labels = read_semantic_labels(filename + ".semantic_labels") snapshot = ida_loader.snapshot_t() snapshot.desc = "Before ida_taint2.py @ %s" % (datetime.datetime.now()) ida_kernwin.take_database_snapshot(snapshot) input_file = open(filename, "r") reader = csv.reader(input_file) labels_for_pc = {} # skip header next(reader, None) for row in reader: pid = int(row[1]) pc = int(row[2], 16) label = int(row[3]) try: label = semantic_labels[label] except KeyError: pass if pid != selected_pid: continue fn = ida_funcs.get_func(pc) if not fn: continue fn_start = fn.start_ea fn_name = ida_funcs.get_func_name(fn_start) if "TAINTED" not in fn_name: ida_name.set_name(fn_start, "TAINTED_" + fn_name, ida_name.SN_CHECK) fn.color = FUNC_COLOR ida_nalt.set_item_color(pc, INST_COLOR) if pc not in labels_for_pc: labels_for_pc[pc] = set() labels_for_pc[pc].add(label) input_file.close() for pc, labels in labels_for_pc.items(): comment = ida_bytes.get_cmt(pc, 0) if not comment: comment = "" label_portion = "taint labels = {}".format(list(labels)) if comment == "": comment = label_portion else: comment += ", " + label_portion ida_bytes.set_cmt(pc, comment, 0)
def _on_commentchanged(self, ea, comment, repeatable): ida_bytes.set_cmt(ea, Unicoder.encode(comment), repeatable)
def __call__(self): ida_bytes.set_cmt(self.ea, Event.encode(self.comment), self.rptble)
def __call__(self): ida_bytes.set_cmt(self.ea, self.comment, self.rptble)
def set_comment(address, comment): assert type(comment) == str # Always succeeds ida_bytes.set_cmt(address, comment, 0)
def apply_signatures(self, start_addr: int, end_addr: int) -> None: total_objs = len(self._signatures) idaapi.msg('Applying obj symbols...\n') objs_list = dict() for sig in self._signatures: bytes_data = sig.get_sig() low_entropy = (not bytes_data.is_bios_call()) and (sig.get_entropy() < self.min_entropy) labels = sig.get_labels() search_addr = start_addr while search_addr < end_addr: addr, _ = masked_search(search_addr, end_addr, bytes_data.get_bytes(), bytes_data.get_masks()) if addr == idaapi.BADADDR: break if not sig.is_applied(): objs_list[sig.get_name()] = (addr, sig.get_entropy()) for lb in labels: lb_name = lb[0] lb_offs = lb[1] if lb_name == '': # removed label continue lb_addr = addr + lb_offs if ida_bytes.is_unknown(ida_bytes.get_flags(lb_addr) and not low_entropy and not (sig.is_applied() and self.only_first)): ida_auto.auto_make_code(lb_addr) is_func = not lb_name.startswith('loc_') new_name = '%s_' % sig.get_name().replace('.', '_') new_lb_name = lb_name.replace('text_', new_name).replace('loc_', new_name) new_lb_name = ('_%s' % new_lb_name) if ('0' <= new_lb_name[0] <= '9') else new_lb_name if not low_entropy and not (sig.is_applied() and self.only_first) and not self.has_non_default_name(lb_addr, new_lb_name): SigApplier.set_function(lb_addr, new_lb_name, is_func, False) idaapi.msg('Symbol %s at 0x%08X\n' % (new_lb_name, lb_addr)) else: prev_comment = ida_bytes.get_cmt(lb_addr, False) prev_comment = ('%s\n' % prev_comment) if prev_comment else '' new_comment = 'Possible %s/%s' % (sig.get_name(), new_lb_name) if prev_comment.find(new_comment) == -1: ida_bytes.set_cmt(lb_addr, '%s%s' % (prev_comment, new_comment), False) idaapi.msg('Possible symbol %s at 0x%08X\n' % (new_lb_name, lb_addr)) sig.set_applied(True) search_addr = addr + 4 idaapi.msg('Applied OBJs for %s: %d/%d:\n' % (self.short_lib_name, len(objs_list), total_objs)) for k, v in objs_list.items(): idaapi.msg('\t0x%08X: %s, %.02f entropy\n' % (v[0], k, v[1]))
if (inst2 != None) and (inst2.get_canon_mnem() == "mov"): inst3 = idautils.DecodePreviousInstruction(inst2.ea) if (inst3 != None) and (inst3.get_canon_mnem() == "lea"): length = inst.Op2.value data_addr = inst3.Op2.addr return data_addr, length def decrypt_string(data, key): crypt = b64decode(data) plain = "".join(chr(ord(c) ^ ord(k)) for c, k in izip(crypt, cycle(key))) return b64decode(plain) arch = 64 if idaapi.get_inf_structure().is_64bit() else 32 ea = ida_name.get_name_ea(idaapi.BADADDR, "main.decodeString") key_addr = ida_name.get_name_ea(idaapi.BADADDR, "main.encoderKey") key = ida_bytes.get_bytes(ida_bytes.get_dword(key_addr), ida_bytes.get_dword(key_addr + arch / 8)) for xref in idautils.CodeRefsTo(ea, True): inst = idautils.DecodeInstruction(xref) if (inst != None) and (inst.get_canon_mnem() == "call"): data_addr, length = get_params(xref) data = ida_bytes.get_bytes(data_addr, length) decrypted_str = decrypt_string(data, key) print "0x{:08x} -> 0x{:x}[0x{:x}] = \"{}\"".format( xref, data_addr, length, decrypted_str) ida_bytes.set_cmt(xref, decrypted_str, False)
""" This file is part of Polichombr (c) ANSSI-FR 2018 Description: Semi automated test that add some data in the IDA database, that should be reflected in the second database """ import ida_name, ida_bytes, ida_struct import idc ida_name.set_name(0x401000, "TESTFUNCTION") ida_bytes.set_cmt(0x40100A, "TEST COMMENT", 0) ida_bytes.set_cmt(0x40100F, "TEST RPT COMMENT", 1) struct_1 = ida_struct.add_struc(0, "TESTSTRUCT1") struct_pointer = ida_struct.get_struc(struct_1) ida_struct.add_struc_member(struct_pointer, "TESTMEMBER", 0, 0, None, 0) idc.SetType(0x401000, "int __cdecl start(char *lpszTestArg);")
def define_item(address, size, shortdesc, comment): del_items(address, True) create_data(address, (word_flag() if size == IOREG_16 else byte_flag()), size, ida_netnode.BADNODE) set_name(address, shortdesc) set_cmt(address, comment, True)
def set_ida_comment(addr, cmt, rpt, func_cmt=False): if func_cmt: print(f"SETTING FUNC COMMENT: '{cmt}'") idc.set_func_cmt(addr, cmt, rpt) else: ida_bytes.set_cmt(addr, cmt, rpt)
def do_import(): db = {} module = idaapi.get_root_filename().lower() base = idaapi.get_imagebase() file = ida_kernwin.ask_file(0, "x64dbg database|{}".format(get_file_mask()), "Import database") if not file: return print("Importing database {}".format(file)) with open(file) as dbdata: db = json.load(dbdata) count = 0 labels = db.get("labels", []) for label in labels: try: if label["module"] != module: continue ea = int(label["address"], 16) + base name = label["text"] ida_name.set_name(ea, str(name), 0) count += 1 except: pass print("{:d}/{:d} label(s) imported".format(count, len(labels))) count = 0 comments = db.get("comments", []) for comment in comments: try: if comment["module"] != module: continue ea = int(comment["address"], 16) + base name = comment["text"] ida_bytes.set_cmt(ea, str(name), 1) count += 1 except: pass print("{:d}/{:d} comment(s) imported".format(count, len(comments))) count = 0 breakpoints = db.get("breakpoints", []) for breakpoint in breakpoints: try: if breakpoint["module"] != module: continue ea = int(breakpoint["address"], 16) + base bptype = breakpoint["type"] if bptype == BPNORMAL: count += 1 ida_dbg.add_bpt(ea, 1, BPT_DEFAULT) elif bptype == BPHARDWARE: titantype = int(breakpoint["titantype"], 16) hwtype = (titantype >> 4) & 0xF if hwtype == UE_HARDWARE_EXECUTE: hwtype = BPT_EXEC elif hwtype == UE_HARDWARE_WRITE: hwtype = BPT_WRITE elif hwtype == UE_HARDWARE_READWRITE: hwtype = BPT_RDWR else: continue hwsize = titantype & 0xF if hwsize == UE_HARDWARE_SIZE_1: hwsize = 1 elif hwsize == UE_HARDWARE_SIZE_2: hwsize = 2 elif hwsize == UE_HARDWARE_SIZE_4: hwsize = 4 elif hwsize == UE_HARDWARE_SIZE_8: hwsize = 8 else: continue count += 1 ida_dbg.add_bpt(ea, hwsize, hwtype) except: pass print("{:d}/{:d} breakpoint(s) imported".format(count, len(breakpoints))) print("Done!")
def make_rpt(): """ Inserting a comment """ ida_bytes.set_cmt(comment["address"], comment["data"].encode('ascii', 'replace'), 1)
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