Forensic metadata extraction from ext2/3/4 filesystems. stat for the kernel-interpreted view, debugfs for raw inode + EXTENTS + deletion time, find for hidden-file sweeps, fls for image-based filesystem walks. Verified against GNU coreutils stat 9.7, debugfs 1.47.2, sleuthkit fls.
Side: blue
stat — kernel-interpreted inode view
stat /etc/passwd # full inode dump
stat -c '%n %s %i %A %U %y' /etc/passwd # selected fields, custom format
find <dir> -exec stat {} \; # batch over a directory treeOutput decoded
File: secret-code.txt
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 801h/2049d Inode: 789983 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2022-09-05 05:20:52.323629828 -0400
Modify: 2022-09-05 05:20:52.323629828 -0400
Change: 2022-09-05 05:20:52.323629828 -0400
Birth: 2022-09-05 05:20:52.323629828 -0400
| Field | Meaning |
|---|---|
File, Size, Blocks, IO Block | filename (resolved from directory entry), byte size, number of 512-byte filesystem blocks, FS block size |
Device | device-major/minor — match against /dev/sda1 etc. |
Inode | inode number |
Links | hard-link count. 1 for files; for directories, 2 + number of subdirectories (. and .. always present) |
Access: (mode) | permission bits in octal + rwx form, owning uid + gid |
Access: (timestamp) | atime — last read |
Modify: | mtime — last content write |
Change: | ctime — last metadata or content change |
Birth: | crtime — file creation. ext4 only. Shows as - on ext2/ext3 |
The four-timestamp model (a/m/c + birth) is unique to ext4. NTFS exposes its own four-time set (STANDARD_INFORMATION). Compare-and-contrast goes in the report.
touch -a sets atime, touch -m sets mtime, touch -t sets both. ctime cannot be set to a past time without filesystem-level manipulation — anti-forensic timestomping that touches mtime but leaves ctime out of sync is detectable.
debugfs — raw inode + EXTENTS
debugfs is the ext2/3/4 inspector. Reads the raw inode, not the kernel’s interpreted view.
sudo debugfs -R 'stat <file>' /dev/sda1 # full inode dump for a single file
sudo debugfs -R 'ls /etc' /dev/sda1 # directory listing including deleted entries (marked)
sudo debugfs -R 'icheck <block>' /dev/sda1 # block -> inode reverse lookup
sudo debugfs -R 'ncheck <inode>' /dev/sda1 # inode -> filename(s)
sudo debugfs -R 'lsdel' /dev/sda1 # deleted inodes still in the journalDebugfs shows fields plain stat does not:
Generation— inode version counter, increments on each reallocation (used by NFS)EXTENTS:— actual block ranges the file occupies. Required fordd skip=...extraction and slack-space examinationdtime— deletion time. Plainstathas no concept of this; debugfs reads it directly from the inode- raw mode bits and any extended attributes
Caveat: debugfs targets the raw block device. /dev/sda1 is correct for a host whose root is on that partition; on LVM, use df -T / first to find the actual device (/dev/<vg>/<lv>).
Block-level extraction with EXTENTS
# debugfs reports EXTENTS like:
# (ETB0):2105, (0-7):8388616-8388623
# extract block range 8388616 - 8388623 with dd (assuming 4096-byte FS blocks)
sudo dd if=/dev/sda1 bs=4096 skip=8388616 count=8 of=recovered.binThis is how “I have an interesting file” becomes “I have the bytes of that file” for files that have been deleted but whose inode is still parseable.
find — hidden file sweep
# all hidden entries (files and directories) under /home, excluding . and ..
find /home -name '.*' ! -name '.' ! -name '..'
# hidden files only
find /home -type f -name '.*'
# hidden directories only
find /home -type d -name '.*' ! -name '.'
# whole filesystem, exclude pseudo-FS noise
find / -name '.*' -xdev # stay on one mount
find / -name '.*' -not -path '/proc/*' -not -path '/sys/*' # alternative explicit excludesUseful predicates
find /home -mtime -7 # modified in last 7 days
find / -mtime -1 -type f -not -path '/proc/*' -not -path '/sys/*' # recently changed files
find / -newer /tmp/marker -type f # files newer than a reference
find / -size +100M -type f # files larger than 100 MB
find /home -user <username> # owned by a specific user
find / -perm -u+s -type f 2>/dev/null # SUID binaries (privesc surface)
find / -perm -g+s -type f 2>/dev/null # SGID binaries
find / -nogroup -o -nouser 2>/dev/null # files with no owning user/group (suspicious)
find / -name '*.sh' -newer /tmp/marker # recent shell scriptsPitfalls
find /without-xdevrecurses into/procand/syswhich generate enormous synthetic output. Always-xdevor explicit-not -pathexcludes.ls -ais not a search tool — it shows dotfiles in the current directory only. The activity wantsfindfor tree-wide search.- Names like
..test(two leading dots) are hidden —-name '.*'matches them but! -name '..'does not exclude them. Only the literal name..is the parent reference.
fls — image-based filesystem walk (sleuthkit)
fls lists files inside a forensic image without mounting it. Includes deleted entries that are still in directory blocks.
fls -r image.dd # recursive listing
fls -r -m / image.dd > body.txt # mactime body file (timeline source)
fls -d image.dd # deleted entries only
fls -F image.dd # files only, no directories
fls -o <sector_offset> image.dd # offset for multi-partition image
fls -p image.dd # full path on each line
fls image.dd <inode> # contents of one specific directory inodeBuilding a timeline
fls -r -m / image.dd > body.txt
mactime -b body.txt > timeline.txt # mactime turns body file into chronological timeline
mactime -b body.txt -d > timeline.csv # CSV output
mactime -b body.txt 2024-04-15..2024-04-20 > window.txt # restrict to a date windowThe body file format is documented at man mactime. Each row records a file’s MAC times, size, and metadata. mactime sorts by timestamp.
df — filesystem identification
df -h # human-readable, all mounted FS
df -T # show filesystem type
df -B1 /path # exact byte counts for one path
df /etc/passwd # which mount holds this file
df -T / # what FS type is the rootdf <path> reports the filesystem the path resolves to. Cross-reference with the Device field from stat to confirm the file lives where you expected.
/etc/fstab — mount configuration
cat /etc/fstab # static mount table at boot time
findmnt # currently-mounted view (nicer than mount(1) for triage)
findmnt -t ext4 # only ext4 mounts
mount | column -t # all mounts, aligned columns/etc/fstab reflects intended mounts. findmnt reflects actual current state. Compare the two — extra mounts or missing ones are findings.
Forensic time interpretation
Single-file analysis
Modify: 2022-05-02 14:30:00 -0400
Change: 2022-05-02 14:30:00 -0400
Access: 2024-04-21 09:15:33 -0400
Birth: 2022-05-02 14:30:00 -0400
Birth = Modify = Change at the same instant: file written once at creation and never modified afterwards. Access much later = someone read it recently.
Mismatch patterns
| Pattern | Likely cause |
|---|---|
Modify < Birth | timestomp via touch -m -t <past> after creation. Birth is set at creation and cannot be back-dated by touch |
Birth shown as - | not an ext4 filesystem (ext2/ext3 / FAT) |
Change significantly later than Modify and Access | metadata-only operation (chmod, chown, link/unlink, xattr write) |
Access significantly earlier than Modify | file modified after the last read — recent write, not yet read since |
| All four exactly equal at a millisecond | freshly-written file, never read |
Timezone
stat displays times in the analyst host’s local timezone. Forensic reports state times in UTC. Either convert manually or set TZ=UTC stat <file> for the command run.
Pitfalls
statshows the kernel’s interpreted view. For deleted files or inode-level detail, usedebugfs.debugfsagainst a mounted filesystem can return stale data. Best practice is to read against an image, not a live mount.find / -name '*'is enormous and slow. Always scope with-type,-xdev, time predicates, or path excludes.- Times in
statuse the analyst host’s TZ. Convert to UTC before quoting in reports. Birth(crtime) is ext4-only. Do not assume it exists on every Linux filesystem.flson an unmounted image without-odefaults to offset 0 — wrong for multi-partition images. Usemmlsfirst to find the partition’s start sector, then-o <sector>.
links:
Field Manual | Linux Filesystem | Linux Forensics | Mount Disk Images