ReFS Reference

Tool-to-Artifact Map

This page is the bridge between the question in your head and the byte layout that answers it. For each forensic goal — recover deleted names, find the change journal, prove a timestamp was forged — it names the forefst.py / refsanalysis.py invocation that surfaces the artifact and the doc page that documents its on-disk shape. Use it to go from a question straight to a command, and from any tool output back to the structure that justifies it. The basis for every row is given in the Evidence section at the bottom, keyed to the same goal.

One parsing core, two front ends

Both tools share a single parsing core. bootstrap() opens the image, parses the VBR / SUPB / CHKP, builds the Container Table translator and the Object Table map, then exposes every structure through walk_bplus() and obj_map[oid]. That bootstrap is described step by step on the Bootstrap Chain page, and nothing in the bridge table below is reachable until it has run — every artifact is found by walking a specific B+-tree from a known root or OID that bootstrap has already located.

The split between the two tools is about shape of output, not what they can see:

  • forefst.py is the batch lister — one row per file, emitted as CSV, body-file, or JSON, plus volume summaries and version recovery. It is the timeline-friendly path: it sweeps the whole tree and hands you a table.
  • refsanalysis.py is the interactive inspector — registered subcommands that dump and decode one structure at a time. It is the deep-dive path: point it at a single OID or table and it shows the raw row.

Because both read the same on-disk bytes through the same core, a value seen in a lister CSV can always be re-derived with the matching inspector subcommand. That is the discipline behind the whole table: when a timeline entry looks wrong, drop to the inspector on that object and read the bytes the lister summarized.

Bridge table

GoalTool commandArtifactDoc page
Volume version / staterefsanalysis.py IMG summary · forefst.py IMG summaryCHKP volume-state flags (0x002 / 0x602 / 0x682 …), VBR versionversion detection, CHKP
Native vs upgraded discriminationrefsanalysis.py IMG chkp -vv · forefst.py IMG integrity (Redundancy section)CHKP bit 0x080; VBR 0x2A / 0x2C / 0x48; backup-boot version mismatchversion detection, redundancy
Per-file MACB + attributes (timeline)forefst.py IMG files -o out.csv · forefst.py IMG files --body -o t.body · … --jsonResident type-0x30 dir entry + child $SI (Created / Modified / Changed / Accessed at $SI 0x00–0x18)directory entries, $STANDARD_INFORMATION
Single object’s full attribute dumpforefst.py IMG details 0x705 · refsanalysis.py IMG attributesAll embedded sub-records of one OID (markers 0x80000001 / 0x80000002)attributes, Object Table
Search for a file by nameforefst.py IMG search "*.docx" · … search rx --regexType-0x30 filename keys (full long name; ReFS has no 8.3 entry)directory entries
Timestomp detectionforefst.py IMG timestomp · forefst.py IMG files --timestomp (per-row TimestompFlags)$SI MACB anomalies (parent-0x30 vs child-0x10), USN BASIC_INFO_CHANGE cross-checktimestomp detection, $STANDARD_INFORMATION
File content extractionforefst.py IMG extract NAME > out · … extract "NAME:stream"Resident value (key flags 0x01) / non-resident type-0x40 extents; a small ADS (< 2 KB) is inline, a large ADS (≥ 2 KB) is extent-backedresident storage, extent descriptors
Data-extent (datarun) mappingforefst.py IMG dataruns -v24-byte extent descriptors (VLCN @ 0x00, VCN @ 0x0C, runlen @ 0x14)extent descriptors, virtual addressing
Security descriptor / owner SIDforefst.py IMG security --files · forefst.py IMG files (OwnerSid column)OID 0x530 security table; SecurityId at $SI 0x28security descriptors
Reparse points (symlinks / junctions / WSL)forefst.py IMG reparse · … reparse --index · forefst.py IMG files (ReparseTarget column)$REPARSE_POINT data (schema 0x170 / 0x1C0); ReparseTag at $SI 0x54; OID 0x540 indexreparse points, $REPARSE_POINT
Extended attributes / WSL metadatarefsanalysis.py IMG attributes --filter wsl · forefst.py IMG files --filter eaEA sub-records, LX* metadata, $EFS streamattributes, $EA_INFORMATION, $EFS
Stream snapshots vs ADSforefst.py IMG snapshots -v · … snapshots --show/--extract · forefst.py IMG files (HasAds column)Type-0xB0 sub-records: snapshot vs ADS (inline)$SNAPSHOT, copy-on-write
Deleted files — trash / orphan / chkp-diffforefst.py IMG files --deleted · forefst.py IMG deleted --scan-pagesTrash Table (OID 0x0D), orphan MSB+ pages, two-CHKP diffTrash Table, deletion recovery
Deleted directory names from node slackforefst.py IMG deleted --slack · … --extract DIRStale type-0x30 rows in B+-tree node free region (offset slot freed, body persists)deletion recovery, B+-tree node
CoW prior-version recovery (two images)forefst.py IMG files --cow-before EARLIER.rawObject-Table OIDs whose metadata-page LCN changed → old page at stale LCNcopy-on-write, Object Table
Durable log (MLog) transactionsforefst.py IMG mlog --parse · … --csv · … --statsLogCore four-layer records; redo opcode at _SmsRedoRecord + 0x04MLog
USN change journalforefst.py IMG usn --stats · … --csvOID 0x520 $J stream → USN_RECORD_V3 (128-bit FileIDs); $Max at schema 0x1F0USN journal
Super-timeline (MACB + USN + MLog)forefst.py IMG timeline · … --fast · … --source USNMerged $SI / USN / MLog events (USN and $SI join by OID, MLog by path)forensic analysis workflow
Mount-session forensics (OID 0x30)refsanalysis.py IMG oid30Session Activity Table (OID 0x30; v3.10+ only) — mount-session historysystem OIDs
Metadata / checksum integrityforefst.py IMG integrity --checksums · … --fullchecksumsPage-reference Merkle tree; CRC64 (cktype 2) / SHA-256 (cktype 4)checksum architecture, Integrity State
Raw metadata export (“dump the $MFT”)forefst.py IMG export -o DIR · … --what btree,usn,mlogHash-verified VBR / CHKP / SUPB / MLog / USN / B+-tree forest + manifestObject Table, page header
System-table inspectionrefsanalysis.py IMG schema · … objects · … containers -v · … parentchildSchema (roots 3 / 9), Object (0 / 5), Container (7 / 8), Parent-Child (root 4)Schema Table, system OIDs, Parent-Child Table
Boot-sector read / repairrefsanalysis.py IMG boot -vv · … bootedit repair --dry-runVBR fields + ROR1+ADD self-checksum at 0x16VBR

Traps the table is there to prevent

The map exists because the obvious NTFS-trained reading of several of these artifacts is wrong on ReFS, and the wrong reading produces confident-looking false findings. A few are worth stating outright:

  • $SI + 0x70 is not a hard-link counter. It is a resident-layout field that is always 0 or 1, never greater, even on a volume that genuinely has hard links. Real hard links are non-resident and are counted by resolving each name to its shared stream record, not by reading this field — see the $STANDARD_INFORMATION page and copy-on-write for the link mechanism.
  • For a single-named file, the NTFS $SI-vs-$FILE_NAME timestomp cross-check has no ReFS equivalent — ReFS stores no $FILE_NAME and no short name. But a hard-linked file does have a ReFS-only analogue: each name is a separate type-0x30 row with its own MACB, so a name-scoped timestomp leaves the sibling names at the true birth (the HARDLINK_MACB_MISMATCH signal). For single-named files, timestomp detection instead compares the parent’s type-0x30 inline timestamps against the child’s type-0x10 $SI and cross-checks the USN BASIC_INFO_CHANGE reason code. Looking for a $FILE_NAME that does not exist is the classic ReFS mis-read.

Operational notes

A handful of behaviors decide whether a command returns the artifact you expect:

  • The lister populates the SID / owner / ADS / reparse / snapshot columns in every CSV. The inspector subcommands (security, reparse, snapshots) decode the same artifacts in depth, so the CSV columns and the inspectors agree; use an inspector for the full descriptor / target detail behind a column.
  • Deleted-data coverage is layered, not single-shot. The trash / orphan / checkpoint-diff path (--deleted) recovers objects that are referenced but unlinked. Node-slack recovery (deleted --slack) recovers names whose offset slot was freed but whose row body still persists in a B+-tree node’s free region — a class the live-tree iterators of both tools otherwise skip entirely. CoW prior-version recovery (--cow-before) needs a second, earlier image (or a dirty volume): after a clean unmount both checkpoints point at the same roots, so a single clean image yields no prior whole-tree state. The deletion recovery and copy-on-write pages explain why each layer reaches a different population.
  • Integrity has a fast mode and a full mode. integrity --checksums verifies only the root tables; only --fullchecksums walks every object B+-tree for a complete tamper check. Exit code 2 signals any failure, which makes the full mode scriptable for triage. The checksum architecture page documents the page-reference Merkle tree both modes verify.

Every command above accepts --partition-start OFFSET to override GPT detection. forefst.py adds --json / --jsonl (and --body) for structured output and --depth N to bound recursion, and its forensic subcommands take --csv FILE to export. refsanalysis.py adds --json on summary/details and the -v/-vv/--verify/--raw/-H verbosity flags on the structure commands (each command’s row shows which it accepts). refsanalysis.py --list prints the full subcommand set, and refsanalysis.py IMG all sweeps every structure tool in sequence.

Cross-references

  • forefst.py — the batch lister and the shared parsing library both tools build on
  • refsanalysis.py — the interactive inspector with one subcommand per structure
  • Bootstrap Chain — the common initialization that must run before any artifact here is reachable
  • Forensic Analysis Workflow — the end-to-end methodology that sequences these commands into a case
  • Virtual Addressing — why a cluster number in any artifact above is virtual and must be translated first

Evidence

The per-goal backing is:

  • Volume version / state. The observed composite CHKP state values (0x002 / 0x602 / 0x682 …) and the VBR version are confirmed on disk.
  • Native vs upgraded. CHKP bit 0x080 plus the format-time VBR fields 0x2A / 0x2C / 0x48 (never rewritten on upgrade) discriminate native from upgraded.
  • Per-file MACB + attributes. The four $SI timestamps sit at 0x00 / 0x08 / 0x10 / 0x18.
  • Single-object attribute dump. Embedded sub-records use markers 0x80000001 (single-instance) and 0x80000002 (multi-instance).
  • Search by name. ReFS has no 8.3 entry, so the type-0x30 key holds the full name.
  • Timestomp detection. No NTFS $FILE_NAME cross-check for a single-named file (the analog is parent-0x30 vs child-0x10); for a hard-linked file, compare the per-name MACB across the file’s names — a name-scoped stomp leaves siblings at the true birth (the HARDLINK_MACB_MISMATCH signal).
  • File content extraction. Resident value (key flags 0x01) vs non-resident type-0x40 extents; a small ADS (< 2 KB) is inline, a large ADS (≥ 2 KB) is extent-backed.
  • Data-extent mapping. The 24-byte extent entry holds VLCN @ 0x00, file VCN @ 0x0C, run length @ 0x14; extents may be stored out of file order.
  • Security descriptor / owner SID. SecurityId at $SI 0x28 resolves directly in OID 0x530.
  • Reparse points. $REPARSE_POINT schema 0x170 / 0x1C0; ReparseTag at $SI 0x54; OID 0x540 is the reparse index.
  • Extended attributes / WSL. EA sub-records, LX* metadata, and the $EFS stream.
  • Stream snapshots vs ADS — (CoW prior-content recovery). Type-0xB0 sub-records carry both snapshots and named data streams.
  • Deleted files (trash / orphan / chkp-diff).
  • Deleted names from node slack — (Method 5).
  • CoW prior-version recovery. Requires a second/earlier image or a dirty volume — after clean unmount both checkpoints reference the same roots.
  • Durable log (MLog). The redo opcode is at _SmsRedoRecord + 0x04.
  • USN change journal. USN_RECORD_V3 with 128-bit File IDs; $Max metadata is the schema-0x1F0 attribute (v3.14+ schema entry) on the Change Journal file under OID 0x520.
  • Super-timeline.
  • Mount-session forensics. The Session Activity Table (OID 0x30) is present from v3.10+ even when heat tracking is off.
  • Metadata / checksum integrity. CRC64 is checksum-type 2, SHA-256 is type 4.
  • Raw metadata export.
  • System-table inspection. Schema roots 3 / 9, Object roots 0 / 5, Container roots 7 / 8, Parent-Child root 4.
  • Boot-sector read / repair. The VBR carries a ROR1+ADD self-checksum at 0x16.

The $SI + 0x70-is-not-a-counter and no-8.3-short-name traps are confirmed.