3

IDA local types has a local type like:

struct DEMOTYPE<int>
{
_DWORD dw1;
_DWORD dw2;
}

how to use "DEMOTYPE"(C++ type) just like normal c type? press Y can not Can't achieve the goal since the "<>" in it.

i know if the target is function,we can change the function declaration with its mangled name.

In a word, how can we use the c++ type declaration in the local types to change the type of the local variable?

Below is the code I tried, but the F5 pseudocode view cannot be changed.

def setVarType(lvname, lti, isptr=False):
    addr = idc.here()
    c = idaapi.decompile(addr)
    for v in c.lvars:
        if v.name == lvname:
            print("find target variable:", v.name)
            idati = ida_typeinf.get_idati()
            ti = ida_typeinf.tinfo_t()
            if ti.get_numbered_type(idati, lti):
                print("find local type:", lti, ":", ti)
                if isptr:
                    ti_ptr = ida_typeinf.tinfo_t()
                    ti_ptr.create_ptr(ti)  # ti_ptr = ti *
                    bret = v.set_final_lvar_type(ti_ptr)
                else:
                    bret = v.set_final_lvar_type(ti)
                print(bret)
omgkaka
  • 29
  • 6
  • What you are looking at is a class (struct) template and is perfectly normal C++ (and used a lot). Maybe this will help you understand a bit more https://en.cppreference.com/w/cpp/language/templates. (It can also be I totally did not understand your real question ;) ) – Pepijn Kramer Jan 01 '22 at 11:11
  • I known templates,i want to know just is there any way make ida recognize the type declaration "DEMOTYPE" which already exist in local types and it's memory layout already known. if the local types name changed to "DEMOTYPEint" then ida can recognize it, but i don't want to change the name since there is too many such types like that.I think the key point is the angle brackets, a similar problem: to make ida support Chinese function names, you can use hook ida.dll to prevent it from replacing Chinese characters with "_". – omgkaka Jan 01 '22 at 11:45
  • `struct DEMOTYPE` creates an new type with a unique name - implementation dependent. You will need to find a way to get the compiler to tell you the generated (internal) name. The name `DEMOTYPE` does not exist after compilation. – Richard Critten Jan 01 '22 at 12:52
  • I had to lookup what IDA does, and it clearly states : It cannot parse templates and other complex constructs but simple standard cases can be parsed. (https://hex-rays.com/products/ida/support/idadoc/1691.shtml ). Afaik There is no way to convert a template struct to a non-template one. Aliasing (e.g. using DEMOTYPE_INT = DEMOTYPE) or deriving from it will still result in a preprocessor having to parse the template. – Pepijn Kramer Jan 01 '22 at 13:06
  • Richard's idea may be right. If i can find the internal name , i can solve it, or ida checked and filtered "<" during a certain process, which caused the Y function to not be successfully applied. I tried to use set_lvar_type successfully, but this does not change .idb file. Although the mouse prompt type has been changed, I did not find a way to refresh it to pseudo code. What I need is to change the type of local variables in the pseudocode window (similar to press Y ). – omgkaka Jan 01 '22 at 13:31
  • This question has become much more relevant with IDA7.7 which **can** process templated types (via clang), but still won't let you do anything with them afterwards. I don't buy that it has anything to do with the requirement to parse them, as they have already been parsed, and the `<` and `>` are just characters in the type name. _p.s., you **can** change a typename to have `<` or `>` in it by using the structure view and `N`_ – Orwellophile Oct 21 '22 at 17:54
  • A few days after I asked the question, I solved the problem myself and submitted the key information to solve the problem as an answer, unfortunately this answer was marked for deletion, the reason I did not provide the specific complete code but the key information It's my hope that someone like me who encounters this problem can finally solve it on their own. I am submitting again as a comment the key information to solve this problem (IDA SDK - Rename Variable permanently: https://reverseengineering.stackexchange.com/questions/18063/ida-sdk-rename-variable-permanently) – omgkaka Oct 29 '22 at 03:40
  • @omgkaka Ahh, I am familiar with that answer, though I can't see how it helps as it about changing names, not types. However, I have since written an idapython function that changes both (or either), and appears to allow changing of variable types to template-ish values. – Orwellophile Oct 31 '22 at 00:22
  • @Orwellophile name is property, type is also a property,the url link show how to change the name.so.......then use modify_user_lvar_info save the changed info to idb. – omgkaka Oct 31 '22 at 08:12

1 Answers1

0

This should work, though only for local variables (not for function arguments).

Typical usage: set_lvar_name_type(here(), 'v1', None, 'rage::atArray<int>')

def set_lvar_name_type(ea, src, name, t, vu=None):
    """
    Change the name or type of a local variable

    @param ea: address of function
    @param src: current name of variable
    @param name: new name (or None to leave as is)
    @param t: new type (str, tinfo_t, or None to leave as is)
    @param v: handle to existing pseudocode window (vdui_t, or None)

    @note
    Will not work with function arguments or global variables
    """
    # m = [ea for ea in [pprev(ea, 1) for ea in l if GetFuncName(ea)] if ea]
    def get_tinfo_elegant(name):
        ti = ida_typeinf.tinfo_t()
        til = ti.get_til()
        # get_named_type(self, til, name, decl_type=BTF_TYPEDEF, resolve=True, try_ordinal=True)
        if ti.get_named_type(til, name, ida_typeinf.BTF_STRUCT, True, True):
            return ti
        return None

    def get_pseudocode_vu(ea, vu=None):
        func = idaapi.get_func(ea)
        if func:
            return idaapi.open_pseudocode(func.start_ea, 0)

    if isinstance(t, str):
        tif = get_tinfo_elegant(t)
        if not tif:
            raise ValueError("Couldn't get tinfo_t for type '{}'".format(t))
        t = tif
    elif isinstance(t, ida_typeinf.tinfo_t) or t is None:
        pass
    else:
        raise TypeError("Unknown type for t '{}'".format(type(t)))

    vu = get_pseudocode_vu(ea, vu)
    if vu:
        lvars = [n for n in vu.cfunc.lvars if n.name == src]
        if len(lvars) == 1:
            print("changing name/type of {}/{} to {}/{}".format(lvars[0].name, lvars[0].type(), name, str(t)))
            if t:
                vu.set_lvar_type(lvars[0], t)
            if name:
                vu.rename_lvar(lvars[0], name, 1)
        else:
            print("[set_lvar_name_type] couldn't find var {}".format(src))
    return False
Orwellophile
  • 13,235
  • 3
  • 69
  • 45