SleuthKit is probably one of the most comprehensive collections of tools for forensic filesystem analysis. One of the most basic use-cases is the recovery of files that have been deleted. However, SleuthKit can do much, much more. Have a look at the case studies wiki page for an impression.
Let’s assume, there is a FAT volume on our disk (maybe a USB stick or a memory card) and we want to recover all deleted file. The safest way is probably to duplicate the entire volume first and perform an offline analysis. Again, there are quite a few tools for creating (forensic) images, the simpliest probably being dd.
To dump all partitions of your disk use
$ dd if=/dev/sdg of=/tmp/disk.img bs=512
Of course, you could also dump just one partition (e.g. /dev/sdg2).
To get the partition table layout, you can the use mmls on the image file
$ mmls /tmp/disk.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
00: Meta 0000000000 0000000000 0000000001 Primary Table (#0)
01: ----- 0000000000 0000000134 0000000135 Unallocated
02: 00:00 0000000135 0003858623 0003858489 DOS FAT16 (0x06)
03: ----- 0003858624 0003862527 0000003904 Unallocated
fsstat is used to get information about the filesystem itself. In this case, the target partition starts with an offset of 135, so the imgoffset flag -o is mandatory (if you just dump a single partition, there is of course no offset and -o is not needed).
$ fsstat -o 135 /tmp/disk.img FILE SYSTEM INFORMATION -------------------------------------------- File System Type: FAT16 OEM Name: MSDOS5.0 Volume ID: 0x34333064 Volume Label (Boot Sector): NO NAME Volume Label (Root Directory): File System Type Label: FAT16 Sectors before file system: 135 [...]
You can now do all sorts of things with your image file, e.g. recursively list all file and directories (including deleted ones);
$ fls -o 135 -r /tmp/disk.img
To recover a deleted file by inode number, you can use the command line tool icat
icat -o 135 -r /tmp/disk.img 54 > /tmp/DeletedPicture.jpg
For a quick overview and simple examples on other commands have a look at http://rationallyparanoid.com/articles/sleuth-kit.html.
The SleuthKit wiki points to a great script by Dave Henkewick that runs recursively through the image file and uses fls and icat to retrive the inode numbers and restore the files:
#!/usr/bin/perl -w
use strict;
# (C) 2004 dave (at) hoax (dot) ca
# ************* THIS SCRIPT HAS NO WARRANTY! **************
#
# this script works with the output from SleuthKit's fls and icat version: 3.00
# using afflib-3.3.4
#
# dont worry if you do not have the same versions because it should work unless
# the output from the commands have changed
#
# if the script does not work, please email me the debug output and
# the output from manually running fls and icat, thanks!
#
# set the recovery directory
my $fullpath="/tmp/recover/";
# set the absolute path of fls binary
my $FLS="/usr/bin/fls";
# set the fls options
my @FLS_OPT=("-o","135","-f","fat","-pr","-m $fullpath","-s 0");
# set the path of the device to be recovered
my $FLS_IMG="/tmp/disk.img";
# set the inode of the directory to be recovered
my $FLS_inode="2";
# set the path of the icat STDERR log
my $ICAT_LOG="/tmp/icat.log";
# set the absolute path of the icat binary
my $ICAT="/usr/bin/icat";
# set the icat options
my @ICAT_OPT=("-o","135","-f","fat");
my $ICAT_IMG="$FLS_IMG";
# here we go. hold on tight!
list($FLS_inode);
sub list($) {
#make the recovery dir
system("mkdir","-p","$fullpath") && die "Cannot mkdir $fullpath while processing: $_";
#run a recursive FLS on our chosen inode and regex each line
foreach $_ (`$FLS @FLS_OPT $FLS_IMG $_[0] 2>&1`) {
regex($_);
#print $_;
}
}
sub regex($) {
#first, regex for dirs, clean 'em up, and create 'em in recovery dir
#
# the following regex will work on output of the format:
# 0|/directory/file.foo.bar (deleted)|0|r/----------|0|0|0|0|0|0
# 0|/directory/file.foo.bar|1384462|r/rrw-r--r--|1000|1000|971556|1218136846|1218136846|1225037181|0
# 0|/directory|1392712|d/drwxr-xr-x|1000|1000|4096|1225309096|1225309096|1226059913|0
# 0|/directory/file.foo.bar -> /directory2/file2.foo.bar|1384462|l/lrw-r--r--|1000|1000|971556|1218136846|1218136846|1225037181|0
#
#
if (/(\d\|([\S\s]+)\|(\d+)\|\S\/d([\w-]{3})([\w-]{3})([\w-]{3})(\|\d+\|\d+\|\d+\|\d+\|\d+\|\d+\|\d+))/) {
my $fulldir = $2;
my $uid = $4; my $gid = $5; my $oid = $6;
$fulldir =~ s/ (\(deleted(\)|\-realloc\)))$//g;
$fulldir =~ s/ /_/g;
$uid =~ s/-//g; $gid =~ s/-//g; $oid =~ s/-//g;
$uid = lc($uid); $gid = lc($gid); $oid = lc($oid);
#print "mkdir -p $fulldir\n";
system("mkdir","-p","$fulldir") && die "Cannot mkdir $fulldir while processing: $_";
#print "chmod u=$uid,g=$gid,o=$oid $fulldir\n";
system("chmod","u=$uid,g=$gid,o=$oid","$fulldir") && die "Cannot chmod u=$uid,g=$gid,o=$oid $fulldir while processing: $_";
#second, regex for files, sockets, fifos then
#clean and dump them in recovery dir
} elsif (/(\d\|([\S\s]+)\|(\d+)\|\S\/(-|s|f|r)([\w-]{3})([\w-]{3})([\w-]{3})((\|\d+\|\d+\|\d+\|\d+\|\d+\|\d+\|\d+)|(\|\d+\|\d+\|\d+\|\d+\|\d+\|\d+)))/) {
my $inode = $3;
my $fullfile = $2;
$fullfile =~ s/ (\(deleted(\)|\-realloc\)))$//g;
$fullfile =~ s/ /_/g;
#print "$ICAT @ICAT_OPT $ICAT_IMG $inode > $fullfile\n" if ($inode != 0);
system("$ICAT @ICAT_OPT $ICAT_IMG $inode > \"$fullfile\" 2>> $ICAT_LOG") if ($inode != 0);
#cannot use die cuz an invalid inode will kill the script
#&& die "Cannot icat $inode into \"$fullfile\" while processing: $_"
# thrid, regex for symlink, clean, and create in recovery dir
} elsif (/(\d\|([\S\s]+)\s\-\>\s([\S\s]+)\|(\d+)\|\S\/(l)([\w-]{3})([\w-]{3})([\w-]{3})(\|\d+\|\d+\|\d+\|\d+\|\d+\|\d+\|\d+))/) {
#print "$1\n";
my $fullsym_dst = $2; my $fullsym_src = $3;
$fullsym_dst =~ s/ /_/g; $fullsym_src =~ s/ /_/g;
#print "ln -s $fullsym_src $fullsym_dst\n";
system("ln","-s","$fullsym_src","$fullsym_dst") && die "Cannot ln $fullsym_src $fullsym_dst while processing: $_";
} else {
print "Unknown directory listing. File or directory NOT recovered\nDebug:\n$_[0]\n";
}
} #that's all folks. hope y'all had fun!
Another great tool is the Autopsy Forensic Browser, a graphical frontend to the SleuthKit commands that runs in your browser.