STICH — Structural Threat Infection Chain Hash
A new malware-detection hash based on the structure and infection chain of a file — not on its content. STICH recognizes a same infection method even when the attacker changes file names, URLs, domains, IPs, hashes, variable/macro/stream names, GUIDs, paths, embedded resources — or even some intermediate layers.
In one sentence: two files that deliver their payload through the same sequence of formats, objects and techniques produce the same STICH — regardless of the actual malware inside.
Official vocabulary
| Term | Meaning | Example |
|---|---|---|
| STICH | the hash technique (structure + infection chain) | — |
| STICH Path | the canonical chain enriched with MITRE techniques — this is the fingerprint | eml>mime:att>oox:docm>oox:vba~T1027~T1059.005>scr:ps1~T1059.001~T1105 |
| STICH Shape | the structure only, without techniques | eml>mime:att>oox:docm>oox:vba>scr:ps1 |
| STICH Rules | tolerant detection rules (wildcards, technique constraints) | eml>**>scr:ps1~T1059.001 |
The STICH Path is the hash. The fingerprint is the canonical string itself — it is never turned into a SHA-256 digest. A cryptographic hash has no locality (one character of difference produces a completely different digest) and can only be matched by exact equality, which would destroy the two properties that make STICH useful: resilience to small changes and searchability (by token, technique, prefix, substring, or tolerant rules).
Why not a file hash?
A file hash (MD5/SHA-256) changes with a single byte. A fuzzy hash (ssdeep, TLSH) tracks similar content. STICH tracks neither — it describes the morphology of the attack:
| Fingerprint | Describes | Sensitive to |
|---|---|---|
| File hash | exact bytes | any single byte |
| Fuzzy hash | similar content blocks | content, partially |
| STICH Shape | the skeleton of the chain | only added/removed structural steps |
| STICH Path | the skeleton and observed behaviours | steps and techniques |
Anatomy of a STICH Path
A STICH Path is a chain of nodes read from the initial file to a final payload:
eml > mime:att > oox:docm > oox:vba~T1027~T1059.005 > scr:ps1~T1059.001~T1105
└┬┘ └──┬───┘ └───┬───┘ └──────────┬─────────┘ └──────────┬──────────┘
email attachment macro-doc obfuscated VBA PowerShell + download
| Separator | Role |
|---|---|
> | separates two successive nodes (a traversed layer) |
: | separates a family from its sub-type inside a token (arc:zip, oox:rel:ext) |
~ | attaches a MITRE technique to the preceding node |
Canonical tokens
Each node is a canonical token: a short, stable, lowercase identifier that is
language-independent and never translated. It prevents the same concept
from being written differently by different collectors (powershell,
script:ps1, scr:powershell → a single token: scr:ps1).
The interface shows a readable label (e.g. scr:ps1 → “PowerShell script”), but the
token itself is stable.
| Family | Tokens (excerpt) |
|---|---|
| Email / MIME | eml, msg, mime:att, mime:body |
| Archives | arc:zip, arc:rar, arc:7z, arc:entry |
| Office OOXML | oox:docm, oox:xlsm, oox:vba, oox:rel:ext |
| OLE | ole:doc, ole:vba, ole:stream |
pdf, pdf:js, pdf:emb, pdf:stream | |
| Scripts | scr:ps1, scr:js, scr:vbs, scr:wsf |
| Shortcuts / PE | lnk, lnk:cmd, pe:exe, pe:dll |
The taxonomy is versioned; the version is stored with every branch so results remain interpretable across taxonomy changes.
MITRE techniques
A technique (T#### or T####.###) is attached to a node
only when it truly corresponds to what was detected:
- a PowerShell script identifies
T1059.001; a VBA macroT1059.005; T1027(obfuscation) is added only when obfuscation is actually detected;T1105(Ingress Tool Transfer) only when a remote fetch is detected;- an external OOXML relationship maps to
T1221when its conditions are met.
An EML never becomes T1566.001 automatically, and an Office document never becomes T1204.002 just by existing.
Detection view (pruning)
A legitimate file can produce hundreds of decorative branches (styles, themes, media, fonts, icons, metadata, plain text) that are irrelevant to detection. STICH separates the full structure (never modified — shown by the report's File Structure view) from the detection branches (only determinant ones, used for STICH Paths, hashes and rules).
A branch is kept as soon as any of these holds: determinant leaf format; a MITRE technique; a suspect/malicious node; nested content; a script/macro/executable; a significant artifact or anomaly; or a STICH Rule match. It is pruned only when its leaf is secondary by nature and carries no signal. When in doubt, it is kept. The classification is not based on leaf type alone:
| Branch | Verdict |
|---|---|
oox:docx>oox:media>img | pruned |
oox:docx>oox:media>img>arc:zip>pe:exe | kept (hidden payload) |
pe:exe>pe:rsrc>img | pruned |
pe:exe>pe:rsrc>pe:dll | kept (embedded DLL) |
eml>mime:body>text | pruned |
eml>mime:body>text>scr:js | kept (script) |
Rules are evaluated against all branches before pruning, so a normally-secondary branch matched by a rule is promoted and kept. The remaining secondary branches are not persisted individually but summarized in the report (count per leaf token).
Canonicalization
Two analyses of the same infection chain produce exactly the same STICH Path.
Normalization is deterministic: techniques are extracted from free text
(ATT&CK T1564.007 → T1564.007), sorted and
deduplicated; physical file names and sample-specific data are ignored;
comparisons are culture-independent; collector ordering does not matter.
Example: oox:vba~T1059.005~T1027 and oox:vba~T1027~T1059.005 both
canonicalize to oox:vba~T1027~T1059.005.
The two fingerprints
Each branch yields two fingerprints, which are strings:
- STICH Path — the full canonical chain (structure + techniques);
- STICH Shape — the canonical structure only (no techniques).
These strings are the fingerprints: readable, resilient (via rules) and searchable (by token, technique, prefix, substring). No SHA-256 digest is surfaced — an internal fixed-length key exists only for the primary key and exact-equality lookups, never as a fingerprint.
Tolerance to mutations
Exact fingerprints distinguish two close chains. For example, adding a ZIP layer:
eml>mime:att>oox:docm>oox:vba>scr:ps1
eml>mime:att>arc:zip>oox:docm>oox:vba>scr:ps1 (extra ZIP layer)
gives different STICH Shapes. STICH therefore offers two complementary methods:
- Exact match by fingerprint (identical STICH Path or STICH Shape);
- Tolerant match by STICH Rule: the rule
eml>**>oox:vba>**>scr:ps1matches both chains above.
STICH Rules
Rules use the same syntax as branches, plus wildcards.
* — variable part inside a node
scr:* → scr:ps1, scr:js, scr:vbs (and scr:ps1:cmd)
oox:rel:* → oox:rel:ext, …
** — zero, one or more whole nodes
eml>**>scr:ps1 → eml>scr:ps1
eml>mime:att>scr:ps1
eml>mime:att>oox:docm>oox:vba>scr:ps1
Technique constraints
A rule may require one or more techniques on a node. Extra techniques on the branch do not break the match:
Rule : scr:ps1~T1027~T1059.001
Branch : scr:ps1~T1027~T1059.001~T1105 → matches (extra T1105 tolerated)
Branch : scr:ps1~T1059.001 → no match (T1027 missing)
Anchoring
Rules are anchored: the first element must match the first node and the last
element the last node. Use ** to tolerate extra nodes at the head or tail.
| Goal | Rule |
|---|---|
| PowerShell inside an EML | eml>**>scr:ps1 |
| Obfuscated PowerShell in an EML | eml>**>scr:ps1~T1027~T1059.001 |
| VBA macro leading to PowerShell | **>oox:vba~T1059.005>**>scr:ps1~T1059.001 |
| External OOXML relationship | oox:*>**>oox:rel:ext~T1221 |
| JavaScript in a PDF | pdf>**>pdf:js~T1059.007 |
| LNK in an archive or disk image | arc:*>**>lnk |
The rule engine interprets the logical structure directly — not regex — using
dynamic programming in O(elements × nodes). Multiple ** never cause
exponential backtracking (measured: 1.5M rule×branch evaluations in ~730 ms).
Full example
A phishing e-mail: attachment DOCM → obfuscated VBA macro → PowerShell → download.
- the EML collector extracts the attachment with edge
mime:att; - the Office collector types the document
oox:docmand stamps each VBA moduleoox:vba; - obfuscation is detected →
T1027onoox:vba, plusT1059.005; - the code leads to
scr:ps1; the PowerShell collector addsT1059.001and, onDownloadFile,T1105.
The resulting STICH Path:
eml>mime:att>oox:docm>oox:vba~T1027~T1059.005>scr:ps1~T1059.001~T1105
The rule eml>**>oox:vba~T1059.005>**>scr:ps1~T1059.001 matches — even if the
attacker adds an arc:zip layer or changes every name, URL and hash.
Using STICH
- Report — the STICH section shows the canonical tree, each branch's STICH Path / Shape / Hash (copyable and filterable), and the matched STICH Rules.
- Rule management (
/admin/chain-rules) — create, edit, enable, duplicate, archive rules; a live validator explains syntax errors; a tester runs a rule against a STICH Path and explains the match node by node. - Retroactive search — apply a new rule to historical analyses in the background: batched, cancellable, resumable, with progress.
Limits
To resist malformed or structural-explosion files, STICH enforces limits (max nodes, branches, branch depth, techniques per node, rule length, wildcards). When a limit is reached, the analysis does not crash: valid branches are kept and the result is flagged as truncated.