Exemple #1
0
    def visit_expr(self, i):
        if i.op != idaapi.cot_call:
            return 0

        node = i.x
        if node.op == idaapi.cot_cast:
            node = node.x

        if node.op != idaapi.cot_memptr:
            return 0

        offset = node.m
        node = node.x

        type = node.type.get_pointed_object()
        if type is None:
            return 0

        member = idaapi.udt_member_t()
        member.offset = offset * 8

        type.find_udt_member(member, idaapi.STRMEM_OFFSET)

        if member.name != self.method_name:
            return 0

        self.need_update = infer_function_signature(self.cfunc, i,
                                                    self.index_interface,
                                                    self.index_output)
        return 0
Exemple #2
0
def get_virtual_func_address(name, tinfo=None, offset=None):
    """
    :param name: method name
    :param tinfo: class tinfo
    :param offset: virtual table offset
    :return: address of the method
    """

    address = idc.LocByName(name)
    if address != idaapi.BADADDR:
        return address

    address = demangled_names.get(name, idaapi.BADADDR)
    if address != idaapi.BADADDR:
        return address + idaapi.get_imagebase()

    if tinfo is None or offset is None:
        return

    offset *= 8
    udt_member = idaapi.udt_member_t()
    while tinfo.is_struct():
        address = demangled_names.get(tinfo.dstr() + '::' + name,
                                      idaapi.BADADDR)
        if address != idaapi.BADADDR:
            return address + idaapi.get_imagebase()
        udt_member.offset = offset
        tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
        tinfo = udt_member.type
        offset = offset - udt_member.offset
def structure_info_create(vtbs):
    for vtb in vtbs:
        vtb_name = "vtb_" + (hex(vtb.get("vtb_start_addr"))[2:-1]).upper()
        # 创建结构体
        udt_data = idaapi.udt_type_data_t()

        # 函数名称记录列表
        func_name_records_list = []

        # 添加结构体的成员
        for mem in vtb.get('vtb_func_lists'):
            # 创建成员
            udt_member = idaapi.udt_member_t()
            udt_member.type = ptr_type("DWORD")
            udt_member.name = name_filter(mem.get('func_name'))
            # 如果名字为空,需要进行特殊的处理
            # MEMORY[xxxx]
            # print udt_member.name
            if udt_member.name == None or udt_member.name == "":
                udt_member.name = "memory_" + (hex(
                    mem.get("func_addr"))[2:]).upper()
            # 防止函数名称重复
            if udt_member.name in func_name_records_list:
                udt_member.name += "1"
            func_name_records_list.append(udt_member.name)
            # print udt_member.name
            # 插入结构体
            udt_data.push_back(udt_member)
        build_structure_in_ida(udt_data, vtb_name)
Exemple #4
0
def get_fields_at_offset(tinfo, offset):
    """
    Given tinfo and offset of the structure or union, returns list of all tinfo at that offset.
    This function helps to find appropriate structures by type of the offset
    """
    result = []
    if offset == 0:
        result.append(tinfo)
    udt_data = idaapi.udt_type_data_t()
    tinfo.get_udt_details(udt_data)
    udt_member = idaapi.udt_member_t()
    udt_member.offset = offset * 8
    idx = tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
    if idx != -1:
        while idx < tinfo.get_udt_nmembers(
        ) and udt_data[idx].offset <= offset * 8:
            udt_member = udt_data[idx]
            if udt_member.offset == offset * 8:
                if udt_member.type.is_ptr():
                    result.append(idaapi.get_unk_type(Const.EA_SIZE))
                    result.append(udt_member.type)
                    result.append(idaapi.dummy_ptrtype(Const.EA_SIZE, False))
                elif not udt_member.type.is_udt():
                    result.append(udt_member.type)
            if udt_member.type.is_array():
                if (offset - udt_member.offset / 8
                    ) % udt_member.type.get_array_element().get_size() == 0:
                    result.append(udt_member.type.get_array_element())
            elif udt_member.type.is_udt():
                result.extend(
                    get_fields_at_offset(udt_member.type,
                                         offset - udt_member.offset / 8))
            idx += 1
    return result
Exemple #5
0
 def get_udt_member(self):
     udt_member = idaapi.udt_member_t()
     udt_member.type = self.get_ptr_tinfo()
     udt_member.offset = self.offset
     udt_member.name = self.name
     udt_member.size = const.EA_SIZE
     return udt_member
Exemple #6
0
def get_virtual_func_address(name, tinfo=None, offset=None):
    """
    :param name: method name
    :param tinfo: class tinfo
    :param offset: virtual table offset
    :return: address of the method
    """
    # address = idaapi.BADADDR
    # if name in idautils.Functions():
    address = idc.LocByName(name) #f*****g idaapi. It's function work incorrectly. This returned 0xFF005BE7 instead BADADDR in some cases. get_name_ea problem.

    if address != idaapi.BADADDR:
        return address

    address = Cache.demangled_names.get(name, idaapi.BADADDR)
    if address != idaapi.BADADDR:
        return address + idaapi.get_imagebase()

    if tinfo is None or offset is None:
        return

    offset *= 8
    udt_member = idaapi.udt_member_t()
    while tinfo.is_struct():
        address = Cache.demangled_names.get(tinfo.dstr() + '::' + name, idaapi.BADADDR)
        if address != idaapi.BADADDR:
            return address + idaapi.get_imagebase()
        udt_member.offset = offset
        tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
        tinfo = udt_member.type
        offset = offset - udt_member.offset
Exemple #7
0
def call_found(obj, ctx):
    import ida_typeinf
    import idc_bc695
    import ida_xref

    call = ctx.get_expr('call_expr')[0]
    expr = ctx.get_expr('ref')[0]

    print type(expr)
    print '[*] Offset: %#x' % expr.m
    print '[*] First op type: %s' % expr.x.type.dstr().split(' ')[0]
    print '[*] Address %#x' % call.ea
    # vtab.sub_XXXX(...)
    if expr.x.op == idaapi.cot_memref:
        vtable_tinfo = expr.x.type.get_pointed_object()

    # vtab->sub_XXXX(...)
    else:
        vtable_tinfo = expr.x.type
        if vtable_tinfo.is_ptr():
            vtable_tinfo = vtable_tinfo.get_pointed_object()

    udt_member = idaapi.udt_member_t()
    udt_member.offset = expr.m * 8
    vtable_tinfo.find_udt_member(udt_member, idaapi.STRMEM_OFFSET)

    from_addr = call.ea
    to_addr = idc_bc695.LocByName(udt_member.name)

    print '[*] Function: %s' % udt_member.name
    print 'ida_xref.add_cref(%#x, %#x, %d)' % (call.ea, to_addr, ida_xref.fl_CN
                                               | ida_xref.XREF_USER)
    print ida_xref.add_cref(call.ea, to_addr,
                            ida_xref.fl_CN | ida_xref.XREF_USER)
Exemple #8
0
    def activate(self, ctx):
        hx_view = idaapi.get_widget_vdui(ctx.widget)
        ri = self.extract_recast_info(hx_view.cfunc, hx_view.item)
        if not ri:
            return 0

        if isinstance(ri, RecastLocalVariable):
            hx_view.set_lvar_type(ri.local_variable, ri.recast_tinfo)

        elif isinstance(ri, RecastGlobalVariable):
            idaapi.apply_tinfo2(ri.global_variable_ea, ri.recast_tinfo,
                                idaapi.TINFO_DEFINITE)

        elif isinstance(ri, RecastArgument):
            if ri.recast_tinfo.is_array():
                ri.recast_tinfo.convert_array_to_ptr()
            helper.set_func_argument(ri.func_tinfo, ri.arg_idx,
                                     ri.recast_tinfo)
            idaapi.apply_tinfo2(ri.func_ea, ri.func_tinfo,
                                idaapi.TINFO_DEFINITE)

        elif isinstance(ri, RecastReturn):
            cfunc = helper.decompile_function(ri.func_ea)
            if not cfunc:
                return 0

            func_tinfo = idaapi.tinfo_t()
            cfunc.get_func_type(func_tinfo)
            helper.set_func_return(func_tinfo, ri.recast_tinfo)
            idaapi.apply_tinfo2(cfunc.entry_ea, func_tinfo,
                                idaapi.TINFO_DEFINITE)

        elif isinstance(ri, RecastStructure):
            tinfo = idaapi.tinfo_t()
            tinfo.get_named_type(idaapi.cvar.idati, ri.structure_name)
            ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati,
                                              ri.structure_name)
            if ordinal == 0:
                return 0

            udt_member = idaapi.udt_member_t()
            udt_member.offset = ri.field_offset * 8
            idx = tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
            if udt_member.offset != ri.field_offset * 8:
                print("[Info] Can't handle with arrays yet")
            elif udt_member.type.get_size() != ri.recast_tinfo.get_size():
                print("[Info] Can't recast different sizes yet")
            else:
                udt_data = idaapi.udt_type_data_t()
                tinfo.get_udt_details(udt_data)
                udt_data[idx].type = ri.recast_tinfo
                tinfo.create_udt(udt_data, idaapi.BTF_STRUCT)
                tinfo.set_numbered_type(idaapi.cvar.idati, ordinal,
                                        idaapi.NTF_REPLACE, ri.structure_name)
        else:
            raise NotImplementedError

        hx_view.refresh_view(True)
        return 0
 def is_structure_offset(self, tinfo, offset):
     # Checks if structure tinfo contains a member at given offset
     # TODO:array checking
     udt_member = idaapi.udt_member_t()
     udt_member.offset = offset * 8
     if offset >= 0 and tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member) != -1:
         if udt_member.type.is_udt():
             return self.is_structure_offset(udt_member.type, offset - udt_member.offset / 8)
         return udt_member.offset == offset * 8
     return False
Exemple #10
0
    def analyze_type(self, tinfo):
        """
        parse type tinfo;
        adding unknown members to the local types as necessary
        return True if new types were added
        """
        # print "analyze_type : "+str(tinfo)
        has_new_type = False
        if str(tinfo) in self.seen:
            return False
        else:
            self.seen.add(str(tinfo))
            self.import_name(str(tinfo))
            has_new_type = True

        # Struct or union ? Walk members
        if tinfo.is_udt():
            # Hack to avoid problems with:
            # typedef struct _TOTO TOTO
            # IDA considers both _TOTO and TOTO as structs
            # this hack seems to fix it (maybe we could use
            # get_next_type_name)
            # print "---\t %s %s" % (tinfo.get_final_type_name(), str(tinfo))
            if tinfo.get_final_type_name() == str(tinfo):
                # print "adding to structs"
                self.structs.add(str(tinfo))

            u = idaapi.udt_member_t()
            # struct members
            for idx in range(0, tinfo.get_udt_nmembers()):
                u.offset = idx
                tinfo.find_udt_member(u, idaapi.STRMEM_INDEX)

                # print "member :"+str(u.type)
                # Recurse base type
                has_new_type = self.analyze_type(u.type) or has_new_type
                # AND also without pointer
                # to handle both shitty cases like :
                #   - PVOID (pointer but not to struct)
                #   - COMPLEX_STRUCT *
                if u.type.is_ptr_or_array():
                    no_ptr = u.type
                    no_ptr.remove_ptr_or_array()
                    has_new_type = self.analyze_type(no_ptr) or has_new_type

        # Some types are "proxies" like typedef
        # but IDA doesn't seem to be offer a way to
        # differenciate them easily
        next_t = tinfo.get_next_type_name()
        if next_t is not None and next_t not in self.seen:
            # print "import next: "+next_t
            self.import_name(next_t)
            has_new_type = True

        return has_new_type
Exemple #11
0
 def get_udt_member(self, offset=0):
     udt_member = idaapi.udt_member_t()
     tid = self.import_to_structures()
     if tid != idaapi.BADADDR:
         udt_member.name = self.name
         tmp_tinfo = idaapi.create_typedef(self.vtable_name)
         tmp_tinfo.create_ptr(tmp_tinfo)
         udt_member.type = tmp_tinfo
         udt_member.offset = self.offset - offset
         udt_member.size = const.EA_SIZE
     return udt_member
Exemple #12
0
 def get_udt_member(self, array_size=0, offset=0):
     udt_member = idaapi.udt_member_t()
     udt_member.name = "field_{0:X}".format(self.offset - offset) if self.name[:6] == "field_" else self.name
     udt_member.type = self.tinfo
     if array_size:
         tmp = idaapi.tinfo_t(self.tinfo)
         tmp.create_array(self.tinfo, array_size)
         udt_member.type = tmp
     udt_member.offset = self.offset - offset
     udt_member.size = self.size
     return udt_member
Exemple #13
0
 def get_udt_member(self, array_size=0, offset=0):
     udt_member = idaapi.udt_member_t()
     udt_member.name = "{}_{:x}".format(
         get_operand_size_type(self.tinfo), self.offset -
         offset) if re.match(r'(byte|(d|q|t|dq|)word|float|(d|dd)ouble)_',
                             self.name) else self.name
     udt_member.type = self.tinfo
     if array_size:
         tmp = idaapi.tinfo_t(self.tinfo)
         tmp.create_array(self.tinfo, array_size)
         udt_member.type = tmp
     udt_member.offset = self.offset - offset
     udt_member.size = self.size
     return udt_member
Exemple #14
0
    def tinfo(self):
        udt = idaapi.udt_type_data_t()
        for m in self.members:
            new_member = idaapi.udt_member_t()
            new_member.name = m.name
            new_member.type = m.tinfo
            new_member.size = m.size
            new_member.offset = m.offset

            udt.push_back(new_member)

        final_tinfo = idaapi.tinfo_t()
        if final_tinfo.create_udt(udt, idaapi.BTF_STRUCT):
            return final_tinfo
Exemple #15
0
def create_padding_udt_member(offset, size):
    # type: (long, long) -> idaapi.udt_member_t
    """ Creates internal IDA structure with name gap_XXX and appropriate size and offset """

    udt_member = idaapi.udt_member_t()
    udt_member.name = "gap_{0:X}".format(offset)
    udt_member.offset = offset
    udt_member.size = size

    if size == 1:
        udt_member.type = const.BYTE_TINFO
    else:
        array_data = idaapi.array_type_data_t()
        array_data.base = 0
        array_data.elem_type = const.BYTE_TINFO
        array_data.nelems = size
        tmp_tinfo = idaapi.tinfo_t()
        tmp_tinfo.create_array(array_data)
        udt_member.type = tmp_tinfo
    return udt_member
Exemple #16
0
    def check(cfunc, ctree_item):
        if ctree_item.citype != idaapi.VDI_EXPR:
            return

        item = ctree_item.it.to_specific_type
        if item.op != idaapi.cot_memptr:
            return

        parent = cfunc.body.find_parent_of(ctree_item.it).to_specific_type
        if parent.op != idaapi.cot_idx or parent.y.op != idaapi.cot_num:
            return
        idx = parent.y.n._value

        struct_type = item.x.type.get_pointed_object()
        udt_member = idaapi.udt_member_t()
        udt_member.offset = item.m * 8
        struct_type.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
        if udt_member.name[0:3] != "gap":
            return

        return struct_type, udt_member.offset // 8, idx
Exemple #17
0
    def get_padding_member(offset, size):
        udt_member = idaapi.udt_member_t()
        if size == 1:
            udt_member.name = "gap_{0:X}".format(offset)
            udt_member.type = Const.BYTE_TINFO
            udt_member.size = Const.BYTE_TINFO.get_size()
            udt_member.offset = offset
            return udt_member

        array_data = idaapi.array_type_data_t()
        array_data.base = 0
        array_data.elem_type = Const.BYTE_TINFO
        array_data.nelems = size
        tmp_tinfo = idaapi.tinfo_t()
        tmp_tinfo.create_array(array_data)

        udt_member.name = "gap_{0:X}".format(offset)
        udt_member.type = tmp_tinfo
        udt_member.size = size
        udt_member.offset = offset
        return udt_member
Exemple #18
0
    def load_struct(self):

        name = ""
        while True:
            name = idaapi.ask_str(name, idaapi.HIST_TYPE, "Enter type:")
            if name is None:
                return
            sid = idc.get_struc_id(name)
            if sid != idc.BADADDR:
                break

        self.default_name = name

        sid = idc.get_struc_id(name)
        if sid == idc.BADADDR:
            print(("Invalid Struct Name: %s" % name))
            return

        tif = get_tinfo(name)
        sys.modules["__main__"].tif = tif
        nmembers = tif.get_udt_nmembers()
        for index in range(nmembers):
            u = idaapi.udt_member_t()
            u.offset = index
            if tif.find_udt_member(u, idaapi.STRMEM_INDEX) != -1:
                sys.modules["__main__"].udt = u
                member = Member(u.offset // 8, u.type, None)
                member.name = u.name

                # member.cmt = u.cmt
                # u.cmt doesn't work, so we will do something ugly
                _typename = tif.get_type_name()
                name_sid = idc.get_struc_id(_typename)
                member.cmt = idc.get_member_cmt(
                    name_sid, u.offset // 8,
                    0) or "imported from {}".format(name)

                self.add_row(member)
Exemple #19
0
def get_virtual_func_addresses(name, tinfo=None, offset=None):
    """
    Returns set of possible addresses of virtual function by its name.
    If there're symbols in binary and name is the name of an overloaded function, then returns list of all address of
    this overloaded function.
    TODO: After implementing inheritance return set of methods of all child classes

    :param name: method name, can be mangled
    :param tinfo: class tinfo to which this method belong
    :param offset: virtual table offset
    :return: list of possible addresses
    """

    address = idc.LocByName(name)

    if address != idaapi.BADADDR:
        return [address]

    raw_addresses = cache.demangled_names.get(name)
    if raw_addresses:
        addresses = [ea + idaapi.get_imagebase() for ea in raw_addresses]
        return addresses

    if tinfo is None or offset is None:
        return []

    offset *= 8
    udt_member = idaapi.udt_member_t()
    while tinfo.is_struct():
        address = cache.demangled_names.get(tinfo.dstr() + '::' + name,
                                            idaapi.BADADDR)
        if address != idaapi.BADADDR:
            return [address + idaapi.get_imagebase()]
        udt_member.offset = offset
        tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
        tinfo = udt_member.type
        offset = offset - udt_member.offset
Exemple #20
0
def create_padding_udt_member(offset, size):
    # type: (long, long) -> idaapi.udt_member_t
    """ Creates internal IDA structure with name gap_XXX and appropriate size and offset """

    udt_member = idaapi.udt_member_t()
    udt_member.name = "gap_{0:X}".format(offset)
    udt_member.offset = offset
    udt_member.size = size

    if size == 1:
        udt_member.type = const.BYTE_TINFO
    else:
        if size < 1 or size > 0xffffffff:
            print(
                "HexRaysPyTools::core::helper::create_padding_udt_member: size is out of uint32 range (offset:{} size:{})"
                .format(offset, size))
        array_data = idaapi.array_type_data_t()
        array_data.base = 0
        array_data.elem_type = const.BYTE_TINFO
        array_data.nelems = size
        tmp_tinfo = idaapi.tinfo_t()
        tmp_tinfo.create_array(array_data)
        udt_member.type = tmp_tinfo
    return udt_member
Exemple #21
0
    def activate(self, ctx):
        hx_view = idaapi.get_tform_vdui(ctx.widget)
        result = self.check(hx_view.cfunc, hx_view.item)
        if result is None:
            return

        struct_tinfo, offset, idx = result
        ordinal = struct_tinfo.get_ordinal()
        struct_name = struct_tinfo.dstr()

        if (offset + idx) % 2:
            default_field_type = "_BYTE"
        elif (offset + idx) % 4:
            default_field_type = "_WORD"
        else:
            default_field_type = "_DWORD"

        declaration = idaapi.asktext(
            0x10000, "{0} field_{1:X}".format(default_field_type, offset + idx), "Enter new structure member:"
        )
        if declaration is None:
            return

        result = self.__parse_declaration(declaration)
        if result is None:
            return

        field_tinfo, field_name = result
        field_size = field_tinfo.get_size()
        udt_data = idaapi.udt_type_data_t()
        udt_member = idaapi.udt_member_t()

        struct_tinfo.get_udt_details(udt_data)
        udt_member.offset = offset * 8
        struct_tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
        gap_size = udt_member.size // 8

        gap_leftover = gap_size - idx - field_size

        if gap_leftover < 0:
            print "[ERROR] Too big size for the field. Type with maximum {0} bytes can be used".format(gap_size - idx)
            return

        iterator = udt_data.find(udt_member)
        iterator = udt_data.erase(iterator)

        if gap_leftover > 0:
            udt_data.insert(iterator, TemporaryStructureModel.get_padding_member(offset + idx + field_size, gap_leftover))

        udt_member = idaapi.udt_member_t()
        udt_member.offset = offset * 8 + idx
        udt_member.name = field_name
        udt_member.type = field_tinfo
        udt_member.size = field_size

        iterator = udt_data.insert(iterator, udt_member)

        if idx > 0:
            udt_data.insert(iterator, TemporaryStructureModel.get_padding_member(offset, idx))

        struct_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT)
        struct_tinfo.set_numbered_type(idaapi.cvar.idati, ordinal, idaapi.BTF_STRUCT, struct_name)
        hx_view.refresh_view(True)
Exemple #22
0
def get_member_name(tinfo, offset):
    udt_member = idaapi.udt_member_t()
    udt_member.offset = offset * 8
    tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)
    return udt_member.name
Exemple #23
0
    def activate(self, ctx):
        hx_view = idaapi.get_tform_vdui(ctx.form)
        result = self.check(hx_view.cfunc, hx_view.item)

        if result:
            if result[0] == RECAST_LOCAL_VARIABLE:
                tinfo, lvar = result[1:]
                if hx_view.set_lvar_type(lvar, tinfo):
                    hx_view.refresh_view(True)

            elif result[0] == RECAST_GLOBAL_VARIABLE:
                tinfo, address = result[1:]
                if idaapi.apply_tinfo2(address, tinfo, idaapi.TINFO_DEFINITE):
                    hx_view.refresh_view(True)

            elif result[0] == RECAST_ARGUMENT:
                arg_index, func_tinfo, arg_tinfo, address = result[1:]

                func_data = idaapi.func_type_data_t()
                func_tinfo.get_func_details(func_data)
                func_data[arg_index].type = arg_tinfo
                new_func_tinfo = idaapi.tinfo_t()
                new_func_tinfo.create_func(func_data)
                if idaapi.apply_tinfo2(address, new_func_tinfo,
                                       idaapi.TINFO_DEFINITE):
                    hx_view.refresh_view(True)

            elif result[0] == RECAST_RETURN:
                return_type, func_address = result[1:]
                try:
                    cfunc = idaapi.decompile(
                        func_address) if func_address else hx_view.cfunc
                except idaapi.DecompilationFailure:
                    print "[ERROR] Ida failed to decompile function"
                    return

                function_tinfo = idaapi.tinfo_t()
                cfunc.get_func_type(function_tinfo)
                func_data = idaapi.func_type_data_t()
                function_tinfo.get_func_details(func_data)
                func_data.rettype = return_type
                function_tinfo.create_func(func_data)
                if idaapi.apply_tinfo2(cfunc.entry_ea, function_tinfo,
                                       idaapi.TINFO_DEFINITE):
                    hx_view.refresh_view(True)

            elif result[0] == RECAST_STRUCTURE:
                structure_name, field_offset, new_type = result[1:]
                tinfo = idaapi.tinfo_t()
                tinfo.get_named_type(idaapi.cvar.idati, structure_name)

                ordinal = idaapi.get_type_ordinal(idaapi.cvar.idati,
                                                  structure_name)

                if ordinal:
                    udt_member = idaapi.udt_member_t()
                    udt_member.offset = field_offset * 8
                    idx = tinfo.find_udt_member(idaapi.STRMEM_OFFSET,
                                                udt_member)
                    if udt_member.offset != field_offset * 8:
                        print "[Info] Can't handle with arrays yet"
                    elif udt_member.type.get_size() != new_type.get_size():
                        print "[Info] Can't recast different sizes yet"
                    else:
                        udt_data = idaapi.udt_type_data_t()
                        tinfo.get_udt_details(udt_data)
                        udt_data[idx].type = new_type
                        tinfo.create_udt(udt_data, idaapi.BTF_STRUCT)
                        tinfo.set_numbered_type(idaapi.cvar.idati, ordinal,
                                                idaapi.NTF_REPLACE,
                                                structure_name)
                        hx_view.refresh_view(True)
def hexrays_events_callback(*args):
    global potential_negatives

    hexrays_event = args[0]

    if hexrays_event == idaapi.hxe_populating_popup:
        form, popup, hx_view = args[1:]
        item = hx_view.item  # current ctree_item_t

        if Actions.RecastItemRight.check(hx_view.cfunc, item):
            idaapi.attach_action_to_popup(form, popup, Actions.RecastItemRight.name, None)

        if Actions.RecastItemLeft.check(hx_view.cfunc, item):
            idaapi.attach_action_to_popup(form, popup, Actions.RecastItemLeft.name, None)

        if Actions.RenameOther.check(hx_view.cfunc, item):
            idaapi.attach_action_to_popup(form, popup, Actions.RenameOther.name, None)

        if Actions.RenameInside.check(hx_view.cfunc, item):
            idaapi.attach_action_to_popup(form, popup, Actions.RenameInside.name, None)

        if Actions.RenameOutside.check(hx_view.cfunc, item):
            idaapi.attach_action_to_popup(form, popup, Actions.RenameOutside.name, None)

        if hx_view.item.get_lvar() and Helper.is_legal_type(hx_view.item.get_lvar().type()):
            idaapi.attach_action_to_popup(form, popup, Actions.ShallowScanVariable.name, None)
            idaapi.attach_action_to_popup(form, popup, Actions.DeepScanVariable.name, None)
            idaapi.attach_action_to_popup(form, popup, Actions.RecognizeShape.name, None)

        if item.citype == idaapi.VDI_FUNC:
            # If we clicked on function
            if not hx_view.cfunc.entry_ea == idaapi.BADADDR:  # Probably never happen
                idaapi.attach_action_to_popup(form, popup, Actions.AddRemoveReturn.name, None)
                idaapi.attach_action_to_popup(form, popup, Actions.ConvertToUsercall.name, None)
                idaapi.attach_action_to_popup(form, popup, Actions.DeepScanReturn.name, None)

        elif item.citype == idaapi.VDI_LVAR:
            # If we clicked on argument
            local_variable = hx_view.item.get_lvar()          # idaapi.lvar_t
            if local_variable.is_arg_var:
                idaapi.attach_action_to_popup(form, popup, Actions.RemoveArgument.name, None)

        elif item.citype == idaapi.VDI_EXPR:
            if item.e.op == idaapi.cot_num:
                # number_format = item.e.n.nf                       # idaapi.number_format_t
                # print "(number) flags: {0:#010X}, type_name: {1}, opnum: {2}".format(
                #     number_format.flags,
                #     number_format.type_name,
                #     number_format.opnum
                # )
                idaapi.attach_action_to_popup(form, popup, Actions.GetStructureBySize.name, None)
            elif item.e.op == idaapi.cot_var:
                # Check if we clicked on variable that is a pointer to a structure that is potentially part of
                # containing structure
                if item.e.v.idx in potential_negatives:
                    idaapi.attach_action_to_popup(form, popup, Actions.SelectContainingStructure.name, None)
                if Actions.ResetContainingStructure.check(hx_view.cfunc.get_lvars()[item.e.v.idx]):
                    idaapi.attach_action_to_popup(form, popup, Actions.ResetContainingStructure.name, None)

    elif hexrays_event == idaapi.hxe_double_click:

        hx_view = args[1]
        item = hx_view.item
        if item.citype == idaapi.VDI_EXPR and item.e.op == idaapi.cot_memptr:
            # Look if we double clicked on expression that is member pointer. Then get tinfo_t of  the structure.
            # After that remove pointer and get member name with the same offset

            if item.e.x.op == idaapi.cot_memref and item.e.x.x.op == idaapi.cot_memptr:
                vtable_tinfo = item.e.x.type.get_pointed_object()
                method_offset = item.e.m
                class_tinfo = item.e.x.x.x.type.get_pointed_object()
                vtable_offset = item.e.x.x.m
            elif item.e.x.op == idaapi.cot_memptr:
                vtable_tinfo = item.e.x.type.get_pointed_object()
                method_offset = item.e.m
                class_tinfo = item.e.x.x.type.get_pointed_object()
                vtable_offset = item.e.x.m
            else:
                return 0

            udt_member = idaapi.udt_member_t()
            udt_member.offset = method_offset * 8
            vtable_tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)

            func_ea = Helper.get_virtual_func_address(udt_member.name, class_tinfo, vtable_offset)
            if func_ea:
                idaapi.open_pseudocode(func_ea, 0)
                return 1

    elif hexrays_event == idaapi.hxe_maturity:
        cfunc, level_of_maturity = args[1:]

        if level_of_maturity == idaapi.CMAT_BUILT:
            # print '=' * 40
            # print '=' * 15, "LEVEL", level_of_maturity, '=' * 16
            # print '=' * 40
            # print cfunc

            # First search for CONTAINING_RECORD made by Ida
            visitor = NegativeOffsets.SearchVisitor(cfunc)
            visitor.apply_to(cfunc.body, None)
            negative_lvars = visitor.result

            # Second get saved information from comments
            lvars = cfunc.get_lvars()
            for idx in xrange(len(lvars)):
                result = NegativeOffsets.parse_lvar_comment(lvars[idx])
                if result and result.tinfo.equals_to(lvars[idx].type().get_pointed_object()):
                    negative_lvars[idx] = result

            # Third make an analysis of local variables that a structure pointers and have reference that pass
            # through structure boundaries. This variables will be considered as potential pointers to substructure
            # and will get a menu on right click that helps to select Containing Structure from different libraries

            structure_pointer_variables = {}
            for idx in set(range(len(lvars))) - set(negative_lvars.keys()):
                if lvars[idx].type().is_ptr():
                    pointed_tinfo = lvars[idx].type().get_pointed_object()
                    if pointed_tinfo.is_udt():
                        structure_pointer_variables[idx] = pointed_tinfo

            if structure_pointer_variables:
                visitor = NegativeOffsets.AnalyseVisitor(structure_pointer_variables, potential_negatives)
                visitor.apply_to(cfunc.body, None)

            if negative_lvars:
                visitor = NegativeOffsets.ReplaceVisitor(negative_lvars)
                visitor.apply_to(cfunc.body, None)

        elif level_of_maturity == idaapi.CMAT_TRANS2:
            # print '=' * 40
            # print '=' * 15, "LEVEL", level_of_maturity, '=' * 16
            # print '=' * 40
            # print cfunc
            visitor = SpaghettiVisitor()
            visitor.apply_to(cfunc.body, None)
    return 0
def hexrays_events_callback(*args):
    if fDebug:
        pydevd.settrace('localhost', port=31337, stdoutToServer=True, stderrToServer=True, suspend=False)
    hexrays_event = args[0]
    from HexRaysPyTools.Config import hex_pytools_config
    if hexrays_event == idaapi.hxe_populating_popup:
        form, popup, hx_view = args[1:]
        item = hx_view.item  # current ctree_item_t

        for ac in hex_pytools_config.actions_refs.values():
            if ac.ForPopup and hex_pytools_config[ac.name] and ac.check(hx_view.cfunc,item):
                idaapi.attach_action_to_popup(form, popup, ac.name, None)

        # if Actions.RecastStructMember.check(hx_view.cfunc,item):
        #     if hex_pytools_config[Actions.RecastStructMember.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.RecastStructMember.name, None)
        #
        # if Actions.SimpleCreateStruct.check(hx_view.cfunc,item):
        #     if hex_pytools_config[Actions.SimpleCreateStruct.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.SimpleCreateStruct.name, None)
        #
        # if Actions.RecastItemRight.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.RecastItemRight.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.RecastItemRight.name, None)
        #
        # if Actions.RecastItemLeft.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.RecastItemLeft.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.RecastItemLeft.name, None)
        #
        # if Actions.RenameOther.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.RenameOther.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.RenameOther.name, None)
        #
        # if Actions.RenameInside.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.RenameInside.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.RenameInside.name, None)
        #
        # if Actions.RenameOutside.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.RenameOutside.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.RenameOutside.name, None)
        #
        # if Actions.SwapThenElse.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.SwapThenElse.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.SwapThenElse.name, None)
        #
        # if Actions.ShallowScanVariable.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.ShallowScanVariable.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.ShallowScanVariable.name, None)
        #     if hex_pytools_config[Actions.DeepScanVariable.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.DeepScanVariable.name, None)
        #     if hex_pytools_config[Actions.RecognizeShape.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.RecognizeShape.name, None)
        #
        # if Actions.CreateNewField.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.CreateNewField.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.CreateNewField.name, None)
        #
        # if Actions.CreateVtable.check(hx_view.cfunc, item):
        #     if hex_pytools_config[Actions.CreateVtable.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.CreateVtable.name, None)
        #
        # if Actions.AddRemoveReturn.check(hx_view.cfunc, item) and hex_pytools_config[Actions.AddRemoveReturn.name]:
        #     idaapi.attach_action_to_popup(form, popup, Actions.AddRemoveReturn.name, None)
        # if Actions.ConvertToUsercall.check(hx_view.cfunc, item) and hex_pytools_config[Actions.ConvertToUsercall.name]:
        #     idaapi.attach_action_to_popup(form, popup, Actions.ConvertToUsercall.name, None)
        # if Actions.DeepScanReturn.check(hx_view.cfunc, item) and hex_pytools_config[Actions.DeepScanReturn.name]:
        #     idaapi.attach_action_to_popup(form, popup, Actions.DeepScanReturn.name, None)
        #
        # if Actions.RemoveArgument.check(hx_view.cfunc,item) and hex_pytools_config[Actions.RemoveArgument.name]:
        #     idaapi.attach_action_to_popup(form, popup, Actions.RemoveArgument.name, None)
        #
        # if Actions.GetStructureBySize.check(hx_view.cfunc,item) and hex_pytools_config[Actions.GetStructureBySize.name]:
        #     idaapi.attach_action_to_popup(form, popup, Actions.GetStructureBySize.name, None)
        #
        # if Actions.SelectContainingStructure.check(hx_view.cfunc,item) and hex_pytools_config[Actions.SelectContainingStructure.name]:
        #     idaapi.attach_action_to_popup(form, popup, Actions.SelectContainingStructure.name, None)
        #
        # if Actions.ResetContainingStructure.check(hx_view.cfunc,item):
        #     if hex_pytools_config[Actions.ResetContainingStructure.name]:
        #         idaapi.attach_action_to_popup(form, popup, Actions.ResetContainingStructure.name, None)

    elif hexrays_event == idaapi.hxe_double_click:

        hx_view = args[1]
        item = hx_view.item
        if item.citype == idaapi.VDI_EXPR and item.e.op == idaapi.cot_memptr:
            # Look if we double clicked on expression that is member pointer. Then get tinfo_t of  the structure.
            # After that remove pointer and get member name with the same offset

            if item.e.x.op == idaapi.cot_memref and item.e.x.x.op == idaapi.cot_memptr:
                vtable_tinfo = item.e.x.type.get_pointed_object()
                method_offset = item.e.m
                class_tinfo = item.e.x.x.x.type.get_pointed_object()
                vtable_offset = item.e.x.x.m
            elif item.e.x.op == idaapi.cot_memptr:
                vtable_tinfo = item.e.x.type.get_pointed_object()
                method_offset = item.e.m
                class_tinfo = item.e.x.x.type.get_pointed_object()
                vtable_offset = item.e.x.m
            else:
                return 0
            #print vtable_tinfo.get_type_name()
            #print method_offset
            udt_member = idaapi.udt_member_t()
            udt_member.offset = method_offset * 8
            vtable_tinfo.find_udt_member(idaapi.STRMEM_OFFSET, udt_member)

            func_ea = Helper.get_virtual_func_address(udt_member.name, class_tinfo, vtable_offset)
            if func_ea:
                idaapi.open_pseudocode(func_ea, 0)
                return 1
            n = Netnode("$ VTables")
            vt_name = vtable_tinfo.get_type_name()
            if vt_name in n:
                l = n[vt_name]
                #print l
                info = idaapi.get_inf_structure()
                if info.is_32bit():
                    ptr_size = 4
                elif info.is_64bit():
                    ptr_size = 8
                else:
                    ptr_size = 2
                if method_offset%ptr_size == 0 and method_offset/ptr_size < len(l):
                    idaapi.open_pseudocode(l[method_offset/ptr_size] + idaapi.get_imagebase(), 0)


    elif hexrays_event == idaapi.hxe_maturity:
        cfunc, level_of_maturity = args[1:]

        if level_of_maturity == idaapi.CMAT_BUILT:
            # print '=' * 40
            # print '=' * 15, "LEVEL", level_of_maturity, '=' * 16
            # print '=' * 40
            # print cfunc

            # First search for CONTAINING_RECORD made by Ida
            visitor = NegativeOffsets.SearchVisitor(cfunc)
            visitor.apply_to(cfunc.body, None)
            negative_lvars = visitor.result

            # Second get saved information from comments
            lvars = cfunc.get_lvars()
            for idx in xrange(len(lvars)):
                result = NegativeOffsets.parse_lvar_comment(lvars[idx])
                if result and result.tinfo.equals_to(lvars[idx].type().get_pointed_object()):
                    negative_lvars[idx] = result

            # Third make an analysis of local variables that a structure pointers and have reference that pass
            # through structure boundaries. This variables will be considered as potential pointers to substructure
            # and will get a menu on right click that helps to select Containing Structure from different libraries

            structure_pointer_variables = {}
            for idx in set(range(len(lvars))) - set(negative_lvars.keys()):
                if lvars[idx].type().is_ptr():
                    pointed_tinfo = lvars[idx].type().get_pointed_object()
                    if pointed_tinfo.is_udt():
                        structure_pointer_variables[idx] = pointed_tinfo

            if structure_pointer_variables:
                visitor = NegativeOffsets.AnalyseVisitor(structure_pointer_variables, potential_negatives)
                visitor.apply_to(cfunc.body, None)

            if negative_lvars:
                visitor = NegativeOffsets.ReplaceVisitor(negative_lvars)
                visitor.apply_to(cfunc.body, None)

        elif level_of_maturity == idaapi.CMAT_TRANS1:

            visitor = SwapThenElseVisitor(cfunc.entry_ea)
            visitor.apply_to(cfunc.body, None)

        elif level_of_maturity == idaapi.CMAT_TRANS2:
            return 0
            # print '=' * 15, "LEVEL", level_of_maturity, '=' * 16
            # print '=' * 40
            # print cfunc
            visitor = SpaghettiVisitor()
            visitor.apply_to(cfunc.body, None)
    return 0
Exemple #26
0
    def activate(self, ctx):
        hx_view = idaapi.get_widget_vdui(ctx.widget)
        if not self.check(hx_view):
            return

        item = hx_view.item.it.to_specific_type
        parent = hx_view.cfunc.body.find_parent_of(item).to_specific_type
        if parent.op != idaapi.cot_idx or parent.y.op != idaapi.cot_num:
            idx = 0
        else:
            idx = parent.y.numval()

        struct_tinfo = item.x.type
        struct_tinfo.remove_ptr_or_array()

        offset = item.m
        ordinal = struct_tinfo.get_ordinal()
        struct_name = struct_tinfo.dstr()

        if (offset + idx) % 2:
            default_field_type = "_BYTE"
        elif (offset + idx) % 4:
            default_field_type = "_WORD"
        elif (offset + idx) % 8:
            default_field_type = "_DWORD"
        else:
            default_field_type = "_QWORD" if const.EA64 else "_DWORD"

        declaration = idaapi.ask_text(
            0x10000, "{0} field_{1:X}".format(default_field_type, offset + idx), "Enter new structure member:"
        )
        if declaration is None:
            return

        result = self.parse_declaration(declaration)
        if result is None:
            logger.warn("Bad member declaration")
            return

        field_tinfo, field_name = result
        field_size = field_tinfo.get_size()
        udt_data = idaapi.udt_type_data_t()
        udt_member = idaapi.udt_member_t()

        struct_tinfo.get_udt_details(udt_data)
        udt_member.offset = offset * 8
        struct_tinfo.find_udt_member(udt_member, idaapi.STRMEM_OFFSET)
        gap_size = udt_member.size // 8

        gap_leftover = gap_size - idx - field_size

        if gap_leftover < 0:
            logger.error("Too big size for the field. Type with maximum {0} bytes can be used".format(gap_size - idx))
            return

        iterator = udt_data.find(udt_member)
        iterator = udt_data.erase(iterator)

        if gap_leftover > 0:
            udt_data.insert(iterator, helper.create_padding_udt_member(offset + idx + field_size, gap_leftover))

        udt_member = idaapi.udt_member_t()
        udt_member.offset = offset * 8 + idx
        udt_member.name = field_name
        udt_member.type = field_tinfo
        udt_member.size = field_size

        iterator = udt_data.insert(iterator, udt_member)

        if idx > 0:
            udt_data.insert(iterator, helper.create_padding_udt_member(offset, idx))

        struct_tinfo.create_udt(udt_data, idaapi.BTF_STRUCT)
        struct_tinfo.set_numbered_type(idaapi.cvar.idati, ordinal, idaapi.BTF_STRUCT, struct_name)
        hx_view.refresh_view(True)