codevanta 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. codevanta/__init__.py +1 -0
  2. codevanta/analysis/__init__.py +1 -0
  3. codevanta/analysis/binary_diff.py +1168 -0
  4. codevanta/analysis/callgraph.py +542 -0
  5. codevanta/analysis/cfg.py +1201 -0
  6. codevanta/analysis/dataflow.py +762 -0
  7. codevanta/analysis/debugger.py +289 -0
  8. codevanta/analysis/debuginfo.py +304 -0
  9. codevanta/analysis/decompile.py +1094 -0
  10. codevanta/analysis/decompilers/__init__.py +250 -0
  11. codevanta/analysis/decompilers/angr_backend.py +251 -0
  12. codevanta/analysis/decompilers/base.py +278 -0
  13. codevanta/analysis/decompilers/ghidra_backend.py +316 -0
  14. codevanta/analysis/dynamic.py +756 -0
  15. codevanta/analysis/emulate.py +1349 -0
  16. codevanta/analysis/evidence_bundle.py +736 -0
  17. codevanta/analysis/function_hash.py +562 -0
  18. codevanta/analysis/graph_export.py +441 -0
  19. codevanta/analysis/html_view.py +695 -0
  20. codevanta/analysis/jump_tables.py +546 -0
  21. codevanta/analysis/solver.py +715 -0
  22. codevanta/analysis/symbolic.py +1809 -0
  23. codevanta/analysis/trace.py +646 -0
  24. codevanta/analysis/type_propagation.py +1055 -0
  25. codevanta/analysis/type_recovery.py +1214 -0
  26. codevanta/analysis/vtables.py +572 -0
  27. codevanta/analysis/xrefs.py +434 -0
  28. codevanta/api/__init__.py +1 -0
  29. codevanta/cli/__init__.py +1 -0
  30. codevanta/cli/main.py +3038 -0
  31. codevanta/core/__init__.py +31 -0
  32. codevanta/core/disassembler.py +121 -0
  33. codevanta/core/entropy.py +237 -0
  34. codevanta/core/functions.py +176 -0
  35. codevanta/core/loader.py +1351 -0
  36. codevanta/core/report.py +306 -0
  37. codevanta/core/strings.py +109 -0
  38. codevanta/evidence/__init__.py +7 -0
  39. codevanta/evidence/confidence.py +36 -0
  40. codevanta/evidence/models.py +43 -0
  41. codevanta/evidence/provenance.py +37 -0
  42. codevanta/gui/__init__.py +46 -0
  43. codevanta/gui/layout.py +1384 -0
  44. codevanta/gui/server.py +1305 -0
  45. codevanta/ir/__init__.py +6 -0
  46. codevanta/ir/adapters/__init__.py +31 -0
  47. codevanta/ir/base.py +31 -0
  48. codevanta/ir/instruction.py +42 -0
  49. codevanta/mcp_server/__init__.py +5 -0
  50. codevanta/mcp_server/server.py +710 -0
  51. codevanta/mcp_server/tools.py +1364 -0
  52. codevanta/plugins/__init__.py +748 -0
  53. codevanta/setup/__init__.py +28 -0
  54. codevanta/setup/apply.py +22 -0
  55. codevanta/setup/clients.py +285 -0
  56. codevanta/setup/plan.py +79 -0
  57. codevanta/setup/verify.py +43 -0
  58. codevanta/storage/__init__.py +1 -0
  59. codevanta/storage/session.py +514 -0
  60. codevanta-0.1.0.dist-info/METADATA +688 -0
  61. codevanta-0.1.0.dist-info/RECORD +65 -0
  62. codevanta-0.1.0.dist-info/WHEEL +5 -0
  63. codevanta-0.1.0.dist-info/entry_points.txt +2 -0
  64. codevanta-0.1.0.dist-info/licenses/LICENSE +21 -0
  65. codevanta-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,688 @@
1
+ Metadata-Version: 2.4
2
+ Name: codevanta
3
+ Version: 0.1.0
4
+ Summary: CODEVANTA — Advanced Code Intelligence: AI-Powered Reverse Engineering & Binary Analysis Platform
5
+ Author: kevindoni
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/kevindoni/CODEVANTA
8
+ Project-URL: Repository, https://github.com/kevindoni/CODEVANTA
9
+ Project-URL: Issues, https://github.com/kevindoni/CODEVANTA/issues
10
+ Project-URL: Documentation, https://github.com/kevindoni/CODEVANTA/blob/main/docs/install.md
11
+ Project-URL: Changelog, https://github.com/kevindoni/CODEVANTA/blob/main/CHANGELOG.md
12
+ Keywords: reverse-engineering,binary-analysis,disassembly,security,pe,elf,mcp
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Information Technology
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Security
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: lief>=0.14
28
+ Requires-Dist: capstone>=5.0
29
+ Requires-Dist: typer>=0.12
30
+ Requires-Dist: rich>=13.0
31
+ Requires-Dist: mcp>=2.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=8.0; extra == "dev"
34
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.10; extra == "dev"
36
+ Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "dev"
37
+ Requires-Dist: ruff>=0.5; extra == "dev"
38
+ Requires-Dist: build>=1.2; extra == "dev"
39
+ Requires-Dist: unicorn>=2.0; extra == "dev"
40
+ Requires-Dist: pyelftools>=0.31; extra == "dev"
41
+ Provides-Extra: emulation
42
+ Requires-Dist: unicorn>=2.0; extra == "emulation"
43
+ Provides-Extra: dwarf
44
+ Requires-Dist: pyelftools>=0.31; extra == "dwarf"
45
+ Provides-Extra: decompilers
46
+ Requires-Dist: angr>=9.2; extra == "decompilers"
47
+ Requires-Dist: pyghidra>=2.0; extra == "decompilers"
48
+ Dynamic: license-file
49
+
50
+ # CODEVANTA
51
+
52
+ > **Advanced Code Intelligence** — Decode. Analyze. Understand.
53
+
54
+ CODEVANTA is an AI-powered code intelligence, reverse engineering, and binary
55
+ analysis platform. It helps engineers, security researchers, and analysts
56
+ understand software faster — from source code to executables with missing
57
+ symbols or incomplete documentation.
58
+
59
+ ## Vision
60
+
61
+ Build a unified workspace for unpacking software complexity by bringing
62
+ disassembly, decompilation, static analysis, binary inspection, and AI-assisted
63
+ reasoning into one clear, auditable, and extensible experience.
64
+
65
+ ## Core focus
66
+
67
+ - **Binary analysis** — inspect executables, libraries, metadata, sections, symbols, and binary formats.
68
+ - **Reverse engineering** — navigate functions, call graphs, data flow, cross-references, and program behavior.
69
+ - **AI code intelligence** — explain functions, summarize modules, detect patterns, and ask context-aware questions.
70
+ - **Static analysis** — identify suspicious behavior, dependencies, API usage, and risk indicators.
71
+ - **Analyst workflow** — manage workspaces, annotations, findings, evidence, and shareable reports.
72
+
73
+ ## Target workflow
74
+
75
+ ```text
76
+ Import target → Index & normalize → Disassemble/decompile → Analyze → Ask AI → Review evidence → Export report
77
+ ```
78
+
79
+ CODEVANTA prioritizes insights that can be traced back to technical evidence.
80
+ AI acts as a copilot to accelerate analysis, not as a replacement for analyst
81
+ verification.
82
+
83
+ ## Project status
84
+
85
+ 🚧 **Phase 1 (foundation) implemented** — binary loading, disassembly, string
86
+ extraction, function discovery, and JSON export are working and tested.
87
+
88
+ Delivered in phase 1:
89
+
90
+ - PE, ELF, Mach-O, and DEX loaders (format, architecture, bitness, endianness, entry point, image base).
91
+ - Sections, imports, exports, and symbol extraction — every finding carries evidence.
92
+ - x86/x64 disassembly of executable sections and the entry point.
93
+ - Function candidates from exports, function symbols, and the entry point, each with source and confidence.
94
+ - ASCII and UTF-16 string extraction (byte order follows the binary) with file offset and mapped virtual address.
95
+ - CLI: `info`, `functions`, `strings`, `disasm`, `analyze` (+ JSON report).
96
+ - **MCP server** (`codevanta mcp serve`) exposing the phase 1 tools to coding agents.
97
+ - **Guided setup** (`codevanta setup`) for Claude Code, Cursor, Cline, and VS Code, with plan preview, backups, and verification.
98
+
99
+ ### Phase 2 (in progress)
100
+
101
+ Phase 2 adds the first reverse-engineering views on top of the phase 1 engine:
102
+
103
+ - **Cross-references** (`analysis/xrefs.py`) — `call`/`jump`/`branch` references
104
+ recovered from direct branch operands in executable sections, each with
105
+ evidence and an optional callee name. Calls through an absolute or RIP-relative
106
+ pointer slot (`call qword ptr [0x402000]`, `call qword ptr [rip + 0xa]`) now
107
+ resolve to the slot: known imports become `call_import` with a `target_name`,
108
+ other slots become `call_indirect`, and register/indexed calls that cannot be
109
+ resolved are skipped and counted (`indirect_skipped`).
110
+ - **Control-flow graphs** (`analysis/cfg.py`) — basic blocks and successor edges
111
+ for one region. The default is a linear sweep with leader/terminator rules;
112
+ `build_recursive_cfg` (and `codevanta cfg --traversal recursive`) instead walks
113
+ control flow from the start address with a worklist and a visited set, so
114
+ blocks come from real branch targets and unreachable padding after a `ret` or
115
+ `jmp` is excluded. Indirect targets stay unresolved by default;
116
+ `resolve_indirect=True` (and `codevanta cfg --traversal recursive
117
+ --resolve-indirect`) decodes the pointer table behind a `jmp qword ptr [rip +
118
+ disp]` / `jmp qword ptr [abs]` and follows its executable targets, bounded per
119
+ traversal by `max_jump_tables` and `max_table_entries`.
120
+ - **Jump tables** (`analysis/jump_tables.py`) — `resolve_jump_table` decodes a
121
+ bounded array of absolute pointers (4 or 8 bytes, binary endianness) into
122
+ `JumpTableEntry` records with evidence. `mode="relative"` with an explicit
123
+ `base_address` instead reads signed 32-bit offsets and resolves
124
+ `target = base + offset`, which is the shape of position-independent switch
125
+ tables; a zero offset is a valid entry pointing at the base, not a terminator.
126
+ Both modes stop at the first out-of-window target, unmapped target, or
127
+ (with `executable_only`) non-executable target and report why, and both are
128
+ `medium` confidence because a slot array found by shape is evidence of a
129
+ dispatch table, not proof of one.
130
+ - **Function fingerprints** (`analysis/function_hash.py`) —
131
+ `function_fingerprint` takes one bounded linear sweep from an address and
132
+ returns a SHA-256 digest over the *normalized* instruction stream: mnemonics
133
+ are kept, every numeric literal is masked to `#`, and whitespace is collapsed.
134
+ It is `medium` confidence and explicitly not semantic equivalence — equal
135
+ digests are not byte equality, and masked branch targets make different
136
+ callees look alike.
137
+ - **Function similarity** (`analysis/function_hash.py`) — `normalized_tokens`
138
+ exposes the token stream the digest hashes, and `function_similarity` scores
139
+ two regions as multisets of those tokens: `sum(min) / sum(max)` of their
140
+ counts (the Ruzicka / weighted-Jaccard overlap) in `0.0 .. 1.0`, with the
141
+ shared count, both side totals, and a warning per truncated side. It is
142
+ `medium` confidence and a *shape* measure only: literals are masked and the
143
+ comparison is order-insensitive, so `1.0` is not equality and `0.0` is not
144
+ proof of different behaviour. Exposed as the `codevanta_similarity` MCP tool.
145
+ - **Structural binary diff** (`analysis/binary_diff.py`) — `diff_binaries`
146
+ compares two binaries as metadata only: functions matched by address then name,
147
+ sections/exports by name, imports by `(library, name)`. Deltas are `added`,
148
+ `removed`, or `changed`, and the whole comparison is `medium` confidence
149
+ because no bytes and no semantics are compared. `deep=True` adds a content
150
+ signal for address-matched functions only: when their fingerprints differ the
151
+ entry becomes `changed` with both digests, while every structural rule, and
152
+ structural-only mode, stays unchanged. `semantic=True` adds a *pairing* pass
153
+ instead of a new rule: the functions that address and name matching left
154
+ unpaired are scored with `function_similarity` and the highest scores at or
155
+ above `threshold` (default `0.9`) become one `changed` entry each, carrying a
156
+ `similarity` rounded to four decimals. Pairing is greedy — highest score first,
157
+ ties broken by address, one use per candidate — and it never overrides an
158
+ address or name match, so a leftover below the threshold keeps its
159
+ `added`/`removed` verdict. It is bounded twice: at most 4096 leftover pairs are
160
+ scored (the whole pass is skipped, with a warning, above that) and one score
161
+ reads at most 2000 instructions per side.
162
+ - **Call graph** (`analysis/callgraph.py`) — `call`, `call_import`, and
163
+ `call_indirect` cross-references aggregated into nodes and edges. Import slots
164
+ become `import` nodes labelled from the import table; unresolved callees stay
165
+ `external`. Caller attribution is heuristic (nearest function candidate at or
166
+ below the call site in the same section), so the graph reports `medium`
167
+ confidence and warns when a call site cannot be attributed.
168
+ - **Graph export** (`analysis/graph_export.py`) — the call graph rendered as
169
+ Graphviz DOT or GraphML by one dependency-free, deterministic exporter.
170
+ - **Offline graph viewer** (`analysis/html_view.py`) — `codevanta callgraph
171
+ --format html` writes one self-contained HTML5 document with an inline SVG
172
+ view: three kind-based columns, header counts, and a collapsible edge table.
173
+ One inline script adds drag-to-pan, mouse-wheel zoom (0.2x–8x), label search
174
+ with hit/dim highlighting, and per-kind filters. No CDN, no web font, no
175
+ library and no server, so it opens offline from disk — and with scripting
176
+ disabled the static view still renders in full.
177
+ - **Session storage** (`storage/session.py`) — additive SQLite records of each
178
+ analysis run (fingerprint, format, arch, entry point, function/string counts)
179
+ plus per-address analyst annotations (`annotate`, `annotations`,
180
+ `remove_annotation`; one replaceable note per address).
181
+ - **Struct-field suggestions** (`analysis/type_recovery.py`) — `suggest_struct`
182
+ reads the memory operands of a bounded window and reports one
183
+ `SuggestedField` per displacement. Only `[reg]`, `[reg + 0xNN]` and
184
+ `[reg - 0xNN]` are understood (index/scale and segment forms are skipped),
185
+ width comes from the `byte`/`word`/`dword`/`qword` keyword or else the
186
+ pointer width, direction comes from operand position with `cmp`/`test` always
187
+ reads, stack registers are skipped unless `include_stack=True`, and each
188
+ offset keeps its dominant width plus total read/write counts. Each suggestion
189
+ also carries two layout *hints* computed from the fields it reports:
190
+ `alignment`, the greatest common divisor of the absolute non-zero offsets
191
+ (`None` when fewer than two distinct ones were seen), and `array_groups`,
192
+ maximal runs of at least three consecutive fields that share one width and one
193
+ stride. Every record is `medium` confidence and explicitly heuristic: no type
194
+ names, no padding or struct-size inference, and offsets are bucketed per
195
+ displacement so different base registers share one bucket. Each field also
196
+ carries a `signed` hint read from the *mnemonics* that touched its offset:
197
+ `movsx`/`movsxd`/`sar`/`idiv`/`imul` say signed,
198
+ `movzx`/`shr`/`div`/`mul` say unsigned, and every other mnemonic says nothing.
199
+ Only one kind of hint at an offset gives `True`/`False`; no hint gives `None`,
200
+ and a contradiction gives `None` plus a `SignednessConflictWarning` naming the
201
+ offset. `None` means *no evidence*, never "safe", and the key is omitted from
202
+ the JSON rather than emitted as `null`. `suggest_structs` merges up to
203
+ `MAX_MERGED_WINDOWS` (16) windows of the same binary into one suggestion: one
204
+ field per offset, counters summed, the widest per-window width kept with a
205
+ `WidthConflictWarning` when the windows disagree, signedness folded with the
206
+ single-window rule except that a contradiction seen *inside* one window survives
207
+ to the merge (`None` plus a `SignednessConflictWarning`), and
208
+ `alignment`/`array_groups` recomputed from the merged fields. Addresses must be
209
+ unique; a *partial* overlap is allowed but announced with
210
+ `WindowOverlapWarning`, because the shared instructions are then counted by both
211
+ windows and the summed counters are upper bounds. `truncated` is the OR of the
212
+ merge cap and every window's own 64-offset cap, and `window_truncated` names the
213
+ windows that hit theirs. Duplicate, empty, non-integer, negative, or over-limit
214
+ addresses are rejected with `AnalysisError`, and the merge is bounded by
215
+ `max_windows * max_instructions` decoded instructions. The CLI reaches it by
216
+ repeating `--address`.
217
+ - **MCP tools** — `codevanta_similarity` joins `codevanta_struct`,
218
+ `codevanta_diff`, `codevanta_jump_table`, `codevanta_function_hash`,
219
+ `codevanta_xrefs`, `codevanta_cfg`, `codevanta_callgraph`,
220
+ `codevanta_session_save`, and `codevanta_session_list`, alongside the five
221
+ phase 1 tools (fifteen in total). `codevanta_diff` takes `max_functions`,
222
+ `deep`, `semantic`, and `threshold`, so the phase 2j pairing pass is reachable
223
+ from an agent without a separate `codevanta_similarity` call.
224
+ - **`analyze` integration** (`core/report.py`) — the `codevanta analyze` JSON
225
+ report can embed the phase 2 output under additive `xrefs` and `cfg` keys,
226
+ each with its own evidence and warnings, behind `--xrefs` and `--cfg`
227
+ (opt-in, like `--callgraph`). `xrefs` is bounded by `--xref-limit` (default
228
+ 2000) on top of the scanner's 4 MB decode budget; the entry-point CFG is
229
+ bounded by 2000 instructions and 500 blocks. Binaries with no executable
230
+ content still produce a report with degraded, warning-carrying sections.
231
+ - **CLI:** `codevanta struct` (with a repeatable `--address`/`-a` — more than one
232
+ value merges the windows and adds a `windows:` footer line — plus `--function`,
233
+ `--max-instructions`, `--max-fields`, `--include-stack`, `--json`, and a footer
234
+ reporting `alignment:` plus one line per array candidate or `arrays: none`,
235
+ closing with a `signed:` line),
236
+ `codevanta xrefs`, `codevanta cfg` (with
237
+ `--traversal linear|recursive`, default `linear`, and `--resolve-indirect` for
238
+ recursive traversals), `codevanta jump-table` (with
239
+ `--mode absolute|relative` and `--base ADDR` for signed-offset tables),
240
+ `codevanta diff` (with `--deep` for the normalized-shape comparison, and
241
+ `--semantic` / `--threshold` for the shape-similarity pairing),
242
+ `codevanta entropy` (per-section Shannon entropy with a `packed_hint`
243
+ heuristic, `--threshold`, `--max-sample-bytes`, `--json`),
244
+ `codevanta callgraph`, `codevanta analyze` (with `--callgraph` for the call
245
+ graph and `--xrefs` / `--cfg` / `--xref-limit` / `--json` for the phase 2
246
+ sections), plus the `session save|list|show|annotate|notes` subcommands.
247
+
248
+ Phase 2 is deliberately narrow: linear sweep by default with an additional
249
+ bounded recursive traversal for CFGs, direct branch targets plus
250
+ absolute/RIP-relative pointer slots only, jump tables as absolute 4/8-byte
251
+ pointer arrays or signed 32-bit offset tables with an analyst-supplied base
252
+ (`--mode relative --base`) — never register/indexed dispatch, call graph edges
253
+ from `call` / `call_import` / `call_indirect` only, no following calls into
254
+ callees, no cross-function analysis, a structural (metadata-only) binary diff
255
+ plus an opt-in shape-fingerprint comparison of address-matched functions, an
256
+ opt-in shape-similarity pairing of the leftovers, struct fields as per-offset
257
+ hypotheses from `[reg]`/`[reg ± disp]` operands only, struct evidence merged
258
+ across at most 16 windows of one binary through the `suggest_structs` API, and no
259
+ debugger yet. The
260
+ phase 2g switches are `jump-table --mode absolute|relative
261
+ --base ADDR` (plus the same `mode`/`base_address` arguments on
262
+ `resolve_jump_table`), the new `function_fingerprint` API, and `diff --deep`
263
+ (`deep=True`); the CFG's indirect resolution still uses the absolute layout.
264
+ Phase 2h adds `codevanta struct` (and the `suggest_struct` API) plus the
265
+ `codevanta_diff`, `codevanta_jump_table`, and `codevanta_function_hash` MCP
266
+ tools. Phase 2i adds the `alignment`/`array_groups` layout hints on a struct
267
+ suggestion, the `function_similarity`/`normalized_tokens` API, and the
268
+ `codevanta_struct` MCP tool. Phase 2j adds the opt-in semantic pairing pass on the
269
+ binary diff (`semantic=True`, `threshold` defaulting to `0.9`), the
270
+ `codevanta_similarity` MCP tool (fifteen tools), and the `signed` mnemonic hint on
271
+ struct fields, reachable as `diff --semantic --threshold` and as the
272
+ `codevanta struct` footer `signed:` line. Phase 2k adds the `deep` / `semantic` /
273
+ `threshold` arguments to the `codevanta_diff` MCP tool (fifteen tools, no new
274
+ registration), the semantic pass's cross-architecture guard — the pass is skipped
275
+ with a warning naming both `BinaryInfo.architecture` tokens, which are compared
276
+ after trimming whitespace and lower-casing only, so a hand-built `AMD64` does not
277
+ match `x86_64`, headers the loader cannot map (PE `MIPS`, ELF IA-64/RISC-V/PowerPC/
278
+ s390) come out `unknown`, two `unknown` sides bypass the guard, and a diff with no
279
+ leftover on one side emits no warning at all — and the `suggest_structs`
280
+ merged-window API over up to `MAX_MERGED_WINDOWS` (16) addresses of one binary,
281
+ reachable as `codevanta struct -a A -a B` — one field per offset, widest width
282
+ winning, with a `windows:` footer line.
283
+ See [docs/phase2.md](docs/phase2.md), [docs/phase2b.md](docs/phase2b.md),
284
+ [docs/phase2c.md](docs/phase2c.md), [docs/phase2d.md](docs/phase2d.md),
285
+ [docs/phase2e.md](docs/phase2e.md), [docs/phase2f.md](docs/phase2f.md),
286
+ [docs/phase2g.md](docs/phase2g.md), [docs/phase2h.md](docs/phase2h.md),
287
+ [docs/phase2i.md](docs/phase2i.md), [docs/phase2j.md](docs/phase2j.md), and
288
+ [docs/phase2k.md](docs/phase2k.md) for
289
+ scope, confidence semantics, and limitations.
290
+
291
+ ## Installation
292
+
293
+ ```powershell
294
+ cd D:\PALIKASIKU\CODEVANTA
295
+ python -m pip install -e ".[dev]"
296
+ ```
297
+
298
+ One-line install (installs, then prints a setup plan):
299
+
300
+ ```powershell
301
+ irm https://raw.githubusercontent.com/kevindoni/CODEVANTA/main/scripts/install.ps1 | iex
302
+ ```
303
+
304
+ See [docs/install.md](docs/install.md) for the macOS/Linux one-liner, manual
305
+ installs, and the full setup/uninstall reference.
306
+
307
+ ## Usage
308
+
309
+ ```powershell
310
+ codevanta info C:\Windows\System32\notepad.exe
311
+ codevanta functions C:\Windows\System32\kernel32.dll --limit 8
312
+ codevanta strings C:\Windows\System32\notepad.exe --min-length 8
313
+ codevanta entropy C:\Windows\System32\notepad.exe --threshold 7.2
314
+ codevanta disasm C:\Windows\System32\notepad.exe --count 40
315
+ codevanta analyze samples\elf64_text.bin --output samples\report.json
316
+
317
+ # Phase 2
318
+ codevanta analyze C:\Windows\System32\notepad.exe --xrefs --cfg # report + xrefs + cfg
319
+ codevanta analyze C:\Windows\System32\notepad.exe # phase 1 only
320
+ codevanta analyze C:\Windows\System32\notepad.exe --xref-limit 200 --xrefs -o report.json
321
+ codevanta xrefs C:\Windows\System32\notepad.exe --limit 40
322
+ codevanta cfg C:\Windows\System32\notepad.exe --address 0x140001000
323
+ codevanta cfg C:\Windows\System32\notepad.exe --address 0x140001000 --traversal recursive
324
+ codevanta cfg C:\Windows\System32\notepad.exe --address 0x140001000 --traversal recursive --resolve-indirect
325
+ codevanta jump-table C:\Windows\System32\notepad.exe --address 0x140003000
326
+ codevanta jump-table C:\Windows\System32\notepad.exe --address 0x140003000 --entries 64 --json
327
+ codevanta diff samples\v1.bin samples\v2.bin
328
+ codevanta diff samples\v1.bin samples\v2.bin --max-functions 20000 --json
329
+ codevanta diff samples\v1.bin samples\v2.bin --semantic
330
+ codevanta diff samples\v1.bin samples\v2.bin --semantic --threshold 0.75 --json
331
+ codevanta callgraph C:\Windows\System32\notepad.exe --format dot -o callgraph.dot
332
+ codevanta callgraph C:\Windows\System32\notepad.exe --format graphml -o callgraph.graphml
333
+ codevanta callgraph C:\Windows\System32\notepad.exe --format html -o callgraph.html
334
+ Invoke-Item callgraph.html # drag to pan, wheel to zoom, search labels, filter by kind
335
+ codevanta analyze C:\Windows\System32\notepad.exe --callgraph -o report.json
336
+ codevanta session save C:\Windows\System32\notepad.exe --notes "baseline triage"
337
+ codevanta session list --limit 10
338
+ codevanta session show 4f9c1a7b2d3e
339
+ codevanta session annotate 4f9c1a7b2d3e 0x401000 "decrypts config with XOR 0x5a"
340
+ codevanta session notes 4f9c1a7b2d3e
341
+ codevanta struct C:\Windows\System32\notepad.exe --address 0x140001000
342
+ codevanta struct samples\handle.bin --function process --include-stack --json
343
+
344
+ # Phase 3
345
+ codevanta decompile C:\Windows\System32\notepad.exe 0x1400019c0 --backend native
346
+ codevanta decompile samples\pe64_text.bin --json
347
+ codevanta decompile samples\pe64_text.bin --max-instructions 20 --output rendering.c
348
+ codevanta emulate samples\pe64_text.bin # returns 42
349
+ codevanta emulate samples\pe64_text.bin --set rdi=2 --mem 0x600000=48454c4c4f
350
+ codevanta emulate C:\Windows\System32\notepad.exe --resolve-target # jmp/call [rip+..]
351
+
352
+ # Phase 5 — symbol-grade views and dynamic sessions
353
+ codevanta dwarf samples\hello-dwarf # DWARF symbols + type layouts
354
+ codevanta vtable samples\shapes-vtable --scan # vtable candidates + thunk chains
355
+ codevanta trace samples\elf64_text.bin --input samples\gdb_trace.log
356
+ codevanta trace samples\elf64_text.bin --input samples\frida_trace.jsonl --json
357
+ codevanta attach samples\elf64_text.bin 0x401000 --provider gdb --max-hits 4 --write session
358
+
359
+ # Phase 6 — exploration, dataflow, evidence, plugins
360
+ codevanta symbolic samples\pe64_text.bin --max-paths 16 --set edi=1
361
+ codevanta symbolic samples\pe64_text.bin --json # PathExploration document
362
+ codevanta dataflow samples\elf64_text.bin # def-use + provable constants
363
+ codevanta evidence-bundle samples\elf64_text.bin --entry report=samples\report_elf64.json -o bundle.json
364
+ codevanta plugins list
365
+ codevanta plugins run metrics samples\elf64_text.bin
366
+ ```
367
+
368
+ `diff --semantic` prints one dim
369
+ `semantic pair 0x401000 -> 0x401010 (<name>): similarity 1.0000` line per pair
370
+ after the unchanged function table (`--threshold` defaults to `0.9` and is
371
+ validated before either file is loaded), and `codevanta struct` closes its footer
372
+ with `signed: 0x10 signed, 0x18 unsigned`, or `signed: none` when no mnemonic
373
+ hinted anything. The same data comes back from Python and JSON:
374
+
375
+ ```python
376
+ from codevanta.analysis.binary_diff import diff_binaries
377
+
378
+ # Leftovers paired by normalized instruction-shape similarity (default 0.9)
379
+ diff = diff_binaries("samples/v1.bin", "samples/v2.bin", semantic=True, threshold=0.9)
380
+ for delta in diff.functions_changed:
381
+ print(hex(delta.address), delta.similarity) # None unless the pair was scored
382
+ ```
383
+
384
+ All addresses in reports are absolute virtual addresses (VA). Function
385
+ candidates always state their detection source (`export`, `symbol`,
386
+ `entry_point`) and confidence (`high`, `medium`, `low`, `unknown`).
387
+
388
+ The `codevanta analyze` JSON report can include the phase 2 results: `--xrefs`
389
+ adds an `xrefs` section (bounded by `--xref-limit`, default 2000) and `--cfg`
390
+ adds the entry-point `cfg` (at most 2000 instructions and 500 blocks), both with
391
+ evidence and warnings. Binaries with no executable content still produce a
392
+ report with degraded, warning-carrying sections, and without the flags the
393
+ report is the phase 1 payload.
394
+
395
+ Phase 2 results carry their own evidence: xrefs are `certain` (the target is
396
+ read directly from the decoded operand), CFG blocks are `medium` (block
397
+ boundaries come from mnemonic heuristics), jump-table entries are `medium` (a
398
+ pointer array found by shape is not proof a dispatcher indexes it), the
399
+ structural diff is `medium` (metadata only, never bytes or behavior), the call
400
+ graph is `medium` (calls are decoded, but caller attribution is a
401
+ nearest-candidate heuristic), struct fields are `medium` (an operand proves
402
+ an access, not a type or a layout — `alignment` is only the gcd of the observed
403
+ offsets and an `array_groups` entry is only a repeated width and stride, and a
404
+ `signed` hint is only the mnemonics that happened to touch that offset), a
405
+ function fingerprint is `medium` (normalized shape, not bytes), and a similarity
406
+ score is `medium` (multiset overlap of normalized tokens, not semantics).
407
+ `codevanta callgraph` defaults to
408
+ `--format json`
409
+ and can emit `dot`, `graphml`, or `html` (one self-contained file with an inline
410
+ SVG view that pans, zooms, searches, and filters by kind without any CDN, opened
411
+ straight from disk); `codevanta cfg` defaults to the entry point and to
412
+ `--traversal linear`, `--traversal recursive` reports the same shape with
413
+ evidence source `cfg.recursive_traversal`, and `--resolve-indirect` (recursive
414
+ only) adds jump-table successors; `codevanta jump-table` takes a decimal or `0x`
415
+ hex `--address` and a `--entries` slot budget; `codevanta diff` exits `0`
416
+ whether or not the binaries differ, and `2` on load or input errors;
417
+ `codevanta struct` defaults to the entry point, starts at `--address` or
418
+ `--function` when given, reports each field's offset, width, read and write
419
+ counts, and adds a footer naming the base registers the sweep saw — a single
420
+ window re-sweeps itself to find them, while a merged run does not decode anything
421
+ twice and therefore prints `base registers: not recorded by the merge` — the
422
+ inferred `alignment:` (`unknown` when none could be derived), one
423
+ `array at 0x..: N x W-byte, stride S` line per array candidate (or
424
+ `arrays: none`), plus one `warning:` line per limitation (`--json` for the full
425
+ document, including `alignment` and `array_groups`). Sessions
426
+ default to `$env:CODEVANTA_DB` or `~/.codevanta/sessions.db`, and
427
+ `session annotate` accepts decimal or `0x` hex addresses.
428
+
429
+ Calls through a pointer slot report the **slot** address, not the callee: the
430
+ pointer is read at run time, so the code behind it is unknown here. A slot that
431
+ matches the import table becomes `call_import` with a `target_name`; any other
432
+ absolute or RIP-relative slot becomes `call_indirect` (`high` confidence — the
433
+ slot is proven, the callee is not); register and indexed operands are skipped and
434
+ counted in `indirect_skipped`, which `codevanta xrefs --json` prints.
435
+ `codevanta analyze --callgraph` embeds the graph in the report, bounded to 1000
436
+ functions and 5000 edges, and marks it `truncated` when a cap cuts it short.
437
+ The `xrefs` and `cfg` sections use the same opt-in shape (`--xrefs`, `--cfg`).
438
+
439
+ `codevanta dwarf` reads DWARF debug info that a build kept: producer-grade
440
+ function names with byte-exact extents plus named type layouts (structs,
441
+ unions, enums, classes) with byte sizes — the strongest symbol evidence a
442
+ binary can carry (`dwarf.debug_info`, high confidence). ELF only; needs the
443
+ optional `pyelftools` extra (`pip install -e ".[dwarf]"`, already in `dev`),
444
+ and fails with a typed message naming the extra when it is missing.
445
+ PDB (PE) stays open: the LIEF OSS build gates its PDB parser behind the
446
+ Extended distribution.
447
+
448
+ `codevanta vtable` recovers indirect cross-references the xref scanner cannot
449
+ see: C++ vtable candidates — runs of consecutive code pointers in data
450
+ sections (PIE slots are filled via dynamic-relocation overlay, so virtualized
451
+ builds work) — and thunk chains, where a slot target is a one-instruction
452
+ tail-call that forwards to the real override (`resolved_target`). Every
453
+ candidate and slot carries `vtable.candidate` / `vtable.slot_ref` /
454
+ `vtable.thunk_chain` evidence at **medium** confidence: a run of code pointers
455
+ is a heuristic, not proof.
456
+
457
+ Phase 3 adds the two commands that read a function instead of a file:
458
+ `codevanta decompile` renders one function as pseudo-C and `codevanta emulate`
459
+ computes what it returns. Decompilation is `low` confidence by design — control
460
+ flow, argument count and types come from mnemonics only — and every result says
461
+ so in its evidence record and in a header comment inside the text.
462
+ `--backend auto` (the default) prefers an installed Ghidra/pyghidra or angr and
463
+ falls back to the built-in renderer, printing one `warning:` per skipped backend
464
+ so a fallback is never silent; `--backend ghidra|angr` is strict and exits `2`
465
+ with the probe's reason instead of substituting a provider. Emulation runs the
466
+ file's bytes on a private unicorn CPU — nothing executes on the host — and always
467
+ ends with a stated reason (`return`, `budget`, `unmapped`, `unsupported`,
468
+ `error`); a value left in `rax` after a budget stop is reported as a register,
469
+ never as a return value. `codevanta emulate` needs the optional `unicorn` engine
470
+ and exits `2` with the reason when it is missing. See
471
+ [docs/phase3.md](docs/phase3.md).
472
+ ### Try it in the browser
473
+
474
+ ```powershell
475
+ codevanta gui # http://127.0.0.1:8765/ (opens a browser)
476
+ codevanta gui --port 9000 # pick a port
477
+ codevanta gui --no-browser # print the URL and wait
478
+ ```
479
+
480
+ `codevanta gui` serves one self-contained dashboard page over a loopback-only,
481
+ read-only HTTP server — no extra dependencies, no network access, and the
482
+ analysed file is never executed or written. The page drives fourteen JSON routes
483
+ (`/api/health`, `/api/info`, `/api/functions`, `/api/strings`, `/api/xrefs`,
484
+ `/api/cfg`, `/api/struct`, `/api/callgraph`, `/api/diff`, `/api/decompile`,
485
+ `/api/emulate`, `/api/symbolic`, `/api/session_save`, `/api/session_list`), each
486
+ a thin adapter over the engine of the same name, so the browser shows the same
487
+ evidence payload the CLI prints (`/api/session_save` is the one route that
488
+ writes — one session row in the local SQLite store). Try it on the committed
489
+ samples:
490
+
491
+ ```powershell
492
+ codevanta info samples\pe64_text.bin # PE32+ with one export
493
+ codevanta disasm samples\macho64_text.bin --count 10
494
+ codevanta disasm samples\elf64_text.bin # 5-byte .text, easiest to read
495
+ ```
496
+
497
+ See [docs/samples.md](docs/samples.md) for every sample file and
498
+ [docs/api.md](docs/api.md#codevantagui-local-web-dashboard) for the route
499
+ parameters, status codes, and the `create_server` / `serve` Python API.
500
+
501
+ ## Coding agent setup (MCP)
502
+
503
+ CODEVANTA exposes the same analysis as MCP tools, so coding agents can call it
504
+ directly:
505
+
506
+ ```powershell
507
+ codevanta setup --list # status per client and scope
508
+ codevanta setup --dry-run --client cursor # show the plan, write nothing
509
+ codevanta setup --client cursor --yes --verify # apply and verify
510
+ codevanta setup --client claude --scope user
511
+ codevanta setup --client vscode --scope project --project .
512
+ codevanta uninstall --client cursor
513
+ codevanta mcp serve # run the server over stdio
514
+ codevanta mcp serve --transport sse --port 8000 # HTTP transports are opt-in
515
+ ```
516
+
517
+ Supported clients: `claude` (Claude Code), `cursor`, `cline` (VS Code
518
+ extension), `vscode` (Copilot, project scope).
519
+
520
+ Safety model: every run prints the exact file changes and a diff first; nothing
521
+ is written without `--yes` (or an interactive confirmation); existing configs
522
+ are backed up as `*.codevanta.bak`; re-running the same command is a no-op.
523
+
524
+ MCP tools (twenty-two): `codevanta_info`, `codevanta_functions`,
525
+ `codevanta_strings`, `codevanta_disasm`, `codevanta_analyze`,
526
+ `codevanta_xrefs`, `codevanta_cfg`, `codevanta_callgraph`, `codevanta_diff`,
527
+ `codevanta_jump_table`, `codevanta_function_hash`, `codevanta_similarity`,
528
+ `codevanta_struct`, `codevanta_entropy`, `codevanta_decompile`,
529
+ `codevanta_dwarf`, `codevanta_vtable`, `codevanta_trace`,
530
+ `codevanta_symbolic`, `codevanta_dataflow`,
531
+ `codevanta_session_save`, `codevanta_session_list`.
532
+ `codevanta_analyze` mirrors
533
+ the CLI flags (`include_xrefs` / `include_cfg` / `include_callgraph`, default off)
534
+ so a single call can carry the phase 2 sections when an agent prefers one payload.
535
+
536
+ `codevanta_symbolic` (`path`, `address`, `max_paths`, `max_steps`) and
537
+ `codevanta_dataflow` (`path`, `address`, `max_instructions`, `max_blocks`)
538
+ expose the phase 6 engines: the honest-unicorn path exploration (seeded
539
+ directions flagged, no constraint solving) and the def-use / constant-folding
540
+ pass over the recursive CFG. Both return the module's `to_dict()` payload with
541
+ `evidence`; neither executes anything on the host.
542
+
543
+ `codevanta_decompile` takes `path`, `address`, `backend` (`auto` by default) and
544
+ the same `max_instructions`/`max_blocks` budgets as the CLI, and returns the
545
+ rendering with the provider that produced it, its `language`, `warnings`,
546
+ `evidence` and the number of basic blocks it covers.
547
+
548
+ `codevanta_callgraph` takes the same bounded limits as the CLI
549
+ (`limit_functions`, `limit_edges`, defaulting to 1000 and 5000) and returns nodes,
550
+ edges, `truncated`, `warnings`, and evidence. Import targets arrive as `import`
551
+ nodes labelled from the import table; unresolved callees stay `external`.
552
+ `codevanta_analyze` keeps its phase 1 payload and has no call-graph or phase 2
553
+ flag; ask for the sections from Python with `build_report(path,
554
+ include_xrefs=True)` or use `codevanta_xrefs` / `codevanta_cfg`.
555
+
556
+ `codevanta_diff` compares two binaries structurally (`max_functions` default
557
+ 5000, `deep=False`) and reports `warnings` when a cap truncated the comparison.
558
+ The semantic pairing pass is not exposed here yet — call `codevanta_similarity`
559
+ on the addresses that matter instead.
560
+ `codevanta_jump_table` defaults to `mode="absolute"` and requires `base` when
561
+ `mode="relative"`; `entries` defaults to 256 and values above 4096 are rejected.
562
+ `codevanta_function_hash` returns a SHA-256 over the normalized instruction
563
+ shape (numeric literals masked) with a `truncated` flag — equal digests are not
564
+ byte equality, and different digests are not a semantic difference.
565
+ `codevanta_struct` takes the same `address`/`function`/`max_instructions`/
566
+ `max_fields`/`include_stack` arguments as the CLI and returns the suggestion
567
+ document unchanged, including `alignment` (a number or `null`), `array_groups`,
568
+ and each field's `signed` hint when it is known; fields are `medium` heuristics
569
+ from operand shapes, never verified types.
570
+ `codevanta_similarity` compares two regions as multisets of normalized
571
+ instruction tokens and returns `score` (`shared / union`, four decimals),
572
+ `shared`, `left_total`, `right_total`, `union`, `warnings`, and evidence — a
573
+ shape measure, so `1.0` is not equality.
574
+
575
+ Prompt you can paste into a coding agent:
576
+
577
+ > Install CODEVANTA and connect it to this coding agent. Show me the setup plan
578
+ > first, then verify the installation.
579
+
580
+ ## Project layout
581
+
582
+ ```text
583
+ src/codevanta/
584
+ ├── core/ # loader (LIEF), disassembler (Capstone), strings, functions, shared report
585
+ ├── evidence/ # evidence records, provenance, confidence scoring
586
+ ├── ir/ # backend-neutral instruction model + adapter registry
587
+ ├── mcp_server/ # MCP tools and stdio server for coding agents
588
+ ├── setup/ # client config planning, apply, verify (claude/cursor/cline/vscode)
589
+ ├── gui/ # loopback-only web dashboard (stdlib HTTP server + JSON routes)
590
+ ├── analysis/ # cross-references, call graph, CFG (linear sweep + recursive traversal), jump tables (absolute + relative), function fingerprints and similarity, structural/deep diff, struct-field suggestions with alignment/array hints, graph/HTML export (phase 2)
591
+ ├── api/ # HTTP API (phase 2+)
592
+ ├── cli/ # Typer command line surface
593
+ ├── storage/ # SQLite session storage and annotations (phase 2)
594
+ └── plugins/ # plugin system (phase 5)
595
+ tests/ # unit and integration tests
596
+ docs/ # architecture and install notes
597
+ scripts/ # one-line bootstrap installers
598
+ ```
599
+
600
+ ## Testing
601
+
602
+ ```powershell
603
+ python -m pytest
604
+ ruff check src tests
605
+ ```
606
+
607
+ CI runs the same lint and test job on Python 3.11, 3.13, and 3.14, and builds
608
+ plus smoke-tests the wheel on 3.13.
609
+
610
+ ## Documentation
611
+
612
+ - [Project specification](PROJECT_SPEC.md)
613
+ - [Architecture](docs/architecture.md)
614
+ - [API reference](docs/api.md) — every public Python entry point, the evidence
615
+ contract, the fourteen dashboard routes, and the twenty-two MCP tools
616
+ - [Sample binaries](docs/samples.md) — the committed PE/Mach-O/ELF fixtures and
617
+ how to regenerate them
618
+ - [Contributor attribution](docs/attribution.md) — how agent commits are credited,
619
+ and how to make an agent appear in GitHub's contributor graph
620
+ - [Release checklist](docs/release-checklist.md) — the pending PyPI publisher,
621
+ the `pypi` environment, dry runs, tagging and CI re-runs (maintainers)
622
+ - [Phase 2 — cross-references, CFGs, sessions](docs/phase2.md)
623
+ - [Phase 2b — call graphs, graph export, session annotations](docs/phase2b.md)
624
+ - [Phase 2c — import/indirect calls, embedded call graphs, MCP call graph](docs/phase2c.md)
625
+ - [Phase 2d — offline HTML/SVG graph viewer](docs/phase2d.md)
626
+ - [Phase 2e — recursive CFG traversal](docs/phase2e.md)
627
+ - [Phase 2f — jump tables, CFG indirect resolution, interactive viewer, structural diff](docs/phase2f.md)
628
+ - [Phase 2g — relative jump tables, function fingerprints, deep diff](docs/phase2g.md)
629
+ - [Phase 2h — struct-field suggestions, MCP parity, Python 3.14 CI](docs/phase2h.md)
630
+ - [Phase 2i — alignment/array hints, function similarity, struct over MCP](docs/phase2i.md)
631
+ - [Phase 2j — semantic diff pairing, similarity over MCP, signedness hints](docs/phase2j.md)
632
+ - [Phase 2k — diff options over MCP, cross-architecture guard, merged struct windows](docs/phase2k.md)
633
+ - [Phase 3 — pseudo-C decompilation, bounded emulation, decompiler backends](docs/phase3.md)
634
+ - [Phase 6 — path exploration, dataflow, evidence bundles, plugin SDK, fuzz and bench gates](docs/phase6.md)
635
+
636
+ ## Roadmap
637
+
638
+ Verified against this repository, not against intent. Every ✅ names the file
639
+ that implements it, so each claim is one file lookup away; every ⬜ is absent
640
+ from `src/`. A phase can be **delivered with named gaps** — those gaps are the
641
+ *Open* column, not a follow-up phase.
642
+
643
+ | Phase | Delivered | Open |
644
+ |-------|-----------|------|
645
+ | **1 · Foundation** | ✅ PE / ELF / Mach-O (fat slices too) / DEX loaders — `core/loader.py:363-379` (`dex\n` magic → `_load_dex`)<br>✅ Disassembly, ASCII + UTF-16 strings, function discovery, JSON evidence report — `core/disassembler.py`, `core/strings.py`, `core/functions.py`, `core/report.py`<br>✅ Per-section entropy and packing triage — `core/entropy.py` (`shannon_entropy`, `analyze_entropy`), `codevanta entropy`<br>✅ CLI: 20 commands (19 `@app.command()` + `mcp serve`) plus the `session` sub-app with 5 subcommands — `cli/main.py`<br>✅ MCP server exposing 22 tools — `mcp_server/server.py` (`build_server().list_tools()` returns 22)<br>✅ Guided agent setup for Claude Code, Cursor, Cline and VS Code — `setup/` (`clients.py`, `plan.py`, `apply.py`, `verify.py`) | ⬜ **.NET (CLR), WebAssembly and JVM `.class`/JAR formats** — `loader.py` recognises PE, ELF, Mach-O and DEX only |
646
+ | **2 · RE views** | ✅ Cross-references, incl. `call_import` / `call_indirect` slot resolution — `analysis/xrefs.py`<br>✅ Linear **and** recursive CFG — `analysis/cfg.py` (`build_cfg`, `build_recursive_cfg`), `codevanta cfg --traversal recursive`<br>✅ Call graphs with DOT / GraphML / HTML export — `analysis/callgraph.py`, `analysis/graph_export.py`, `analysis/html_view.py`<br>✅ Absolute and relative jump tables — `analysis/jump_tables.py` (`MODE_ABSOLUTE`, `MODE_RELATIVE`)<br>✅ SQLite sessions with address annotations — `storage/session.py`, `codevanta session save/list/show/annotate/notes`<br>✅ Structural binary diff, function fingerprints, function similarity — `analysis/binary_diff.py`, `analysis/function_hash.py`<br>✅ Struct-field recovery — `analysis/type_recovery.py`, `codevanta struct`<br>✅ Read-only loopback dashboard, 14 endpoints — `gui/server.py` (`ROUTES`) | ⬜ **Live debugger execution** — `codevanta attach` states outright that "the provider is never launched: this command writes a file and prints a command line"; the gdb/Frida session layer generates scripts and replays traces (`analysis/dynamic.py`, `analysis/trace.py`) but nothing runs gdb/Frida against a target<br>✅ GUI session persistence — `/api/session_save` and `/api/session_list` over `storage/session.py`<br>⬜ **Graph-oriented viewer application** — the shipped viewer is the static HTML/SVG export (`analysis/html_view.py`), not an interactive app |
647
+ | **3 · Decompilation** | ✅ Pseudo-C through three providers — `analysis/decompile.py`, `analysis/decompilers/` (`native`, `angr`, `ghidra` reported by `available_backends()`)<br>✅ Type propagation over decompiled output — `analysis/type_propagation.py`<br>✅ Decompiler parity enforced in CI instead of assumed — `.github/workflows/ci.yml` jobs `decompile-parity` and `ghidra-parity` | ⬜ **Embedded Python scripting** — no script command and no sandboxed interpreter; `session` stores annotations only |
648
+ | **4 · Emulation** | ✅ Bounded, offline emulation that never executes on the host, with explicit `return` / `budget` / `unmapped` / `unsupported` stop reasons — `analysis/emulate.py` (Unicorn), `codevanta emulate`<br>✅ 29 emulation tests — `tests/test_emulate.py` | ⬜ **Typed / SSA IR lifting** — `ir/base.py` and `ir/adapters/` are a contract plus an empty registry ("Concrete adapters arrive in phase 4")<br>⚠️ **Symbolic execution** — bounded path exploration over Unicorn exists (`analysis/symbolic.py`, seeded branches recorded as assumptions); no solver-based symbolic execution (`Simulator`/`SimulationManager`/Z3) in `src/` |
649
+ | **5 · Platform** | ✅ CI/CD with real gates — `ci.yml` runs 7 job runs (3 Python versions × `test`, plus `type-check` (mypy), `package` (wheel smoke test), `decompile-parity`, `ghidra-parity`) and `pyproject.toml` sets `fail_under = 85` coverage<br>✅ Release pipeline — `release.yml`: `build` → `publish-pypi` (trusted publishing) → `github-release`<br>✅ Dynamic provider probing, script generation and trace replay reachable from the CLI — `analysis/dynamic.py`, `analysis/trace.py` (`parse_gdb_trace`, `parse_frida_trace`), `codevanta attach`, `codevanta trace` | ✅ **Plugin SDK** — `plugins/` (entry-point discovery, bounded `run_plugin`, built-in registry, `MetricsAnalyzer`)<br>⬜ **Full AI layer** and **multi-user** — no auth, user or tenant model exists in `src/`<br>✅ **Evidence bundle** — `analysis/evidence_bundle.py` (manifest, per-entry tamper detection) and `scripts/report_bundle.py` (report + trace → verifiable bundle)<br>✅ **Fuzz and benchmark** — `scripts/fuzz_parsers.py` (`fuzz-smoke` job) and `scripts/bench_gate.py` (`benchmark` job, informational)<br>✅ **Windows / macOS CI** — `test-platform` matrix py3.13 on windows-latest and macos-latest (non-blocking platform signal)<br>⬜ **PyPI release** — publishing is wired but has never run: `git tag -l` is empty, so no `v*` tag has been cut |
650
+
651
+ ## Product principles
652
+
653
+ 1. **Evidence first** — important insights should be traceable to an artifact or code location.
654
+ 2. **Analyst in control** — AI provides assistance and context; users remain the decision makers.
655
+ 3. **Composable by design** — engines and analyzers should be extensible through separate components.
656
+ 4. **Secure by default** — analyzed targets are treated as untrusted input.
657
+ 5. **Clarity over magic** — outputs should explain limitations, confidence, and assumptions.
658
+
659
+ ## Use cases
660
+
661
+ - Understand legacy executables without complete source code
662
+ - Map dependencies and behavior in internal libraries
663
+ - Triage malware artifacts in an isolated environment
664
+ - Explain native or low-level functions to engineering teams
665
+ - Generate technical documentation for poorly documented software
666
+ - Support binary-focused code review and security research
667
+
668
+ > **Security note:** never open untrusted binaries or samples in a production
669
+ > environment. Use an appropriate sandbox, VM, or isolated analysis environment.
670
+
671
+ ## Contributing
672
+
673
+ Contributions, design discussions, and bug reports are welcome. Before opening a
674
+ pull request, describe the change context, compatibility risks, and validation
675
+ steps.
676
+
677
+ ## Community
678
+
679
+ - [Contributing](CONTRIBUTING.md) — development setup, checks, and conventions
680
+ - [Contributors](CONTRIBUTORS.md) — maintainer, agent workstreams, and how to be listed
681
+ - [Code of conduct](CODE_OF_CONDUCT.md)
682
+ - [Security policy](SECURITY.md) — report vulnerabilities privately
683
+ - [Repository settings checklist](docs/repository-settings.md) — maintainers
684
+ - [Changelog](CHANGELOG.md)
685
+
686
+ ## License
687
+
688
+ MIT — see [LICENSE](LICENSE). Third-party components keep their own licenses.