Skip to content

370rokas/disk-analysis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

disk-analysis (da)

A terminal tool for disk image analysis and file extraction. Built on The Sleuth Kit (TSK) with support for human-readable, CSV, and JSON output and a Lua scripting engine for automated workflows.

Quick Start

# List partitions on a disk image
disk-analysis disk.img ls

# Display the file tree of partition 1
disk-analysis disk.img tree 1

# Extract a file from partition 1
disk-analysis disk.img extract 1 /etc/passwd ./passwd.txt

# Run a Lua script against the image
disk-analysis disk.img script ./scripts/largest_files.lua

Usage

disk-analysis [options] <image> <subcommand> [args]

<image> is a path to a disk image file (.img, .bin, .dd, etc.) or a physical device node. It must exist and be readable.

Global options

Flag Description
-j, --json Output in JSON format
-c, --csv Output in CSV format
-l, --log <file> Write log messages to a file
--lc, --console Print log messages to the console

--json and --csv are mutually exclusive. The default output is human-readable text.


ls — List partitions

disk-analysis [options] <image> ls

Lists every non-metadata partition found in the image. If no partition table is detected (e.g. a raw USB stick formatted as a single filesystem), the entire disk is shown as one entry with ID 0.

Human-readable output:

ID    Name             Byte Offset    Byte Length    Has Filesystem    Filesystem Type
1     Linux (0x83)     1048576        10737418240    Y                 ext4
2     Linux swap       10738466816    2147483648     N                 None

JSON output (--json):

[
  {
    "id": 1,
    "name": "Linux (0x83)",
    "byte_offset": 1048576,
    "byte_length": 10737418240,
    "has_filesystem": true,
    "fs_type": "ext4"
  },
  {
    "id": 2,
    "name": "Linux swap",
    "byte_offset": 10738466816,
    "byte_length": 2147483648,
    "has_filesystem": false,
    "fs_type": "None"
  }
]

CSV output (--csv):

id,name,byte_offset,byte_length,has_filesystem,fs_type
1,"Linux (0x83)",1048576,10737418240,true,"ext4"
2,"Linux swap",10738466816,2147483648,false,"None"

tree — Display filesystem tree

disk-analysis [options] <image> tree <partition>

Recursively walks the filesystem on <partition> and prints every file and directory. Use the ID from ls for <partition>.

Unallocated entries, ., .., and NTFS $OrphanFiles are excluded. Hard-linked inodes are shown once; subsequent appearances are displayed as links pointing to the first occurrence.

Human-readable output:

/ (size: 0, dir)
  bin (size: 4096, dir)
    bash (size: 1234576, file)
    ls (size: 147912, file)
  etc (size: 4096, dir)
    hostname (size: 12, file)
    passwd (size: 2048, file)
  usr (size: 4096, dir)
    bin (size: 4096, dir) → [link: /bin]

JSON output (--json):

{
  "name": "",
  "size": 0,
  "is_directory": true,
  "children": [
    {
      "name": "etc",
      "size": 4096,
      "is_directory": true,
      "children": [
        {
          "name": "passwd",
          "size": 2048,
          "is_directory": false
        }
      ]
    },
    {
      "name": "lib",
      "size": 0,
      "is_directory": true,
      "is_link": true,
      "link_target": "/usr/lib"
    }
  ]
}

CSV output (--csv) — the name column contains the full path:

name,size,is_directory,linksTo
"/etc",4096,true,null
"/etc/passwd",2048,false,null
"/lib",0,true,/usr/lib

extract — Extract a file

disk-analysis <image> extract <partition> <src-path> <dest-path>

Extracts a single file from <partition> at <src-path> (absolute path within the filesystem) and writes it to <dest-path> on the host. Output format flags have no effect on this subcommand.

# Extract /etc/shadow from partition 1
disk-analysis disk.img extract 1 /etc/shadow ./shadow.txt

# Extract a binary from an NTFS image
disk-analysis disk.img extract 2 /Windows/System32/cmd.exe ./cmd.exe

script — Run a Lua script

disk-analysis <image> script <script.lua> [settings]

Executes a Lua script against the loaded image. The optional settings string is passed as-is to the script via da.settings and can carry arbitrary configuration (paths, flags, etc.).

# Run a script
disk-analysis disk.img script ./scripts/carve_images.lua

# Run a script with a settings string
disk-analysis disk.img script ./scripts/export.lua "out=/tmp/export,ext=jpg"

Lua Scripting

Scripts have access to a da global table that exposes the image and TSK filesystem API.

Global: da

Name Type Description
da.image_path string Path to the disk image passed on the command line
da.settings string The optional settings argument passed after the script path
da.list_partitions() function Returns a table (array) of PartitionInfo objects
da.open_fs(id) function Opens the filesystem on partition id, returns a FileSystem
da.log_info(msg) function Log at INFO level
da.log_warn(msg) function Log at WARN level
da.log_error(msg) function Log at ERROR level

PartitionInfo

Fields are read-only. Obtain instances via da.list_partitions().

Field Type Description
.id integer Partition ID (use this with da.open_fs and tree/extract)
.name string Partition description from the partition table
.byte_offset integer Start of the partition in bytes
.byte_length integer Size of the partition in bytes
.has_filesystem boolean Whether a recognisable filesystem was found
.fs_type string Filesystem type name (e.g. "ext4", "ntfs", "fat32")

FileSystem

Obtain via da.open_fs(id).

Method Returns Description
fs:root() FSEntry Root directory entry of the filesystem
fs:extract(src, dest) boolean Extract file at src (absolute FS path) to dest on the host

FSEntry

Method Returns Description
entry:name() string File or directory name
entry:full_path() string Absolute path within the filesystem (e.g. /etc/passwd)
entry:size() integer Size in bytes (0 for directories)
entry:is_directory() boolean
entry:is_valid() boolean false if this entry is a hard link placeholder
entry:is_link() boolean true for hard-linked inodes after the first occurrence
entry:link_target() string Path of the first occurrence (only meaningful when is_link() is true)
entry:load_all_descendants() Recursively loads all children into memory
entry:children() table { name → FSEntry } map of direct children (triggers lazy load)

Example script

-- Export all .jpg files from every partition to /tmp/export/
local partitions = da.list_partitions()

for _, p in ipairs(partitions) do
    if not p.has_filesystem then goto continue end

    da.log_info(string.format("Scanning partition %d (%s)", p.id, p.fs_type))
    local ok, fs = pcall(da.open_fs, p.id)
    if not ok then goto continue end

    local root = fs:root()
    root:load_all_descendants()

    local function walk(entry)
        if entry:is_link() or not entry:is_valid() then return end

        if entry:is_directory() then
            for _, child in pairs(entry:children()) do
                walk(child)
            end
        elseif entry:name():match("%.jpg$") then
            local dest = "/tmp/export" .. entry:full_path()
            if fs:extract(entry:full_path(), dest) then
                da.log_info("Exported: " .. entry:full_path())
            else
                da.log_warn("Failed:   " .. entry:full_path())
            end
        end
    end

    walk(root)
    ::continue::
end

Logging

Logging is off by default. Enable it with either flag — both can be used together:

# Log to a file
disk-analysis -l analysis.log disk.img tree 1

# Log to console
disk-analysis --console disk.img ls

# Log to both
disk-analysis -l analysis.log --console disk.img script carve.lua

Prerequisites

Before building, ensure you have the following installed:

  • Build Tools: CMake (3.10+) and a C++20 compiler.
  • Package Manager: VCPKG.
  • Library: SleuthKit (TSK)

Building

# 1. Clone the repository
git clone https://github.com/370rokas/disk-analysis.git
cd disk-analysis

# 2. Install vcpkg dependencies
vcpkg install

# 3. Configure and build
cmake -B build
cmake --build build

# 4. Run
./build/disk-analysis --help

To build with AddressSanitizer enabled (development only):

cmake -B build -DENABLE_ASAN=ON
cmake --build build

Project Structure

src/
├── main.cpp              # Entry point — parses CLI and dispatches to actions
├── defs.hpp              # ActionType enum
├── core/                 # TSK wrappers and domain types
│   ├── disk.hpp          # Disk image (TSK_IMG_INFO)
│   ├── volume.hpp        # Partition table (TSK_VS_INFO) + PartitionInfo
│   ├── filesystem.hpp    # Filesystem handle (TSK_FS_INFO)
│   ├── fsEntry.hpp/cpp   # File/directory entry with lazy child loading
│   ├── context.hpp       # Global singleton — config, disk handle, inode map
│   └── logger.hpp        # spdlog initialisation
├── actions/              # Business logic
│   ├── partitions.hpp/cpp  # Partition listing and filesystem access
│   └── extract.hpp/cpp     # File extraction (shared by CLI and Lua)
├── ui/cli/               # Command-line interface
│   ├── cli.hpp           # CLI11 parser + CliConfig struct
│   └── wrappers.hpp      # Output formatters for each subcommand
└── scripting/            # Lua integration
    ├── lua.hpp/cpp       # sol2 bindings and script runner
scripts/                  # Example Lua scripts

TODO

  • Implement basic TSK wrappers.
  • Implement different output format support (human readable, CSV, JSON).
  • Implement LUA scripting support (da.list_partitions, da.open_fs, da.extract, logging bindings).
  • Implement basic subcommands:
    • ls: List partitions.
    • tree: Display file system tree.
    • extract: Extract a specific file.
  • Create documentation and usage examples.
  • Automated testing for core functionality.
  • Automated builds and releases.
  • (idea): MCP server for AI agents.
  • (idea): Interactive TUI with live filesystem browsing.
  • (idea): Support for Windows Registry hives and other non-filesystem data structures.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

CLI tool for disk image analysis and file extraction, built on The Sleuth Kit with Lua scripting

Topics

Resources

License

Stars

Watchers

Forks

Contributors