Skip to content

Instantly share code, notes, and snippets.

@daaximus
Forked from trietptm/idapython_ctree.md
Created October 20, 2022 19:20
Show Gist options
  • Save daaximus/7441af5ca361ec1359304c36037f8f88 to your computer and use it in GitHub Desktop.
Save daaximus/7441af5ca361ec1359304c36037f8f88 to your computer and use it in GitHub Desktop.
Notes on CTREE usage with IDAPython

IDAPython CTREE

Important links

Description

The CTREE is built from the optimized microcode (maturity at CMAT_FINAL), it represents an AST-like tree with C statements and expressions. It can be printed as C code.

Play with decompiled function

Decompile a function

ea = idc.here()
cfunc = idaapi.decompile(ea)

Get decompiled function from pseudocode widget

w = ida_kernwin.get_current_widget()
# if widget type is pseudocode
if ida_kernwin.get_widget_type(w) == ida_kernwin.BWN_PSEUDOCODE:
    vu = ida_hexrays.get_widget_vdui(w)
    cfunc = vu.cfunc

Refresh pseudocode in widget

vu.refresh_ctext()

Get local variables

lvars = cfunc.get_lvars()

Get calling convention

tinfo = idaapi.tinfo_t()
cfunc.get_func_type(tinfo)
funcdata = idaapi.func_type_data_t()
tinfo.get_func_details(funcdata)
cc = funcdata.cc # can be one of CM_CC_* -> examples: CM_CC_CDECL, CM_CC_STDCALL, CM_CC_FASTCALL

Get arguments

for i in cfunc.argidx:
    tinfo = lvars[i].type()

Manipulate types of local variables

tinfo = lvars[0].type()
if tinfo.is_funcptr():
    number_of_args = tinfo.get_nargs()
    rettype = tinfo.get_rettype()
    for i in number_of_args:
        tinfo_arg = tinfo.get_nth_arg(i)

Exploring the CTREE

Create a CTREE visitor

import ida_hexrays

class my_super_visitor(ida_hexrays.ctree_visitor_t):
  def __init__(self):
      ida_hexrays.ctree_visitor_t.__init__(self, ida_hexrays.CV_FAST) # CV_FAST does not keep parents nodes in CTREE
    
   def visit_insn(self, i):
      return 0
   
   def visit_expr(self, e):
      if e.op != ida_hexrays.cot_asg:
          return 0
      
      return 0
          
cfunc = idaapi.decompile(idc.here())
v = my_super_visitor()
v.apply_to(cfunc.body, None)

Type of expressions and statements

enum ctype_t
{
  cot_empty    = 0,
  cot_comma    = 1,   ///< x, y
  cot_asg      = 2,   ///< x = y
  cot_asgbor   = 3,   ///< x |= y
  cot_asgxor   = 4,   ///< x ^= y
  cot_asgband  = 5,   ///< x &= y
  cot_asgadd   = 6,   ///< x += y
  cot_asgsub   = 7,   ///< x -= y
  cot_asgmul   = 8,   ///< x *= y
  cot_asgsshr  = 9,   ///< x >>= y signed
  cot_asgushr  = 10,  ///< x >>= y unsigned
  cot_asgshl   = 11,  ///< x <<= y
  cot_asgsdiv  = 12,  ///< x /= y signed
  cot_asgudiv  = 13,  ///< x /= y unsigned
  cot_asgsmod  = 14,  ///< x %= y signed
  cot_asgumod  = 15,  ///< x %= y unsigned
  cot_tern     = 16,  ///< x ? y : z
  cot_lor      = 17,  ///< x || y
  cot_land     = 18,  ///< x && y
  cot_bor      = 19,  ///< x | y
  cot_xor      = 20,  ///< x ^ y
  cot_band     = 21,  ///< x & y
  cot_eq       = 22,  ///< x == y int or fpu (see EXFL_FPOP)
  cot_ne       = 23,  ///< x != y int or fpu (see EXFL_FPOP)
  cot_sge      = 24,  ///< x >= y signed or fpu (see EXFL_FPOP)
  cot_uge      = 25,  ///< x >= y unsigned
  cot_sle      = 26,  ///< x <= y signed or fpu (see EXFL_FPOP)
  cot_ule      = 27,  ///< x <= y unsigned
  cot_sgt      = 28,  ///< x >  y signed or fpu (see EXFL_FPOP)
  cot_ugt      = 29,  ///< x >  y unsigned
  cot_slt      = 30,  ///< x <  y signed or fpu (see EXFL_FPOP)
  cot_ult      = 31,  ///< x <  y unsigned
  cot_sshr     = 32,  ///< x >> y signed
  cot_ushr     = 33,  ///< x >> y unsigned
  cot_shl      = 34,  ///< x << y
  cot_add      = 35,  ///< x + y
  cot_sub      = 36,  ///< x - y
  cot_mul      = 37,  ///< x * y
  cot_sdiv     = 38,  ///< x / y signed
  cot_udiv     = 39,  ///< x / y unsigned
  cot_smod     = 40,  ///< x % y signed
  cot_umod     = 41,  ///< x % y unsigned
  cot_fadd     = 42,  ///< x + y fp
  cot_fsub     = 43,  ///< x - y fp
  cot_fmul     = 44,  ///< x * y fp
  cot_fdiv     = 45,  ///< x / y fp
  cot_fneg     = 46,  ///< -x fp
  cot_neg      = 47,  ///< -x
  cot_cast     = 48,  ///< (type)x
  cot_lnot     = 49,  ///< !x
  cot_bnot     = 50,  ///< ~x
  cot_ptr      = 51,  ///< *x, access size in 'ptrsize'
  cot_ref      = 52,  ///< &x
  cot_postinc  = 53,  ///< x++
  cot_postdec  = 54,  ///< x--
  cot_preinc   = 55,  ///< ++x
  cot_predec   = 56,  ///< --x
  cot_call     = 57,  ///< x(...)
  cot_idx      = 58,  ///< x[y]
  cot_memref   = 59,  ///< x.m
  cot_memptr   = 60,  ///< x->m, access size in 'ptrsize'
  cot_num      = 61,  ///< n
  cot_fnum     = 62,  ///< fpc
  cot_str      = 63,  ///< string constant
  cot_obj      = 64,  ///< obj_ea
  cot_var      = 65,  ///< v
  cot_insn     = 66,  ///< instruction in expression, internal representation only
  cot_sizeof   = 67,  ///< sizeof(x)
  cot_helper   = 68,  ///< arbitrary name
  cot_type     = 69,  ///< arbitrary type
  cot_last     = cot_type,
  cit_empty    = 70,  ///< instruction types start here
  cit_block    = 71,  ///< block-statement: { ... }
  cit_expr     = 72,  ///< expression-statement: expr;
  cit_if       = 73,  ///< if-statement
  cit_for      = 74,  ///< for-statement
  cit_while    = 75,  ///< while-statement
  cit_do       = 76,  ///< do-statement
  cit_switch   = 77,  ///< switch-statement
  cit_break    = 78,  ///< break-statement
  cit_continue = 79,  ///< continue-statement
  cit_return   = 80,  ///< return-statement
  cit_goto     = 81,  ///< goto-statement
  cit_asm      = 82,  ///< asm-statement
  cit_end
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment