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.
- codevanta/__init__.py +1 -0
- codevanta/analysis/__init__.py +1 -0
- codevanta/analysis/binary_diff.py +1168 -0
- codevanta/analysis/callgraph.py +542 -0
- codevanta/analysis/cfg.py +1201 -0
- codevanta/analysis/dataflow.py +762 -0
- codevanta/analysis/debugger.py +289 -0
- codevanta/analysis/debuginfo.py +304 -0
- codevanta/analysis/decompile.py +1094 -0
- codevanta/analysis/decompilers/__init__.py +250 -0
- codevanta/analysis/decompilers/angr_backend.py +251 -0
- codevanta/analysis/decompilers/base.py +278 -0
- codevanta/analysis/decompilers/ghidra_backend.py +316 -0
- codevanta/analysis/dynamic.py +756 -0
- codevanta/analysis/emulate.py +1349 -0
- codevanta/analysis/evidence_bundle.py +736 -0
- codevanta/analysis/function_hash.py +562 -0
- codevanta/analysis/graph_export.py +441 -0
- codevanta/analysis/html_view.py +695 -0
- codevanta/analysis/jump_tables.py +546 -0
- codevanta/analysis/solver.py +715 -0
- codevanta/analysis/symbolic.py +1809 -0
- codevanta/analysis/trace.py +646 -0
- codevanta/analysis/type_propagation.py +1055 -0
- codevanta/analysis/type_recovery.py +1214 -0
- codevanta/analysis/vtables.py +572 -0
- codevanta/analysis/xrefs.py +434 -0
- codevanta/api/__init__.py +1 -0
- codevanta/cli/__init__.py +1 -0
- codevanta/cli/main.py +3038 -0
- codevanta/core/__init__.py +31 -0
- codevanta/core/disassembler.py +121 -0
- codevanta/core/entropy.py +237 -0
- codevanta/core/functions.py +176 -0
- codevanta/core/loader.py +1351 -0
- codevanta/core/report.py +306 -0
- codevanta/core/strings.py +109 -0
- codevanta/evidence/__init__.py +7 -0
- codevanta/evidence/confidence.py +36 -0
- codevanta/evidence/models.py +43 -0
- codevanta/evidence/provenance.py +37 -0
- codevanta/gui/__init__.py +46 -0
- codevanta/gui/layout.py +1384 -0
- codevanta/gui/server.py +1305 -0
- codevanta/ir/__init__.py +6 -0
- codevanta/ir/adapters/__init__.py +31 -0
- codevanta/ir/base.py +31 -0
- codevanta/ir/instruction.py +42 -0
- codevanta/mcp_server/__init__.py +5 -0
- codevanta/mcp_server/server.py +710 -0
- codevanta/mcp_server/tools.py +1364 -0
- codevanta/plugins/__init__.py +748 -0
- codevanta/setup/__init__.py +28 -0
- codevanta/setup/apply.py +22 -0
- codevanta/setup/clients.py +285 -0
- codevanta/setup/plan.py +79 -0
- codevanta/setup/verify.py +43 -0
- codevanta/storage/__init__.py +1 -0
- codevanta/storage/session.py +514 -0
- codevanta-0.1.0.dist-info/METADATA +688 -0
- codevanta-0.1.0.dist-info/RECORD +65 -0
- codevanta-0.1.0.dist-info/WHEEL +5 -0
- codevanta-0.1.0.dist-info/entry_points.txt +2 -0
- codevanta-0.1.0.dist-info/licenses/LICENSE +21 -0
- 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.
|