home / skills / mrexodia / ida-pro-mcp / idapython

idapython skill

/skills/idapython

This skill helps you automate IDA Pro reverse engineering tasks by leveraging modern ida_* modules to analyze, decompile, and manipulate IDA databases.

npx playbooks add skill mrexodia/ida-pro-mcp --skill idapython

Review the files below or copy the command above to add this skill to your agents.

Files (105)
SKILL.md
4.9 KB
---
name: idapython
description: IDA Pro Python scripting for reverse engineering. Use when writing IDAPython scripts, analyzing binaries, working with IDA's API for disassembly, decompilation (Hex-Rays), type systems, cross-references, functions, segments, or any IDA database manipulation. Covers ida_* modules (50+), idautils iterators, and common patterns.
---

# IDAPython

Use modern `ida_*` modules. Avoid legacy `idc` module.

## Module Router

| Task | Module | Key Items |
|------|--------|-----------|
| Bytes/memory | `ida_bytes` | `get_bytes`, `patch_bytes`, `get_flags`, `create_*` |
| Functions | `ida_funcs` | `func_t`, `get_func`, `add_func`, `get_func_name` |
| Names | `ida_name` | `set_name`, `get_name`, `demangle_name` |
| Types | `ida_typeinf` | `tinfo_t`, `apply_tinfo`, `parse_decl` |
| Decompiler | `ida_hexrays` | `decompile`, `cfunc_t`, `lvar_t`, ctree visitor |
| Segments | `ida_segment` | `segment_t`, `getseg`, `add_segm` |
| Xrefs | `ida_xref` | `xrefblk_t`, `add_cref`, `add_dref` |
| Instructions | `ida_ua` | `insn_t`, `op_t`, `decode_insn` |
| Stack frames | `ida_frame` | `get_frame`, `define_stkvar` |
| Iteration | `idautils` | `Functions()`, `Heads()`, `XrefsTo()`, `Strings()` |
| UI/dialogs | `ida_kernwin` | `msg`, `ask_*`, `jumpto`, `Choose` |
| Database info | `ida_ida` | `inf_get_*`, `inf_is_64bit()` |
| Analysis | `ida_auto` | `auto_wait`, `plan_and_wait` |
| Flow graphs | `ida_gdl` | `FlowChart`, `BasicBlock` |
| Register tracking | `ida_regfinder` | `find_reg_value`, `reg_value_info_t` |

## Core Patterns

### Iterate functions
```python
for ea in idautils.Functions():
    name = ida_funcs.get_func_name(ea)
    func = ida_funcs.get_func(ea)
```

### Iterate instructions in function
```python
for head in idautils.FuncItems(func_ea):
    insn = ida_ua.insn_t()
    if ida_ua.decode_insn(insn, head):
        print(f"{head:#x}: {insn.itype}")
```

### Cross-references
```python
for xref in idautils.XrefsTo(ea):
    print(f"{xref.frm:#x} -> {xref.to:#x} type={xref.type}")
```

### Read/write bytes
```python
data = ida_bytes.get_bytes(ea, size)
ida_bytes.patch_bytes(ea, b"\x90\x90")
```

### Names
```python
name = ida_name.get_name(ea)
ida_name.set_name(ea, "new_name", ida_name.SN_NOCHECK)
```

### Decompile function
```python
cfunc = ida_hexrays.decompile(ea)
if cfunc:
    print(cfunc)  # pseudocode
    for lvar in cfunc.lvars:
        print(f"{lvar.name}: {lvar.type()}")
```

### Walk ctree (decompiled AST)
```python
class MyVisitor(ida_hexrays.ctree_visitor_t):
    def visit_expr(self, e):
        if e.op == ida_hexrays.cot_call:
            print(f"Call at {e.ea:#x}")
        return 0

cfunc = ida_hexrays.decompile(ea)
MyVisitor().apply_to(cfunc.body, None)
```

### Apply type
```python
tif = ida_typeinf.tinfo_t()
if ida_typeinf.parse_decl(tif, None, "int (*)(char *, int)", 0):
    ida_typeinf.apply_tinfo(ea, tif, ida_typeinf.TINFO_DEFINITE)
```

### Create structure
```python
udt = ida_typeinf.udt_type_data_t()
m = ida_typeinf.udm_t()
m.name = "field1"
m.type = ida_typeinf.tinfo_t(ida_typeinf.BTF_INT32)
m.offset = 0
m.size = 4
udt.push_back(m)
tif = ida_typeinf.tinfo_t()
tif.create_udt(udt, ida_typeinf.BTF_STRUCT)
tif.set_named_type(ida_typeinf.get_idati(), "MyStruct")
```

### Strings list
```python
for s in idautils.Strings():
    print(f"{s.ea:#x}: {str(s)}")
```

### Wait for analysis
```python
ida_auto.auto_wait()  # Block until autoanalysis completes
```

## Key Constants

| Constant | Value/Use |
|----------|-----------|
| `BADADDR` | Invalid address sentinel |
| `ida_name.SN_NOCHECK` | Skip name validation |
| `ida_typeinf.TINFO_DEFINITE` | Force type application |
| `o_reg`, `o_mem`, `o_imm`, `o_displ`, `o_near` | Operand types |
| `dt_byte`, `dt_word`, `dt_dword`, `dt_qword` | Data types |
| `fl_CF`, `fl_CN`, `fl_JF`, `fl_JN`, `fl_F` | Code xref types |
| `dr_R`, `dr_W`, `dr_O` | Data xref types |

## Critical Rules

1. **NEVER convert hex/decimal manually** — use `int_convert` MCP tool
2. **Wait for analysis**: Call `ida_auto.auto_wait()` before reading results
3. **Thread safety**: IDA SDK calls must run on main thread (use `@idasync`)
4. **64-bit addresses**: Always assume `ea_t` can be 64-bit

## Anti-Patterns

| Avoid | Do Instead |
|-------|------------|
| `idc.*` functions | Use `ida_*` modules |
| Hardcoded addresses | Use names, patterns, or xrefs |
| Manual hex conversion | Use `int_convert` tool |
| Blocking main thread | Use `execute_sync()` for long ops |
| Guessing at types | Derive from disassembly/decompilation |

## Detailed API Reference

For comprehensive documentation on any module, read `docs/<module>.md`:
- **High-use**: `ida_bytes`, `ida_funcs`, `ida_hexrays`, `ida_typeinf`, `ida_name`, `idautils`
- **Medium-use**: `ida_segment`, `ida_xref`, `ida_ua`, `ida_frame`, `ida_kernwin`
- **Specialized**: `ida_dbg` (debugger), `ida_nalt` (netnode storage), `ida_regfinder` (register tracking)

Full RST sources from hex-rays.com available at `docs/<module>.rst`.

Overview

This skill provides practical IDAPython guidance and patterns for writing IDA Pro Python scripts focused on binary analysis, decompilation, and database manipulation. It emphasizes modern ida_* modules, common iterators from idautils, Hex-Rays decompiler usage, and best practices to avoid legacy pitfalls. Use it to accelerate scripting, automate triage, and safely modify an IDA database.

How this skill works

The skill maps common reverse-engineering tasks to the appropriate ida_* modules (bytes, functions, types, xrefs, decompiler, segments, etc.) and supplies concise code patterns for iteration, decoding, type application, and ctree traversal. It enforces critical rules: wait for autoanalysis, run SDK calls on the main thread, treat ea_t as 64-bit, and avoid manual hex/decimal conversions by using the int_convert tool. Examples show reading/patching bytes, enumerating functions and strings, working with tinfo_t, and walking the Hex-Rays AST.

When to use it

  • Writing or refactoring IDAPython scripts that target modern IDA APIs
  • Automating cross-reference, function, or string enumeration tasks
  • Applying or parsing types and structures from decompiled output
  • Interacting with the Hex-Rays decompiler (ctree) for data-flow or call analysis
  • Patching bytes, creating segments, or programmatically adding names and functions

Best practices

  • Prefer ida_* modules over legacy idc functions for stability and clarity
  • Call ida_auto.auto_wait() before reading analysis results
  • Run SDK/IDA calls on the main thread (use @idasync or execute_sync for background tasks)
  • Avoid hardcoded addresses; use names, xrefs, and patterns instead
  • Use idautils iterators (Functions, FuncItems, XrefsTo, Strings) for efficient traversal

Example use cases

  • Batch-rename functions using ida_name.get_name/set_name and idautils.Functions()
  • Decompile a function and extract local variable types via ida_hexrays.decompile and cfunc.lvars
  • Find all callers of an API using idautils.XrefsTo and classify call sites
  • Apply a parsed typedef to an address with ida_typeinf.parse_decl and apply_tinfo
  • Patch bytes across a range using ida_bytes.get_bytes and ida_bytes.patch_bytes while respecting autoanalysis

FAQ

Should I still use idc functions?

No. Prefer ida_* modules; idc is legacy and can lead to brittle scripts.

How do I avoid blocking UI during long operations?

Use execute_sync() or run long tasks in background threads and marshal SDK calls to the main thread with @idasync.