-
-
Notifications
You must be signed in to change notification settings - Fork 0
Output and Reports
This page explains what RE-Toolkit produces, how the output tree is organized,
the structure of _summary.json, how severity is computed, and how to read a
report.
- Output tree
- Per-target artifacts
- Run-level artifacts
- The summary schema
- Severity and scoring
- Reading a report
- Visualizations
- Working with the JSON
- Self-contained by design
Each target gets its own directory under the output root, with per-stage subdirectories named to match the stage that produced them.
out/
├── index.html Codebase-wide index across all targets
├── _run.json Run manifest and toolchain versions
├── _similarity-matrix.json Cross-target similarity, when applicable
└── target.exe/
├── _input/ Sandboxed copy of the original
├── 00-triage/ Identity, hashes, entropy, signatures
├── 10-pe/ PE structure
├── 12-lief/ Format-agnostic structural parse
├── 20-dotnet/ IL disassembly and decompilation
├── 22-de4dot/ Deobfuscation output
├── 30-ghidra/ Ghidra headless dump
├── 40-r2/ radare2 analysis
├── 42-rizin/ rizin analysis
├── 80-iocs/ Extracted and classified indicators
├── 81-fuzzyhash/ Fuzzy hashes for similarity comparison
├── 89-viz/ Inline SVG visualizations
├── 90-logs/ Per-tool logs and the run ledger
├── _summary.json Structured findings, the source of truth
├── _verdict.txt One-line human-readable verdict
└── _report.html Self-contained tabbed report
Which subdirectories appear depends on the detected type. An ELF target has no
20-dotnet/, and a PDF has neither. Subdirectory numbering matches the stage
that produced it, so output is traceable back to a specific stage file.
The directory layout mirrors the input by default only when --preserve-tree is
passed. Otherwise every target gets a flat subdirectory under the output root.
Three files matter most, and they have a strict relationship.
| File | Role |
|---|---|
_summary.json |
The authoritative structured findings |
_report.html |
A rendering of _summary.json
|
_verdict.txt |
A one-line verdict for scripting and quick review |
_summary.json is the source of truth. The report presents it and is never
independent of it, so any disagreement between the two is a report bug rather
than an analysis discrepancy. When automating, read the JSON.
90-logs/ holds the per-tool logs and the run ledger. When a tool produced no
findings, this is where you determine whether it ran and found nothing, was
skipped, timed out, or failed. That distinction is not visible from the presence
or absence of output files alone.
| File | Contents |
|---|---|
index.html |
Every target with its verdict and score, linked to its report |
_run.json |
What was analyzed, with which toolchain versions, and when |
_similarity-matrix.json |
Pairwise similarity across targets |
_run.json records the resolved version of every tool used. This is what makes
a result reproducible: rerunning months later against a different toolchain can
produce different findings, and the manifest is how you detect that rather than
being surprised by it.
Similarity output only appears for multi-target runs, since a single binary has nothing to be compared against. It is computed from the fuzzy hashes each target contributed, which is why per-target hashing has to complete before any comparison can happen.
_summary.json is a single object whose top-level keys group findings by
source. Keys present depend on the target type and which stages ran.
| Key | Contents |
|---|---|
_meta |
Schema version, generation timestamp, target path, output path |
file |
Name, size, type, hashes |
entropy |
Overall and per-section entropy |
die, trid
|
Packer, compiler, and file-type fingerprints |
yara_hits, clamav_hits
|
Signature matches |
capa, capability_matrix
|
Detected capabilities and MITRE ATT&CK mapping |
strings_stats |
String extraction statistics |
iocs |
Extracted indicators with classification |
pe, dotnet
|
PE structure and managed-code detail |
macho, wasm, pyc, jar, pdf, ole
|
Format-specific findings |
apk, manifest, dex, apksig
|
Android findings |
mitigations |
Hardening posture, for example canary, NX, PIE |
authenticode, authenticode_chain
|
Signature validation |
ghidra |
Function inventory, decompilation, cross-references |
code_structure, function_purpose, data_flow
|
Structural characterization |
obfuscator_unified |
Detected obfuscator across all detection sources |
fuzzy_hashes |
ssdeep and TLSH digests |
crypto_keys |
Recovered cryptographic material |
go_info, rust_info
|
Runtime-specific findings |
dynamic |
Dynamic tier results, when dynamic analysis ran |
viz |
Visualization metadata |
_meta.version is the schema version and is intentionally distinct from the
RE-Toolkit release version. A consumer should key on the schema version when
deciding how to parse, not on the tool version.
Absent keys and empty keys mean different things. An absent key means the stage did not run. A present key with empty contents means the stage ran and found nothing. Consumers should distinguish the two rather than treating both as "no findings".
Severity comes from a weighted, explainable model. Each contributing signal is recorded as a named tuple:
| Field | Meaning |
|---|---|
name |
Stable identifier for the signal |
weight |
Points contributed to the total |
evidence |
The specific observation supporting it |
The total maps to a band:
| Band | Score |
|---|---|
| Critical | 100 and above |
| High | 60 to 99 |
| Medium | 30 to 59 |
| Low | 10 to 29 |
| Informational | Below 10 |
Two behaviors matter more than the thresholds.
Related signals do not compound. When a composite indicator fires, the narrower signals it subsumes are suppressed, so one underlying observation cannot inflate a score by being counted several ways. Without this, a packed binary would accumulate points from entropy, packer detection, section characteristics, and import scarcity, all describing a single fact.
Evidence is ordered by weight. The explanation of a verdict leads with what drove it, not with whichever check happened to run first.
A score is a triage aid, not a verdict on intent. A high score means several weighted indicators fired and the evidence list says which. A legitimate packed commercial application and a packed malware sample can score similarly, because the observable properties overlap. Read the evidence, not just the band.
_report.html is a tabbed document. A productive order to read it:
- The verdict banner. The score, the band, and the top contributing signals. If the evidence list explains the score to your satisfaction, you may be done.
- Capabilities. What the binary can do, mapped to ATT&CK techniques. This is usually the fastest route to understanding intent.
- Indicators. Behavioral indicators are listed first; infrastructure indicators are tagged separately, because a certificate authority hostname is not evidence of malicious behavior in the way a hardcoded command-and-control address is.
- Structure. Sections, imports, and hardening posture, for how the binary is built and what it links against.
- Code. Decompilation and function inventory, when you need to read the logic itself.
- Tool coverage. Which tools ran, were skipped, timed out, or failed. Check this before concluding that a quiet result means a clean binary.
That last step is the one most often skipped and most often decisive. An absence of findings from a stage that never ran is not evidence of anything.
Visualizations are rendered as inline SVG under 89-viz/, each independently
viewable and also embedded in the report:
| Visualization | Shows |
|---|---|
| Section treemap | Relative section sizes and entropy |
| Imports chart | Imported libraries and their function counts |
| capa and ATT&CK heatmap | Detected capabilities against the ATT&CK matrix |
| IOC distribution | Indicator counts by category |
| Severity contribution | How each signal contributed to the score |
| Dynamic behavior | Observed behavior, when dynamic analysis ran |
| Graphs | Call graph and control-flow graph |
Missing input degrades to an empty visualization with explanatory text rather than failing the stage, so a partial run still produces a readable report.
_summary.json is designed for programmatic consumption.
# Verdict and score for one target
jq -r '.file.name, ._meta.version' out/target.exe/_summary.json
# Every target above a score threshold
for f in out/*/_summary.json; do
jq -r 'select(.score >= 60) | .file.name' "$f" 2>/dev/null
done
# Collect behavioral indicators across a run
jq -r '.iocs[]? | select(.ioc_class != "infrastructure") | .value' \
out/*/_summary.json | sort -uWhen writing a consumer, treat unknown keys as forward compatibility rather than
error, and check _meta.version before assuming a structure.
Reports and visualizations use inline SVG and inline styling. There are no external stylesheets, no content delivery network references, and no JavaScript libraries fetched at view time.
This is deliberate for two reasons. Analysts frequently work on isolated networks, and a report that only renders with internet access is a report that fails where it is needed most. It also means opening a report generates no outbound network traffic, so the act of reviewing a sample cannot signal that analysis is underway.
A report can be copied to another machine, attached to a ticket, or archived, and it will render identically years later.
RE-Toolkit 3.7.3 -- MIT License. RE-Toolkit analyzes hostile binaries and, when
explicitly enabled, executes them: run it in a disposable virtual machine. Wiki
pages are kept at parity with the README and CHANGELOG.md in the
repository.
Getting started
Reference
Understanding it
Help
Contributing