Beispiel #1
0
def parse(info):
    '''Parse the string `info` into an ``idaapi.tinfo_t``.'''
    if idaapi.__version__ < 7.0:
        til, ti = idaapi.cvar.idati, idaapi.tinfo_t(),
    else:
        til, ti = idaapi.get_idati(), idaapi.tinfo_t(),

    # Convert info to a string if it's a tinfo_t
    info_s = "{!s}".format(info) if isinstance(info, idaapi.tinfo_t) else info

    # Firstly we need to ';'-terminate the type the user provided in order
    # for IDA's parser to understand it.
    terminated = info_s if info_s.endswith(';') else "{:s};".format(info_s)

    # Ask IDA to parse this into a tinfo_t for us. We pass the silent flag so
    # that we're responsible for raising an exception if there's a parsing
    # error of some sort. If it succeeds, then we can return our typeinfo.
    # Otherwise we return None because of the inability to parse it.
    if idaapi.__version__ < 6.9:
        return None if idaapi.parse_decl2(til, terminated, None, ti,
                                          idaapi.PT_SIL) is None else ti
    elif idaapi.__version__ < 7.0:
        return None if idaapi.parse_decl2(til, terminated, ti,
                                          idaapi.PT_SIL) is None else ti
    return None if idaapi.parse_decl(ti, til, terminated,
                                     idaapi.PT_SIL) is None else ti
def make_basic_structs():
    strucid = ida_struct.get_struc_id("Vector")
    if strucid == idc.BADADDR:
        struc = ida_struct.get_struc(
            ida_struct.add_struc(idc.BADADDR, "Vector"))
        ida_struct.add_struc_member(struc, "x", idc.BADADDR, idc.FF_DWRD, None,
                                    4)
        ida_struct.add_struc_member(struc, "y", idc.BADADDR, idc.FF_DWRD, None,
                                    4)
        ida_struct.add_struc_member(struc, "z", idc.BADADDR, idc.FF_DWRD, None,
                                    4)

    global VECTOR
    VECTOR = idaapi.tinfo_t()
    idaapi.parse_decl2(None, "Vector;", VECTOR, 0)

    strucid = ida_struct.get_struc_id("QAngle")
    if strucid == idc.BADADDR:
        struc = ida_struct.get_struc(
            ida_struct.add_struc(idc.BADADDR, "QAngle"))
        ida_struct.add_struc_member(struc, "x", idc.BADADDR, idc.FF_DWRD, None,
                                    4)
        ida_struct.add_struc_member(struc, "y", idc.BADADDR, idc.FF_DWRD, None,
                                    4)
        ida_struct.add_struc_member(struc, "z", idc.BADADDR, idc.FF_DWRD, None,
                                    4)
Beispiel #3
0
    def _replace_with_check_helper(self, ctx, l): # type: (...) -> None
        type_name_ea = ctx.type_info_obj.obj_ea
        name = idaapi.demangle_name(idaapi.get_name(type_name_ea), 0)
        if not name:
            name = idaapi.get_name(type_name_ea)

        type_name = name
        var_type = None
        if "::getRuntimeTypeInfoStatic(void)::typeInfo" in name:
            type_name = name.split("::getRuntimeTypeInfoStatic(void)::typeInfo")[0]
            var_type = idaapi.tinfo_t()
            idaapi.parse_decl2(idaapi.cvar.idati, type_name + "*;", var_type, idaapi.PT_TYP)
            if not str(var_type):
                var_type = None

        call_expr = make_helper_call("void*", "dynamic_cast<" + type_name + ">", ["void*"])
        call_expr.a.push_back(make_carg_t(ctx.original_var))

        asg_expr = hr.cexpr_t()
        asg_expr.op = hr.cot_asg
        asg_expr.x = hr.cexpr_t()
        asg_expr.x.assign(ctx.dynamic_cast_var)
        asg_expr.y = call_expr
        asg_expr.type = var_type if var_type else idaapi.tinfo_t(idaapi.BT_VOID)

        if var_type:
            self._types_to_set.append((ctx.dynamic_cast_var.v.idx, var_type))

        replace_expr_with(l[0].cexpr, asg_expr)
        for item in l[1:]:
            item.cleanup()
Beispiel #4
0
    def run(self, vu, tree, parent): # type: (...) -> None
        class ctx:
            string_vidx = int()

        def is_string_vtable_assignment(c, p): # type: (...) -> bool
            if c.op != hr.cot_asg:
                return False

            lhs = c.x
            if lhs.op != hr.cot_var:
                return False
            pointed_type = lhs.type.get_pointed_object()
            if not pointed_type or pointed_type.get_type_name() != SAFESTRINGBASE_VTABLE_STRUCT_NAME:
                return False

            rhs = c.y
            if rhs.op != hr.cot_ref:
                return False
            if rhs.x.op != hr.cot_obj:
                return False

            ctx.string_vidx = lhs.v.idx
            return True

        cv = ConstraintVisitor([ConstraintChecker(is_string_vtable_assignment)], "ctor")
        variables = [] # type: typing.List[int]
        cv.match(tree, parent, lambda l: variables.append(ctx.string_vidx))
        t = idaapi.tinfo_t()
        idaapi.parse_decl2(idaapi.cvar.idati, "sead::SafeString;", t, idaapi.PT_TYP)
        for vidx in variables:
            vu.set_lvar_type(vu.cfunc.get_lvars()[vidx], t)
def import_vtable(classname, struc):
    ea = get_vtable(classname)
    if ea == idc.BADADDR:
        return

    # Mildly adapted from Asherkin's vtable dumper
    ea = ea + 8  # Skip typeinfo and thisoffs

    funcs = []
    while ea != idc.BADADDR:
        offs = idc.get_wide_dword(ea)
        if not ida_bytes.is_code(ida_bytes.get_full_flags(offs)):
            break
        name = idc.get_name(offs, ida_name.GN_VISIBLE)
        funcs.append(name)

        ea = ida_bytes.next_not_tail(ea)


#	print(funcs)

    if not len(funcs):
        return

    strucid = add_struc_ex2(classname + "_vftable")
    vstruc = ida_struct.get_struc(strucid)
    for i in funcs:
        # Gotta do a fancy demangle, it can't have special chars
        # and there can't be multiples of the same name, so let's just jazz around all of that
        demangled = idc.demangle_name(i, idc.get_inf_attr(idc.INF_SHORT_DN))
        if demangled == None:
            demangled = i
        else:
            demangled = demangled[demangled.find("::") + 2:demangled.find("(")]
            demangled = demangled.replace("~",
                                          "_").replace("<",
                                                       "_").replace(">", "_")
        while 1:
            error = ida_struct.add_struc_member(vstruc, demangled, idc.BADADDR,
                                                idc.FF_DWRD, None, 4)

            if error == 0:
                break

            demangled = demangled + "_"  # This is dumb but lol

    # Now assign the vtable to the actual struct
    ti = idaapi.tinfo_t()
    idaapi.parse_decl2(None, classname + "_vftable;", ti, 0)
    ti.create_ptr(ti)
    ida_struct.set_member_tinfo(struc, ida_struct.get_member(struc, 0), 0, ti,
                                0)
Beispiel #6
0
def test_xx(idx, ctx):
    import ida_typeinf
    uni = ctx.get_expr('union_type')
    var = ctx.get_var('v1')
    tname = var.typ.dstr().split(' ')[0]
    tinfo = idaapi.tinfo_t()
    if tname == 'class1':
        idaapi.parse_decl2(idaapi.cvar.idati, 'vptr1_1 *;', tinfo,
                           idaapi.PT_TYP)
        uni[0].type = tinfo
        uni[0].m = 0
    elif tname == "class2":
        idaapi.parse_decl2(idaapi.cvar.idati, 'struc_5 *;', tinfo,
                           idaapi.PT_TYP)
        uni[0].type = tinfo
        uni[0].m = 1
Beispiel #7
0
def parse_decl(arg):
    '''str -> tinfo_t'''
    ti = idaapi.tinfo_t()
    success = idaapi.parse_decl2(idaapi.cvar.idati, arg + ';', '', ti, 0)
    if success is False:
        raise ParseDeclError("%s: couldn't parse type" % arg)
    return ti
Beispiel #8
0
 def getUserDeclType(self, decl):
     tinfo = idaapi.tinfo_t()
     ret = idaapi.parse_decl2(idaapi.cvar.idati, decl, 'blah', tinfo, 0)
     if not ret:
         self.logger.info('parse_decl2 failed')
         return None
     return tinfo
Beispiel #9
0
def parse_decl(arg):
    '''str -> tinfo_t'''
    ti = idaapi.tinfo_t()
    success = idaapi.parse_decl2(idaapi.cvar.idati, arg + ';', '', ti, 0)
    if success is False:
        raise ParseDeclError("%s: couldn't parse type" % arg)
    return ti
Beispiel #10
0
    def activate(self, ctx):
        sel = []
        for idx in ctx.chooser_selection:
            # rename the function
            ea = get_name_ea_simple(self.items[idx][2])
            sfname = str(self.items[idx][4])
            #set_name(ea, sfname)
            idaapi.do_name_anyway(ea, sfname)
            success('{:#x}: renamed to {}'.format(ea, sfname))
            # set the function prototype
            sptype = str(self.items[idx][5])
            if sptype != 'None':
                tinfo = idaapi.tinfo_t()
                idaapi.parse_decl2(idaapi.cvar.idati, sptype, tinfo, 0)
                #idaapi.apply_callee_tinfo(ea, tinfo)
                if idaapi.apply_tinfo(ea, tinfo, 0):
                    success('{:#x}: function prototype set to {}'.format(
                        ea, sptype))
                else:
                    error(
                        '{:#x}: function prototype set FAILED (maybe you should import the types?)'
                        .format(ea))
                    if ask_yn(0, 'Do you import types from the secondary idb?'
                              ) == 1:
                        if self.import_types():
                            tinfo = idaapi.tinfo_t()
                            idaapi.parse_decl2(idaapi.cvar.idati, sptype,
                                               tinfo, 0)
                            if idaapi.apply_tinfo(ea, tinfo, 0):
                                success('{:#x}: function prototype set to {}'.
                                        format(ea, sptype))
                            else:
                                error(
                                    '{:#x}: function prototype set FAILED again'
                                    .format(ea))

            # insert the comment
            score = self.items[idx][0]
            mmatch = self.items[idx][1]
            cmt = 'fn_fuzzy: ssdeep={}, machoc={}'.format(score, mmatch)
            set_func_cmt(ea, cmt, 1)
            #set_decomplier_cmt(ea, cmt) # not sure how to avoid orphan comment

        # update the Choose rows
        ida_kernwin.refresh_chooser(self.title)
Beispiel #11
0
 def getUserDeclType(self, decl):
     tinfo = idaapi.tinfo_t()
     #self.logger.debug('Trying to parse declaration: %r', decl)
     ret = idaapi.parse_decl2(idaapi.cvar.idati, decl, tinfo, idaapi.PT_TYP)
     #self.logger.debug('Return from parse_decl2: %r', ret)
     if ret is None:
         self.logger.info('parse_decl2 failed')
         return None
     return tinfo
Beispiel #12
0
 def getUserDeclType(self, decl):
     tinfo = idaapi.tinfo_t()
     #logger.debug('Trying to parse declaration: %r', decl)
     ret = idaapi.parse_decl2(idaapi.cvar.idati, decl, tinfo, idaapi.PT_TYP)
     #logger.debug('Return from parse_decl2: %r', ret)
     if ret is None:
         logger.info('parse_decl2 failed')
         return None
     return tinfo
Beispiel #13
0
def make_helper_call(ret_type, name, arg_types): # type: (str, str, typing.List[str]) -> hr.cexpr_t
    """Make a call expression to a helper function (non-existing function with arbitrary name)."""

    helper_expr = hr.cexpr_t()
    helper_expr.ea = idaapi.BADADDR
    helper_expr.op = hr.cot_helper
    helper_expr.helper = name

    call_expr = hr.cexpr_t()
    call_expr.op = hr.cot_call
    call_expr.x = helper_expr
    call_expr.a = hr.carglist_t()

    # EXTREMELY IMPORTANT: set the expression types. Without this, Hex-Rays will crash
    # in mysterious ways.
    t = idaapi.tinfo_t()
    idaapi.parse_decl2(idaapi.cvar.idati, "%s (__cdecl *)(%s);" % (ret_type, ','.join(arg_types)),
                       t, idaapi.PT_TYP)
    helper_expr.type = t
    call_expr.a.functype = t
    call_expr.type = t.get_rettype()

    return call_expr
Beispiel #14
0
 def setData(self, column, value):
     if column == 0:
         if idaapi.isident(value) and self.name != value:
             self.name = value
             self.name_modified = True
             for parent in self.parents:
                 parent.modified = True
             return True
     elif column == 1:
         tinfo = idaapi.tinfo_t()
         split = value.split('(')
         if len(split) == 2:
             value = split[0] + ' ' + self.name + '(' + split[1] + ';'
             if idaapi.parse_decl2(idaapi.cvar.idati, value, '', tinfo, idaapi.PT_TYP):
                 if tinfo.is_func():
                     tinfo.create_ptr(tinfo)
                     if tinfo.dstr() != self.tinfo.dstr():
                         self.tinfo = tinfo
                         self.tinfo_modified = True
                         for parent in self.parents:
                             parent.modified = True
                         return True
     return False
Beispiel #15
0
def parse(c, struc):
    if c.tag == "sendtable":
        if c.attrib.get("name", None) and c.attrib.get("name",
                                                       None).startswith("DT_"):
            for i in c:
                parse(i, struc)
    elif c.tag == "property":
        classname = c.attrib.get("name", None)
        if classname != None:
            if classname == "baseclass":
                for p in c:
                    parse(p, struc)
            else:
                t = c.find("type")
                if t == None:
                    return

                offset = c.find("offset")
                offset = int(offset.text) if offset != None else None
                if offset == None or offset is 0:
                    return

                # Have to be a little special with datatables
                if t.text == "datatable":
                    ida_struct.add_struc_member(struc, classname, offset,
                                                idc.FF_DWRD, None, 4)
                    sendtable = c.find("sendtable")
                    if sendtable != None:
                        mycls = sendtable.attrib.get("name", None)
                        if mycls != None:
                            if mycls.startswith("DT_"):
                                mycls = mycls.replace("DT_", "C", 1)
                                strucid = ida_struct.get_struc_id(mycls)
                                if strucid == idc.BADADDR:  # If this struct didn't exist, parse it
                                    strucid = ida_struct.add_struc(
                                        idc.BADADDR, mycls)
                                    parse(sendtable,
                                          ida_struct.get_struc(strucid))
                                ti = idaapi.tinfo_t(
                                )  # Assign the sendtable type to the struct
                                idaapi.parse_decl2(None, mycls + ";", ti, 0)
                                if str(
                                        ti
                                ) != "CAttributeList":  # HACK; this one doesn't work and idk what else to try
                                    ida_struct.set_member_tinfo(
                                        struc,
                                        ida_struct.get_member(struc, offset),
                                        0, ti, 0)
                            else:  # Iterate the array and update the struct member size, hackily
                                flag, sizemult = get_sendtable_size(sendtable)
                                if sizemult > 4:
                                    ida_struct.set_member_type(
                                        struc, offset, flag, None, sizemult)
                    return

                sz = c.find("bits")
                sz = int(sz.text) if sz != None else None
                if sz == None:
                    return

                flags, numbytes = calcszdata(sz)

                #				if t.text == "float":
                #					flags |= idc.FF_FLOAT

                #				print(idc.FF_BYTE, idc.FF_DWRD)
                #				print(flags, numbytes)

                if t.text == "vector":
                    ida_struct.add_struc_member(struc, classname, offset,
                                                idc.FF_DWRD, None, 12)
                    global VECTOR
                    ida_struct.set_member_tinfo(
                        struc, ida_struct.get_member(struc, offset), 0, VECTOR,
                        0)
                else:
                    returnval = ida_struct.add_struc_member(
                        struc, classname, offset, flags, None, numbytes)
                    if returnval:
                        print("Could not add struct member {}.{}! Error {}".
                              format(ida_struct.get_struc_name(struc.id),
                                     classname, returnval))
def set_member_type_info(struc, member, decl):
    ti = idaapi.tinfo_t()
    idaapi.parse_decl2(None, decl, ti, 0)
    idaapi.set_member_tinfo(struc, member, 0, ti, 0)