Hashes a file every useful way at once: crypto, fuzzy, and PE structure, so you can ask "have I seen this before?" across all of them. Originally a Python script, now a single Go binary for Windows, macOS, and Linux that ships without a runtime.
- Cryptographic Hashes: MD5, SHA1, SHA256.
- Fuzzy Hashes: SSDEEP, TLSH (Pure Go implementations - no DLLs required!).
- PE Analysis: ImpHash, Rich Header Hash, Section Hashes, Entropy.
- Output: Terminal output with colors (via Lipgloss) or JSON for piping.
- Forensic Metadata: JSON output now includes a timestamp, tool version, and unique system information (hostname, OS, architecture, user, and a stable machine ID) for forensic host identification.
Download the latest release for your platform from the Releases page.
# Analyze a file
./malware_hashes malicious_file.exe
# Output JSON for piping to other tools, including forensic metadata
./malware_hashes malicious_file.exe --json
# Override the default 1 GiB safety limit (bytes); 0 explicitly disables it
./malware_hashes large_sample.bin --max-size 2147483648Files are hashed as streams, so memory use stays bounded instead of growing with the input size. The size limit is enforced while reading as well as from file metadata, which also covers files that grow during analysis.
- Zero Dependencies: No Python interpreter, no
pip install, no C headers, no DLL hell. - Fast: Compiled to native machine code.
- Cross-Platform: Works identically on Windows, Mac, and Linux.
Plain Go build (1.25+ minimum; go.mod pins toolchain go1.26.6):
go build -o malware_hashes main.goThe release matrix lives in .dagger/ as a Dagger module, so CI and a local
dev box run exactly the same build. You need Docker (or another OCI runtime)
and the dagger CLI.
# Build every release artifact into ./dist
dagger call build-all --src=. --version=v0.0.0-dev export --path=./dist
# Build a single target
dagger call build --src=. --goos=linux --goarch=arm64 export --path=./dist/
# Smoke test: go vet + go build for every package
dagger call test --src=.Supported release targets:
| OS | Architecture | Artifact |
|---|---|---|
| Linux | amd64 | malware_hashes-linux-amd64 |
| Linux | arm64 | malware_hashes-linux-arm64 |
| macOS | amd64 | malware_hashes-macos-amd64 |
| macOS | arm64 | malware_hashes-macos-arm64 |
| Windows | amd64 | malware_hashes-windows-amd64.exe |
| Windows | arm64 | malware_hashes-windows-arm64.exe |
If you download the binary from GitHub Releases, macOS Gatekeeper may block it because it is not notarized. To fix this, remove the quarantine attribute:
xattr -d com.apple.quarantine malware_hashes-macos-amd64Now you can run it normally.
The forensic machine_id included in the JSON output is derived from stable, OS-specific identifiers:
- Windows:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid - Linux:
/var/lib/dbus/machine-idor/etc/machine-id - macOS:
IOPlatformUUID(viaioreg)
This ID is stable across reboots but may be duplicated if a Virtual Machine is cloned without proper generalization (sysprep/machine-id reset).
Analysis is local; the tool does not upload the selected file or its hashes. JSON and rich output do include the full input path plus host-identifying metadata (hostname, user, and machine ID). Redact those fields before sharing reports outside the intended forensic workflow.
MD5 and SHA-1 are emitted for malware-corpus compatibility and identification, not as proof that a file is authentic or untampered. Use the SHA-256 value when you need a collision-resistant digest.