
Binary visualiser and triage tool — entropy, byte-class and Hilbert surfaces, dot plots and control-flow graphs over one shared address-space model.
Binary visualiser & triage tool: linked interactive views (entropy, histograms, image/dot-plot surfaces, control-flow graphs) over a single shared address-space model.
pipx install binviz && binviz serve
Open a file and every view is looking at the same address space. Select a range in one and the rest follow — the point is to answer "what is this region" by looking at it several ways at once.
binviz model parses ELF/PE/Mach-O through LIEF into regions,
symbols and an offset↔virtual-address mapping, materialising gaps and
overlays. Malformed input falls back to a raw model rather than failing.binviz triage says what the file looks like and why;
in the UI each finding clicks through to the bytes it was derived from.The UI is five workspaces — Overview, Bytes, Patterns, Code, and All — over the same selection. Static analysis only: samples are parsed, never executed.




Rendered by the same code the UI draws with, straight from the CLI —
regenerate with python docs/make_plates.py.
| A static binary | The same program, UPX-packed |
|---|---|
![]() | ![]() |
| Code, strings and padding separate into visible territories. | Structure collapses into uniform noise — the signature of packing. |
![]() | ![]() |
| Windowed entropy stays banded and low. | Flat and high, right up to the unpacking stub. |
| Right row stride | Wrong row stride |
|---|---|
![]() | ![]() |
Same bytes, one number different. That is why the stride suggester exists: the wrong row stride turns a photograph into diagonal noise, and you conclude there is no photograph.
ARCHITECTURE.md is how it is put together: what ships, the branding every
surface inherits, the conventions a new screen must follow, and the
limitations that are deliberate. SECURITY.md is the security posture.
python -m venv .venv
# -c pins to the exact versions the suite is green against; pyproject.toml
# publishes ranges, so without it you get whatever resolves today
.venv/Scripts/pip install -e ".[dev]" -c constraints-dev.txt # POSIX: .venv/bin/pip
# build the ground-truth corpus (uses zig cc from the ziglang pip package;
# needs UPX on PATH, in $UPX, or unzipped into corpus/tools/upx-*/)
make -C corpus # or: python corpus/build.py
# thresholds are measured, never hardcoded (see ARCHITECTURE.md §2.1)
python corpus/calibrate.py # writes corpus/calibration.json
pytest # functional suite
pytest -m perf -s # 100 MB performance targets
binviz probe corpus/out/hello_O2
binviz model corpus/out/hello_upx
binviz signal corpus/out/hello_upx --name entropy_4096 --png out.png
binviz hist corpus/out/ramp16.bin --n 2 --dtype u16le --png bigram.png
# surfaces: -p passes surface parameters
binviz surface corpus/out/hello_static --name hilbert -p mode=byteclass --png h.png
binviz surface corpus/out/rgb_raw.bin --name image -p mode=rgb8 -p width=320 --png i.png
binviz surface corpus/out/repeats.bin --name dotplot -p mode=exact --png d.png
binviz stride corpus/out/bayer_raw.bin --mode bayer_RGGB_RGB_12
# code
binviz disasm corpus/out/hello_O2 --limit 20
binviz functions corpus/out/hello_static --sort size
binviz cfg corpus/out/hello_O2 --func main --dot main.dot
# the verdict, and why
binviz triage corpus/out/hello_upx
binviz serve # 127.0.0.1:8000
It prints a URL containing a session token — open that. Every /api route
requires the token, because "it only listens on localhost" is not a defence
against a web page in another tab, which reaches 127.0.0.1 just like any
other origin. SECURITY.md has the reasoning.
File access is confined to --root (default: the working directory), so
paths outside it are refused.
All four have a flag and an environment variable, and all four exist to stop a local caller consuming more than you intended. Defaults are chosen for a laptop; raise them if your machine is bigger.
| Flag | Env | Default | What it bounds |
|---|---|---|---|
--max-cache BYTES | BINVIZ_MAX_CACHE | 5 GiB | Total size of cached analyses. Past this, least-recently-used entries are evicted — never one being analysed or viewed. |
--max-upload BYTES | BINVIZ_MAX_UPLOAD | 8 GiB | Largest accepted upload. |
--max-analyses N | — | 4 | Simultaneous analyses; beyond it /api/open returns 503. |
--root DIR | — | cwd | Directory the server may read files from. |