예제 #1
0
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_FLOAT,
                                    None, 4)
        ida_struct.add_struc_member(struc, "y", idc.BADADDR, idc.FF_FLOAT,
                                    None, 4)
        ida_struct.add_struc_member(struc, "z", idc.BADADDR, idc.FF_FLOAT,
                                    None, 4)

    global VECTOR
    VECTOR = idaapi.tinfo_t()
    idaapi.parse_decl(VECTOR, None, "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_FLOAT,
                                    None, 4)
        ida_struct.add_struc_member(struc, "y", idc.BADADDR, idc.FF_FLOAT,
                                    None, 4)
        ida_struct.add_struc_member(struc, "z", idc.BADADDR, idc.FF_FLOAT,
                                    None, 4)
예제 #2
0
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_ex(classname + "_vtbl")
    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_DWORD, None, 4)

            if error == 0:
                break

            demangled += "_{}".format(
                hex(ida_struct.get_struc_last_offset(vstruc) * 4 + 4)[2:])

    # Now assign the vtable to the actual struct
    ti = idaapi.tinfo_t()
    idaapi.parse_decl(ti, None, classname + "_vtbl;", 0)
    ti.create_ptr(ti)
    ida_struct.set_member_tinfo(struc, ida_struct.get_member(struc, 0), 0, ti,
                                0)
예제 #3
0
def import_vtable(typename, funcs):
	typestrucid = add_struc_ex(typename)
	typestruc = ida_struct.get_struc(typestrucid)
	vstrucid = add_struc_ex(typename + "_vtbl")
	vstruc = ida_struct.get_struc(vstrucid)

	loffs = ida_struct.get_struc_last_offset(vstruc)
	if loffs != idc.BADADDR:
		ida_struct.del_struc_members(vstruc, 0, loffs + 4)

	for i in funcs:
		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("(")]
			# As per https://stackoverflow.com/questions/3411771/best-way-to-replace-multiple-characters-in-a-string
			# this isn't as slow as you'd think
			demangled = demangled\
				.replace("~", "_")\
				.replace("<", "_")\
				.replace(">", "_")\
				.replace(",", "_")\
				.replace("*", "_")\
				.replace(" ", "_")\
				.replace("operator==", "__eq__")\
				.replace("operator+", "__add__")\
				.replace("operator-", "__sub__")\
				.replace("operator*", "__mul__")\
				.replace("operator/", "__div__")\
				.replace("operator%", "__mod__")\
				.replace("operator<<", "__lshift__")\
				.replace("operator>>", "__rshift__")\
				.replace("operator&", "__and__")\
				.replace("operator|", "__or__")\
				.replace("operator^", "__xor__")\
				.replace("operator~", "__invert__")
		while 1:
			error = ida_struct.add_struc_member(vstruc, demangled, idc.BADADDR, idc.FF_DWORD, None, 4)

			if error == 0:
				break

			demangled += "_{}".format(hex(ida_struct.get_struc_last_offset(vstruc) + 4)[2:])

	try:
		ti = idaapi.tinfo_t()
		idaapi.parse_decl(ti, None, typename + "_vtbl;", 0)
		ti.create_ptr(ti)
		ida_struct.add_struc_member(typestruc, "__vftable", 0, idc.FF_DWORD, None, 4)
		ida_struct.set_member_tinfo(typestruc, ida_struct.get_member(typestruc, 0), 0, ti, 0)
	except:
		print("Prevented a terrible, horrible, no good, very bad crash with {}!".format(typename))
예제 #4
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
예제 #5
0
 def getUserDeclType(self, decl):
     tinfo = idaapi.tinfo_t()
     #logger.debug('Trying to parse declaration: %r', decl)
     ret = idaapi.parse_decl(tinfo, idaapi.cvar.idati, decl, idaapi.PT_TYP)
     #logger.debug('Return from parse_decl2: %r', ret)
     if ret is None:
         logger.info('parse_decl failed')
         return None
     return tinfo
예제 #6
0
 def setData(self, column, value):
     if column == 0:
         if idaapi.is_ident(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_decl(tinfo, idaapi.cvar.idati, value, idaapi.PT_TYP) is not None:
                 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
예제 #7
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 == 0:
                    return

                # Have to be a little special with datatables
                if t.text == "datatable":
                    ida_struct.add_struc_member(struc, classname, offset,
                                                idc.FF_DWORD, 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_decl(ti, None, mycls + ";", 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
                    numbytes = 4

                if t.text == "vector":
                    ida_struct.add_struc_member(struc, classname, offset,
                                                idc.FF_DWORD, 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))