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.