IDA Colors
Parser for color tags in IDA.
Usage
$ uv run ida-colors <path-to-idb>
...
"LDR X8, [X19,#0x10]"
Insn("LDR")
Opnd1(Reg("X8"))
Opnd2(Symbol("["), Reg("X19"), Symbol(",#"), Number("0x10"), Symbol("]"))
...
Numbers
numbers() returns the integers of a parsed line, with the - printed in front of each one applied:
>>> from ida_colors import numbers, parse_full
>>> numbers(parse_full(ida_lines.generate_disasm_line(ea, 0))) # STP XZR, XZR, [X1,#-0xD8]
[Number(value=-216, operand=3, standalone=False)]
standalone is true when the number is the entire operand, give or take a #, = or -: #0x10, -1 and
=0xCBF29CE4 are, while [X1,#0x10] and [rsp+28h+var_20] are not.
u8() to u64() and i8() to i64() reinterpret the value at a width, so -1 and 0xFFFFFFFF compare equal as
u32(), and return None when it doesn't fit. Spellings other than plain decimal, 0x10 and 10h (floats, chars,
other radixes) are skipped rather than guessed.
Strings
strings() returns the strings and chars that IDA shows in a line's automatic comments, as printed: quotes removed,
escapes kept.
>>> from ida_colors import parse_full, strings
>>> strings(parse_full(ida_lines.generate_disasm_line(ea, 0))) # lea rsi, aSslSession ; "SSL-Session:\n"
[String(text='SSL-Session:\\n', char=False, addr=844343, truncated=False)]
addr is where the string starts, also when IDA shows it through a pointer ("/dev/urandom" ...). truncated is
true when IDA cut it short ("abi.NewName: tag too long: hw.optional."...). Chars (sub esi, 35h ; '5') have char
set and no addr. Names shown the same way (; __gmon_start__) and anything else that doesn't look exactly like a
string or a char are skipped.
The CLI needs IDA 9+ and the ida extra (idapro). The parser itself has no dependencies.
Development
$ uv run ruff check && uv run ruff format --check
$ uv run ty check
$ uv run pytest
tests/test_ida_constants.py checks the constants copied from IDA against a local IDA install, and is
skipped when idapro can't load one. tests/test_ida_numbers.py checks parsed immediates against IDA's operand values
on every .i64 in $IDA_COLORS_IDBS (opened as temporary copies), and tests/test_ida_strings.py checks parsed
strings against the string literals there. Both are skipped when it's unset.
Why?
IDA's disassembly isn't just the decoded instruction. Between decode_insn and the line you see, the processor module's
printer applies a lot of heuristics and user annotations: offsets, stack variables, struct offsets, enums, chars,
@PAGE/@PAGEOFF pairs, hidden implicit operands. The printed line is the only place where all of that comes together,
and IDA marks it up with color tags. Parsing the tags gets you what IDA decided, without reimplementing its printer for
every processor.
The textbook alternative, decode_insn and op_t.type (o_imm, o_mem, o_displ, ...), tells you what the bytes
encode, not what they mean:
| Instruction | decode_insn says |
IDA prints |
|---|---|---|
PowerPC addis r30, r30, (off_11FA38 - loc_1923C)@ha |
o_imm, value 0x10 |
the high half of an address difference |
RISC-V auipc t2, %pcrel_hi(off_C8380) |
o_imm, value 0xbc |
a PC-relative reference to off_C8380 |
ARM64 ADRP X16, #qword_11FFF8@PAGE |
o_imm, value 0x11f000 |
a reference to qword_11FFF8 |
SPARC add %fp, arg_727, %l1 |
o_imm, value 0x727 |
the stack argument arg_727 |
x86-64 mov [rbp+var_30], rax |
o_displ, value 0xffffffffffffffd0 |
the stack variable var_30 |
x86-64 lea rdi, ds:1[rdx*2] |
o_mem, address 0x1 |
a plain number |
RISC-V nop |
one operand, o_imm |
no operands |
PowerPC mflr r0 |
two operands, the second o_idpspec0 |
one operand |
x86-64 mul rcx |
two operands, implicit rax first |
one operand, tagged as operand 2 |
Metadata
Release files for ida-colors 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ida_colors-0.0.3.tar.gz | 10.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ida_colors-0.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.5 kB
Release files / ida_colors-0.0.3.tar.gz
| Download URL | ida_colors-0.0.3.tar.gz |
|---|---|
| Size | 10.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f22ec48f980a2d8b8faea1f565294842824e13e9398961fcaceca2494cf7d34a
|
|
BLAKE2b-256 checksum How to use checksums |
0da75bf128c394c4e134c8a5cee304f49eae86e8439283540f10df81de65d291
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / ida_colors-0.0.3-py3-none-any.whl
| Download URL | ida_colors-0.0.3-py3-none-any.whl |
|---|---|
| Size | 13.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7340dd18333da77a30937d3e3215ebf1dd2c2cb90b804f2bfada6f31f5768dc7
|
|
BLAKE2b-256 checksum How to use checksums |
034a8fc71fefbfdd1dc4a809dc52ceb21a8810f0bc5b9fa9473b6b792da8df97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|