Hands-On Forensics: Analyzing Disk Images with The Sleuth Kit (TSK) on macOS

As part of my master’s thesis in Privacy, Information and Cybersecurity at Skövde University in Sweden, I’ve been exploring practical forensic analysis techniques using open-source tools. In an upcoming blog post, I’ll walk you through the installation and test analysis of The Sleuth Kit (TSK) on macOS—a powerful command-line toolkit widely used in digital forensics. This tutorial will guide you step-by-step through setting up TSK via Homebrew, then using it to conduct a forensic investigation on a disk image. You’ll learn how to identify partitions with mmls, list files within a partition using fls, recover specific files by inode with icat, inspect file metadata with istat, and perform bulk recovery of deleted files with tsk_recover. These procedures are being applied and documented as part of my thesis work, which focuses on evaluating and comparing traditional and AI-enhanced forensic tools for analyzing hidden or obfuscated files across modern file systems.

Use Homebrew to install Sleuth Kit:


% brew install sleuthkit
==> Auto-updating Homebrew...
Adjust how often this is run with HOMEBREW_AUTO_UPDATE_SECS or disable with
HOMEBREW_NO_AUTO_UPDATE. Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).


.....
==> Pouring openjdk--24.0.1.arm64_sequoia.bottle.tar.gz
🍺  /opt/homebrew/Cellar/openjdk/24.0.1: 556 files, 368.9MB
==> Installing sleuthkit
==> Pouring sleuthkit--4.14.0.arm64_sequoia.bottle.tar.gz
🍺  /opt/homebrew/Cellar/sleuthkit/4.14.0: 142 files, 18.9MB
==> Running `brew cleanup sleuthkit`...



The confirmation can be check by the following command:


% fls -V       
The Sleuth Kit ver 4.14.0


There are sample data available on the internet from big techs as Oracle via (Oracle Open Data) and Amazon via (Digital Corpora) in case you do not have samples to test.

The following test validates TSK’s reliability in parsing partition data across various sample images with .HEIC, .dmg, .csv, .doc, .pdf and .docx files:



(forensic-nlp) breisdas@breisdas-mac test_files % ls -ltr
total 178336
-rw-r--r--@ 1 breisdas  staff   1451602 Apr  7 09:49 IMG_5839.HEIC
-rw-r--r--@ 1 breisdas  staff   1454426 Apr  7 09:49 IMG_5840.HEIC
-rw-r--r--@ 1 breisdas  staff   1101374 Apr  7 09:49 IMG_5847.HEIC
-rw-r--r--@ 1 breisdas  staff  85282660 May  2 19:53 instantclient-basic-macos.x64-19.16.0.0.0dbru.dmg
-rw-r--r--@ 1 breisdas  staff      7918 May  4 17:24 sample4.csv
-rw-r--r--@ 1 breisdas  staff       723 May  4 17:24 sample3.csv
-rw-r--r--@ 1 breisdas  staff       502 May  4 17:24 sample1.csv
-rw-r--r--@ 1 breisdas  staff     32768 May  4 17:24 sample2.doc
-rw-r--r--@ 1 breisdas  staff     26069 May  4 17:24 sample1.doc
-rw-r--r--@ 1 breisdas  staff   1253607 May  4 17:24 sample3.pdf
-rw-r--r--@ 1 breisdas  staff     65715 May  4 17:24 sample2.pdf
-rw-r--r--@ 1 breisdas  staff    581407 May  4 17:24 sample1.pdf
drwxr-xr-x  7 breisdas  staff       224 Jun 30 19:08 venv
-rw-r--r--@ 1 breisdas  staff     23161 Jul  5 20:26 samples23.docx

To address this, I created the following script, which utilizes the mmls tool to accurately detect and display partition tables from a series of raw disk image files.


 % cat run_mmls.sh
#!/bin/bash
cd /Users/breisdas/Desktop/test_files

for file in *.HEIC *.dmg *.csv *.doc *.pdf *.docx; do
  [ -e "$file" ] || continue  # skip if no match
  echo "=== Partition Table for $file ==="
  mmls "$file"
  echo ""
done

-- Give the permissions and execute the file:

 % chmod +x run_mmls.sh
 % % ./run_mmls.sh 

=== Partition Table for IMG_5839.HEIC ===

=== Partition Table for IMG_5840.HEIC ===

=== Partition Table for IMG_5847.HEIC ===

=== Partition Table for instantclient-basic-macos.x64-19.16.0.0.0dbru.dmg ===

=== Partition Table for sample1.csv ===

=== Partition Table for sample3.csv ===

=== Partition Table for sample4.csv ===

=== Partition Table for sample1.doc ===

=== Partition Table for sample2.doc ===

=== Partition Table for sample1.pdf ===

=== Partition Table for sample2.pdf ===

=== Partition Table for sample3.pdf ===

=== Partition Table for samples23.docx ===



While running the mmls script across a folder of files, you might notice that some files produce no output at all—just the header message like === Partition Table for sample1.docx === followed by silence. This can be confusing at first, but it’s expected behavior. The mmls tool is specifically designed to analyze raw disk image files such as .dd, .img, or .dmg that may contain valid partition tables. If you run it on standard document or media files like .pdf, .csv, .docx, or .HEIC, it won’t return any output because those file types do not contain partition structures for mmls to parse. The tool doesn’t throw an error—it simply returns nothing, which can give the impression that something went wrong. In reality, it’s a subtle reminder to carefully filter your input files when using low-level forensic tools like those in The Sleuth Kit.

Now that the forensic environment is set up, I’m moving forward with testing on a real-world forensic image: Jean’s disk in EnCase E01 format, officially named nps-2008-jean.E01. This image is publicly available from the Digital Corpora repository at https://downloads.digitalcorpora.org/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01. The .E01 format is widely used in digital forensics and contains not just raw disk data, but also metadata such as hashes and acquisition details. Before analysis, I’ll convert this image into raw format using the ewfexport tool provided by the libewf library, allowing me to apply The Sleuth Kit’s tools—such as mmls, fls, and icat—to extract partition structures, list files, and recover deleted data. This test represents a key part of my thesis evaluation, using real-world datasets to validate forensic workflows.


-- Install libewf-tools (to convert .E01 to .raw) (I already had this installed)

% brew install libewf
Warning: libewf 20140816 is already installed and up-to-date.
To reinstall 20140816, run:
  brew reinstall libewf

-- Download a test disk image (e.g., from Digital Corpora):

 % wget https://downloads.digitalcorpora.org/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01

--2025-07-08 19:30:21--  https://downloads.digitalcorpora.org/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01
Resolving downloads.digitalcorpora.org (downloads.digitalcorpora.org)... 173.236.136.226
Connecting to downloads.digitalcorpora.org (downloads.digitalcorpora.org)|173.236.136.226|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://digitalcorpora.s3.amazonaws.com/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01 [following]
--2025-07-08 19:30:21--  https://digitalcorpora.s3.amazonaws.com/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01
Resolving digitalcorpora.s3.amazonaws.com (digitalcorpora.s3.amazonaws.com)... 52.92.248.49, 52.92.225.145, 52.92.232.217, ...
Connecting to digitalcorpora.s3.amazonaws.com (digitalcorpora.s3.amazonaws.com)|52.92.248.49|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1572860321 (1,5G) [binary/octet-stream]
Saving to: ‘nps-2008-jean.E01’

nps-2008-jean.E01                  90%[=====================================================>      ]   1,32G  7,45MB/s   

....

Length: 1572860321 (1,5G) [binary/octet-stream]
Saving to: ‘nps-2008-jean.E01’

nps-2008-jean.E01                 100%[===========================================================>]   1,46G  3,94MB/s    in 6m 17s  

2025-07-08 19:36:39 (3,98 MB/s) - ‘nps-2008-jean.E01’ saved [1572860321/1572860321]



After download, I can now export the file convert .E01 to Raw image and then run the mmls to see a valid partition table with fls, icat, etc


-- Install libewf-tools (to convert .E01 to .raw) (I already had this installed)

% brew install libewf
Warning: libewf 20140816 is already installed and up-to-date.
To reinstall 20140816, run:
brew reinstall libewf

-- Download a test disk image (e.g., from Digital Corpora):

% wget https://downloads.digitalcorpora.org/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01

--2025-07-08 19:30:21--  https://downloads.digitalcorpora.org/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01
Resolving downloads.digitalcorpora.org (downloads.digitalcorpora.org)… 173.236.136.226
Connecting to downloads.digitalcorpora.org (downloads.digitalcorpora.org)|173.236.136.226|:443… connected.
HTTP request sent, awaiting response… 302 Found
Location: https://digitalcorpora.s3.amazonaws.com/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01 [following]
--2025-07-08 19:30:21--  https://digitalcorpora.s3.amazonaws.com/corpora/drives/nps-2008-m57-jean/nps-2008-jean.E01
Resolving digitalcorpora.s3.amazonaws.com (digitalcorpora.s3.amazonaws.com)… 52.92.248.49, 52.92.225.145, 52.92.232.217, …
Connecting to digitalcorpora.s3.amazonaws.com (digitalcorpora.s3.amazonaws.com)|52.92.248.49|:443… connected.
HTTP request sent, awaiting response… 200 OK
Length: 1572860321 (1,5G) [binary/octet-stream]
Saving to: ‘nps-2008-jean.E01’

nps-2008-jean.E01                  90%[=====================================================>      ]   1,32G  7,45MB/s

….

Length: 1572860321 (1,5G) [binary/octet-stream]
Saving to: ‘nps-2008-jean.E01’

nps-2008-jean.E01                 100%[===========================================================>]   1,46G  3,94MB/s    in 6m 17s

2025-07-08 19:36:39 (3,98 MB/s) - ‘nps-2008-jean.E01’ saved [1572860321/1572860321]

To proceed with forensic analysis using The Sleuth Kit tools, I first needed to convert the downloaded EnCase image file (nps-2008-jean.E01) into a raw disk image format compatible with tools like mmls, fls, and icat. I used the ewfexport utility from the libewf toolkit to perform this conversion. During the process, the tool prompted for several parameters. I accepted the default export format as raw and specified the output filename as RAW_datasetnps2008jean, omitting any file extension as required. The export process successfully extracted approximately 10 GB of image data in just 28 seconds, averaging a throughput of 365 MB/s. Despite a single read error reported between sectors 9,075,200 and 20,971,519, the export completed successfully. An MD5 hash was generated to verify data integrity: 9e9648f3bb60ad9da8da1968d46e298f. The resulting raw image file, now ready for partition analysis and forensic inspection, is located in the working directory under the name RAW_datasetnps2008jean.raw.


% ewfexport nps-2008-jean.E01
ewfexport 20140816

Information for export required, please provide the necessary input
Export to format (raw, files, ewf, smart, ftk, encase1, encase2, encase3, encase4, encase5, encase6, encase7, encase7-v2, linen5, linen6, linen7, ewfx) [raw]: 
Target path and filename without extension or - for stdout: RAW_datasetnps2008jean
Evidence segment file size in bytes (0 is unlimited) (0 B <= value <= 7.9 EiB) [0 B]: 0
Start export at offset (0 <= value <= 10737418240) [0]: 0
Number of bytes to export (0 <= value <= 10737418240) [10737418240]: 10737418240

Export started at: Jul 08, 2025 19:48:38
This could take a while.

Status: at 9%.
        exported 988 MiB (1036288000 bytes) of total 10 GiB (10737418240 bytes).
        completion in 40 second(s) with 232 MiB/s (244032232 bytes/second).

Status: at 21%.
        exported 2.1 GiB (2292056064 bytes) of total 10 GiB (10737418240 bytes).
        completion in 30 second(s) with 269 MiB/s (282563637 bytes/second).

Status: at 32%.
        exported 3.2 GiB (3513679872 bytes) of total 10 GiB (10737418240 bytes).
        completion in 25 second(s) with 276 MiB/s (290200492 bytes/second).

Status: at 46%.
        exported 4.6 GiB (4966907904 bytes) of total 10 GiB (10737418240 bytes).
        completion in 18 second(s) with 301 MiB/s (315806418 bytes/second).

Status: at 64%.
        exported 6.4 GiB (6917652480 bytes) of total 10 GiB (10737418240 bytes).
        completion in 11 second(s) with 330 MiB/s (346368330 bytes/second).

Status: at 80%.
        exported 8.0 GiB (8657698816 bytes) of total 10 GiB (10737418240 bytes).
        completion in 6 second(s) with 341 MiB/s (357913941 bytes/second).

Status: at 96%.
        exported 9.6 GiB (10365665280 bytes) of total 10 GiB (10737418240 bytes).
        completion in 1 second(s) with 353 MiB/s (370255801 bytes/second).

Export completed at: Jul 08, 2025 19:49:06

Written: 10 GiB (10737418240 bytes) in 28 second(s) with 365 MiB/s (383479222 bytes/second).
MD5 hash calculated over data:		9e9648f3bb60ad9da8da1968d46e298f
Read errors during export:
	total number: 1
	at sector(s): 9075200 - 20971519 (number: 11896320) in segment file(s):

ewfexport: SUCCESS



Following the successful export, I confirmed that the raw image file RAW_datasetnps2008jean.raw was generated alongside a small metadata file RAW_datasetnps2008jean.raw.info. With the raw image in place, I proceeded to run the mmls command to inspect the partition structure. The output revealed a DOS partition table, indicating the presence of an NTFS or exFAT partition starting at sector 63 and extending to sector 2,094,8759, with two regions marked as unallocated before and after the main partition. This information is critical for guiding subsequent analysis steps using fls, icat, or tsk_recover, as I now know where the primary file system begins and ends. The presence of an NTFS/exFAT partition suggests that the disk image is compatible with standard forensic workflows, and the unallocated sections may contain remnants of deleted data, making them key targets for further investigation.


RAW_datasetnps2008jean.raw
-rw-r--r--  1 breisdas  staff          158 Jul  8 19:49 RAW_datasetnps2008jean.raw.info
(forensic-nlp) breisdas@breisdas-mac test_files % mmls RAW_datasetnps2008jean.raw
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000000062   0000000063   Unallocated
002:  000:000   0000000063   0020948759   0020948697   NTFS / exFAT (0x07)
003:  -------   0020948760   0020971519   0000022760   Unallocated


With the partition boundaries now identified, the next step is to walk through the core forensic workflow using The Sleuth Kit (TSK) on the RAW_datasetnps2008jean.raw image. This includes several essential operations: listing the files present in the NTFS partition using fls, recovering a specific file by its inode number with icat, and examining that file’s metadata using istat. Additionally, to further investigate potential artifacts, I can optionally run tsk_recover to extract all recoverable files—including those that were deleted but not yet overwritten. These steps provide a practical foundation for analyzing the disk image at the file system level and support the broader goals of my thesis in understanding how traditional forensic tools perform in realistic investigation scenarios.


 % fls -o 63 RAW_datasetnps2008jean.raw
-/d 3519-144-6:	Documents and Settings
-/r 0-128-1:	$MFT
-/r 1-128-1:	$MFTMirr
-/r 2-128-1:	$LogFile
-/r 3-128-3:	$Volume
-/r 4-128-4:	$AttrDef
-/r 6-128-1:	$Bitmap
-/r 7-128-1:	$Boot
-/r 8-128-2:	$BadClus
-/r 8-128-1:	$BadClus:$Bad
-/r 9-144-17:	$Secure:$SDH
-/r 9-144-16:	$Secure:$SII
-/r 9-128-18:	$Secure:$SDS
-/r 10-128-1:	$UpCase
-/d 11-144-4:	$Extend
-/r 3481-128-3:	ntldr
-/r 3485-128-3:	NTDETECT.COM
-/r 3513-128-3:	boot.ini
-/d 3522-144-6:	System Volume Information
-/d 3999-144-6:	Program Files
-/r 7450-128-1:	CONFIG.SYS
-/r 7451-128-1:	AUTOEXEC.BAT
-/r 7452-128-1:	IO.SYS
-/r 7453-128-1:	MSDOS.SYS
-/d 23827-144-1:	RECYCLER
-/r 27624-128-3:	IPH.PH
-/d 28-144-6:	WINDOWS
V/V 32848:	$OrphanFiles
-/r 27-128-1:	pagefile.sys

The previous output provides a list of files and directories along with their inode numbers, making it possible to recover a file based on its inode number.

To demonstrate file recovery using The Sleuth Kit, I used the icat command to extract a specific file from the NTFS partition of the raw image based on its inode reference. By executing icat -o 63 RAW_datasetnps2008jean.raw 3485-128-3 > NTDETECTcom, I successfully recovered the file and saved it locally as NTDETECTcom. Verifying the result with ls -ltr confirmed that the file was created and has a size of 47,564 bytes. This recovery step shows how TSK enables precise file extraction directly from raw disk data using inode-level targeting. With the file now recovered, the next step is to use the istat tool to retrieve detailed metadata about the file—including timestamps, size, and allocation status—further supporting forensic analysis and evidentiary documentation.


% icat -o 63 RAW_datasetnps2008jean.raw 3485-128-3 > NTDETECTcom 
(forensic-nlp) breisdas@breisdas-mac test_files % ls -ltr NTDETECTcom
-rw-r--r--  1 breisdas  staff  47564 Jul  8 20:28 NTDETECTcom

 %  istat -o 63 RAW_datasetnps2008jean.raw 3485-128-3
MFT Entry Header Values:
Entry: 3485        Sequence: 1
$LogFile Sequence Number: 19734637
Allocated File
Links: 1

$STANDARD_INFORMATION Attribute Values:
Flags: Read Only, Hidden, System, Archive
Owner ID: 0
Security ID: 277  ()
Created:	2004-08-04 04:38:34.000000000 (CEST)
File Modified:	2004-08-04 04:38:34.000000000 (CEST)
MFT Modified:	2008-05-14 00:20:52.968750000 (CEST)
Accessed:	2008-05-14 00:19:55.906250000 (CEST)

$FILE_NAME Attribute Values:
Flags: Archive
Name: NTDETECT.COM
Parent MFT Entry: 5 	Sequence: 5
Allocated Size: 49152   	Actual Size: 47564
Created:	2008-05-14 00:19:55.281250000 (CEST)
File Modified:	2008-05-14 00:19:55.906250000 (CEST)
MFT Modified:	2008-05-14 00:19:55.906250000 (CEST)
Accessed:	2008-05-14 00:19:55.906250000 (CEST)

Attributes: 
Type: $STANDARD_INFORMATION (16-0)   Name: N/A   Resident   size: 72
Type: $FILE_NAME (48-4)   Name: N/A   Resident   size: 90
Type: $DATA (128-3)   Name: N/A   Non-Resident   size: 47564  init_size: 47564
1284131 1284132 1284133 1284134 1284135 1284136 1284137 1284138 
1284139 1284140 1284141 1284142 

As part of my thesis work, I came up with the idea of analyzing the internal content of files—such as text and embedded metadata—as a means to enhance the identification of sensitive or hidden information. This aligns with the tool I’ve been developing, which is designed to semantically evaluate the content of documents rather than relying solely on filenames or extensions. However, through practical experimentation, I learned that The Sleuth Kit (TSK) cannot analyze the actual content inside files like PDFs or documents. TSK is a file system-level forensic tool—it focuses on listing and recovering files from disk images, extracting them by inode, viewing timestamps and allocation details, recovering deleted files, and identifying partition structures. While The Sleuth Kit is highly effective for locating, recovering, and inspecting files at the storage level—for instance, using fls and icat to recover a file like my thesis PDF from a raw image, or istat to extract its metadata—it does not parse or interpret the file’s inner contents. To analyze the actual document structure, text, or embedded metadata, one must use external tools beyond TSK. This experience clearly illustrates the boundary between traditional forensic utilities and modern AI-powered solutions, where the former is adept at structural recovery and the latter excels at content-level awareness and interpretation.

Related posts