def activate(self, ctx): import json filepath = idc.AskFile(False, "*.zmu;*.overlay;*", "Load Zelos Overlay...") if filepath is None: return f = open(filepath, "r") zelos_data = f.read() f.close() zelos_data = zelos_data[len("DISAS\n"):] zelos_dump = json.loads(zelos_data) # Apply the overlay data for comment in zelos_dump["comments"]: ea = comment["address"] try: comment_text = str(comment["text"]) except UnicodeEncodeError: comment_text = "" color = comment.get("color", 0x73F0DF) # Set color of instruction line idaapi.set_item_color(ea, color) idaapi.set_cmt(ea, comment_text, False) # Set function name if not already changed idc.GetFunctionAttr(ea, idc.FUNCATTR_START) name = idc.GetFunctionName(ea) if len(name) > 0 and name.startswith("zmu_") is False: idc.MakeName(ea, "zmu_" + name) return 1
def activate(self, ctx): import json filepath = idc.AskFile(False, '*.zmu;*.overlay;*', 'Load Zemu Overlay...') if filepath is None: return f = open(filepath, 'r') zemu_data = f.read() f.close() zemu_data = zemu_data[len('DISAS\n'):] zemu_dump = json.loads(zemu_data) # Apply the overlay data for comment in zemu_dump['comments']: ea = comment['address'] comment_text = str(comment['text']) color = comment.get('color', 0x73f0df) # Set color of instruction line idaapi.set_item_color(ea, color) idaapi.set_cmt(ea, comment_text, False) # Set function name if not already changed idc.GetFunctionAttr(ea, idc.FUNCATTR_START) name = idc.GetFunctionName(ea) if len(name) > 0 and name.startswith('zmu_') == False: idc.MakeName(ea, 'zmu_' + name) return 1
def get_decode_xrefs(): """ Find all cross-refernces to 0x132549a in our REvil malware sample. Decode the string and annotate the IDA database, this will make analysis a lot easier """ for xref in idautils.XrefsTo(0x132549a): # first of all, we need to find the arguments to this function, the signature is: # BYTE* __cdecl decode_string(char* base, int keyOffset, int keyLen, int dataLen, BYTE* pOut); args = get_decode_args(xref.frm) if args: base, key_offset, key_len, data_len = args # get the data from the image, data = [keyBytes][encryptedData] data = ida_bytes.get_bytes(base + key_offset, key_len + data_len) str = data_to_str(decode_string(data, key_len, data_len)) print("0x%08x: %s" % (xref.frm, str)) # put a comment in the code cfunc = idaapi.decompile(xref.frm) if cfunc is not None: tl = idaapi.treeloc_t() tl.ea = xref.frm tl.itp = idaapi.ITP_SEMI cfunc.set_user_cmt(tl, str) cfunc.save_user_cmts() idaapi.set_cmt(int(xref.frm), str, True) else: # We could not get the arguments, likely because it may be a register and not an immediate # value, so we'd need to go back further and find what value that register was assigned with. # Would be easier to just tell user, and let him decode it manually (HexRays has the actual args) print("0x%08x: Could not decode arguments" % xref.frm)
def add_to_comment(ea, key, value): """Add key:value to comm string at EA.""" from bap_comment import add_to_comment_string old_comm = idaapi.get_cmt(ea, 0) if old_comm is None: old_comm = '' new_comm = add_to_comment_string(old_comm, key, value) idaapi.set_cmt(ea, new_comm, 0)
def update(self, ea, key, value): """Add key=values to comm string at EA.""" cmt = idaapi.get_cmt(ea, 0) comm = cmt and bap_comment.parse(cmt) or {} values = comm.setdefault(key, []) if value and value != '()' and value not in values: values.append(value) idaapi.set_cmt(ea, bap_comment.dumps(comm), 0)
def add_refs(): global refs for (ea, target_addr, target_name) in refs: if target_name and len(target_name) != 0: idaapi.set_cmt(ea, "%s - 0x%X" % (target_name, ea + 4), False) else: idaapi.set_cmt(ea, "0x%X - 0x%X" % (target_addr, ea + 4), False) idaapi.add_dref(ea, target_addr, idc.dr_O)
def handle_comments(delta, segs): for cmt_offset in get_all_comments(): for is_repeatable in (True, False): cmt = idaapi.get_cmt(cmt_offset, is_repeatable) if not cmt: continue new_cmt = rebase_comment(segs, delta, cmt) if not new_cmt: continue idaapi.set_cmt(cmt_offset, new_cmt, is_repeatable)
def _loadFunctionsNames(self, file_name: Optional[str], ext: str) -> Optional[Tuple[int, int]]: """Loads functions names from the given file into the internal mappings. Fromats: CSV (default), or TAG (PE-bear, PE-sieve compatibile). """ if file_name is None or len(file_name) == 0: return None curr_functions = self._listFunctionsAddr() delim = "," # new delimiter (for CSV format) delim2 = ":" # old delimiter rva_indx = 0 cmt_indx = 1 is_imp_list = False if ".imports.txt" in ext: is_imp_list = True cmt_indx = 2 if ".tag" in ext: # a TAG format was chosen delim2 = ";" functions = 0 comments = 0 with open(file_name, 'r') as f: for line in f.readlines(): line = line.strip() fn = line.split(delim) if len(fn) < 2: fn = line.split(delim2) # try old delimiter if len(fn) < 2: continue start = 0 addr_chunk = fn[rva_indx].strip() if not _is_hex_str(addr_chunk): continue try: start = int(addr_chunk, 16) except ValueError: # this line doesn't start from an offset, so skip it continue func_name = fn[cmt_indx].strip() if start < idaapi.get_imagebase(): # it is RVA start = rva_to_va(start) # convert to VA if is_imp_list or (start in curr_functions): if is_imp_list: func_name = self._stripImportName(func_name) thunk_val = int(fn[1].strip(), 16) self._defineImportThunk(start, thunk_val) if self.subDataManager.setFunctionName(start, func_name): functions += 1 continue set_cmt(start, func_name, 1) # set the name as a comment comments += 1 return (functions, comments)
def implement(self): if self._comment_type == "regular": idaapi.set_cmt(self._linear_address, self._value, 0) elif self._comment_type == "repetable": idaapi.set_cmt(self._linear_address, self._value, 1) elif self._comment_type == "function": idc.set_func_cmt(self._linear_address, self._value, 0) elif self._comment_type == "anterior": ida_lines.add_extra_cmt(self._linear_address, 1, self._value) elif self._comment_type == "posterior": ida_lines.add_extra_cmt(self._linear_address, 0, self._value)
def clear_bap_comments(self): """Ask user for confirmation and then clear (BAP ..) comments.""" if idaapi.askyn_c(ASKBTN_YES, "Delete all `BAP: ..` comments?") != ASKBTN_YES: return for ea in ida.addresses(): # TODO: store actually commented addresses comm = idaapi.get_cmt(ea, 0) if comm and comm.startswith('BAP:'): idaapi.set_cmt(ea, '', 0)
def setComments(info, decStr): #Set Comment for Decompile (hexray) cfunc = idaapi.decompile(info['addr']) tl = idaapi.treeloc_t() tl.ea = info['addr'] + 7 tl.itp = idaapi.ITP_SEMI cfunc.set_user_cmt(tl, decStr) cfunc.save_user_cmts() #Set Comment for Disasemble (IDA) idaapi.set_cmt(info['addr'], decStr, None)
def req_rcmt(self, hash): msg, offset, base = hash['msg'], hash['offset'], hash['base'] offset, msg = self.addr_switch(offset, msg) if not offset: return ea = self.rebase(base, offset) if not ea: return idaapi.set_cmt(ea, str(''), False) rs_log("reset comment at 0x%x" % ea)
def req_rcmt(self, hash): msg, offset, base = hash["msg"], hash["offset"], hash["base"] offset, msg = self.addr_switch(offset, msg) if not offset: return ea = self.rebase(base, offset) if not ea: return idaapi.set_cmt(ea, str(""), False) print ("[*] reset comment at 0x%x" % ea)
def fix_relocs(base_address, relocs_address, relocs_size): cursor = relocs_address end = relocs_address+relocs_size multiplier = 4 * (idaapi.get_dword(cursor) & 1) + 4 cursor += 4 print 'starting to fix relocs...' nb_relocs = 0 delta = idaapi.get_dword(cursor) while delta != 0xFFFFFFFF and cursor < end: current_reloc = base_address + delta while True: decorated_addr = idaapi.get_qword(current_reloc) if decorated_addr & 0x4000000000000000 == 0: if decorated_addr & 0x8000000000000000: #tagged ptr sign_type = (decorated_addr >> 49) & 3 real_addr = base_address + (decorated_addr & 0xFFFFFFFF) modifier = ((decorated_addr >> 32) & 0xFFFF) if decorated_addr & 0x1000000000000: if modifier == 0: modifier = current_reloc modifier_type = 'ptr_addr' else: modifier_type = '0x%X << 48 | ptr_addr & 0xFFFFFFFFFFFF'%(modifier) modifier = (current_reloc & 0xFFFFFFFFFFFF) | (modifier << 48) else: modifier_type = '0x%X'%modifier if sign_type == 0: decorator = 'PACIA %s'%modifier_type if modifier else 'PACIZA' elif sign_type == 1: decorator = 'PACIB %s'%modifier_type if modifier else 'PACIZB' elif sign_type == 2: decorator = 'PACDA %s'%modifier_type if modifier else 'PACDZA' elif sign_type == 3: decorator = 'PACDB %s'%modifier_type if modifier else 'PACDZB' idaapi.set_cmt(current_reloc , decorator, 1) else: real_addr = ((decorated_addr << 13) & 0xFF00000000000000) | (decorated_addr & 0x7ffffffffff) if decorated_addr & 0x40000000000: real_addr |= 0xfffc0000000000 idaapi.patch_qword(current_reloc, real_addr) idaapi.op_offset(current_reloc, 0, idaapi.REF_OFF64) nb_relocs += 1 delta_next_reloc = ((decorated_addr >> 51) & 0x7ff) * multiplier if delta_next_reloc == 0: break current_reloc += delta_next_reloc cursor += 4 delta = idaapi.get_dword(cursor) print '%d relocs fixed!'%nb_relocs
def activate(self, ctx): start, end = idc.read_selection_start(), idc.read_selection_end() if start == idaapi.BADADDR: print 'Please select something' return import capstone md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) md.details = True data = idaapi.get_bytes(start, end - start) for insn in md.disasm(data, start): # print "0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str) idaapi.set_cmt(insn.address, str('%s %s' % (insn.mnemonic, insn.op_str)), False)
def implement(self): if self._comment_type == "regular": idaapi.set_cmt(self._linear_address, self._value, 0) elif self._comment_type == "repetable": idaapi.set_cmt(self._linear_address, self._value, 1) elif self._comment_type == "function": idc.set_func_cmt(self._linear_address, self._value, 0) elif self._comment_type == "anterior" or self._comment_type == "posterior": ida_lines.del_extra_cmt(self._linear_address, self._idx) is_anterior = 1 if self._idx - 1000 < 1000 else 0 if not self._value: return 0 ida_lines.add_extra_cmt(self._linear_address, is_anterior, self._value)
def activate(self, ctx): info = idaapi.get_inf_structure() selection = idaapi.read_selection() start = selection[1] end = selection[2] if selection[0] == False: start = idaapi.get_screen_ea() if start == idaapi.BADADDR: print 'Easy Nop :: Screen EA == idaapi.BADADDR' return 0 end = start + idaapi.get_item_size(start) else: end += idaapi.get_item_size(end) if start == idaapi.BADADDR: print 'Easy Nop :: Selection EA == idaapi.BADADDR' return 0 if start == end: print 'Easy Nop :: Nothing to nop' return 0 for x in range(start, end): # Maybe theres a smarter way to get the nop value for different archs e.g. Assemble('nop') -> 0x90 idaapi.patch_byte(x, 0x90) for x in range(start + 1, end): idaapi.hide_item(x) # Must do this else it bugs out on 2x 1 byte instructions being nopped idaapi.hide_item(start) idaapi.unhide_item(start) # Search for hidden nops and add to count while idaapi.get_byte(end) == 0x90 and idaapi.is_hidden_item( end) == True: end += 1 count = end - start if count > 1: idaapi.set_cmt(start, "truncated nops (%d)" % (count), False) print end print start return 1
def activate(self, ctx): sel = idaapi.read_selection() if not sel[0]: print 'Please select something' return import capstone md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) md.details = True data = idaapi.get_many_bytes(sel[1], sel[2] - sel[1]) for insn in md.disasm(data, sel[1]): # print "0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str) idaapi.set_cmt(insn.address, str('%s %s' % (insn.mnemonic, insn.op_str)), False)
def activate(self, ctx): t0, t1, view = idaapi.twinpos_t(), idaapi.twinpos_t( ), idaapi.get_current_viewer() if idaapi.read_selection(view, t0, t1): start, end = t0.place(view).toea(), t1.place(view).toea() end += idaapi.get_item_size(end) else: start = idaapi.get_screen_ea() if start == idaapi.BADADDR: print('Easy Nop :: Screen EA == idaapi.BADADDR') return 0 end = start + idaapi.get_item_size(start) if start == idaapi.BADADDR: print('Easy Nop :: Selection EA == idaapi.BADADDR') return 0 if start == end: print('Easy Nop :: Nothing to nop') return 0 for x in range(start, end): # Maybe theres a smarter way to get the nop value for different archs e.g. Assemble('nop') -> 0x90 idaapi.patch_byte(x, 0x90) for x in range(start + 1, end): idaapi.hide_item(x) # Must do this else it bugs out on 2x 1 byte instructions being nopped idaapi.hide_item(start) idaapi.unhide_item(start) # Search for hidden nops and add to count while idaapi.get_byte(end) == 0x90 and idaapi.is_hidden_item( end) == True: end += 1 count = end - start if count > 1: idaapi.set_cmt(start, "truncated nops (%d)" % (count), False) print(end) print(start) return 1
def decode_at_ea(addr, offset, keyLen, dataLen): """ use for manually decoding with IDA and will put a comment at screen_ea """ data = ida_bytes.get_bytes(addr + offset, keyLen + dataLen) cmt = data_to_str(decode_string(data, keyLen, dataLen)) print("%s" % cmt) ea = idc.get_screen_ea() idaapi.set_cmt(ea, cmt, True) # disassembly comment cfunc = idaapi.decompile(ea) if cfunc is not None: # decompiled comment tl = idaapi.treeloc_t() tl.ea = ea tl.itp = idaapi.ITP_SEMI cfunc.set_user_cmt(tl, cmt) cfunc.save_user_cmts()
def decode(): ea = ScreenEA() if ea == idaapi.BADADDR: idaapi.msg(PLUGIN_NAME + " ERROR: Could not get get_screen_ea()") return str_id = idaapi.get_highlighted_identifier() if not str_id: idaapi.msg(PLUGIN_NAME + " ERROR: No Ioctl Code highlighted!") return try: if str_id[-1] == 'h': code = int(str_id[:-1], 16) elif str_id[-1] == 'o': code = int(str_id[:-1], 8) elif str_id[-1] == 'b': code = int(str_id[:-1], 2) else: code = int(str_id) except ValueError: idaapi.msg(PLUGIN_NAME + " ERROR: Not a valid Ioctl Code: " + str(str_id)) return try: decoder = IOCTL_Decoder(code) ioctl_data = decoder.decode() #print decoded IOCTL to cli msg_string = "That IOCTL decodes to: \n\tDevice: %s \n\tFunction: %s \n\tAccess: %s \n\tMethod: %s" idaapi.msg(msg_string % (ioctl_data["device"], ioctl_data["function"], ioctl_data["access"], ioctl_data["method"])) #add decoded IOCTL as comment comment_string = "dwIoControlCode: \n\t\tDevice: %s \n\t\tFunction: %s \n\t\tAccess: %s \n\t\tMethod: %s" idaapi.set_cmt( ea, comment_string % (ioctl_data["device"], ioctl_data["function"], ioctl_data["access"], ioctl_data["method"]), 0) except Exception as e: idaapi.msg(PLUGIN_NAME + " ERROR: " + str(e)) return
def loadcmt(self): total = 0 count = 0 for line in self.sym_file: total+=1 sm = re.search("C[\s]+([\dA-F]+)[\s]+(.+)", line) if sm: if is_printable(sm.group(2)) is False: continue if idaapi.set_cmt(int(sm.group(1), 16), sm.group(2), 0): count += 1 else: print "set comment %s:%s failed" % (sm.group(1), sm.group(2)) print "total %d applied %d comments" % (total,count)
def old_changed(cls, ea, repeatable_cmt): cmt = utils.string.of(idaapi.get_cmt(ea, repeatable_cmt)) fn = idaapi.get_func(ea) # if we're in a function, then clear our contents. if fn: internal.comment.contents.set_address(ea, 0) # otherwise, just clear the tags globally else: internal.comment.globals.set_address(ea, 0) # simply grab the comment and update its refs res = internal.comment.decode(cmt) if res: cls._create_refs(ea, res) # otherwise, there's nothing to do if its empty else: return # and then re-write it back to its address idaapi.set_cmt(ea, utils.string.to(internal.comment.encode(res)), repeatable_cmt)
def _event(cls): while True: # cmt_changing event ea,rpt,new = (yield) old = idaapi.get_cmt(ea, rpt) f,o,n = idaapi.get_func(ea),internal.comment.decode(old),internal.comment.decode(new) # update references before we update the comment cls._update_refs(ea, o, n) # wait for cmt_changed event newea,nrpt,none = (yield) # now fix the comment the user typed if (newea,nrpt,none) == (ea,rpt,None): ncmt,repeatable = idaapi.get_cmt(ea, rpt), cls._is_repeatable(ea) if (ncmt or '') != new: logging.warn("internal.{:s}.event : Comment from event is different from database : {:x} : {!r} != {!r}".format('.'.join((__name__,cls.__name__)), ea, new, ncmt)) # delete it if it's the wrong type # if nrpt != repeatable: # idaapi.set_cmt(ea, '', nrpt) # # write the tag back to the address # if internal.comment.check(new): idaapi.set_cmt(ea, internal.comment.encode(n), repeatable) # # write the comment back if it's non-empty # elif new: idaapi.set_cmt(ea, new, repeatable) # # otherwise, remove it's reference since it's being deleted # else: cls._delete_refs(ea, n) if internal.comment.check(new): idaapi.set_cmt(ea, internal.comment.encode(n), rpt) elif new: idaapi.set_cmt(ea, new, rpt) else: cls._delete_refs(ea, n) continue # if the changed event doesn't happen in the right order logging.fatal("{:s}.event : Comment events are out of sync, updating tags from previous comment. : {!r} : {!r}".format('.'.join((__name__,cls.__name__)), o, n)) # delete the old comment cls._delete_refs(ea, o) idaapi.set_cmt(ea, '', rpt) logging.warn("{:s}.event : Previous comment at {:x} : {!r}".format('.'.join((__name__,cls.__name__)), o)) # new comment new = idaapi.get_cmt(newea, nrpt) n = internal.comment.decode(new) cls._create_refs(newea, n) continue return
def _event(cls): while True: # cmt_changing event ea, rpt, new = (yield) old = utils.string.of(idaapi.get_cmt(ea, rpt)) f, o, n = idaapi.get_func(ea), internal.comment.decode(old), internal.comment.decode(new) # update references before we update the comment cls._update_refs(ea, o, n) # wait for cmt_changed event newea, nrpt, none = (yield) # now fix the comment the user typed if (newea, nrpt, none) == (ea, rpt, None): ncmt, repeatable = utils.string.of(idaapi.get_cmt(ea, rpt)), cls._is_repeatable(ea) if (ncmt or '') != new: logging.warn(u"{:s}.event() : Comment from event at address {:#x} is different from database. Expected comment ({!s}) is different from current comment ({!s}).".format('.'.join((__name__, cls.__name__)), ea, utils.string.repr(new), utils.string.repr(ncmt))) # delete it if it's the wrong type # if nrpt != repeatable: # idaapi.set_cmt(ea, '', nrpt) # # write the tag back to the address # if internal.comment.check(new): idaapi.set_cmt(ea, utils.string.to(internal.comment.encode(n)), repeatable) # # write the comment back if it's non-empty # elif new: idaapi.set_cmt(ea, utils.string.to(new), repeatable) # # otherwise, remove its reference since it's being deleted # else: cls._delete_refs(ea, n) if internal.comment.check(new): idaapi.set_cmt(ea, utils.string.to(internal.comment.encode(n)), rpt) elif new: idaapi.set_cmt(ea, utils.string.to(new), rpt) else: cls._delete_refs(ea, n) continue # if the changed event doesn't happen in the right order logging.fatal(u"{:s}.event() : Comment events are out of sync at address {:#x}, updating tags from previous comment. Expected comment ({!s}) is different from current comment ({!s}).".format('.'.join((__name__, cls.__name__)), ea, utils.string.repr(o), utils.string.repr(n))) # delete the old comment cls._delete_refs(ea, o) idaapi.set_cmt(ea, '', rpt) logging.warn(u"{:s}.event() : Deleted comment at address {:#x} was {!s}.".format('.'.join((__name__, cls.__name__)), ea, utils.string.repr(o))) # new comment new = utils.string.of(idaapi.get_cmt(newea, nrpt)) n = internal.comment.decode(new) cls._create_refs(newea, n) continue return
def tag_write(ea, key, value, repeatable=0): dict = tag_read(ea, repeatable=repeatable) dict[key] = value res = internal.comment.toString(dict) return idaapi.set_cmt(ea, res, int(bool(repeatable)))
def hwreg(ea, name, comment): idaapi.doDwrd(ea, 4) idaapi.set_name(ea, name) idaapi.set_cmt(ea, cmt, True) # repeatable comment
def AsmAndWrite(self, mnem, instr=None, write_ea=None, function=None): if mnem == '': return if write_ea != None: ea_write = write_ea else: ea_write = self.free_ea idc.MakeUnkn(ea_write, 0) #tmp = idaapi.assemble(self.free_ea, self.segment_start, self.free_ea, 1, mnem) if debug: print ">Assemble:AsmAndWrite - !Writing @ ea[%08x] ip[%08x] instr[%s]" % (ea_write, ea_write, mnem) tmp = idaapi.assemble(ea_write, 0, ea_write, 1, mnem) if instr != None: idaapi.set_cmt(ea_write, "%08x" % instr.GetOriginEA(), 0) if tmp == 0: if instr == None and function != None: raise MiscError if debug: print '>Assemble:AsmAndWrite - !Messy instruction', mnem print '>Assemble:AsmAndWrite - Trying original opcodes!' refs_from = [x for x in function.GetRefsFrom(instr.GetOriginEA()) if x != None] if len(refs_from) == 0: if instr.GetIsModified() == True: raise MiscError instr_op = instr.GetOpcode() for pos in xrange(0, len(instr_op)): idc.PatchByte(ea_write+pos, ord(instr_op[pos])) if idc.MakeCode(ea_write) == 0: raise MiscError ea_write += idc.ItemSize(ea_write) elif len(refs_from) == 1: instr_op = instr.GetOpcode() for pos in xrange(0, len(instr_op)): idc.PatchByte(ea_write+pos, ord(instr_op[pos])) if idc.MakeCode(ea_write) == 0: raise MiscError ea_write += idc.ItemSize(ea_write) else: #print '>Assemble:AsmAndWrite - GetRefsFrom(%08x)' % instr.GetOriginEA(), [hex(x) for x in function.GetRefsFrom(instr.GetOriginEA()) if x != None] print '>Assemble:AsmAndWrite - refs_from', refs_from print '>Assemble:AsmAndWrite - ea_write [%08x]' % ea_write print '>Assemble:AsmAndWrite - mnem', mnem print '>Assemble:AsmAndWrite - instr.GetMnem', instr.GetMnem() print '>Assemble:AsmAndWrite - instr.GetDisasm', instr.GetDisasm() raise MiscError else: if idc.MakeCode(ea_write) == 0: raise MiscError ea_write += idc.ItemSize(ea_write) if write_ea == None: self.free_ea = ea_write
def tag_write(ea, key, value, repeatable=0): dict = tag_read(ea, repeatable=repeatable) dict[key] = value res = _comment.toString(dict) return idaapi.set_cmt(ea, res, int(bool(repeatable)))
def repeat(self, comment): idaapi.set_cmt(self._ea, comment, 1)
def regular(self, comment): idaapi.set_cmt(self._ea, comment, 0)
def load_file(f, neflags, format): idaapi.set_processor_type("arm:armv8", idaapi.SETPROC_LOADER) f.seek(-0x20, os.SEEK_END) nseg, = struct.unpack("<12xI16x", f.read(0x20)) print(f"Number of segments: {nseg}") for sno in range(nseg): f.seek(-0x20-0x20*(nseg-sno), os.SEEK_END) mem_addr, file_addr, size, name = struct.unpack("<QII8x8s", f.read(0x20)) name, _, _ = name.partition(b'\0') name = name.decode() print(f"Segment {sno}: {name} at mem={hex(mem_addr)} file={hex(file_addr)} size={hex(size)}") ida_seg_type = None if name == "__TEXT": ida_seg_type = "CODE" if name == "__DATA": ida_seg_type = "DATA" idaapi.add_segm(0, mem_addr, mem_addr + size, name, ida_seg_type) f.file2base(file_addr, mem_addr, mem_addr + size, True) f.seek(-0x20-0x20*nseg, os.SEEK_END) footer_start = f.tell() footer_end = footer_start + 0x20 + 0x20 * nseg idaapi.add_segm(0, footer_start, footer_end, "__FOOTER", "DATA") f.file2base(footer_start, footer_start, footer_end, True) header_start = footer_start + 0x20 * nseg idaapi.add_extra_line(header_start, True, "") idaapi.add_extra_cmt(header_start, True, f"File Header") idaapi.create_strlit(header_start, 4, 0) idaapi.set_cmt(header_start, "Magic", False) idaapi.create_dword(header_start + 4, 4) idaapi.set_cmt(header_start + 4, "Version?", False) idaapi.create_dword(header_start + 8, 4) idaapi.set_cmt(header_start + 8, "File length minus headers", False) idaapi.create_dword(header_start + 12, 4) idaapi.set_cmt(header_start + 12, "Section count", False) for sno in range(nseg): header_start = footer_start + 0x20 * sno idaapi.add_extra_line(header_start, True, "") idaapi.add_extra_cmt(header_start, True, f"Segment {sno + 1}") idaapi.create_qword(header_start, 8) idaapi.set_cmt(header_start, "Memory Address", False) idaapi.create_dword(header_start + 8, 4) idaapi.set_cmt(header_start + 8, "File Offset", False) idaapi.create_dword(header_start + 12, 4) idaapi.create_qword(header_start + 16, 8) idaapi.set_cmt(header_start + 12, "Segment Length", False) idaapi.create_strlit(header_start + 24, 8, 0) idaapi.set_cmt(header_start + 24, "Segment Name", False) idaapi.add_entry(0, 0, "start", 1) return 1
def process_data_result(start, data): # 16 bytes on a line # one byte take 4 char: 2 hex char, a space and a char if isalnum # one line take 3 char addtion: two space and \n, and ea hex address BYTES_PER_LINE = 16 MAX_BYTES_HEX_DUMP = BYTES_PER_LINE * 64 # 64 lines printLen = len(data) if printLen > MAX_BYTES_HEX_DUMP: printLen = MAX_BYTES_HEX_DUMP plg_print("Only hexdump first %d bytes" % MAX_BYTES_HEX_DUMP) nLines = printLen // BYTES_PER_LINE # Number of lines nOdd = printLen % BYTES_PER_LINE # Number of bytes at last line isStr = True sHex = str() for i in range(printLen): if isStr and chr(data[i]) not in string.printable: isStr = False if i % BYTES_PER_LINE == 0: sHex += "%s: " % idaapi.ea2str(start + i) sHex += "%02X " % data[i] if (i % BYTES_PER_LINE == BYTES_PER_LINE - 1) or (i == printLen - 1): # add the end of data or end of a line if nLines: lineIdx = i // BYTES_PER_LINE # current line number low = lineIdx * BYTES_PER_LINE high = i + 1 else: low = 0 high = printLen sHex += " " # Padding last line if i == printLen - 1 and nLines and nOdd: sHex += " " * (BYTES_PER_LINE - nOdd) * 3 for j in range(low, high): ch = chr(data[j]) sHex += ch if ch.isalnum() else "." sHex += "\n" # Print out the hexdump string print(sHex) if isStr: txt = str(data) print("String result: '%s'" % txt) idaapi.set_cmt(start, txt, 1) if idaapi.ask_yn(idaapi.ASKBTN_NO, "Do you want to patch selected range with result data ?") == idaapi.ASKBTN_YES: idaapi.patch_bytes(start, bytes(data)) if idaapi.ask_yn(idaapi.ASKBTN_YES, "Do you want to dump result data to file ?") == idaapi.ASKBTN_YES: dump_data_to_file("Dump_At_0x%X_Size_%d.dump" % (start, len(data)), data)
def AsmAndWrite(self, mnem, instr=None, write_ea=None, function=None): if mnem == '': return if write_ea != None: ea_write = write_ea else: ea_write = self.free_ea idc.MakeUnkn(ea_write, 0) #tmp = idaapi.assemble(self.free_ea, self.segment_start, self.free_ea, 1, mnem) if debug: print ">Assemble:AsmAndWrite - !Writing @ ea[%08x] ip[%08x] instr[%s]" % ( ea_write, ea_write, mnem) tmp = idaapi.assemble(ea_write, 0, ea_write, 1, mnem) if instr != None: idaapi.set_cmt(ea_write, "%08x" % instr.GetOriginEA(), 0) if tmp == 0: if instr == None and function != None: raise MiscError if debug: print '>Assemble:AsmAndWrite - !Messy instruction', mnem print '>Assemble:AsmAndWrite - Trying original opcodes!' refs_from = [ x for x in function.GetRefsFrom(instr.GetOriginEA()) if x != None ] if len(refs_from) == 0: if instr.GetIsModified() == True: raise MiscError instr_op = instr.GetOpcode() for pos in xrange(0, len(instr_op)): idc.PatchByte(ea_write + pos, ord(instr_op[pos])) if idc.MakeCode(ea_write) == 0: raise MiscError ea_write += idc.ItemSize(ea_write) elif len(refs_from) == 1: instr_op = instr.GetOpcode() for pos in xrange(0, len(instr_op)): idc.PatchByte(ea_write + pos, ord(instr_op[pos])) if idc.MakeCode(ea_write) == 0: raise MiscError ea_write += idc.ItemSize(ea_write) else: #print '>Assemble:AsmAndWrite - GetRefsFrom(%08x)' % instr.GetOriginEA(), [hex(x) for x in function.GetRefsFrom(instr.GetOriginEA()) if x != None] print '>Assemble:AsmAndWrite - refs_from', refs_from print '>Assemble:AsmAndWrite - ea_write [%08x]' % ea_write print '>Assemble:AsmAndWrite - mnem', mnem print '>Assemble:AsmAndWrite - instr.GetMnem', instr.GetMnem() print '>Assemble:AsmAndWrite - instr.GetDisasm', instr.GetDisasm( ) raise MiscError else: if idc.MakeCode(ea_write) == 0: raise MiscError ea_write += idc.ItemSize(ea_write) if write_ea == None: self.free_ea = ea_write