def processIMethods(self, offst, size): sz = ida_struct.get_struc_size(ida_struct.get_struc_id("imethod")) comm = [] for i in xrange(size): comm.append(self.processIMethod(offst + i * sz)) idc.set_cmt(offst, "\n".join(comm), 0) return comm
def rename(self, name=None): """ Renames (and comments) the string variable in IDA. :param str name: New name to given encoded string. (defaults to decoded_string) """ name = name or self.display_name if not name: logger.warning( 'Unable to rename encoded string due to no decoded string: {!r}'.format(self)) # Set name and comment in stack variable. comment = '"{}"'.format(name[:self._MAX_COMMENT_LENGTH]) if len(name) > self._MAX_COMMENT_LENGTH: comment += ' (truncated)' if self.frame_id and self.stack_offset: idc.set_member_cmt(self.frame_id, self.stack_offset, comment, repeatable=1) var_name = re.sub('[^_$?@0-9A-Za-z]', '_', name[:self._MAX_NAME_LENGTH]) # Replace invalid characters if not var_name: raise ValueError('Unable to calculate var_name for : {!r}'.format(self)) var_name = 'a' + var_name.capitalize() idc.set_member_name(self.frame_id, self.stack_offset, var_name) # Add a comment where the string is being used. if self.string_reference: idc.set_cmt(self.string_reference, comment, 1)
def resolve_all_APIs(resolve_ea, mode): if resolve_ea is None: print('resolve fails..') return for ref in idautils.CodeRefsTo(resolve_ea, 1): # only 1 ref curr_ea = ref while True: prev_instruction_ea = idc.prev_head(curr_ea) if mode == 1: if idc.print_insn_mnem(prev_instruction_ea) == 'push': hash_val = idc.get_operand_value(prev_instruction_ea, 0) if hash_val in export_hashes: print(hex(ref) + ' : ' + export_hashes[hash_val]) idc.set_cmt(ref, export_hashes[hash_val], 0) break else: if idc.print_insn_mnem(prev_instruction_ea) == 'mov': hash_val = idc.get_operand_value(prev_instruction_ea, 1) print(hex(hash_val)) if hash_val in export_hashes: print(hex(ref) + ' : ' + export_hashes[hash_val]) idc.set_cmt(ref, export_hashes[hash_val], 0) break curr_ea = prev_instruction_ea
def do_unpatch_call(va_callsite): size = idc.get_item_size(va_callsite) ida_xref.del_cref(va_callsite, fva_stub, 0) cmt = idc.get_cmt(va_callsite, 0) newcmt = cmt # Remove automated comments if newcmt.startswith(g_patched_call_cmt): newcmt = newcmt[newcmt.find('\n') + 1:] if newcmt.find('\n') == -1: newcmt = '' else: newcmt = newcmt[newcmt.find('\n') + 1:] if newcmt.startswith(g_cmt_pointed): if newcmt.find('\n') == -1: newcmt = '' else: newcmt = newcmt[newcmt.find('\n') + 1:] if newcmt != cmt: idc.set_cmt(va_callsite, newcmt, 0) if idc.get_operand_type(va_callsite, 0) == ida_ua.o_mem: patch_import(va_callsite, idc.BADADDR) elif idc.get_operand_type(va_callsite, 0) == ida_ua.o_reg: va_imp = self._get_imp_for_register_call(va_callsite) if va_imp: patch_pointer_width(va_imp, idc.BADADDR) else: revert_patch(va_callsite, size)
def append_comment(ea, s, repeatable=False): """ add the given string as a (possibly repeating) comment to the given address. does not add the comment if it already exists. adds the comment on its own line. Args: ea (int): the address at which to add the comment. s (str): the comment text. repeatable (bool): if True, set a repeatable comment. """ # see: http://blogs.norman.com/2011/security-research/improving-ida-analysis-of-x64-exception-handling if repeatable: string = idc.get_cmt(ea, 1) else: string = idc.get_cmt(ea, 0) if not string: string = s # no existing comment else: if s in string: # ignore duplicates return string = string + "\\n" + s if repeatable: idc.set_cmt(ea, string, 1) else: idc.set_cmt(ea, string, 0)
def add_arg_descr(function, segment_ea, arg_description_format): """ Name address in added segment annotated with argument descriptions. Arguments: function -- function object segment_ea -- start looking for empty byte to annotate from this ea Return: next possible free address to add information to """ # No arguments if len(function.arguments) == 0: return segment_ea for argument in function.arguments: try: free_ea = get_segment_end_ea(segment_ea) except FailedToExpandSegmentException as e: raise e fields = { "function_name": function.name, "function_dll": function.dll, "argument_name": argument.name, } name = arg_description_format.format(**fields) if not name_exists(name): g_logger.debug(' Adding name {} at {}'.format(name, hex(free_ea))) idaapi.set_name(free_ea, name) description = argument.description[:MAX_ARG_DESCR_LEN] idc.set_cmt(free_ea, format_comment(description), 0) else: g_logger.debug(' Name %s already exists' % name) return (free_ea + 1)
def markupLine(self, loc, sym): comm = '%s!%s' % (sym.libName, sym.symbolName) logger.debug("Making comment @ 0x%08x: %s", loc, comm) if using_ida7api: idc.set_cmt(loc, str(comm), False) else: idc.MakeComm(loc, str(comm))
def set_jit_info(self, method_id, start): end = self.get_func_end(start) if (end < start or end - start > self.jit_max_size): return method = next((x for x in self.as3dump if x["id"] == method_id), None) if (method is None): return stackvars = self.get_stack_vars(start, end) save_eip = self.get_save_eip(method, stackvars) ea = start while (ea < end): if ("ebp" in idc.print_operand(ea, 0) and idc.get_operand_type(ea, 1) == idc.o_imm): op0 = idc.get_operand_value(ea, 0) op1 = idc.get_operand_value(ea, 1) if (op0 == save_eip): idc.set_cmt(ea, method["instructions"][op1], 0) ea += idc.get_item_size(ea)
def process(self, nids, symbols): if self.INFO > Relocation.R_X86_64_ORBIS_GOTPCREL_LOAD: self.INDEX = self.INFO >> 32 self.INFO &= 0xFF symbol = next(value for key, value in enumerate(symbols) if key + 2 == self.INDEX)[1] else: self.INDEX = 0 # String (Offset) == Base + AddEnd (B + A) if self.type() == 'R_X86_64_RELATIVE': idaapi.put_qword(self.OFFSET, self.ADDEND) idaapi.create_data(self.OFFSET, FF_QWORD, 0x8, BADNODE) # Object if self.type() in [ 'R_X86_64_64', 'R_X86_64_GLOB_DAT', 'R_X86_64_DTPMOD64', 'R_X86_64_DTPOFF64' ]: # Resolve the NID... idc.set_cmt(self.OFFSET, 'NID: ' + symbol, False) object = nids.get(symbol[:11], symbol) # Rename the Object... idc.set_name(self.OFFSET, object, SN_NOCHECK | SN_NOWARN | SN_FORCE) return self.type()
def resolve_symbols(self, dll): tmpdir = tempfile.gettempdir().replace('\\', '/') + '/' # File who will first contain ordinals then symbols tmpfile = tmpdir + "dotNIETsymbols.txt" tmplog = tmpdir + "dotNIETlogs.txt" # Destination path for a copy of SharedLibrary.dll tmpdll = tmpdir + os.path.basename(dll) # Path to the idat binary, needed to parse a remote idb idat = idc.idadir().replace('\\','/') + '/' + 'idat' + \ ['64' if utils.is_x64(dll) else ''][0] if os.getenv("windir") is not None: idat += '.exe' # script called along with idat in order to parse SharedLibrary.idb parsing_script_path = '"' + os.path.dirname(os.path.realpath(__file__)).replace('\\','/')\ + '/dotNIET/resolve.py"' # we first copy SharedLibrary.dll to tmp to be sure we are in a # writable location shutil.copyfile(dll, tmpdll) # we have to use temporary files because of the ida headless stuff... # pretty dirty ordinals = [] with open(tmpfile, 'w') as f: for i in range(self.nb_symbols): ordinals.append((idaapi.get_qword(self.ordinals + i * 8) & ~0x8000000000000000) * 4) f.write(",".join([str(x) for x in ordinals])) # be prepared to wait as this will load the binary + pdb idaapi.msg("Starting parsing of %d symbols...\n" % self.nb_symbols) subprocess.run([idat, "-L" + tmplog, "-c", "-A", "-S" + \ parsing_script_path + " " + tmpfile, tmpdll], creationflags=subprocess.CREATE_NO_WINDOW, check=True) # we read back tmpfile which now contains symbols symbols = [] with open(tmpfile, 'r') as f: symbolsArray = f.read() symbols = symbolsArray.split(',') # we first have to undef structure as it is an array and ida will # refuse to set names within it idc.del_items(self.ordinals) idc.set_cmt(self.ordinals - 8, "Custom imports from SharedLibrary.dll", 0) # we then apply the symbols at this very same location (start of .idata) for i in range(self.nb_symbols): idc.set_name(self.ordinals + i * 8, symbols[i], SN_NOCHECK | SN_FORCE | SN_NODUMMY) # finally we remove our temp files os.remove(tmpfile) os.remove(tmpdll) # ida generate a db os.remove(tmpdll + '.i64') # if everything went smoothly, we should not need this anymore os.remove(tmplog)
def import_objects(objs, add_names=True, always_thumb=True): """ Create IDA function and data according to symbol definitions. Create name if add_name is True :param add_names: Create name for symbols? """ failed_objs = [] for name, size, addr, _ in objs: if not is_data_start(addr): if size: ok = idaapi.create_data(addr, idc.FF_BYTE, size, 0) else: ok = idc.create_byte(addr) if not ok: reason = "Could not create data at {addr:#x}".format(addr=addr) data = (name, size, addr) failed_objs.append((data, reason)) """continue""" idc.set_cmt(addr, "obj.%s" % name, 0) if add_names: ok = idc.set_name(addr, name, idc.SN_CHECK) if not ok: reason = "Could not add name {name} at {addr:#x}".format( name=name, addr=addr) data = (name, size, addr) failed_objs.append((data, reason)) print("waiting for ida to finish analysis") ida_auto.auto_wait() print("ida finished import") return failed_objs
def decryptor(index, call_addr): decrypted_string = "" current_struct_start = struct_start + 8 * index current_struct_bytes = idc.get_bytes(current_struct_start, 8) print(current_struct_bytes.hex()) #structure parsing and xoring key = int.from_bytes(current_struct_bytes[0:1], byteorder='little', signed=False) length = int.from_bytes(current_struct_bytes[2:4], byteorder='little', signed=False) buffer_string_addr = int.from_bytes(current_struct_bytes[4:8], byteorder='little', signed=False) print(hex(key), hex(length), hex(buffer_string_addr)) #decrypting for i in range(0, length): decrypted_string += chr(key ^ idc.get_wide_byte(buffer_string_addr + i)) print(decrypted_string) #commenting assembly view idc.set_cmt(call_addr, decrypted_string, 0) #commenting decompile view on the same address as assembly view cfunc = idaapi.decompile(call_addr) tl = idaapi.treeloc_t() tl.ea = call_addr tl.itp = idaapi.ITP_SEMI cfunc.set_user_cmt(tl, decrypted_string) cfunc.save_user_cmts()
def set_name(addr, name): # FIXME creates unnamed_178 etc. instead of proper function name in IDA 7.2 on CYW20735 name = name.replace("sub_", "unnamed_") cmt = idc.get_cmt(addr, 0) name_cmt = "fcn.%s" % name if cmt: name_cmt = cmt + ", " + name_cmt idc.set_cmt(addr, name_cmt, 0) if not add_names: return if name.isupper(): try: # hackish way to stop warning about hex import # FIXME leave 'sub_' intact if it already exists # FIXME do not set the name to the hex prologue because it has duplicates, set it to # 'pp_{position}' instead a = int(name, 16) """continue""" except ValueError: pass ok = idc.set_name(addr, name, idc.SN_CHECK) if not ok: data = (name, size, addr) failed_fncs.append((data, "name")) print("{0:#x}: cannot add name, {1}".format(addr, name)) countername_Fail = countername_Fail + 1 else: imported_functions[addr].add(name)
def treat_element(): "Display an element" global graphs, comments, sol_nb, settings, addr, ir_arch, ircfg try: graph = next(graphs) except StopIteration: comments = {} print("Done: %d solutions" % (sol_nb)) return sol_nb += 1 print("Get graph number %02d" % sol_nb) filename = os.path.join(tempfile.gettempdir(), "solution_0x%08x_%02d.dot" % (addr, sol_nb)) print("Dump the graph to %s" % filename) open(filename, "w").write(graph.graph.dot()) for node in graph.relevant_nodes: try: offset = ircfg.blocks[node.loc_key][node.line_nb].instr.offset except IndexError: print("Unable to highlight %s" % node) continue comments[offset] = comments.get(offset, []) + [node.element] idc.set_color(offset, idc.CIC_ITEM, settings.color) if graph.has_loop: print('Graph has dependency loop: symbolic execution is inexact') else: print("Possible value: %s" % next(iter(viewvalues(graph.emul(ir_arch))))) for offset, elements in viewitems(comments): idc.set_cmt(offset, ", ".join(map(str, elements)), 0)
def clean_lines(): "Remove previous comments" global comments for offset in comments: idc.set_color(offset, idc.CIC_ITEM, 0xffffff) idc.set_cmt(offset, "", 0) comments = {}
def handle_offset(self, offset): #Check if we already parse this if offset in self.type_addr: return print ("Processing: %x" % offset) self.type_addr.append(offset) #Set type and get name idc.SetType(offset, "type") name = self.getName(offset) idc.set_cmt(offset, name, 0) #get kind name kind_name = self.getKindEnumName(offset) print (kind_name) if name[0] == "*" and kind_name != "PTR": name = name[1:] name = Utils.relaxName(name) Utils.rename(offset, name) self.betterTypePlease(offset) sid = ida_struct.get_struc_id("type") addr = self.getPtrToThis(sid, offset) if addr != 0: addr = self.getOffset(addr) self.handle_offset(addr) return if kind_name != "FUNC": self.processUncommon(sid, offset)
def add_stub_func(va, sc, nm): idaapi.patch_bytes(va, binascii.unhexlify(sc)) idc.create_insn(va) idc.add_func(va) mykutils.makename_safe(va, self._stubname(nm)) cmt = ('%s implementation generated by FLARE Code Grafter' % (nm)) idc.set_cmt(va, cmt, 1)
def references(function_location, decoding_str): """decodes all decoded strings by a given function by applying decoding_str to every byte. decoding_str should contain encoded_byte, for example: decode.references(0x401000, "(encoded_byte ^ 0xA2) + 0x21")""" for xref in idautils.XrefsTo(function_location): ea = xref.frm # The function needs to be defined for get_arg_addrs to work args = idaapi.get_arg_addrs(ea) encoded = idc.get_operand_value(args[0], 0) decoded = idc.get_operand_value(args[1], 0) decoded_str = "" i = 0 encoded_byte = ida_bytes.get_wide_byte(encoded) while encoded_byte != 0: decoded_byte = eval(decoding_str) decoded_str += chr(decoded_byte) ida_bytes.patch_byte(decoded + i, decoded_byte) i += 1 encoded_byte = ida_bytes.get_wide_byte(encoded + i) ida_bytes.create_strlit(decoded, i, STRTYPE_C) idc.set_cmt(ea, f"Decoded: {decoded_str}", 0) print(f"##At {hex(ea)} decoded: {decoded_str}")
def createUserTypeStruct(self, addr, name, size, self_size): fields = [] sid = ida_struct.get_struc_id("structField") sz = ida_struct.get_struc_size(sid) sid_type = ida_struct.get_struc_id("type") fields = [] curr_offset = 0 idc.set_cmt(addr, name, 0) for i in range(size): fieldname = self.nameFromOffset(self.getPtr(sid, addr+i*sz,"Name")) type_addr = self.getPtr(sid, addr+i*sz, "typ") typename = self.getType(type_addr) size = self.getPtr(sid_type, type_addr, "size") if fieldname == "" or fieldname is None: fieldname = "unused_"+Utils.id_generator() offset = self.getStructFieldOffset(sid, addr+i*sz) print(f"Get offset: {offset:x}") if offset != curr_offset: print("Offset missmatch.Got %d expected %d. Adding padding..." % (curr_offset, offset)) if offset < curr_offset: raise("Too many bytes already") while offset != curr_offset: fields.append(("padding", "char")) curr_offset += 1 curr_offset += size if size != 0: offset_kind = idc.get_member_offset(sid_type, "kind") kind_of_type = self.getKindEnumName(type_addr) print(kind_of_type) if kind_of_type == "STRUCT_": #Disabled for now name_type = self.getName(type_addr) while name_type[0] == "*": name_type = name_type[1:] name_type = Utils.relaxName(name_type) name_type = "ut_" + name_type #print("setting type %s" % name_type) fields.append((fieldname, name_type)) elif kind_of_type == "STRING": fields.append((fieldname, "string")) elif kind_of_type == "SLICE": fields.append((fieldname, "slice")) elif kind_of_type == "INTERFACE": fields.append((fieldname, "__iface")) else: fields.append((fieldname, "char [%d]" % size)) if curr_offset != self_size: print("%x: Structure size mismatch: %x" % (addr, curr_offset)) if self_size < curr_offset: raise("Too many bytes already") while self_size != curr_offset: fields.append(("padding", "char")) curr_offset += 1 new_type = [(name, fields)] self.settings.structCreator.createTypes(new_type) new_type_sid = ida_struct.get_struc_id(name) sz = ida_struct.get_struc_size(new_type_sid) if sz != self_size: print("%x" % addr ) raise("Error at creating structure")
def enum_arg(call_addr): idc.set_color(call_addr, CIC_ITEM, 0x00ff00) arg = [] for arg_addr in idaapi.get_arg_addrs(call_addr): idc.set_cmt(arg_addr, "addr: 0x%x" % (call_addr), 0) idc.set_color(arg_addr, CIC_ITEM, 0x00fff0) arg.append(find_arg(arg_addr)) return arg
def markupLine(self, loc, sym, useDecompiler=False): comm = '%s!%s' % (sym.libName, sym.symbolName) logger.debug("Making comment @ 0x%08x: %s", loc, comm) if using_ida7api: idc.set_cmt(loc, str(comm), False) if useDecompiler and idaapi.get_func(loc) != None: self.addDecompilerComment(loc, str(comm)) else: idc.MakeComm(loc, str(comm))
def rename_argument(ea, function, argument, arg_description_format): """ Rename function's argument comment at ea based on config string. """ fields = { "function_name": function.name, "function_dll": function.dll, "argument_name": argument.name, } new_arg = str(arg_description_format.format(**fields).encode('utf-8')) idc.set_cmt(ea, new_arg, 0)
def dump_names(list_of_vtbl): f = open('classes_rtii_autonaming_subs.txt', 'w+') for cls in list_of_vtbl: for n, a in cls.functions.items(): idc.set_cmt(a, cls.base_name, 0) print(cls.base_name) f.write(cls.base_name + "\n") f.close()
def resolve(self, alphabet, nids, symbols, libraries): if self.INFO > Relocation.R_X86_64_ORBIS_GOTPCREL_LOAD: self.INDEX = self.INFO >> 32 self.INFO &= 0xFF symbol = next(value for key, value in enumerate(symbols) if key + 2 == self.INDEX)[1] else: self.INDEX = 0 # Library try: lid1 = alphabet[symbol[12:13]] # [base64]# if symbol[13:14] == '#': library = libraries[lid1] # [base64][base64]# elif symbol[14:15] == '#': lid2 = alphabet[symbol[13:14]] library = libraries[lid1 + lid2] else: raise # Not a NID except: library = '' # Function Name (Offset) == Symbol Value + AddEnd (S + A) # Library Name (Offset) == Symbol Value (S) # Resolve the NID... idc.set_cmt(idc.get_qword(self.OFFSET) - 0x6, 'NID: ' + symbol, False) function = nids.get(symbol[:11], symbol) # Rename the Jump Function... idc.set_name(self.OFFSET, '__imp_' + function, SN_NOCHECK | SN_NOWARN | SN_FORCE) # Rename the Real Function... idc.add_func(idc.get_qword(self.OFFSET) - 0x6) idc.set_name( idc.get_qword(self.OFFSET) - 0x6, function, SN_NOCHECK | SN_NOWARN) try: import_node = idaapi.netnode(library, 0, True) import_node.supset(ea2node(self.OFFSET), function) # Requires customized loader.i / ida_loader.py(d) idaapi.import_module(library, None, import_node.index(), None, 'linux') except: pass return self.type()
def comment(self, value): """ Setter which allow to set the value of the comment. :param value: The comment to set :type value: :class:`str` """ if value is None: value = "" idc.set_cmt(self.ea, value, 0)
def activate(self, ctx): pos = idc.get_screen_ea() # Get current comment for this instruction and remove the C define from it, if present comment = idc.get_cmt(pos, 0) code = get_operand_value(pos) define = ioctl_decoder.get_define(code) comment = comment.replace(define, "") idc.set_cmt(pos, comment, 0) # Remove the ioctl from the valid list and add it to the invalid list to avoid 'find_all_ioctls' accidently re-indexing it. ioctl_tracker.remove_ioctl(pos, code)
def make_comment(pos, string): """ Creates a comment with contents `string` at address `pos`. If the address is already commented append the new comment to the existing comment """ current_comment = idc.get_cmt(pos, 0) if not current_comment: idc.set_cmt(pos, string, 0) elif string not in current_comment: idc.set_cmt(pos, current_comment + " " + string, 0)
def main(): print("[*] loading crypto constants") for const in non_sparse_consts: const["byte_array"] = convert_to_byte_array(const) for start in idautils.Segments(): print("[*] searching for crypto constants in %s" % idc.get_segm_name(start)) ea = start while ea < idc.get_segm_end(start): bbbb = list(struct.unpack("BBBB", idc.get_bytes(ea, 4))) for const in non_sparse_consts: if bbbb != const["byte_array"][:4]: continue if map(lambda x:ord(x), idc.get_bytes(ea, len(const["byte_array"]))) == const["byte_array"]: print(("0x%0" + str(digits) + "X: found const array %s (used in %s)") % (ea, const["name"], const["algorithm"])) idc.set_name(ea, const["name"]) if const["size"] == "B": idc.create_byte(ea) elif const["size"] == "L": idc.create_dword(ea) elif const["size"] == "Q": idc.create_qword(ea) idc.make_array(ea, len(const["array"])) ea += len(const["byte_array"]) - 4 break ea += 4 ea = start if idc.get_segm_attr(ea, idc.SEGATTR_TYPE) == 2: while ea < idc.get_segm_end(start): d = ida_bytes.get_dword(ea) for const in sparse_consts: if d != const["array"][0]: continue tmp = ea + 4 for val in const["array"][1:]: for i in range(8): if ida_bytes.get_dword(tmp + i) == val: tmp = tmp + i + 4 break else: break else: print(("0x%0" + str(digits) + "X: found sparse constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(idc.prev_head(ea), 0) if cmt: idc.set_cmt(idc.prev_head(ea), cmt + ' ' + const["name"], 0) else: idc.set_cmt(idc.prev_head(ea), const["name"], 0) ea = tmp break ea += 1 print("[*] finished")
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 get_stacked_bytes(dec_func_addr): func_stacked_bytes_addr_dict = {} xrefs = idautils.CodeRefsTo(dec_func_addr, 0) for xref in xrefs: prev_addr = idc.prev_head(xref) prev_addr_2 = idc.prev_head(prev_addr) if idc.print_insn_mnem(prev_addr_2) == "call": func_name = idc.print_operand(prev_addr_2, 0) func_addr = idc.get_name_ea_simple(func_name) func_stacked_bytes_addr_dict[xref] = func_addr # enc_mod_addr = list(set(enc_mod_addr)) # [Debug] Get unique functions only for xref, stacked_bytes_addr in func_stacked_bytes_addr_dict.items(): print(f"Address: {hex(stacked_bytes_addr)}") func_ea = idc.get_func_attr(stacked_bytes_addr, idc.FUNCATTR_START) bytes_collected = bytearray() # Collected stack string store here for ins in idautils.FuncItems(func_ea): if ida_bytes.is_code(ida_bytes.get_full_flags(ins)): if idc.print_insn_mnem(ins) == "mov": if idc.get_operand_type(ins, 1) == idc.o_imm: # disasm = idc.GetDisasm(ins) # [Debug] hex_str_len = len( idc.print_operand(ins, 1).lstrip("0").rstrip("h")) const_hex_byte = idc.print_operand( ins, 1).lstrip("0").rstrip("h") if hex_str_len != 8: # Skip if const hex byte less than 8 append_zero = "0" * (8 - hex_str_len) const_hex_byte = append_zero + const_hex_byte # print(struct.pack("<I", int(const_hex_byte, 16))) # [Debug] # else: # print(struct.pack("<I", int(const_hex_byte, 16))) # [Debug] bytes_collected += struct.pack("<I", int(const_hex_byte, 16)) if len(bytes_collected) >= 1: cmt_str = "" if dec_func_addr == 0x10001253: # fn_name_addr print(f"{decode_fnname(bytes_collected[4:])}") cmt_str = decode_fnname(bytes_collected[4:]) elif dec_func_addr == 0x1000122B: # mod_name_addr print(f"{decode_modname(bytes_collected[4:])}") cmt_str = decode_modname(bytes_collected[4:]) idc.set_cmt(xref, cmt_str, 1) # Comment near xref decoder function else: print(f"[-] {hex(stacked_bytes_addr)} addr error")
def make_comments(self): """make comments in idb""" EFI_BOOT_SERVICES_ID = idc.get_struc_id("EFI_BOOT_SERVICES") self.get_boot_services() empty = True for service in self.gBServices: for address in self.gBServices[service]: message = f"EFI_BOOT_SERVICES->{service}" idc.set_cmt(address, message, 0) idc.op_stroff(address, 0, EFI_BOOT_SERVICES_ID, 0) empty = False print(f"[ {address:016X} ] {message}") if empty: print(" * list is empty")
def main(doAllFuncs=True): #doAllFuncs=False #jayutils.configLogger(__name__, logging.DEBUG) jayutils.configLogger(__name__, logging.INFO) logger = jayutils.getLogger('stackstrings') logger.debug('Starting up now') filePath = jayutils.getInputFilepath() if filePath is None: self.logger.info('No input file provided. Stopping') return vw = jayutils.loadWorkspace(filePath) ea = idc.here() res = -1 if using_ida7api: res = idc.ask_yn(0, 'Use basic-block local aggregator') else: res = idc.AskYN(0, 'Use basic-block local aggregator') if res == idaapi.ASKBTN_CANCEL: print 'User canceled' return uselocalagg = (res == 1) ranges = getFuncRanges(ea, doAllFuncs) for funcStart, funcEnd in ranges: try: logger.debug('Starting on function: 0x%x', funcStart) stringList = runStrings(vw, funcStart, uselocalagg) for node, string in stringList: if isLikelyFalsePositiveString(string): #if it's very likely a FP, skip annotating continue print '0x%08x: %s' % (node[0], string) #print '0x%08x: 0x%08x: %s %s' % (node[0], node[1], binascii.hexlify(string), string) if using_ida7api: idc.set_cmt(node[0], string.strip(), 0) else: idc.MakeComm(node[0], string.strip()) except Exception, err: logger.exception('Error during parse: %s', str(err))
def append_comment(va, new_cmt, repeatable=False): """ Append a comment to an address in IDA Pro. :param va: comment address :param new_cmt: comment string :param repeatable: if True, append as repeatable comment :return: True if success """ cmt = idc.get_cmt(va, repeatable) if not cmt: # no existing comment cmt = new_cmt else: if new_cmt in cmt: # comment already exists return True cmt = cmt + "\n" + new_cmt return idc.set_cmt(va, cmt, repeatable)