Beispiel #1
0
 def postprocess_action(self):
     self._plugin.logger.debug("postprocess_action()")
     if len(self.actions):
         name, ea = self.actions.pop()
         if name == "MakeUnknown":
             flags = ida_bytes.get_full_flags(ea)
             if ida_bytes.is_unknown(flags):
                 self._send_packet(evt.MakeUnknown(ea))
         elif name == "MakeCode":
             flags = ida_bytes.get_full_flags(ea)
             if ida_bytes.is_code(flags):
                 self._send_packet(evt.MakeCodeEvent(ea))
Beispiel #2
0
def _try_map_byte(memory, ea, seg_ref):
    """Try to map a byte into memory."""
    seg = _find_segment_containing_ea(ea, seg_ref)
    if not seg:
        return False

    can_write = 0 != (seg.perm & ida_segment.SEGPERM_WRITE)
    can_exec = _is_executable_seg(seg)

    val = 0
    if ida_bytes.has_value(ida_bytes.get_full_flags(ea)):
        val = ida_bytes.get_wide_byte(ea) & 0xFF

    flags = ida_bytes.get_full_flags(ea)
    memory.map_byte(ea, val, can_write, can_exec)
    return True
def extract_operand(inst_t, op_n, x_set):
    # There are three types of data storage locations: registers, stack variables, and memory variables
    full_flags = ida_bytes.get_full_flags(inst_t.ea)
    if ida_bytes.is_stkvar(full_flags, op_n):
        varname = get_stkvar_name(inst_t, op_n)
        if varname:
            x_set.add(varname)
            return

    operand = inst_t.ops[op_n]
    if operand.type == ida_ua.o_void:
        # o_void: No Operand.
        return
    if operand.type == ida_ua.o_mem:
        x_set.add(operand.addr)
        return
    if operand.type == ida_ua.o_reg:
        x_set.add(operand.reg)
        return
    if operand.type == ida_ua.o_phrase:
        x_set.add((operand.reg, operand.phrase))
        return
    if operand.type == ida_ua.o_displ:
        x_set.add((operand.reg, operand.phrase, operand.addr))
    return
def get_ea_name(ea, fromaddr=idc.BADADDR, true=False, user=False):
    """Get the name of an address.

    This function returns the name associated with the byte at the specified address.

    Arguments:
        ea: The linear address whose name to find.

    Options:
        fromaddr: The referring address. Default is BADADDR. Some addresses have a
            location-specific name (for example, labels within a function). If fromaddr is not
            BADADDR, then this function will try to retrieve the name of ea from fromaddr's
            perspective. The global name will be returned if no location-specific name is found.
        true: Retrieve the true name rather than the display name. Default is False.
        user: Return "" if the name is not a user name.

    Returns:
        The name of the address or "".
    """
    if user and not idc.hasUserName(ida_bytes.get_full_flags(ea)):
        return ""
    if true:
        return ida_name.get_ea_name(fromaddr, ea)
    else:
        return idc.get_name(
            ea, ida_name.GN_VISIBLE | idc.calc_gtn_flags(fromaddr, ea))
Beispiel #5
0
    def __process_exports(self):
        exports = list()

        for i in range(0, ida_entry.get_entry_qty()):
            ordinal = ida_entry.get_entry_ordinal(i)

            ea = ida_entry.get_entry(ordinal)

            flags = ida_bytes.get_full_flags(ea)
            type = 'unknown'
            if ida_bytes.is_func(flags):
                type = 'function'
            elif ida_bytes.is_data(flags):
                type = 'data'

            export = {
                'ordinal': ordinal,
                'rva': ea - self._base,
                'name': ida_entry.get_entry_name(ordinal),
                'type': type
            }

            exports.append(export)

        return exports
Beispiel #6
0
    def create_object(obj,
                      overwrite_names,
                      offset,
                      dummy_names=True,
                      always_thumb=True):
        name = obj.get("name")
        addr = int(obj.get("addr"))
        addr = int(addr)
        size = int(obj.get("size"))

        if dummy_names:
            if IDAtools.is_dummy_name(name):
                return
        if type(addr) == int:
            if ida_bytes.is_unknown(ida_bytes.get_full_flags(addr)):
                if size:
                    ok = idaapi.create_data(addr, idc.FF_BYTE, size, 0)
                else:
                    ok = idc.create_byte(addr)
                if not ok:
                    if not ok:
                        reason = "Could not create data at {addr:#x}".format(
                            addr=addr)
                        print(reason)

        if overwrite_names and IDAtools.is_dummy_name_by_addr(addr):
            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)
                print(reason)

        IDAtools.ida_wait()
Beispiel #7
0
    def extract_all_user_names(filename=None):
        """
        Get all user-named labels inside IDA. Also prints into output window.
        :return: dictionary of all user named labels: label_name -> ea
        """
        results = {}
        output = ''

        for ea, name in idautils.Names():
            if ida_kernwin.user_cancelled():
                return results

            if '_' in name:
                if name.split('_')[0] in ('def', 'sub', 'loc', 'jpt', 'j',
                                          'nullsub'):
                    continue
            flags = ida_bytes.get_full_flags(ea)
            if ida_bytes.has_user_name(flags):
                results[name] = ea
                output += '{} = 0x{:08x};\n'.format(name, ea)

        if filename is not None:
            with open(filename, 'w') as f:
                f.write(output)

        return results
    def guess_dummy_type(self, interface_ea):
        if self.dummy:
            if is_struct(get_full_flags(interface_ea)):
                return

            t = guess_type(interface_ea)
            if t is not None:
                next(self.members()).type = t
Beispiel #9
0
def _process_stubs_section(segstart, make_thunk, next_stub):
    """Process all the functions in a __stubs section."""
    segend = idc.get_segm_end(segstart)
    # We'll go through each address and check if it has a reference. If it does, it is likely a
    # stub. As long as the address doesn't already have a stub name, process it.
    for ea in idau.Addresses(segstart, segend, step=1):
        if idc.isRef(ida_bytes.get_full_flags(ea)) and not stub_name_target(
                idau.get_ea_name(ea)):
            _process_possible_stub(ea, make_thunk, next_stub)
Beispiel #10
0
    def flags(self):
        """
            Property for getting the flags of the element. Those flags are the
            one from ida such as returned by ``ida_bytes.get_full_flags``.

            :return: The flags for the element
            :rtype: int
        """
        return ida_bytes.get_full_flags(self.ea)
Beispiel #11
0
def _function_name(ea):
    """Try to get the name of a function."""
    try:
        flags = ida_bytes.get_full_flags(ea)
        if ida_bytes.has_name(flags):
            return ida_funcs.get_func_name(ea)
    except:
        pass
    return "sub_{:x}".format(ea)
Beispiel #12
0
 def name(self):
     ea = self.address()
     try:
         flags = ida_bytes.get_full_flags(ea)
         if ida_bytes.has_name(flags):
             return ida_name.get_ea_name(ea)
     except:
         pass
     return ""
Beispiel #13
0
def _variable_name(ea):
    """Return the name of a variable."""
    try:
        flags = ida_bytes.get_full_flags(ea)
        if ida_bytes.has_name(flags):
            return ida_name.get_ea_name(ea)
    except:
        pass
    return ""
Beispiel #14
0
    def op_type_changed(self, ea, n):
        self._plugin.logger.debug("op_type_changed(ea = %x, n = %d)" % (ea, n))

        def gather_enum_info(ea, n):
            id = ida_bytes.get_enum_id(ea, n)[0]
            serial = ida_enum.get_enum_idx(id)
            return id, serial

        extra = {}
        mask = ida_bytes.MS_0TYPE if not n else ida_bytes.MS_1TYPE
        flags = ida_bytes.get_full_flags(ea)
        self._plugin.logger.debug("op_type_changed: flags = 0x%X)" % flags)

        def is_flag(type):
            return flags & mask == mask & type

        if is_flag(ida_bytes.hex_flag()):
            op = "hex"
        elif is_flag(ida_bytes.dec_flag()):
            op = "dec"
        elif is_flag(ida_bytes.char_flag()):
            op = "chr"
        elif is_flag(ida_bytes.bin_flag()):
            op = "bin"
        elif is_flag(ida_bytes.oct_flag()):
            op = "oct"
        elif is_flag(ida_bytes.off_flag()):
            op = "offset"
        elif is_flag(ida_bytes.enum_flag()):
            op = "enum"
            id, serial = gather_enum_info(ea, n)
            ename = ida_enum.get_enum_name(id)
            extra["ename"] = Event.decode(ename)
            extra["serial"] = serial
        elif flags & ida_bytes.stroff_flag():
            op = "struct"
            path = ida_pro.tid_array(1)
            delta = ida_pro.sval_pointer()
            path_len = ida_bytes.get_stroff_path(path.cast(), delta.cast(), ea,
                                                 n)
            spath = []
            for i in range(path_len):
                sname = ida_struct.get_struc_name(path[i])
                spath.append(Event.decode(sname))
            extra["delta"] = delta.value()
            extra["spath"] = spath
        elif is_flag(ida_bytes.stkvar_flag()):
            op = "stkvar"
        # FIXME: No hooks are called when inverting sign
        # elif ida_bytes.is_invsign(ea, flags, n):
        #     op = 'invert_sign'
        else:
            return 0  # FIXME: Find a better way to do this
        self._send_packet(evt.OpTypeChangedEvent(ea, n, op, extra))
        return 0
Beispiel #15
0
    def instr_iter(self):
        """
            Return a generator of :class:`BipInstr` corresponding to the
            instructions of the basicblock. This implementation will be just
            a little more performant than the :meth:`instr` property.

            :return: A generator of object :class:`BipInstr` .
        """
        for h in idautils.Heads(self.ea, self.end):
            if idc.is_code(ida_bytes.get_full_flags(h)):
                yield bip.base.instr.BipInstr(h)
Beispiel #16
0
    def instr(self):
        """
            Return a list of :class:`BipInstr` corresponding to the instructions
            of the basicblock.

            :return: A list of object :class:`BipInstr` .
        """
        return [
            bip.base.instr.BipInstr(h)
            for h in idautils.Heads(self.ea, self.end)
            if idc.is_code(ida_bytes.get_full_flags(h))
        ]
Beispiel #17
0
    def is_dummy_name(self):
        """
            Property for checking if the current name of this function is a
            "dummy" name (a name set by default by IDA when it does not know
            how to call an element) with a special prefix. This function will
            not recognize the ``aSTRING`` naming,
            see :meth:`~BipFunction.is_auto_name`, and :meth:`~BipFunction.is_ida_name`.

            :return: ``True`` if the function has a dummy name, ``False``
                otherwise.
        """
        return ida_bytes.has_dummy_name(ida_bytes.get_full_flags(self.ea))
Beispiel #18
0
    def is_user_name(self):
        """
            Property for checking if the current name is a "user name". In
            practice this check a flag that the API can avoid setting, so
            there is no garantee it is an actual user name.
            See :meth:`~BipFunction.is_ida_name` for checking if a name was
            generated by IDA.

            :return: ``True`` if the name is marked as set by a user,
                ``False`` otherwise.
        """
        return ida_bytes.has_user_name(ida_bytes.get_full_flags(self.ea))
Beispiel #19
0
    def is_auto_name(self):
        """
            Property for checking if the current name of this function is an
            "auto-generated" name, those are the default name generated by
            IDA but without a special prefix
            (see :meth:`~BipFunction.is_dummy_name`) such as the one for the
            string. See also :meth:`~BipFunction.is_ida_name`.

            :return: ``True`` if the function has an auto-generated name,
                ``False`` otherwise.
        """
        return ida_bytes.has_auto_name(ida_bytes.get_full_flags(self.ea))
Beispiel #20
0
    def _has_code(self):
        """
        Checks if any address in the changed data area has code in it

        :return: (int) address of the code start, or None.
        """
        for i in xrange(self.data):
            maybe_start_of_item = ida_bytes.get_item_head(self.address + i)
            if ida_bytes.is_code(
                    ida_bytes.get_full_flags(maybe_start_of_item)):
                return self.address + i
        return None
Beispiel #21
0
    def get_conflict(self):
        """

        :return: None if there's no conflict, empty string if there's no change, data if there's a change.
        """
        # TODO: Fill docstring, plus, make the function return 0,1,2 and save the current data by itself.
        code_address = self._has_code()
        if code_address:
            return 'Code: 0x%x' % code_address

        num_of_elements = self._get_num_of_elements()

        data_undefined = True
        for i in xrange(self.data):
            ea_flags = ida_bytes.get_full_flags(self.address + i)
            if ea_flags & 0x400:  # Data defined
                data_undefined = False
        if data_undefined:
            return None  # No conflict

        # Iterate over all local data, and check if there's any conflict with the type
        conflict = ''
        for i in xrange(num_of_elements):
            current_address = self.address + (
                i * self.TYPE_TO_SIZE[self.data_type])
            current_address = ida_bytes.get_item_head(current_address)
            ea_flags = ida_bytes.get_full_flags(current_address)
            if not ida_bytes.is_data(ea_flags):
                conflict += 'unknown at 0x%x\n' % current_address
                continue
            current_data_type = ea_flags & ida_bytes.DT_TYPE
            if self.data_type != current_data_type:  # Different data
                conflict += '%s at 0x%x\n' % (
                    self.TYPE_TO_NAME[current_data_type], current_address)
        if conflict:
            return conflict

        # TODO: Deal with the case it's just multiple type definitions in the area?
        return ''  # No difference
Beispiel #22
0
    def op_type_changed(self, ea, n):
        def gather_enum_info(ea, n):
            id = ida_bytes.get_enum_id(ea, n)[0]
            serial = ida_enum.get_enum_idx(id)
            return id, serial

        extra = {}
        mask = ida_bytes.MS_0TYPE if not n else ida_bytes.MS_1TYPE
        flags = ida_bytes.get_full_flags(ea) & mask

        def is_flag(type):
            return flags == mask & type

        if is_flag(ida_bytes.hex_flag()):
            op = 'hex'
        elif is_flag(ida_bytes.dec_flag()):
            op = 'dec'
        elif is_flag(ida_bytes.char_flag()):
            op = 'chr'
        elif is_flag(ida_bytes.bin_flag()):
            op = 'bin'
        elif is_flag(ida_bytes.oct_flag()):
            op = 'oct'
        elif is_flag(ida_bytes.enum_flag()):
            op = 'enum'
            id, serial = gather_enum_info(ea, n)
            ename = ida_enum.get_enum_name(id)
            extra['ename'] = Event.decode(ename)
            extra['serial'] = serial
        elif is_flag(flags & ida_bytes.stroff_flag()):
            op = 'struct'
            path = ida_pro.tid_array(1)
            delta = ida_pro.sval_pointer()
            path_len = ida_bytes.get_stroff_path(path.cast(), delta.cast(), ea,
                                                 n)
            spath = []
            for i in range(path_len):
                sname = ida_struct.get_struc_name(path[i])
                spath.append(Event.decode(sname))
            extra['delta'] = delta.value()
            extra['spath'] = spath
        elif is_flag(ida_bytes.stkvar_flag()):
            op = 'stkvar'
        # IDA hooks for is_invsign seems broken
        # Inverting sign don't trigger the hook
        # elif ida_bytes.is_invsign(ea, flags, n):
        #     op = 'invert_sign'
        else:
            return 0  # FIXME: Find a better way
        self._send_event(OpTypeChangedEvent(ea, n, op, extra))
        return 0
Beispiel #23
0
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 _convert_address_to_function(func):
    """Convert an address that IDA has classified incorrectly into a proper function."""
    # If everything goes wrong, we'll try to restore this function.
    orig = idc.first_func_chunk(func)
    # If the address is not code, let's undefine whatever it is.
    if not ida_bytes.is_code(ida_bytes.get_full_flags(func)):
        if not is_mapped(func):
            # Well, that's awkward.
            return False
        item = ida_bytes.get_item_head(func)
        itemend = ida_bytes.get_item_end(func)
        if item != idc.BADADDR:
            _log(1, 'Undefining item {:#x} - {:#x}', item, itemend)
            ida_bytes.del_items(item, ida_bytes.DELIT_EXPAND)
            idc.create_insn(func)
            # Give IDA a chance to analyze the new code or else we won't be able to create a
            # function.
            #ida_auto.auto_wait()
            autoanalyze()
            idc.plan_and_wait(item, itemend)
    else:
        # Just try removing the chunk from its current function. IDA can add it to another function
        # automatically, so make sure it's removed from all functions by doing it in loop until it
        # fails.
        for i in range(1024):
            if not idc.remove_fchunk(func, func):
                break
    # Now try making a function.
    if ida_funcs.add_func(func) != 0:
        return True
    # This is a stubborn chunk. Try recording the list of chunks, deleting the original function,
    # creating the new function, then re-creating the original function.
    if orig != idc.BADADDR:
        chunks = list(idautils.Chunks(orig))
        if ida_funcs.del_func(orig) != 0:
            # Ok, now let's create the new function, and recreate the original.
            if ida_funcs.add_func(func) != 0:
                if ida_funcs.add_func(orig) != 0:
                    # Ok, so we created the functions! Now, if any of the original chunks are not
                    # contained in a function, we'll abort and undo.
                    if all(idaapi.get_func(start) for start, end in chunks):
                        return True
            # Try to undo the damage.
            for start, _ in chunks:
                ida_funcs.del_func(start)
    # Everything we've tried so far has failed. If there was originally a function, try to restore
    # it.
    if orig != idc.BADADDR:
        _log(0, 'Trying to restore original function {:#x}', orig)
        ida_funcs.add_func(orig)
    return False
Beispiel #25
0
    def get_conflict(self):
        """

        :return: None if there's no conflict, empty string if there's no change, data if there's a change.
        """
        # TODO: Fill docstring, plus, make the function return 0,1,2 and save the current data by itself.
        conflicts = ""
        conflict_flag = False
        for i in xrange(self.data):
            current_address = self.address + i
            head_address = ida_bytes.get_item_head(current_address)
            if ida_bytes.is_code(ida_bytes.get_full_flags(head_address)):
                conflict_flag = True
            ea_flags = ida_bytes.get_full_flags(head_address)
            if not ida_bytes.is_data(ea_flags):
                continue
            conflict_flag = True
            conflicts += '%s at 0x%x\n' % (
                self.TYPE_TO_NAME[ea_flags & ida_bytes.DT_TYPE], head_address)

        if conflict_flag:
            return conflicts
        return None
Beispiel #26
0
 def is_dummy_name_by_addr(addr):
     name = idc.get_name(addr)
     dummyList = {
         "", "sub_", "locret_", "loc_", "off_", "seg_", "asc_", "byte_",
         "word_", "dword_", "qword_", "byte3_", "xmmword", "_ymmword_",
         "packreal_", "flt_", "dbl_", "tbyte_", "stru_", "custdata_",
         "algn_", "unk_"
     }
     if ida_bytes.is_unknown(ida_bytes.get_full_flags(addr)):
         return True
     for items in dummyList:
         if name.startswith(items):
             return True
     return False
Beispiel #27
0
    def __process_functions(self):
        functions = list()

        start = ida_ida.cvar.inf.min_ea
        end = ida_ida.cvar.inf.max_ea

        # find first function head chunk in the range
        chunk = ida_funcs.get_fchunk(start)

        if not chunk:
            chunk = ida_funcs.get_next_fchunk(start)
        while chunk and chunk.start_ea < end and (chunk.flags
                                                  & ida_funcs.FUNC_TAIL) != 0:
            chunk = ida_funcs.get_next_fchunk(chunk.start_ea)

        func = chunk

        while func and func.start_ea < end:
            start_ea = func.start_ea

            func_flags = ida_bytes.get_full_flags(start_ea)
            func_name = ida_funcs.get_func_name(start_ea)
            func_name_demangled = ida_name.get_demangled_name(
                start_ea, 0xFFFF, 0, 0)
            func_autonamed = func_flags & ida_bytes.FF_LABL != 0
            func_public = ida_name.is_public_name(start_ea)

            function = {
                'start_rva': start_ea - self._base,
                'name': func_name,
                'name_demangled': func_name_demangled,
                'is_public': func_public,
                'is_autonamed': func_autonamed
            }

            # PE32/PE32+ only support binaries up to 2GB
            if function['start_rva'] >= 2**32:
                print('RVA out of range for function: ' + function['name'],
                      file=sys.stderr)

            self.__process_function_typeinfo(function, func)

            function['labels'] = self.__process_function_labels(func)

            functions.append(function)

            func = ida_funcs.get_next_func(start_ea)

        return functions
Beispiel #28
0
def test_bipelt00():
    # ea, flags, size
    assert BipElt(0x01800D325A).ea == 0x01800D325A
    assert BipElt(0x01800D325A).flags == ida_bytes.get_full_flags(0x01800D325A)
    assert BipElt(0x01800D325A).size == 4
    assert BipElt(0x018015D260).size == 1
    assert BipElt(0x018015D228).size == 8
    # bytes
    assert BipElt(0x01800D325A).bytes == [0x48, 0x83, 0xC4, 0x60]
    BipElt(0x01800D325A).bytes = [0x90, 0x90, 0x90, 0x90]
    assert BipElt(0x01800D325A).bytes == [0x90, 0x90, 0x90, 0x90]
    assert BipElt(0x01800D325A).original_bytes == [0x48, 0x83, 0xC4, 0x60]
    BipElt(0x01800D325A).bytes = b"\xAA" * 4
    assert BipElt(0x01800D325A).bytes == [0xAA, 0xAA, 0xAA, 0xAA]
    BipElt(0x01800D325A).bytes = [0x48, 0x83, 0xC4, 0x60]
    assert BipElt(0x01800D325A).bytes == [0x48, 0x83, 0xC4, 0x60]
    # name
    assert BipElt(0x01800D325A).name == 'loc_1800D325A'
    assert BipElt(0x01800D325A).is_dummy_name
    assert not BipElt(0x01800D325A).is_auto_name
    assert BipElt(0x01800D325A).is_ida_name
    assert not BipElt(0x01800D325A).is_user_name
    ie = BipElt(0x01800D325A)
    prevname = ie.name
    ie.name = "idaelt_test"
    assert ie.name == "idaelt_test"
    assert not BipElt(0x01800D325A).is_dummy_name
    assert not BipElt(0x01800D325A).is_auto_name
    assert not BipElt(0x01800D325A).is_ida_name
    assert BipElt(0x01800D325A).is_user_name
    ie.name = None
    assert BipElt(0x01800D325A).name == 'loc_1800D325A'
    assert BipElt(0x01800D325A).is_dummy_name
    assert not BipElt(0x01800D325A).is_auto_name
    assert BipElt(0x01800D325A).is_ida_name
    assert not BipElt(0x01800D325A).is_user_name
    assert BipElt(0x018014F7FF).is_auto_name
    assert not BipElt(0x018014F7FF).is_dummy_name
    assert BipElt(0x018014F7FF).is_ida_name
    assert BipElt(0x0180125828).demangle_name is None
    # TODO: need other binary for demangle name
    # color
    assert BipElt(0x01800D325A).color == idc.get_color(0x01800D325A, idc.CIC_ITEM)
    ie = BipElt(0x01800D325A)
    prevcolor = ie.color
    ie.color = 0xAABBCC
    assert ie.color == 0xAABBCC
    ie.color = prevcolor
Beispiel #29
0
    def search_str_addr(s, start_ea=None, end_ea=None, down=True, nxt=True):
        """
            Static method for searching a string. In practice this perform
            a search_bytes on the binary by encoding correctly the string
            passed in argument and returning only reference to data elements.

            .. warning::

                This is different from idapython ``FindText`` method as this
                will only search for bytes in the binary (and more precisely
                the data)! It should also be way faster.

            .. todo:: this should allow to handle encoding.

            :param str s: The C string for which to search. If the string
                is NULL terminated the NULL byte must be included.
            :param start_ea: The address at which to start the search, if
                ``None`` the current address will be used.
            :param end_ea: The address at which to stop the search, if
                ``None`` the maximum or minimum (depending of searching up or
                down) will be used.
            :param down: If True (the default) search below the given
                address, if False search above.
            :param nxt: If True (the default) the current element will not
                be included in the search.
            :return: The address at which the string was found.  It will
                always be data. If no matching element was found None will be
                return.
        """
        # lets encode the string
        byt = " ".join(["{:X}".format(ord(c)) for c in s])
        # we want to skip everything which is not data without making the
        #   search, this should be faster
        curr_addr = BipElt.next_data_addr(start_ea, down=down)
        while curr_addr is not None:
            curr_addr = BipElt.search_bytes_addr(byt,
                                                 start_ea=curr_addr,
                                                 end_ea=end_ea,
                                                 down=down,
                                                 nxt=nxt)
            if curr_addr is None:
                return None  # not found
            if idc.is_data(ida_bytes.get_full_flags(curr_addr)):
                return curr_addr  # found!
            # lets continue
            curr_addr = BipElt.next_data_addr(curr_addr, down=down)
        return None  # not found
Beispiel #30
0
    def op_type_changed(self, ea, n):
        extra = {}
        mask = ida_bytes.MS_0TYPE if not n else ida_bytes.MS_1TYPE
        flags = ida_bytes.get_full_flags(ea) & mask

        if flags == mask & ida_bytes.hex_flag():
            op = 'hex'
        elif flags == mask & ida_bytes.dec_flag():
            op = 'dec'
        elif flags == mask & ida_bytes.char_flag():
            op = 'chr'
        elif flags == mask & ida_bytes.bin_flag():
            op = 'bin'
        elif flags == mask & ida_bytes.oct_flag():
            op = 'oct'
        elif flags == mask & ida_bytes.enum_flag():
            op = 'enum'
            enum_id = ida_bytes.get_enum_id(ea, n)[0]
            enum_serial = ida_enum.get_enum_idx(enum_id)
            ename = ida_enum.get_enum_name(enum_id)
            extra['ename'] = Unicoder.decode(ename)
            extra['serial'] = enum_serial
        elif flags == mask & ida_bytes.stroff_flag():
            op = 'struct'
            path = ida_pro.tid_array(1)
            delta = ida_pro.sval_pointer()
            path_len = ida_bytes.get_stroff_path(path.cast(), delta.cast(), ea,
                                                 n)
            spath = []
            for i in range(path_len):
                sname = ida_struct.get_struc_name(path[i])
                spath.append(Unicoder.decode(sname))
            extra['delta'] = delta.value()
            extra['spath'] = spath
        elif flags == mask & ida_bytes.stkvar_flag():
            op = 'stkvar'
        else:
            return 0
        self._network.send_event(
            EventType.OPTYPECHANGED,
            ea=ea,
            n=n,
            op=Unicoder.decode(op),
            extra=extra,
        )
        return 0
Beispiel #31
0
def _is_address_of_struct_field(ea):
  prev_head_ea = idc.prev_head(ea)

  if is_invalid_ea(prev_head_ea):
    return False

  prev_item_size = idc.get_item_size(prev_head_ea)
  if ea >= (prev_head_ea + prev_item_size):
    return False

  # Try to get a type for the last item head.
  flags = ida_bytes.get_full_flags(ea)
  ti = ida_nalt.opinfo_t()
  oi = ida_bytes.get_opinfo(ti, ea, 0, flags)
  if not oi:
    return False

  # Get the size of the struct, and keep going if the suze of the previous
  # item is a multiple of the struct's size (e.g. one struct or an array
  # of that struct).
  struct_size = idc.get_struc_size(oi.tid)
  if not struct_size or 0 != (prev_item_size % struct_size):
    return False

  # Figure out the offset of `ea` within its structure, which may belong to
  # an array of structures, and then check if that offset is associated with
  # a named field.
  arr_index = int((ea - prev_head_ea) / struct_size)
  struct_begin_ea = (arr_index & struct_size) + prev_head_ea
  off_in_struct = ea - struct_begin_ea
  if not idc.get_member_name(oi.tid, off_in_struct):
    return False

  field_begin_ea = struct_begin_ea + off_in_struct
  if field_begin_ea != ea:
    return False

  field_size = idc.GetMemberSize(oi.tid, off_in_struct)
  if not field_size:
    return False

  return True