Write and execute IDAPython scripts — full API reference included
print() for all output — it's captured and returned to you.None / BADADDR returns (e.g., ida_funcs.get_func() returns None if no function).ida_auto.auto_wait() after bulk modifications to let auto-analysis settle.ida_hexrays.mark_cfunc_dirty(ea) before re-decompiling a function you've modified.ida_struct and ida_enum — use ida_typeinf for all type operations.The execute_python tool provides:
idaapi, idautils, idc — high-level wrappersida_funcsida_nameida_bytesida_segmentida_typeinfida_naltida_xrefida_kernwinida_hexraysida_linesida_searchida_idaida_entryida_frameida_autoida_gdlida_netnodeBADADDR is available via idaapi.BADADDRval = ida_bytes.get_byte(ea) # uint8
val = ida_bytes.get_dword(ea) # uint32
val = ida_bytes.get_qword(ea) # uint64
raw = ida_bytes.get_bytes(ea, size) # bytes
s = ida_bytes.get_strlit_contents(ea, -1, ida_nalt.STRTYPE_C)
for func_ea in idautils.Functions():
name = idc.get_func_name(func_ea)
func = ida_funcs.get_func(ea) # func_t or None
# func.start_ea, func.end_ea, func.flags
idc.add_func(ea) # create function
ida_name.set_name(ea, "new_name", ida_name.SN_CHECK)
cfunc = ida_hexrays.decompile(ea) # cfuncptr_t
pseudocode = cfunc.get_pseudocode() # simpleline_t vector
for line in pseudocode:
print(ida_lines.tag_remove(line.line))
# Local variables
for lvar in cfunc.get_lvars():
print(f"{lvar.name}: {lvar.type()}")
# CTree visitor
class MyVisitor(ida_hexrays.ctree_visitor_t):
def __init__(self):
super().__init__(ida_hexrays.CV_FAST)
def visit_expr(self, expr):
if expr.op == ida_hexrays.cot_call:
print(f"Call at {hex(expr.ea)}")
return 0
visitor = MyVisitor()
visitor.apply_to(cfunc.body, None)
for xref in idautils.XrefsTo(ea):
print(f"from {hex(xref.frm)}, type={xref.type}")
for xref in idautils.XrefsFrom(ea):
print(f"to {hex(xref.to)}")
for ref in idautils.CodeRefsTo(ea, False): # False = no flow
print(hex(ref))
for ref in idautils.DataRefsTo(ea):
print(hex(ref))
Critical: udm_t.offset is in BITS, not bytes. udm_t.size is also in BITS.
import ida_typeinf
# Helper: make a simple integer tinfo_t
def make_int_type(byte_size: int, signed: bool = False) -> ida_typeinf.tinfo_t:
bt_map = {
(1, False): ida_typeinf.BT_INT8,
(1, True): ida_typeinf.BT_INT8,
(2, False): ida_typeinf.BT_INT16,
(2, True): ida_typeinf.BT_INT16,
(4, False): ida_typeinf.BT_INT32,
(4, True): ida_typeinf.BT_INT32,
(8, False): ida_typeinf.BT_INT64,
(8, True): ida_typeinf.BT_INT64,
}
t = ida_typeinf.tinfo_t()
t.create_simple_type(bt_map[(byte_size, signed)])
return t
# Helper: make a pointer type
def make_ptr_type(inner: ida_typeinf.tinfo_t) -> ida_typeinf.tinfo_t:
pd = ida_typeinf.ptr_type_data_t()
pd.obj_type = inner
t = ida_typeinf.tinfo_t()
t.create_ptr(pd)
return t
# Helper: make an array type
def make_array_type(elem: ida_typeinf.tinfo_t, count: int) -> ida_typeinf.tinfo_t:
ad = ida_typeinf.array_type_data_t()
ad.elem_type = elem
ad.nelems = count
t = ida_typeinf.tinfo_t()
t.create_array(ad)
return t
# Build struct — offsets in BITS
def make_struct(name: str, fields: list) -> ida_typeinf.tinfo_t:
"""fields = [(name, tinfo_t, byte_offset), ...]"""
udt = ida_typeinf.udt_type_data_t()
for fname, ftype, byte_off in fields:
udm = ida_typeinf.udm_t()
udm.name = fname
udm.type = ftype
udm.offset = byte_off * 8 # ← BITS, not bytes
udt.push_back(udm)
tif = ida_typeinf.tinfo_t()
tif.create_udt(udt, ida_typeinf.BTF_STRUCT)
tif.set_named_type(None, name, ida_typeinf.NTF_REPLACE)
return tif
# Example: struct Elf32_auxv_entry { uint32_t a_type; uint32_t a_val; }
auxv_tif = make_struct("Elf32_auxv_entry", [
("a_type", make_int_type(4, False), 0),
("a_val", make_int_type(4, False), 4),
])
# Example: struct with pointer and array fields
char_ptr = make_ptr_type(make_int_type(1)) # char*
char_pp = make_ptr_type(char_ptr) # char**
u8_arr = make_array_type(make_int_type(1), 16) # uint8_t[16]
make_struct("StartupInfo", [
("argv", char_pp, 0),
("buf", u8_arr, 8),
])
# Reference a previously defined struct by name
def get_named_type(name: str) -> ida_typeinf.tinfo_t:
t = ida_typeinf.tinfo_t()
if not t.get_named_type(None, name):
raise ValueError(f"Type '{name}' not found in type library")
return t
# Apply type to address
ida_typeinf.apply_tinfo(ea, auxv_tif, ida_typeinf.TINFO_DEFINITE)
# Validate after creation
t = ida_typeinf.tinfo_t()
if t.get_named_type(None, "Elf32_auxv_entry"):
print(f"OK: {t.dstr()}, size={t.get_size()} bytes")