Mass-restore files from corrupted media with sleuthkit
Not so long ago, I mentioned that one of my external hard drives become little
bit too slow, and was not able to remove some files, and system was always
proposing me to run file system check. But I was always in hurry, until one day,
when I decided to move files to another drive. Unfortunately, by some reason, I
decided to run fsck
before copying file on another drive. When I came in the
morning my drive was not working properly anymore…
So, I lost all my porn photos. It was impossible to mount it, and the syslog
was full of messages like Buffer I/O error on device sdb
. Googling left me
with sad feeling that I will never get my data recovered. But I was wrong and
thanks to all developers of safecopy
, testdisk
, sleuthkit
and autopsy
.
Grabbing image of a failing drive
As you might already guessed, dd
was useless for me. So here’s where
might safecopy
comes for the rescue :)) This brilliant application helped
me to get as much data from drive as possible without any extra work:
$ cd /media/storage/recover-my-broken-drive
$ safecopy --stage1 /dev/sdb sdb-data
...
$ safecopy --stage2 /dev/sdb sdb-data
...
$ safecopy --stage3 /dev/sdb sdb-data
Use man safecopy
for details. :))
Bringing data back alive
So the next day I was able to run testdisk
on the result image file. And it
was able to determine my filesystem. Even more, I was able to mount this image,
but it was working really buggy. So I have investigated that image with
autopsy
. I needed all files under one particular directory and all it’s
sub-directories. Unfortunately autopsy does not gives you an option to recover
“all files from that directory”. But it gives you an inode of each file and
directory. That was what I was looking for. Now, knowing the inode of my
diretory I was able to get the list of all nested entries (files, dirs, etc):
$ fls -f ext2 -p -r ./sdb-data 8650754
r/r 8651063: INCITS+ISO+IEC+14882-2003.pdf
...
You can read details on the output format on a [fls wiki page][fls-wik]. But in short I needed all dirs/files that are not deleted, so the final command was:
$ fls -f ext2 -p -r ./sdb-data 8650754 \
| grep -v '^..-' | grep -v '^... \*' > files.lst
Now I had a “clean” list of files and directories I need to restore. To restore
a directory, all we have to do is to, surprise-surprise, mkdir
it ;)) but to
recover a file, we need to output it’s content. To get contents of a file from
the image byt it’s inode, I used another tool from the sleuthkit box: icat
.
Grabbing each file manually is dead-boring task, so here’s a small BASH script
that did all the dirty work for me:
IMAGE=$1
LIST=$2
DEST=$3
HT=`printf '\x09'`
cat $LIST | while read line; do
filetype=`echo "$line" | awk {'print $1'}`
filenode=`echo "$line" | awk {'print $2'}`
filenode=${filenode%:}
filename=`echo "$line" | cut -f 2 -d "$HT"`
if [ $filetype == "r/r" ]; then
echo "$filename"
mkdir -p "`dirname "$DEST/$filename"`"
icat -f ext2 -r -s $IMAGE "$filenode" > "$DEST/$filename"
fi
done
And again, man icat
for details ;))
That’s all!
Hope this will help somebody. And I hope I will never need it by myself. ;))
UPDATE (Tue 26 Nov 2013 11:22:34 PM CET)
If files extractor above doesn’t work for you, you might want try version, kindly proposed by Dan O'Day in comments:
IMAGE=$1
LIST=$2
DEST=$3
while IFS=$' \t:' read filetype filenode filename; do
if [ "$filetype" = "r/r" ]; then
echo "$filename"
mkdir -p "`dirname "$DEST/$filename"`"
icat -f ntfs -r -s $IMAGE "$filenode" > "$DEST/$filename"
fi
done < $LIST