Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

histext2fs — EXT2 Filesystem Forensic Analyzer

A C++ tool that reads raw EXT2 filesystem images and performs forensic analysis — reconstructing the full directory hierarchy (including deleted/ghost entries) and recovering the complete filesystem action history from inode metadata.

Features

  • Raw EXT2 parsing — Directly reads superblock, block group descriptors, inode tables, and directory entries from disk images. No mounting, no external libraries, no kernel code.
  • Directory tree reconstruction — Builds and displays the complete file hierarchy using depth-first traversal, including proper handling of indirect blocks (single, double, triple).
  • Ghost entry detection — Recovers "deleted" directory entries that still exist in slack space after being absorbed by neighboring entries via length expansion. These represent files/directories that were moved or removed.
  • Action history recovery — Correlates inode timestamps (access_time, change_time, modification_time, deletion_time) with directory entry metadata to reconstruct the sequence of filesystem operations:
    • touch — File creation
    • mkdir — Directory creation
    • rm / rmdir — File/directory deletion
    • mv — File/directory moves and renames (including chain moves detected via multiple ghost entries)

How It Works

┌───────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  EXT2 Image   │────▶│  Parse Structures│────▶│  Build Directory │
│  (raw bytes)  │     │  (SB, BGD, Inodes│     │  Tree + Ghosts   │
└───────────────┘     └──────────────────┘     └──────────────────┘
                                                        │
                      ┌──────────────────┐              │
                      │  Correlate       │◀─────────────┘
                      │  Timestamps      │
                      │  + Ghost Entries │
                      └──────────────────┘
                              │
              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
        ┌──────────┐   ┌──────────┐   ┌──────────┐
        │  State   │   │  History │   │  Move    │
        │  Output  │   │  Output  │   │  Chains  │
        │  (tree)  │   │  (events)│   │  (A→B→C) │
        └──────────┘   └──────────┘   └──────────┘

The analyzer works in two passes:

  1. State pass: DFS traversal from root (inode 2), printing the directory hierarchy. Ghost entries are detected by scanning slack space in directory blocks and displayed in parentheses.
  2. History pass: Collects all unique timestamps from every discovered inode, then classifies each timestamp as a creation, deletion, or move event based on which inode fields match.

Build

make all

Requires a C++17 compatible compiler (g++ or clang++).

Usage

./histext2fs <image_path> <state_output> <history_output>
Argument Description
image_path Path to the raw EXT2 filesystem image
state_output Output file for the current directory hierarchy
history_output Output file for the reconstructed action history

Example

./histext2fs disk.img state.txt history.txt

State Output Format

- 2:root/
-- 11:lost+found/
-- 13:home/
--- 15:user1/
---- 22:file1.txt
---- 20:file2.txt
---- (19:file1.txt)
--- 21:user2/
---- 19:file4.txt
--- (16:user3/)
-- 12:etc/
--- 14:config.txt
  • Dashes indicate depth level (root = 1 dash)
  • Directories end with /
  • Ghost (deleted/moved) entries are wrapped in (parentheses)
  • Ghost directories show only the entry, not their contents

History Output Format

1746963260 mkdir [/home] [2] [13]
1746963353 touch [/home/user1/file1.txt] [15] [19]
1746963412 mv [/home/user1/file1.txt /home/user2/file4.txt] [15 21] [19]
1746963455 rm [/home/user3/file5.txt] [16] [17]

Each line: TIMESTAMP ACTION [ARGS] [AFFECTED_DIRS] [AFFECTED_INODES]

  • Timestamps are Unix timestamps (seconds since epoch)
  • ? is used when information cannot be recovered (e.g., intermediate move timestamps)

Technical Details

EXT2 Structures Parsed

Structure Location
Superblock Byte offset 1024
Block Group Descriptor Table First block after superblock
Inode Table From BGDT inode_table field
Directory Entries Variable-length linked list in blocks

Ghost Entry Detection Algorithm

When a file is moved or deleted, its directory entry isn't erased — the neighboring entry's length field is expanded to absorb the space. The ghost entry's content remains intact in the "slack space." The analyzer scans this slack space by:

  1. Computing the minimum record length for each live entry
  2. Scanning the gap between that minimum and the actual length field
  3. Validating potential ghost entries by checking inode number range and reading the inode from disk

Move Detection with Chain Moves

When a file is moved multiple times (A → B → C), it leaves ghost entries in each intermediate directory. The analyzer:

  1. Identifies chain moves by finding inodes with 2+ ghost entries and 1 live entry
  2. Outputs intermediate moves with ? timestamps (since the on-disk timestamps are overwritten by subsequent operations)
  3. Detects the final move using the inode's change_time

Project Structure

├── histext2fs.cpp   # Main implementation (~700 lines)
├── ext2fs.h         # EXT2 structure definitions
├── Makefile         # Build configuration
└── README.md

License

MIT

About

EXT2 filesystem forensic analyzer — reconstructs directory hierarchy and action history from raw disk images

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages