The $I file format explained (v1 & v2 byte layout)
3 min read
The $I is a tiny, fixed-layout structure. You can parse it in a hex
editor in under a minute. Two versions exist in the wild: v1 from Vista
through Windows 8.1, and v2 from Windows 10 onwards. Both share the same
opening header.
The header (both versions)
| Offset | Size | Field |
|---|---|---|
0x00 | 8 | Format version (little-endian, 1 or 2) |
0x08 | 8 | Original file size in bytes (little-endian uint64) |
0x10 | 8 | Deletion time (Windows FILETIME, little-endian) |
0x18 | … | Original path (UTF-16LE) — encoding differs by version |
Two consequences of this layout that are worth keeping in mind:
- The version field is eight bytes, not one. A garbage
$Ifrom carving will frequently fail the version sanity check (anything other than 1 or 2 in the low byte, anything nonzero in the upper seven). - The size field includes the size of the original file, not the size
of the
$Iitself. Comparing it against the paired$Rsize is a fast tamper check.
v1 — Vista, 7, 8, 8.1
Total file size is a fixed 544 bytes. The path at offset 0x18
occupies exactly 520 bytes (260 UTF-16LE characters, NUL-padded).
260 maps to the classic MAX_PATH.
A v1 $I whose total size is not 544 is almost certainly truncated.
Tools that pad the file out and then "succeed" parsing it are giving
you fiction.
v2 — Windows 10 and 11
Variable length. After the header:
| Offset | Size | Field |
|---|---|---|
0x18 | 4 | Path length in UTF-16LE code units, including the NUL terminator |
0x1C | N * 2 | UTF-16LE path |
That uint32 path length lets v2 carry long paths (think OneDrive
backed-up filenames that breach MAX_PATH). It also means you must
validate the length against the on-disk file size before reading the
path buffer, or a corrupted/maliciously-crafted $I can lead a sloppy
parser past the buffer end.
The deletion FILETIME
64-bit little-endian, 100-nanosecond intervals since
1601-01-01 00:00:00 UTC. The
FILETIME conversion post
covers the math. It is UTC. It has no timezone. Always present it as UTC
or label the offset explicitly.
Cross-checking with other artefacts
- The
$STANDARD_INFORMATIONM/A/Ctimes in the MFT entry of the surviving$Rpartner often pre-date the$Ideletion timestamp by milliseconds — that is the move from the original location into$Recycle.Bin. - The USN journal records the same event
pair:
RENAME_OLD_NAME+RENAME_NEW_NAMEwith the new path under$Recycle.Bin\<SID>.
Further reading
Frequently asked questions
- What is the structure of a $I file?
- An 8-byte little-endian header: version at 0x00, original size at 0x08, deletion FILETIME at 0x10, then the original path as UTF-16LE starting at 0x18.
- What is the difference between $I v1 and v2?
- v1 (Vista–8.1) is a fixed 544 bytes with a 260-character UTF-16LE path. v2 (Windows 10/11) is variable: a uint32 path length at 0x18, then that many UTF-16LE code units.
- What time format does the $I file use?
- A Windows FILETIME — the number of 100-nanosecond intervals since 1601-01-01 UTC. This tool converts it to your locale's date, and CSV export keeps strict ISO-8601 UTC.
- How do I tell which $I version I have?
- Read the first 8 bytes as a little-endian integer: value 1 means v1, value 2 means v2. The parser on this site detects it automatically.