Exemple #1
0
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
Exemple #2
0
    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
Exemple #3
0
 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
Exemple #4
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)
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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)
Exemple #8
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
Exemple #9
0
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
Exemple #10
0
 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
Exemple #11
0
def get_comment(address):
    comment = ida_bytes.get_cmt(address, 0)
    if comment is None or 0 == len(comment):
        return None
    return comment
Exemple #12
0
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)))
Exemple #13
0
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)
Exemple #14
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]))
Exemple #15
0
 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
Exemple #16
0
def Comment(ea):
    return ida_bytes.get_cmt(ea, 0)
Exemple #17
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
Exemple #18
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
Exemple #19
0
def RptCmt(ea):
    return ida_bytes.get_cmt(ea, 1)