1

I am using IDA Pro 7.6 on win32 x86 binaries.

I'm trying to use the ida_hexrays interface to decompile subroutines. I want all of the local variables and arguments of the subroutine to have integral types, no pointer types. I made this function to do all the processing for me

import ida_hexrays
import ida_typeinf as ida_type
import ida_lines

def decompile_function( function_location ):
    decompile_handle = ida_hexrays.decompile( function_location, flags = ida_hexrays.DECOMP_NO_CACHE )

    for local_variable in decompile_handle.lvars:
        type_info = local_variable.type()

        try:    
            if ida_type.is_type_ptr( type_info.get_decltype() ):
                pointed_object = type_info.get_pointed_object()

                if ida_type.is_type_integral( pointed_object.get_decltype() ):
                    local_variable.set_lvar_type( type_info.get_pointed_object() )      
        except:
            pass

    decompile_handle.refresh_func_ctext()

    pseudo_code = decompile_handle.get_pseudocode()
    decompile_result = ""

    for code_line in pseudo_code:
        decompile_result = decompile_result + ida_lines.tag_remove( code_line.line ) + "\n";

    return decompile_result

When I decompile, I can see in the variable list that all of the variables are integral types

unsigned __int8 v7; // al
int v10; // eax
unsigned int v11; // esi
const char v12; // cl
_DWORD v13; // eax

v13 = (_DWORD *)v11;

However, as you may notice above, v13 = (_DWORD *)v11 v13 is improperly being set as a pointer. As it turns out, none of the code except the variable declarations gets changed. This happens for every subroutine that I try to decompile with this.

But when I right-click and use reset pointer value, the code changes and it would look like v13 = v11;. What is the issue with my code, or is IDAPython/IDAHexrays to blame? How do I make it actually reset the pointer value and not just in the declaration list?

1 Answer 1

0

That function, lvar_t::set_lvar_type, is accompanied by the following comment:

  /// Note: this function does not modify the idb, only the lvar instance
  /// in the memory. For permanent changes see modify_user_lvars()

Instead of calling set_lvar_type, you're going to want something like this instead:

def ChangeVariableType(func_ea, lvar, tif):
    lsi = ida_hexrays.lvar_saved_info_t()
    lsi.ll = lvar
    lsi.type = ida_typeinf.tinfo_t(tif)
    if not ida_hexrays.modify_user_lvar_info(func_ea, ida_hexrays.MLI_TYPE, lsi):
        print("[E] Could not modify lvar type for %s" % lvar.name)
        return False
    return True
4
  • I'm sorry, but when I use this code it doesn't seem to make any changes to the decompiled output at all? Here is my new code https://pastebin.com/KqFfkpV1 May 1 at 6:49
  • There are several ways to accomplish what you're trying to do. In short, you're going to need to decompile the function again. If you had a vdui_t object instead of a cfunc_t object, you could call vdui_t::refresh_view with the bool parameter set to True. Alternatively, you could invoke decompile again after the loop that modifies the variable types. May 1 at 18:08
  • Thanks for the help. Now I end up doing something like this. But when I look at the output, still nothing at all has changed. All the types remain the exact same as they were before in the decompiled output. Here is a link to the new code https://pastebin.com/wYh8BQU6 May 2 at 12:30
  • Edit: I realized that _DWORD is an unacceptable integral type, and the decompiler just doesn't seem to agree with it. I changed the type to "int", and voila it worked and all the types persisted throughout the whole code. May 2 at 17:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.