{"id":1216,"date":"2012-03-10T13:37:18","date_gmt":"2012-03-10T11:37:18","guid":{"rendered":"http:\/\/raftaman.net\/?p=1216"},"modified":"2021-05-15T11:46:39","modified_gmt":"2021-05-15T09:46:39","slug":"recovering-deleted-files-with-sleuthkit","status":"publish","type":"post","link":"https:\/\/possiblelossofprecision.net\/?p=1216","title":{"rendered":"Recovering deleted files with SleuthKit"},"content":{"rendered":"<p><a href=\"http:\/\/www.sleuthkit.org\/\">SleuthKit<\/a> 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 <a href=\"http:\/\/wiki.sleuthkit.org\/index.php?title=Case_Studies\">case studies wiki page<\/a> for an impression.<\/p>\n<p>Let&#8217;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 <code>dd<\/code>.<\/p>\n<p>To dump all partitions of your disk use<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n$ dd if=\/dev\/sdg of=\/tmp\/disk.img bs=512\r\n<\/pre>\n<p>Of course, you could also dump just one partition (e.g. <code>\/dev\/sdg2<\/code>).<\/p>\n<p>To get the partition table layout, you can the use <code>mmls<\/code> on the image file<\/p>\n<pre class=\"brush: plain; highlight: [9]; title: ; notranslate\" title=\"\">\r\n$ mmls \/tmp\/disk.img\r\nDOS Partition Table\r\nOffset Sector: 0\r\nUnits are in 512-byte sectors\r\n\r\n     Slot    Start        End          Length       Description\r\n00:  Meta    0000000000   0000000000   0000000001   Primary Table (#0)\r\n01:  -----   0000000000   0000000134   0000000135   Unallocated\r\n02:  00:00   0000000135   0003858623   0003858489   DOS FAT16 (0x06)\r\n03:  -----   0003858624   0003862527   0000003904   Unallocated\r\n<\/pre>\n<p><code>fsstat<\/code> is used to get information about the filesystem itself. In this case, the target partition starts with an <strong>offset of 135<\/strong>, so the <a href=\"http:\/\/www.sleuthkit.org\/sleuthkit\/man\/fls.html\">imgoffset flag<\/a> <code>-o<\/code> is mandatory (if you just dump a single partition, there is of course no offset and <code>-o<\/code> is not needed).<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n$ fsstat -o 135 \/tmp\/disk.img\r\nFILE SYSTEM INFORMATION\r\n--------------------------------------------\r\nFile System Type: FAT16\r\n\r\nOEM Name: MSDOS5.0\r\nVolume ID: 0x34333064\r\nVolume Label (Boot Sector): NO NAME    \r\nVolume Label (Root Directory):\r\nFile System Type Label: FAT16   \r\n\r\nSectors before file system: 135\r\n&#x5B;...]\r\n<\/pre>\n<p>You can now do all sorts of things with your image file, e.g. recursively list all file and directories (including deleted ones);<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n$ fls -o 135 -r \/tmp\/disk.img\r\n<\/pre>\n<p>To recover a deleted file by inode number, you can use the command line tool <code>icat<\/code><\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nicat -o 135 -r \/tmp\/disk.img 54 &gt; \/tmp\/DeletedPicture.jpg\r\n<\/pre>\n<p>For a quick overview and simple examples on other commands have a look at <a href=\"http:\/\/rationallyparanoid.com\/articles\/sleuth-kit.html\">http:\/\/rationallyparanoid.com\/articles\/sleuth-kit.html<\/a>.<\/p>\n<p>The <a href=\"http:\/\/wiki.sleuthkit.org\/index.php?title=Tools_Using_TSK_or_Autopsy\">SleuthKit wiki<\/a> points to a <a href=\"http:\/\/davehenk.blogspot.com\/2007\/06\/recover-deleted-files.html\">great script by Dave Henkewick<\/a> that runs recursively through the image file and uses fls and icat to retrive the inode numbers and restore the files:<\/p>\n<pre class=\"brush: perl; collapse: true; light: false; title: ; toolbar: true; notranslate\" title=\"\">\r\n#!\/usr\/bin\/perl -w\r\nuse strict;\r\n\r\n# (C) 2004 dave (at) hoax (dot) ca\r\n# ************* THIS SCRIPT HAS NO WARRANTY! **************\r\n#\r\n# this script works with the output from SleuthKit's fls and icat version: 3.00\r\n# using afflib-3.3.4\r\n#\r\n# dont worry if you do not have the same versions because it should work unless\r\n# the output from the commands have changed\r\n#\r\n# if the script does not work, please email me the debug output and\r\n# the output from manually running fls and icat, thanks!\r\n#\r\n# set the recovery directory \r\nmy $fullpath=&quot;\/tmp\/recover\/&quot;;\r\n\r\n# set the absolute path of fls binary\r\nmy $FLS=&quot;\/usr\/bin\/fls&quot;;\r\n\r\n# set the fls options\r\nmy @FLS_OPT=(&quot;-o&quot;,&quot;135&quot;,&quot;-f&quot;,&quot;fat&quot;,&quot;-pr&quot;,&quot;-m $fullpath&quot;,&quot;-s 0&quot;);\r\n\r\n# set the path of the device to be recovered\r\nmy $FLS_IMG=&quot;\/tmp\/disk.img&quot;;\r\n\r\n# set the inode of the directory to be recovered\r\nmy $FLS_inode=&quot;2&quot;;\r\n\r\n# set the path of the icat STDERR log\r\nmy $ICAT_LOG=&quot;\/tmp\/icat.log&quot;;\r\n\r\n# set the absolute path of the icat binary\r\nmy $ICAT=&quot;\/usr\/bin\/icat&quot;;\r\n\r\n# set the icat options\r\nmy @ICAT_OPT=(&quot;-o&quot;,&quot;135&quot;,&quot;-f&quot;,&quot;fat&quot;);\r\n\r\nmy $ICAT_IMG=&quot;$FLS_IMG&quot;;\r\n\r\n# here we go. hold on tight!\r\nlist($FLS_inode);\r\n\r\n\r\nsub list($) {\r\n\t#make the recovery dir\r\n\tsystem(&quot;mkdir&quot;,&quot;-p&quot;,&quot;$fullpath&quot;) &amp;&amp; die &quot;Cannot mkdir $fullpath while processing: $_&quot;;\r\n\t#run a recursive FLS on our chosen inode and regex each line\r\n\tforeach $_ (`$FLS @FLS_OPT $FLS_IMG $_&#x5B;0] 2&gt;&amp;1`) {\r\n\t\tregex($_);\r\n\t\t#print $_;\r\n\t}\r\n}\r\n\r\nsub regex($) {\r\n\t#first, regex for dirs, clean 'em up, and create 'em in recovery dir\r\n\t#\r\n\t# the following regex will work on output of the format:\r\n\t# 0|\/directory\/file.foo.bar (deleted)|0|r\/----------|0|0|0|0|0|0\r\n\t# 0|\/directory\/file.foo.bar|1384462|r\/rrw-r--r--|1000|1000|971556|1218136846|1218136846|1225037181|0\r\n\t# 0|\/directory|1392712|d\/drwxr-xr-x|1000|1000|4096|1225309096|1225309096|1226059913|0\r\n\t# 0|\/directory\/file.foo.bar -&gt; \/directory2\/file2.foo.bar|1384462|l\/lrw-r--r--|1000|1000|971556|1218136846|1218136846|1225037181|0\r\n\t#\r\n\t#\r\n\tif (\/(\\d\\|(&#x5B;\\S\\s]+)\\|(\\d+)\\|\\S\\\/d(&#x5B;\\w-]{3})(&#x5B;\\w-]{3})(&#x5B;\\w-]{3})(\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+))\/) {\r\n\t\tmy $fulldir = $2;\r\n\t\tmy $uid = $4; my $gid = $5; my $oid = $6;\r\n\t\t$fulldir =~ s\/ (\\(deleted(\\)|\\-realloc\\)))$\/\/g;\r\n\t\t$fulldir =~ s\/ \/_\/g;\r\n\t\t$uid =~ s\/-\/\/g; $gid =~ s\/-\/\/g; $oid =~ s\/-\/\/g;\r\n\t\t$uid = lc($uid); $gid = lc($gid); $oid = lc($oid);\r\n\t\t#print &quot;mkdir -p $fulldir\\n&quot;;\r\n\t\tsystem(&quot;mkdir&quot;,&quot;-p&quot;,&quot;$fulldir&quot;) &amp;&amp; die &quot;Cannot mkdir $fulldir while processing: $_&quot;;\r\n\t\t#print &quot;chmod u=$uid,g=$gid,o=$oid $fulldir\\n&quot;;\r\n\t\tsystem(&quot;chmod&quot;,&quot;u=$uid,g=$gid,o=$oid&quot;,&quot;$fulldir&quot;) &amp;&amp; die &quot;Cannot chmod u=$uid,g=$gid,o=$oid $fulldir while processing: $_&quot;;\r\n\t#second, regex for files, sockets, fifos then\r\n\t#clean and dump them in recovery dir\t\r\n\t} elsif (\/(\\d\\|(&#x5B;\\S\\s]+)\\|(\\d+)\\|\\S\\\/(-|s|f|r)(&#x5B;\\w-]{3})(&#x5B;\\w-]{3})(&#x5B;\\w-]{3})((\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+)|(\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+)))\/) {\r\n\t\tmy $inode = $3;\r\n\t\tmy $fullfile = $2;\r\n\t\t$fullfile =~ s\/ (\\(deleted(\\)|\\-realloc\\)))$\/\/g;\r\n\t\t$fullfile =~ s\/ \/_\/g;\r\n\t\t#print &quot;$ICAT @ICAT_OPT $ICAT_IMG $inode &gt; $fullfile\\n&quot; if ($inode != 0);\r\n\t\tsystem(&quot;$ICAT @ICAT_OPT $ICAT_IMG $inode &gt; \\&quot;$fullfile\\&quot; 2&gt;&gt; $ICAT_LOG&quot;) if ($inode != 0);\r\n\t\t#cannot use die cuz an invalid inode will kill the script\r\n\t\t#&amp;&amp; die &quot;Cannot icat $inode into \\&quot;$fullfile\\&quot; while processing: $_&quot;\r\n\t\t\r\n\t# thrid, regex for symlink, clean, and create in recovery dir\r\n\t} elsif (\/(\\d\\|(&#x5B;\\S\\s]+)\\s\\-\\&gt;\\s(&#x5B;\\S\\s]+)\\|(\\d+)\\|\\S\\\/(l)(&#x5B;\\w-]{3})(&#x5B;\\w-]{3})(&#x5B;\\w-]{3})(\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+\\|\\d+))\/) {\r\n\t\t#print &quot;$1\\n&quot;;\r\n\t\tmy $fullsym_dst = $2; my $fullsym_src = $3;\r\n\t\t$fullsym_dst =~ s\/ \/_\/g; $fullsym_src =~ s\/ \/_\/g;\r\n\t\t#print &quot;ln -s $fullsym_src $fullsym_dst\\n&quot;;\r\n\t\tsystem(&quot;ln&quot;,&quot;-s&quot;,&quot;$fullsym_src&quot;,&quot;$fullsym_dst&quot;) &amp;&amp; die &quot;Cannot ln $fullsym_src $fullsym_dst while processing: $_&quot;;\r\n\t} else {\r\n\t\tprint &quot;Unknown directory listing. File or directory NOT recovered\\nDebug:\\n$_&#x5B;0]\\n&quot;;\r\n\t}\r\n} #that's all folks. hope y'all had fun!\r\n<\/pre>\n<p>Another great tool is the <a href=\"http:\/\/www.sleuthkit.org\/autopsy\/\">Autopsy Forensic Browser<\/a>, a graphical frontend to the SleuthKit commands that runs in your browser.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;s assume, there is a FAT volume on our disk (maybe&#8230; <a href=\"https:\/\/possiblelossofprecision.net\/?p=1216\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[46],"class_list":["post-1216","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-sleuthkit"],"_links":{"self":[{"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=\/wp\/v2\/posts\/1216","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1216"}],"version-history":[{"count":12,"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=\/wp\/v2\/posts\/1216\/revisions"}],"predecessor-version":[{"id":1863,"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=\/wp\/v2\/posts\/1216\/revisions\/1863"}],"wp:attachment":[{"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1216"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/possiblelossofprecision.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}