二进制可视化与分类工具:在单一共享地址空间模型上提供关联交互视图(熵、直方图、图像/点图表面、控制流图)。
pipx install binviz && binviz serve
打开一个文件后,所有视图都指向同一地址空间。在一个视图中选择范围,其余视图会同步跟随——其目的在于通过多种方式同时观察,回答“这个区域是什么”的问题。
binviz model 通过 LIEF 将 ELF/PE/Mach-O 解析为区域、符号以及偏移↔虚拟地址映射,并填充间隙与覆盖层。格式错误的输入会回退到原始模型,而不是直接失败。binviz triage 说明文件看起来像什么以及原因;在界面中,每个发现都可点击跳转到其来源的字节。界面包含五个工作区——概览、字节、模式、代码和全部——均基于同一选择。仅进行静态分析:样本只被解析,绝不执行。




由界面绘制所用的同一代码直接从命令行渲染——使用 python docs/make_plates.py 重新生成。
| 正确的行步长 | 错误的行步长 |
|---|---|
![]() | ![]() |
相同的字节,仅一个数字不同。这就是步长建议器存在的原因:错误的行步长会把照片变成对角线噪声,让你误以为根本没有照片。
ARCHITECTURE.md 说明了其构建方式:发布内容、每个表面继承的品牌标识、新屏幕必须遵循的约定,以及有意为之的限制。SECURITY.md 说明了安全态势。
python -m venv .venv
# -c 固定到测试套件通过的确切版本;pyproject.toml
# 发布的是范围,因此不加此参数会解析到今天可用的任意版本
.venv/Scripts/pip install -e ".[dev]" -c constraints-dev.txt # POSIX: .venv/bin/pip
# 构建真实语料库(使用 ziglang pip 包中的 zig cc;
# 需要 UPX 在 PATH、$UPX 中,或解压到 corpus/tools/upx-*/)
make -C corpus # 或:python corpus/build.py
# 阈值是测量得出的,从不硬编码(参见 ARCHITECTURE.md §2.1)
python corpus/calibrate.py # 写入 corpus/calibration.json
pytest # 功能测试套件
pytest -m perf -s # 100 MB 性能目标
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
# 表面:-p 传递表面参数
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
# 代码
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
# 结论及其原因
binviz triage corpus/out/hello_upx
binviz serve # 127.0.0.1:8000
它会打印一个包含会话令牌的 URL——打开该 URL。每个 /api 路由都需要令牌,因为“仅监听 localhost”并不能防御另一个标签页中的网页,该网页与其他任何源一样可以访问 127.0.0.1。SECURITY.md 中有详细论证。
文件访问被限制在 --root(默认:当前工作目录)内,因此其外的路径会被拒绝。
四个限制项都有对应的标志和环境变量,它们的存在都是为了阻止本地调用者消耗超出你预期的资源。默认值针对笔记本电脑设定;如果你的机器性能更强,可以提高它们。
分析结果缓存在 ~/.cache/binviz(或 $BINVIZ_CACHE)下,以内容哈希为键,因此重新打开二进制文件是即时的。如果你希望保留更多分析结果,可以提高 --max-cache;缓存随时可以手动删除——最坏的情况是下次打开时重新分析。
其他标志:--token 用于在重启后固定令牌(与读取 BINVIZ_TOKEN 的 Vite 开发代理配合使用)、--port、--cache 和用于 CI 的 --no-auth。--no-auth 会打印一条横幅,说明它关闭了什么;不要在你与他人共享的机器上使用它。
pip install "binviz[app]"
binviz app # 原生窗口;--browser 使用你的浏览器
与 binviz serve 相同的服务器、相同的令牌、相同的 --root 限制——唯一区别是显示方式。如果未安装 pywebview,binviz app 会改为打开你的浏览器。
它会打印正在服务的 URL,这是有意为之:将界面包装在窗口中并不会移除网络监听器,只会让人更容易忘记它的存在。无论哪种方式,监听器都已认证,且 binviz app 没有 --no-auth 选项。
窗口只向页面暴露一个函数——原生文件选择器——除此之外没有其他。参见 src/binviz/app.py 了解为什么这个列表如此之短。
发布版本只附带 wheel 包,没有其他。一个未签名的冻结 Python 可执行文件,捆绑了 capstone 和 lief,用于分析加壳二进制文件——这正是 SmartScreen 和杀毒软件启发式误报的典型特征——因此,与其发布一个这样的文件,仓库中提供了自行构建所需的一切,这完全绕过了代码签名。
pip install pyinstaller # 6.x
python tools/build_ui.py # 构建 web/ 并将其暂存到包中
pyinstaller packaging/binviz.spec # -> dist/binviz/
预计约 100 MB,主要由 numpy 和 lief 占据。这是一个 onedir 捆绑包,而非单个自解压文件:启动 dist/binviz/binviz.exe(或双击它)打开桌面窗口,或传入任意子命令——dist/binviz/binviz.exe triage sample.exe——因为冻结构建是完整的 CLI,而不仅仅是窗口。
暂存步骤不可省略。web/dist 位于 Python 包之外,因此跳过它会产生一个窗口打开后显示 JSON 404 的应用;spec 文件会拒绝构建,而不是让这种情况悄悄发生。
在 macOS 上,同一命令还会生成 dist/Striate.app,使用 packaging/icons/icon.icns 作为品牌图标。两者都未在 Mac 上运行过——参见 ARCHITECTURE.md §5。
--root 仍默认指向当前工作目录,因此双击的可执行文件被限制在其启动所在的文件夹内——通常是应用自身的文件夹。设置快捷方式的“起始位置”,或使用 --root DIR 启动。
双击的可执行文件会要求输入凭据。 无参数时,冻结构建运行 binviz app --auth local,这是与 wheel 默认无登录界面的唯一区别。两者回答的问题不同:在终端中键入 binviz app 已经是会话所有者有意识的行为,而双击则不能证明任何东西——这是唯一没有终端、没有键入命令、没有限制决策的启动路径。要求输入凭据是窗口大声说出终端本会说的话的方式。先运行 binviz passwd 设置凭据,或显式传入 --auth none 跳过;你在命令行提供的任何内容仍然优先。
默认情况下没有登录界面,也没有需要复制的内容:服务器生成会话令牌并将其注入到它提供的页面中,因此打开 http://127.0.0.1:8000/ 即可直接使用,同时每个 API 调用仍然经过认证。
在你共享的机器上,启用登录界面:
binviz passwd # 提示输入;scrypt 摘要,权限 0600
binviz serve --auth local
如果跳过 binviz passwd,首次登录将认领该安装——启动横幅会对此发出警告,因为先到达端口的人将成为该账户。
双击的冻结可执行文件会自行启用 --auth local;参见构建独立应用了解为什么该默认值与 wheel 不同。
登录界面不是安全边界;每个 /api 路由上的令牌检查才是。机器上的任何东西都可以跳过表单直接调用 API,这正是令牌存在的原因。参见 SECURITY.md。
binviz 会打开攻击者选择的文件——这是其本职工作,而非边缘情况,而一个分析恶意软件却导致分析者被攻破的分类工具是最严重的失败。样本只被解析,绝不执行。 其余方面的处理如下:
针对恶意二进制
/api/{id}/… 路由中的 id 在用于构建路径之前必须恰好是 64 个十六进制字符。针对恶意浏览器——“仅监听 localhost”这一威胁并未解决,因为另一个标签页中的页面可以像任何其他源一样访问 127.0.0.1:
/api 路由都需要令牌。 令牌在启动时生成并注入页面,因此无需手动粘贴,也没有路由保持开放。--root 内,默认指向当前工作目录。其外的路径会被拒绝。Host 白名单和严格的 CORS,因此需要访问的源是唯一获得访问权的源。桌面窗口不会移除网络监听器,只会让人更容易忘记。因此 binviz app 没有 --no-auth 选项,且 js_api 桥接只暴露一个方法——pick_file(),它不接受参数,并通过相同的 --root 限制返回路径。如果出现第二个方法,测试将失败。
--auth local 的凭据是 scrypt 摘要,写入权限为 0600;binviz 不存储明文密码。
SECURITY.md 包含威胁模型、每项控制措施背后的理由、有意未完成的事项,以及如何私下报告漏洞。
MIT——参见 LICENSE。
语料库使用 zig cc 交叉编译 ELF 样本,因此 Windows/macOS 上无需 Linux 工具链——样本只被解析,绝不执行。
| 静态二进制 | 同一程序,UPX 加壳 |
|---|
![]() | ![]() |
| 代码、字符串和填充分离为可见的区域。 | 结构坍缩为均匀噪声——加壳的特征。 |
![]() | ![]() |
| 窗口熵保持带状且较低。 | 平坦且较高,一直持续到解壳桩。 |
| 标志 | 环境变量 | 默认值 | 限制内容 |
|---|
--max-cache BYTES | BINVIZ_MAX_CACHE | 5 GiB | 缓存分析的总大小。超过此值后,最久未使用的条目会被逐出——绝不会逐出正在分析或查看的条目。 |
--max-upload BYTES | BINVIZ_MAX_UPLOAD | 8 GiB | 可接受的最大上传大小。 |
--max-analyses N | — | 4 | 同时进行的分析数量;超过后 /api/open 返回 503。 |
--root DIR | — | cwd | 服务器可读取文件的目录。 |