aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: b826acd6556dd014964f2e86dbe015c98ca9e92a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
![ida-tui](logo-trans.png)

**IDA Pro in a terminal.** Listing, decompiler, graph — keyboard-first, mouse-capable.

`disasm` · `pseudocode` · `cfg` · `hex` · `strings` · `structs` · `traces` · `rpc`

---

```
┌ ida-tui ─────────────────────────────────────────────────────────────────────┐
│ .text:00002490 ; ---------- S U B R O U T I N E ----------                   │
│ .text:00002490 main            proc near                                     │
│ .text:00002490                 endbr64                                       │
│ .text:00002494                 push    rbp                ; ← cursor         │
│ .text:00002495                 mov     rbp, rsp                              │
│ .text:00002498                 sub     rsp, 0B0h          ; `o` → 176        │
└──────────────────────────────────────────────────────────────────────────────┘
```

> **Status: personal project, actively hacked on.** No packaging, no versioning,
> no support. It assumes a licensed IDA Pro and a venv at `~/ida-venv`. Things
> move and break. Poke around; don't file expectations.

## Why

IDA's own UI is excellent and it is a GUI. This is for the times you're in a
terminal over SSH, in a tmux pane next to your notes, or driving RE from a
script — and still want the listing, Hex-Rays, and a real control-flow graph.

It is **not** a reimplementation of IDA. It's a frontend: IDA does the analysis,
this draws it.

## Install

Needs **Python ≥ 3.11** and **IDA Pro 9.4+ with idalib**.

```sh
uv sync
```

That pulls [ida-codemode](https://github.com/HexRaysSA/ida-codemode) from PyPI,
which is how ida-tui talks to IDA. To also attach to databases you have open in
the IDA GUI, install its plugin:

```sh
uvx --prerelease=allow --from ida-codemode ida-codemode-mcp --install-plugin
```

Hacking on ida-codemode itself? Point at a checkout instead:

```sh
uv add --editable ../ida-codemode
```

## Run

```sh
./ida-tui /path/to/binary        # attach to a GUI session, or open a managed database
./ida-tui                        # attach, when exactly one database is registered
```

ida-tui never owns an IDA process — it takes a **lease**. A matching database open
in the IDA GUI is reused, otherwise Code Mode starts or shares a managed idalib
worker. Quitting drops the lease and leaves everyone else alone.

Headerless blobs need a hint, or IDA assumes x86 at address 0 and analyses nothing:

```sh
./ida-tui fw.bin --processor arm --base 0x8000000
```

These apply only when the database is **created** — an existing IDB already records
them. On ARM, `t` toggles ARM/Thumb at the cursor, `T` scans a vector table for
Thumb entry points.

## Keys

| | |
|---|---|
| `enter` `escape` | follow / back |
| `tab` `F5` | listing ↔ pseudocode |
| `space` | control-flow graph (`z` zoom, `m` minimap, `J`/`K` walk edges) |
| `s` | split view — listing and pseudocode, cursor-synced |
| `g` `/` `?` | goto · search · search back |
| `x` `n` `y` `;` | xrefs · rename · retype · comment |
| `c` `d` `p` `u` `a` | make code · data · function · undefine · string |
| `o` `O` `B` | cycle this literal's format · reverse · opcode bytes |
| `\` `"` `ctrl+t` | hex · strings · structs |
| `ctrl+n` `ctrl+p` | symbol palette · command palette |
| `ctrl+s` `ctrl+l` `q` | save · reload as… · quit |
| `F1` | all of them |

## What's in it

**Listing** — code, data and undefined runs in one continuous view, with IDA's own
colours. Line-virtualized: a 400 MB binary scrolls like a text file.

**Decompiler** (`tab`) — Hex-Rays pseudocode, highlighted, with per-line address
anchors. Renames, retypes and comments write back.

**Graph** (`space`) — basic blocks laid out with a real layered (Sugiyama) algorithm
and routed, colour-coded edges. The boxes hold the *same rows* as the listing, so
renames and xrefs work inside them. → [`docs/GRAPH_VIEW.md`](docs/GRAPH_VIEW.md)

**Split view** (`s`) — listing and pseudocode side by side, cursor-synced. The
focused pane drives; the other highlights the instructions the current C line owns.

**Search** (`ctrl+f`) — the whole database, as **text** through the disassembly or as
**bytes** with IDA's wildcard patterns (`48 8b ?? c3`). It guesses which you meant;
`hex:`/`text:` overrides.

**Structs / types** (`ctrl+t`) — local types as plain C, editable and highlighted.
`ctrl+s` declares it straight back into the database.

**Literal formats** (`o`) — hex → decimal → binary → char → offset, IDA's own key.
Skips the stops that wouldn't change anything, so no press is a silent no-op.

**Findings export** (`ctrl+e`) — the session as a markdown writeup: your comments,
names and prototypes, grouped by function. idatui journals its own edits, so the
report is *yours*, not IDA's analyzer's.

**Execution traces** — load a [Tenet](https://github.com/gaasedelen/tenet) trace and
move through time. Both code views paint the execution trail; the dock shows
registers and stack as of that instant.

```sh
./ida-tui /path/to/binary --trace trace.0.log     # ] [ step · } { step over
```

**RPC** — drive the live TUI from another process (agent-driven RE, livestreams):

```sh
./ida-tui /abs/path/bin --rpc /tmp/ida.sock
python -m idatui.drive pc main               # pseudocode of main
python -m idatui.drive rename sub_5BE0 foo   # goto + rename
```

→ [`docs/RPC.md`](docs/RPC.md) · scripted feature tour for screen recordings:
`python tools/demo.py --spawn`

**Also** — hex view (`\`), strings (`"`), symbol and command palettes
(`ctrl+n`/`ctrl+p`), multi-binary projects, and a splash that renders as a real
image on terminals speaking the kitty graphics protocol.

## Tests

```sh
python3 tests/run.py --fast     # 380 checks, <1s, any python3 — between edits
python3 tests/run.py --list     # what runs, and what needs IDA
python3 tests/run.py            # 1031 checks, ~50s — before a commit
```

Every suite declares `NEEDS_IDA`; `--fast` runs only the pure ones (stdlib, no
IDA, no database). The rest drive a headless Textual `Pilot` against a real
database. Iterate on one with `--only`:

```sh
~/ida-venv/bin/python tests/test_scenarios.py targets/echo --only hex,rename
```

Before optimising or debugging a slow run, read
[`.fastfeedback/SPEED.md`](.fastfeedback/SPEED.md) — per-suite timings, the known
flake, and the four ways a test here wastes minutes.

## Docs

- [`docs/RPC.md`](docs/RPC.md) — the RPC protocol, verb by verb
- [`docs/GRAPH_VIEW.md`](docs/GRAPH_VIEW.md) — how the graph is laid out
- [`docs/CODEMODE_UPSTREAM.md`](docs/CODEMODE_UPSTREAM.md) — findings from porting to
  IDA Code Mode, and which are fixed upstream
- [`docs/PROJECTS.md`](docs/PROJECTS.md), [`docs/SPLIT_VIEW.md`](docs/SPLIT_VIEW.md),
  [`docs/TEXTUAL_NOTES.md`](docs/TEXTUAL_NOTES.md),
  [`docs/PAGING_FINDINGS.md`](docs/PAGING_FINDINGS.md),
  [`docs/TRISKEL_EVAL.md`](docs/TRISKEL_EVAL.md)

### Working on this with an LLM agent

[`.agents/skills/idatui/SKILL.md`](.agents/skills/idatui/SKILL.md) is an
[Agent Skills](https://agentskills.io/specification) skill covering the architecture,
the test loop, and the traps that cost real time here. Compatible harnesses pick it
up automatically; point others at the file. (A user-level skill of the same name
wins, so symlink yours if you keep one.)

—

[sl0p.foo](https://sl0p.foo)