Skip to content

Instantly share code, notes, and snippets.

@icecr4ck
Last active September 8, 2025 01:56
Show Gist options
  • Select an option

  • Save icecr4ck/9dea9d1de052f0b2b417abf0046cc0f6 to your computer and use it in GitHub Desktop.

Select an option

Save icecr4ck/9dea9d1de052f0b2b417abf0046cc0f6 to your computer and use it in GitHub Desktop.

Revisions

  1. icecr4ck revised this gist Nov 25, 2020. 1 changed file with 8 additions and 8 deletions.
    16 changes: 8 additions & 8 deletions idapython_ctree.md
    Original file line number Diff line number Diff line change
    @@ -14,17 +14,17 @@ The CTREE is built from the optimized microcode (maturity at `CMAT_FINAL`), it r
    ### Decompile a function

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

    ### Get decompiled function from pseudocode widget

    ```python
    w = ida_kernwin.get_current_widget()
    w = idaapi.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)
    if idaapi.get_widget_type(w) == idaapi.BWN_PSEUDOCODE:
    vu = idaapi.get_widget_vdui(w)
    cfunc = vu.cfunc
    ```

    @@ -73,17 +73,17 @@ if tinfo.is_funcptr():
    ### Create a CTREE visitor

    ```python
    import ida_hexrays
    import idaapi

    class my_super_visitor(ida_hexrays.ctree_visitor_t):
    class my_super_visitor(idaapi.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
    idaapi.ctree_visitor_t.__init__(self, idaapi.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:
    if e.op != idaapi.cot_asg:
    return 0

    return 0
  2. icecr4ck revised this gist Apr 7, 2020. 1 changed file with 105 additions and 12 deletions.
    117 changes: 105 additions & 12 deletions idapython_ctree.md
    Original file line number Diff line number Diff line change
    @@ -57,7 +57,20 @@ for i in cfunc.argidx:
    tinfo = lvars[i].type()
    ```

    ## Visit a CTREE
    ### Manipulate types of local variables

    ```python
    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

    ```python
    import ida_hexrays
    @@ -80,15 +93,95 @@ v = my_super_visitor()
    v.apply_to(cfunc.body, None)
    ```

    ## Play with local variables

    ### Manipulate types of local variables

    ```python
    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)
    ### Type of expressions and statements

    ```c
    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
    };
    ```
  3. icecr4ck revised this gist Apr 7, 2020. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion idapython_ctree.md
    Original file line number Diff line number Diff line change
    @@ -24,7 +24,6 @@ cfunc = idaapi.decompile(ea)
    w = ida_kernwin.get_current_widget()
    # if widget type is pseudocode
    if ida_kernwin.get_widget_type(w) == ida_kernwin.BWN_PSEUDOCODE:
    # get cfunc
    vu = ida_hexrays.get_widget_vdui(w)
    cfunc = vu.cfunc
    ```
  4. icecr4ck revised this gist Apr 7, 2020. 1 changed file with 17 additions and 2 deletions.
    19 changes: 17 additions & 2 deletions idapython_ctree.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,14 @@
    # IDAPython CTREE

    ## Important links

    * [Hex-Rays Decompiler Primer](http://www.hexblog.com/?p=107)
    * [hexrays.hpp](https://www.hex-rays.com/products/decompiler/manual/sdk/hexrays_8hpp_source.shtml)

    ## 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
    @@ -20,6 +29,12 @@ if ida_kernwin.get_widget_type(w) == ida_kernwin.BWN_PSEUDOCODE:
    cfunc = vu.cfunc
    ```

    ### Refresh pseudocode in widget

    ```python
    vu.refresh_ctext()
    ```

    ### Get local variables

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

    ### Get arguments
    @@ -70,7 +85,7 @@ v.apply_to(cfunc.body, None)

    ### Manipulate types of local variables

    ```
    ```python
    tinfo = lvars[0].type()
    if tinfo.is_funcptr():
    number_of_args = tinfo.get_nargs()
  5. icecr4ck created this gist Apr 7, 2020.
    80 changes: 80 additions & 0 deletions idapython_ctree.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,80 @@
    # IDAPython CTREE

    ## Play with decompiled function

    ### Decompile a function

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

    ### Get decompiled function from pseudocode widget

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

    ### Get local variables

    ```python
    lvars = cfunc.get_lvars()
    ```

    ### Get calling convention

    ```python
    tinfo = idaapi.tinfo_t()
    cfunc.get_func_type(tinfo)
    funcdata = idaapi.func_type_data_t()
    tinfo.get_func_details(funcdata)
    cc = funcdata.cc
    ```

    ### Get arguments

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

    ## Visit a CTREE

    ```python
    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)
    ```

    ## Play with local variables

    ### 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)
    ```