def get_single_line_comment(ea): """ Get line comment :param ea: Function offset :return: Comment string or None """ regular = ida_bytes.get_cmt(ea, False) repeatable = ida_bytes.get_cmt(ea, True) cmt = get_single_comment(regular, repeatable) return cmt
def handle_nt_assert(self, ins): # recognize call !DbgRaiseAssertionFailure <fast:>.0 if not ins.is_helper("DbgRaiseAssertionFailure"): return False # did we already add an argument? fi = ins.d.f; if not fi.args.empty(): return False # use a comment from the disassembly listing as the call argument cmt = ida_bytes.get_cmt(ins.ea, False) if not cmt: return False # remove "NT_ASSERT("...")" to make the listing nicer if cmt.startswith("NT_ASSERT(\""): cmt = cmt[11:] if cmt.endswith("\")"): cmt = cmt[:-2] # all ok, transform the instruction by adding one more call argument fa = fi.args.push_back() fa.t = ida_hexrays.mop_str; fa.cstr = cmt fa.type = ida_typeinf.tinfo_t.get_stock(ida_typeinf.STI_PCCHAR) # const char * fa.size = fa.type.get_size() return True
def cmt_changed(self, ea, repeatable_cmt): cmt = ida_bytes.get_cmt(ea, repeatable_cmt) cmt = Unicoder.decode(u'') if not cmt else Unicoder.decode(cmt) self._network.send_event(EventType.COMMENTCHANGED, ea=ea, comment=cmt, repeatable=repeatable_cmt) return 0
def rcomment(self): """ Property which return the repeatable comment of the item. :return: The value of the comment or ``None`` if there is no repeatable comment. :rtype: :class:`str` """ return ida_bytes.get_cmt(self.ea, 1)
def get_repeated_comment(address): if is_function_start(address): pfn = ida_funcs.get_func(address) repeated_comment = ida_funcs.get_func_cmt(pfn, 1) else: repeated_comment = ida_bytes.get_cmt(address, 1) if repeated_comment is None or len(repeated_comment) == 0: return None return repeated_comment
def is_runtime_external_data_reference(ea): """This can happen in ELF binaries, where you'll have somehting like `stdout@@GLIBC_2.2.5` in the `.bss` section, where at runtime the linker will fill in the slot with a pointer to the real `stdout`. IDA discovers this type of reference, but it has no real way to cross-reference it to anything, because the target address will only exist at runtime.""" comment = ida_bytes.get_cmt(ea, 0) if comment and "Copy of shared data" in comment: return True else: return False
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 is_tls(ea): if is_invalid_ea(ea): return False if is_tls_segment(ea): return True # Something references `ea`, and that something is commented as being a # `TLS-reference`. This comes up if you have an thread-local extern variable # declared/used in a binary, and defined in a shared lib. There will be an # offset variable. for source_ea in drefs_to(ea): comment = ida_bytes.get_cmt(source_ea, 0) if isinstance(comment, str) and "TLS-reference" in comment: return True return False
def is_external_vtable_reference(ea): """ It checks the references of external vtable in the .bss section, where it is referred as the `Copy of shared data`. There is no way to resolve the cross references for these vtable as the target address will only appear during runtime. It is introduced to avoid lazy initilization of runtime typeinfo variables which gets referred by the user-defined exception types. """ if not is_runtime_external_data_reference(ea): return False comment = ida_bytes.get_cmt(ea, 0) if comment and "Alternative name is '`vtable" in comment: return True else: return
def cmt_changed(self, ea, repeatable_cmt): cmt = ida_bytes.get_cmt(ea, repeatable_cmt) cmt = "" if not cmt else cmt self._send_packet(evt.CmtChangedEvent(ea, cmt, repeatable_cmt)) return 0
def get_comment(address): comment = ida_bytes.get_cmt(address, 0) if comment is None or 0 == len(comment): return None return comment
def save_x(unique_name=None, start=None, size=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 or not size: seg = ida_segment.getseg(ea) start = seg.start_ea size = seg.size() # (start_addr, end_addr, names, comms) saved_data = {} 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()) if received_data: saved_data = received_data # save names (func_names, labels, etc) # (addr, name, is_code) names_addr_name = [] names = idautils.Names() for addr, name in names: if start <= addr <= start + size: flags = ida_bytes.get_flags(addr) names_addr_name.append( (addr - start, name, ida_bytes.is_code(flags))) # save comments comms_addr_type_comm = [] # (addr, TYPE, comment) # type 0:comment 1:rpt_comment end = start + size for i in range(start, end + 1): if ida_bytes.get_cmt(i, 0): # 0 Comment comms_addr_type_comm.append((i - start, 0, ida_bytes.get_cmt(i, 0))) if ida_bytes.get_cmt(i, 1): # 1 RptCmt comms_addr_type_comm.append((i - start, 1, ida_bytes.get_cmt(i, 1))) # breakpoints bpts_addr_size_type = [] bpt = ida_dbg.bpt_t() global remove_on_exit_bpts for i in range(start, end + 1): if ida_dbg.get_bpt(i, bpt): bpts_addr_size_type.append((i - start, bpt.size, bpt.type)) remove_on_exit_bpts.append(i) # functions funcs_addr = [] flag = ida_bytes.get_flags(start) if ida_bytes.is_func(flag): funcs_addr.append(0) # start addr next_func = ida_funcs.get_next_func(start) while next_func: funcs_addr.append(next_func.start_ea - start) next_func = ida_funcs.get_next_func(next_func.start_ea) # SAVE saved_data[unique_name] = (start, start + end, names_addr_name, comms_addr_type_comm, bpts_addr_size_type, funcs_addr) if MD5_hash_data_file: with open(MD5_hash_data_file, "wb") as ifile: serial_data = pickle.dumps(saved_data) ifile.write(serial_data) print("dumpDyn::save:\n\ Name: {}\n\ Start address: {}".format(unique_name, hex(start)))
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 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]))
def cmt_changed(self, ea, repeatable_cmt): cmt = ida_bytes.get_cmt(ea, repeatable_cmt) cmt = "" if not cmt else cmt print("Detected a comment changed at 0x%x for %s, %s" % (ea, cmt, repeatable_cmt)) return 0
def Comment(ea): return ida_bytes.get_cmt(ea, 0)
def extra_cmt_changed(self, ea, line_idx, cmt): print("extra cmt changed") cmt = ida_bytes.get_cmt(ea, 0) if cmt: self.ida_comment_changed(cmt, ea, "cmt") return 0
def cmt_changed(self, ea, repeatable_cmt): print("cmt changed") cmt = ida_bytes.get_cmt(ea, repeatable_cmt) if cmt: self.ida_comment_changed(cmt, ea, "cmt") return 0
def RptCmt(ea): return ida_bytes.get_cmt(ea, 1)