From 2eb2a0a8cff586fffecfcb068c53b65e8f6f9839 Mon Sep 17 00:00:00 2001 From: blasty Date: Fri, 7 Aug 2026 22:55:27 +0200 Subject: Export findings as markdown (Ctrl+E), and the journal that makes it true The output of an RE session is what you worked out, and it was locked in a .i64 that only IDA can read. Ctrl+E (or `drive export`, or the `export` RPC verb) writes it out: your comments grouped by function with the line each annotates, the names and prototypes you set, the types you declared. **The hard part was provenance, and it needed a mechanism, not a filter.** A database does not record WHO wrote a comment or a name. IDA's analyzer sets `; switch 73 cases` and `; s1` with the same `set_cmt` a person uses, and the ELF loader sets `elf_gnu_hash_nbuckets` and `File class: 64-bit` the same way. Four probes, all negative: the FF_COMM flag is identical, `get_cmt` returns them all, `generate_disasm_line` tags every one of them COLOR_REGCMT (not COLOR_AUTOCMT), and they survive with auto-comments switched off. A first cut filtered by shape and produced a report whose first screen was ELF header trivia and `; jumptable ... case 99`. So idatui journals its own edits (idatui/journal.py) into a netnode in the database: it rides along in the .i64, it is still there next session, and the report is then exactly what was done here -- 2 findings out of a database carrying 693 other annotations. Recorded at the choke points in edit_ctl (rename, name-address, comment, retype) and in the struct editor; flushed on save, on export and on quit, so no edit pays a round trip. Without a journal (a database worked on in the IDA GUI, or predating this) the report falls back to filtering by shape -- dummy names, imports, loader segments, the analyzer's stereotyped switch/jumptable strings -- and says so in the document rather than claiming authorship it cannot prove. idatui/findings.py splits gather (needs IDA) from render (does not), so the formatting, grouping, sorting, escaping and the empty cases are tested offline: tests/test_findings.py, 32 checks, no worker, 0.1s. The pilot scenario covers the round trip that matters -- edit through the UI, export, find it in the file, and reload the journal from the .i64. Full suite: 842 passed, 0 failed, 51.2s. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'README.md') diff --git a/README.md b/README.md index c52019b..1092219 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,12 @@ a 400 MB binary scrolls like a text file. **Decompiler** — Hex-Rays pseudocode with syntax highlighting, per-line address anchors, and rename/retype/comment that write back. +**Findings export** (`ctrl+e`) — the session as a markdown writeup: your +comments grouped by function, the names and prototypes you set, the types you +declared. A `.i64` does not record *who* wrote a comment — IDA's own analyzer +uses the same call — so idatui journals its edits into the database as it makes +them, and the report is built from that. Also `python -m idatui.drive export`. + **Structs / types** (`ctrl+t`) — local types as plain C: the list on the left, an editable, syntax-highlighted definition on the right. `Ctrl+S` declares it back into the database and reformats to IDA's own layout, `Ctrl+N` starts a new -- cgit v1.3.1-sl0p