# # $Date: 2006/05/03 22:12:56 $ # # Data / Content layer functions # # Brian Carrier [carrier@sleuthkit.org] # Copyright (c) 2001-2005 by Brian Carrier. All rights reserved # # This file is part of the Autopsy Forensic Browser (Autopsy) # # Autopsy is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Autopsy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Autopsy; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE. # IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package Data; $Data::FRAME = 1; $Data::ENTER = 2; $Data::CONT = 3; $Data::CONT_MENU = 4; $Data::CONT_MENU_FR = 5; $Data::REPORT = 6; $Data::LIST = 7; $Data::EXPORT = 8; $Data::BLANK = 9; # Display types that use the sort variable $Data::SORT_ASC = 0; $Data::SORT_HEX = 1; $Data::SORT_STR = 2; # Types of block numbers $Data::ADDR_DD = 0; $Data::ADDR_DLS = 1; sub main { # By default, show the main frame $Args::args{'view'} = $Args::enc_args{'view'} = $Data::FRAME unless (exists $Args::args{'view'}); Args::check_view(); my $view = Args::get_view(); # Check Basic Args Args::check_vol('vol'); # These windows don't need the data unit address if ($view == $Data::FRAME) { return frame(); } elsif ($view == $Data::ENTER) { return enter(); } elsif ($view == $Data::LIST) { return list(); } elsif ($view == $Data::BLANK) { return blank(); } # These windows do need the data unit address Args::check_block(); if ($view == $Data::CONT) { return content(); } elsif ($view == $Data::CONT_MENU) { return content_menu(); } elsif ($view == $Data::CONT_MENU_FR) { return content_menu_frame(); } elsif ($view == $Data::REPORT) { return report(); } elsif ($view == $Data::EXPORT) { return export(); } else { Print::print_check_err("Invalid Data View"); } } # Generate the 2 frames for block browsing sub frame { Print::print_html_header_frameset("Data Browse on $Args::args{'vol'}"); print "<frameset cols=\"20%,80%\">\n"; # Data Contents if (exists $Args::args{'block'}) { my $len = Args::get_len(); print "<frame src=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::ENTER&" . "$Args::baseargs&block=$Args::enc_args{'block'}\">\n" . "<frame src=\"$::PROGNAME?" . "mod=$::MOD_DATA&view=$Data::CONT_MENU_FR&" . "block=$Args::enc_args{'block'}&$Args::baseargs&len=$len\" " . "name=\"content\">\n</frameset>\n"; } else { print "<frame src=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::ENTER&" . "$Args::baseargs\">\n" . "<frame src=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::BLANK&" . "$Args::baseargs\" name=\"content\">\n</frameset>\n"; } Print::print_html_footer_frameset(); return 0; } # Frame to enter the data into sub enter { Print::print_html_header(""); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $bs = Args::get_unitsize(); print "<form action=\"$::PROGNAME\" method=\"get\" " . "target=\"content\">\n" . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_DATA\">\n" . "<input type=\"hidden\" name=\"view\" value=\"$Data::CONT_MENU_FR\">\n" . "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n" . Args::make_hidden() . # Address "<b>$Fs::addr_unit{$ftype} Number:</b><br> " . "<input type=\"text\" name=\"block\" size=12 maxlength=12"; print " value=\"$Args::enc_args{'block'}\"" if (exists $Args::args{'block'}); print ">\n"; # Number of units print "<p><b>Number of $Fs::addr_unit{$ftype}" . "s:</b>" . "<br> " . "<input type=\"text\" name=\"len\" value=\"1\" size=6 maxlength=6>\n"; print "<p><b>$Fs::addr_unit{$ftype} Size:</b>" . " $bs\n"; # dls images do not get to select this # if (($ftype ne 'dls') && ($ftype ne 'swap') && ($ftype ne 'raw')) { if ($Fs::is_fs{$ftype} == 1) { print "<p><b>Address Type:</b><br> " . "<select name=\"btype\" size=1>\n" . "<option value=\"$Data::ADDR_DD\" selected>Regular (dd)</option>\n" . "<option value=\"$Data::ADDR_DLS\">Unallocated (dls)</option>\n" . "</select>\n"; } else { print "<input type=\"hidden\" name=\"btype\" value=\"$Data::ADDR_DD\">\n"; } # Lazarus print "<p><b>Lazarus Addr:</b> " . "<input type=\"checkbox\" name=\"btype2\">\n" . "<p><input type=\"image\" src=\"pict/but_view.jpg\" " . "width=45 height=22 alt=\"View\" border=\"0\">\n" . "</form>\n"; print "<hr><p>" . "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::LIST&$Args::baseargs\" target=\"content\">" . "<img src=\"pict/but_alloc_list.jpg\" border=\"0\" " . "width=113 height=20 alt=\"Allocation List\"></a><br>\n" if ($Fs::is_fs{$ftype} == 1); # unless (($ftype eq 'dls') || ($ftype eq 'swap') || ($ftype eq 'raw')); # If there is a dls image, then provide a button for it if (($ftype ne 'dls') && (exists $Caseman::vol2dls{$vol})) { print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n" . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FRAME\">\n" . "<input type=\"hidden\" name=\"submod\" value=\"$::MOD_DATA\">\n" . "<input type=\"hidden\" name=\"vol\" value=\"$Caseman::vol2dls{$vol}\">\n" . Args::make_hidden() . "<p><input type=\"image\" src=\"pict/srch_b_lun.jpg\" " . "alt=\"Load Unallocated Image\" border=\"0\">\n<br></form>\n"; } # If we are using a dls image, then give a button for the original elsif (($ftype eq 'dls') && (exists $Caseman::mod2vol{$vol})) { print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n" . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FRAME\">\n" . "<input type=\"hidden\" name=\"submod\" value=\"$::MOD_DATA\">\n" . "<input type=\"hidden\" name=\"vol\" value=\"$Caseman::mod2vol{$vol}\">\n" . Args::make_hidden() . "<p><input type=\"image\" src=\"pict/srch_b_lorig.jpg\" " . "alt=\"Load Original Image\" border=\"0\">\n<br></form>\n"; } Print::print_html_footer(); return 0; } # generate frame for block content sub content_menu_frame { Print::print_html_header_frameset(""); my $sort = $Data::SORT_ASC; $sort = $1 if ((exists $Args::args{'sort'}) && ($Args::args{'sort'} =~ /^(\d+)$/)); my $len = Args::get_len(); if ($len == 0) { Print::print_err("Invalid length: 0"); } my $blk; my $ifind = Args::get_ifind(); # off is 1 if a lazarus block number as they are off by one my $off = 0; $off = -1 if (exists $Args::args{'btype2'}); # Do we need to convert from dls value to dd value ? if ( (exists $Args::args{'btype'}) && ($Args::args{'btype'} == $Data::ADDR_DLS)) { my $vol = Args::get_vol('vol'); my $b = Args::get_block() + $off; my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/dcalc' -f $ftype -u $b -o $offset -i $imgtype $img"); $blk = Exec::read_pipe_line(*OUT); close(OUT); $blk = "Error getting block" if ((!defined $blk) || ($blk eq "")); if ($blk !~ /^\d+$/) { print "$blk\n"; return 1; } } else { $blk = Args::get_block() + $off; } print "<frameset rows=\"25%,75%\">\n" . "<frame src=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT_MENU&$Args::baseargs" . "&block=$blk&sort=$sort&len=$len&ifind=$ifind\">\n" . "<frame src=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT&$Args::baseargs" . "&block=$blk&sort=$sort&len=$len\" name=\"cont2\">\n" . "</frameset>"; Print::print_html_footer_frameset(); return 0; } sub print_ifind { my $block = Args::get_block(); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; Print::log_host_inv( "$Caseman::vol2sname{$vol}: Finding $Fs::meta_str{$ftype} for data unit $block" ); local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/ifind' -f $ftype -d $block -o $offset -i $imgtype $img"); my $meta = Exec::read_pipe_line(*OUT); close(OUT); $meta = "Error getting meta address" if ((!defined $meta) || ($meta eq "")); if ($meta =~ /^($::REG_META)$/o) { $meta = $1; my $tmpr = $Caseman::vol2mnt{$vol}; print "<b>Pointed to by $Fs::meta_str{$ftype}:</b> " . "<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&" . "meta=$meta\" target=\"_top\">$meta</a><br>\n"; print "<b>Pointed to by file:</b>\n"; Exec::exec_pipe(*OUT, "'$::TSKDIR/ffind' -f $ftype -a -o $offset -i $imgtype $img $meta"); while ($_ = Exec::read_pipe_line(*OUT)) { chop; # Make it red if it is deleted if (/^(\*)\s+\/*(.*)$/) { Print::print_output( "<tt><font color=\"$::DEL_COLOR[0]\">$tmpr$2</font></tt> (deleted)<br>\n" ); } # If it starts with a '/' then it must be a file elsif (/^\/(.*)$/) { Print::print_output("<tt>$tmpr$1</tt><br>\n"); } # this must be an error else { Print::print_output("$_<br>\n"); } } close(OUT); } else { print "$meta\n"; } } # Generate index for block content sub content_menu { Print::print_html_header(""); my $block = Args::get_block(); my $prev = $block - 1; my $next = $block + 1; my $sort = Args::get_sort(); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $ifind = Args::get_ifind(); my $len = Args::get_len(); my $bs = Args::get_unitsize(); if ($len == 0) { Print::print_err("Invalid length: 0"); } print "<center>"; my $url = "$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT_MENU_FR&" . "$Args::baseargs&sort=$sort&len=$len" . "&ifind=$ifind"; # Next and Previous pointers print "<table cellspacing=\"0\" cellpadding=\"2\">\n" . "<tr>\n"; # Previous if ($prev < $Fs::first_addr{$ftype}) { print "<td align=\"right\"> </td>\n"; } else { print "<td align=\"right\">" . "<a href=\"$url&block=$prev\" target=\"_parent\">\n" . "<img src=\"pict/but_prev.jpg\" alt=\"previous\" " . "width=\"89\" height=20 border=\"0\"></a></td>\n"; } # Next print "<td align=\"left\"><a href=\"$url&block=$next\"" . " target=\"_parent\">" . "<img src=\"pict/but_next.jpg\" alt=\"next\" " . "width=\"89\" height=20 border=\"0\"></a></td>\n</tr>\n"; print "<tr><td align=\"right\"><a href=\"$::PROGNAME?" . "mod=$::MOD_DATA&view=$Data::EXPORT&$Args::baseargs&" . "block=$block&len=$len\">" . "<img src=\"pict/but_export.jpg\" border=\"0\" alt=\"Export\" " . "width=123 height=20></a></td>\n"; if ($::USE_NOTES == 1) { print "<td align=\"left\">" . "<a href=\"$::PROGNAME?mod=$::MOD_NOTES&view=$Notes::ENTER_DATA&$Args::baseargs&block=$block&len=$len\" " . "target=\"_blank\">" . "<img src=\"pict/but_addnote.jpg\" border=\"0\" " . "width=\"89\" height=20 alt=\"Add Note\"></a></td>\n"; } else { print "<td align=\"left\"> </td>\n"; } print "</tr></table>\n"; # Display formats print "<table cellspacing=\"0\" cellpadding=\"2\">\n" . "<tr><td>ASCII ("; if ($sort == $Data::SORT_ASC) { print "display - "; } else { print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT_MENU_FR&" . "$Args::baseargs&" . "sort=$Data::SORT_ASC&block=$block&len=$len\" target=\"_parent\">" . "display</a> - \n"; } print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::REPORT&" . "$Args::baseargs&sort=$Data::SORT_ASC" . "&block=$block&len=$len\" target=\"_blank\">report</a>)</td>\n" . "<td>*</td>\n"; print "<td>Hex ("; if ($sort == $Data::SORT_HEX) { print "display - "; } else { print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT_MENU_FR&" . "$Args::baseargs&" . "sort=$Data::SORT_HEX&block=$block&len=$len\" target=\"_parent\">" . "display</a> - \n"; } print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::REPORT&" . "$Args::baseargs&sort=$Data::SORT_HEX" . "&block=$block&len=$len\" target=\"_blank\">report</a>)</td>\n" . "<td>*</td>\n"; print "<td>ASCII Strings ("; if ($sort == $Data::SORT_STR) { print "display - "; } else { print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT_MENU_FR&" . "$Args::baseargs&" . "sort=$Data::SORT_STR&block=$block&len=$len\" target=\"_parent\">" . "display</a> - \n"; } print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::REPORT&" . "$Args::baseargs&sort=$Data::SORT_STR" . "&block=$block&len=$len\" target=\"_blank\">report</a>)</td>\n" . "</tr></table>\n"; # Special case for 'dls' b.c. we need to specify original data unit size local *OUT; if ($ftype eq 'dls') { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype -u $bs -o $offset -i $imgtype $img $block | '$::FILE_EXE' -z -b -" ); } else { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype -o $offset -i $imgtype $img $block | '$::FILE_EXE' -z -b -" ); } my $file_type = Exec::read_pipe_line(*OUT); close(OUT); $file_type = "Error getting file type" if ((!defined $file_type) || ($file_type eq "")); print "<b>File Type:</b> $file_type<br></center>\n"; if ($len == 1) { print "<b>$Fs::addr_unit{$ftype}:</b> $block<br>\n"; } else { my $end = $block + $len - 1; print "<b>$Fs::addr_unit{$ftype}" . "s:</b> $block-$end<br>\n"; } if ($Fs::is_fs{$ftype} == 1) { Exec::exec_pipe(*OUT, "'$::TSKDIR/dstat' -f $ftype -o $offset -i $imgtype $img $block"); my $cnt = 0; while ($_ = Exec::read_pipe_line(*OUT)) { if ($_ =~ /((Not )?Allocated)/) { print "<font color=\"$::DEL_COLOR[0]\">" if (defined $2); print "<b>Status:</b> $1<br>"; print "</font>" if (defined $2); } elsif ($_ =~ /Group: (\d+)/) { print "<b>Group:</b> $1<br>\n"; } $cnt++; } close(OUT); if ($cnt == 0) { print "Invalid $Fs::addr_unit{$ftype} address<br>\n"; return; } # Make ifind an option $url = "$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT_MENU&" . "$Args::baseargs&sort=$sort&len=$len&block=$block"; if ($ifind == 0) { print "<a href=\"$url&ifind=1\">Find Meta Data Address</a><br>\n"; } else { print "<a href=\"$url&ifind=0\">Hide Meta Data Address</a><br>\n"; print_ifind(); } } # Option to view original if it exists if ( ($ftype eq 'dls') && (exists $Caseman::mod2vol{$vol})) { print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&" . "view=$Data::CONT_MENU_FR&${Args::baseargs_novol}" . "&vol=$Caseman::mod2vol{$vol}&" . "block=$block&sort=$sort&len=$len&btype=$Data::ADDR_DLS\" " . "target=\"_parent\">View Original</a><br>\n"; } Print::print_html_footer(); return 0; } #Display actual block content sub content { Args::check_sort(); Print::print_text_header(); my $sort = Args::get_sort(); my $block = Args::get_block(); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $len = Args::get_len(); my $bs = Args::get_unitsize(); my $range = ""; if ($len == 0) { print "Invalid length: 0\n"; exit(1); } elsif ($len == 1) { $range = "$Fs::addr_unit{$ftype} $block"; } else { my $end = $block + $len - 1; $range = "$Fs::addr_unit{$ftype}" . "s $block-$end"; } my $str = "Contents of $range in $Caseman::vol2sname{$vol}\n\n\n"; my $log_str = "contents of $range"; my $usize_str = ""; $usize_str = " -u $bs " if ($ftype eq 'dls'); local *OUT; if ($sort == $Data::SORT_HEX) { print "Hex " . $str; Print::log_host_inv( "$Caseman::vol2sname{$vol}: Displaying Hex $log_str"); Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -h -o $offset -i $imgtype $img $block $len" ); } elsif ($sort == $Data::SORT_ASC) { print "ASCII " . $str; Print::log_host_inv( "$Caseman::vol2sname{$vol}: Displaying ASCII $log_str"); Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -a -o $offset -i $imgtype $img $block $len" ); } elsif ($sort == $Data::SORT_STR) { print "ASCII String " . $str; Print::log_host_inv( "$Caseman::vol2sname{$vol}: Displaying string $log_str"); Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -o $offset -i $imgtype $img $block $len | '$::TSKDIR/srch_strings' -a" ); } print $_ while ($_ = Exec::read_pipe_data(*OUT, 512)); close(OUT); Print::print_text_footer(); return 0; } sub report { Args::check_sort(); my $sort = Args::get_sort(); my $vol = Args::get_vol('vol'); my $block = Args::get_block(); my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $len = Args::get_len(); my $type; if ($len == 0) { print("Invalid length: 0"); exit(1); } my $bs = Args::get_unitsize(); my $usize_str = ""; $usize_str = " -u $bs " if ($ftype eq 'dls'); Print::print_text_header("$vol" . "-" . "$Fs::addr_unit{$ftype}" . "$Args::args{'block'}" . ".txt"); if ($sort == $Data::SORT_ASC) { Print::log_host_inv( "$Caseman::vol2sname{$vol}: Generating ASCII report on data unit $block" ); $type = "ascii"; } elsif ($sort == $Data::SORT_STR) { Print::log_host_inv( "$Caseman::vol2sname{$vol}: Generating ASCII strings report on data unit $block" ); $type = "string"; } elsif ($sort == $Data::SORT_HEX) { Print::log_host_inv( "$Caseman::vol2sname{$vol}: Generating hex report on data unit $block" ); $type = "hex"; } else { print "\n\n"; print "invalid sort value"; return 1; } print " Autopsy $type $Fs::addr_unit{$ftype} Report\n\n" . "-" x 70 . "\n" . " GENERAL INFORMATION\n\n"; if ($len == 1) { print "$Fs::addr_unit{$ftype}: $Args::args{'block'}\n"; } else { my $end = $block + $len - 1; print "$Fs::addr_unit{$ftype}" . "s: $Args::args{'block'}-$end\n"; } print "$Fs::addr_unit{$ftype} Size: $bs\n"; # if (($ftype ne 'dls') && ($ftype ne 'raw') && ($ftype ne 'swap')) { if ($Fs::is_fs{$ftype} == 1) { local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/ifind' -f $ftype -d $block -o $offset -i $imgtype $img" ); my $meta = Exec::read_pipe_line(*OUT); close(OUT); $meta = "Error getting meta address" if ((!defined $meta) || ($meta eq "")); if ($meta =~ /^($::REG_META)$/o) { my $tmpi = $1; print "\nPointed to by $Fs::meta_str{$ftype}: $tmpi\n"; my $tmpr = $Caseman::vol2mnt{$vol}; print "Pointed to by files:\n"; Exec::exec_pipe(*OUT, "'$::TSKDIR/ffind' -f $ftype -a -o $offset -i $imgtype $img $tmpi" ); while ($_ = Exec::read_pipe_line(*OUT)) { chop; if (/^(\*)\s+\/*(.*)$/) { Print::print_output(" $tmpr$2 (deleted)\n"); } elsif (/^\/(.*)$/) { Print::print_output(" $tmpr$1\n"); } else { Print::print_output(" $_\n"); } } close(OUT); } else { print "Not allocated to any meta data structures\n"; } } # not dls Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -o $offset -i $imgtype $img $block $len | '$::TSKDIR/md5'" ); my $md5 = Exec::read_pipe_line(*OUT); close(OUT); $md5 = "Error getting md5" if ((!defined $md5) || ($md5 eq "")); chop $md5; print "MD5 of raw $Fs::addr_unit{$ftype}: $md5\n"; if ($sort == $Data::SORT_HEX) { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -h -o $offset -i $imgtype $img $block $len | '$::TSKDIR/md5'" ); } elsif ($sort == $Data::SORT_ASC) { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -a -o $offset -i $imgtype $img $block $len | '$::TSKDIR/md5'" ); } elsif ($sort == $Data::SORT_STR) { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -o $offset -i $imgtype $img $block $len | '$::TSKDIR/srch_strings' -a | '$::TSKDIR/md5'" ); } $md5 = Exec::read_pipe_line(*OUT); close(OUT); $md5 = "Error getting md5" if ((!defined $md5) || ($md5 eq "")); chop $md5; print "MD5 of $type output: $md5\n"; print "\nImage: $Caseman::vol2path{$vol}\n"; if (($Caseman::vol2start{$vol} == 0) && ($Caseman::vol2end{$vol} == 0)) { print "Offset: Full image\n"; } elsif ($Caseman::vol2end{$vol} == 0) { print "Offset: $Caseman::vol2start{$vol} to end\n"; } else { print "Offset: $Caseman::vol2start{$vol} to $Caseman::vol2end{$vol}\n"; } print "File System Type: $ftype\n"; my $date = localtime(); print "\nDate Generated: $date\n" . "Investigator: $Args::args{'inv'}\n" . "-" x 70 . "\n" . " CONTENT\n\n"; if ($sort == $Data::SORT_HEX) { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -h -o $offset -i $imgtype $img $block $len" ); } elsif ($sort == $Data::SORT_ASC) { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -a -o $offset -i $imgtype $img $block $len" ); } elsif ($sort == $Data::SORT_STR) { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype $usize_str -o $offset -i $imgtype $img $block $len | '$::TSKDIR/srch_strings' -a" ); } Print::print_output($_) while ($_ = Exec::read_pipe_data(*OUT, 512)); close(OUT); print "\n" . "-" x 70 . "\n" . " VERSION INFORMATION\n\n" . "Autopsy Version: $::VER\n"; print "The Sleuth Kit Version: " . ::get_tskver() . "\n"; Print::print_text_footer(); return 0; } # # Display the block allocation list # sub list { Print::print_html_header("Block Allocation List"); my $DLS_GAP = 500; my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $min = 0; $min = Args::get_min() if (exists $Args::args{'min'}); my $max = $min + $DLS_GAP - 1; # set fmin to the minimum for the file system my $fmin = $min; $fmin = $Fs::first_addr{$ftype} if ($min < $Fs::first_addr{$ftype}); Print::log_host_inv( "$Caseman::vol2sname{$vol}: Block Allocation List for $min to $max"); print "<center><H2>$Fs::addr_unit{$ftype}: $min - $max</H2>"; my $tmp; if ($min - $DLS_GAP >= 0) { $tmp = $min - $DLS_GAP; print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::LIST&" . "$Args::baseargs&min=$tmp\">" . "<img src=\"pict/but_prev.jpg\" alt=\"previous\" " . "width=\"89\" height=20 border=\"0\"></a> "; } $tmp = $min + $DLS_GAP; print " <a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::LIST&" . "$Args::baseargs&min=$tmp\">" . "<img src=\"pict/but_next.jpg\" alt=\"next\" " . "width=\"89\" height=20 border=\"0\"></a><br>"; print "</center>\n"; local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/dls' -elb -f $ftype -o $offset -i $imgtype $img $fmin-$max" ); while ($_ = Exec::read_pipe_line(*OUT)) { if (/^(\d+)\|([af])/) { print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&" . "view=$Data::CONT_MENU_FR&$Args::baseargs&block=$1\">" . "$1:</a> "; if ($2 eq "a") { print "allocated<br>\n"; } else { print "<font color=\"$::DEL_COLOR[0]\">free</font><br>\n"; } } } close(OUT); print "<center>\n"; if ($min - $DLS_GAP >= 0) { $tmp = $min - $DLS_GAP; print "<a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::LIST&" . "$Args::baseargs&min=$tmp\">" . "<img src=\"pict/but_prev.jpg\" alt=\"previous\" " . "width=\"89\" height=20 border=\"0\"></a> "; } $tmp = $min + $DLS_GAP; print " <a href=\"$::PROGNAME?mod=$::MOD_DATA&view=$Data::LIST&" . "$Args::baseargs&min=$tmp\">" . "<img src=\"pict/but_next.jpg\" alt=\"next\" " . "width=\"89\" height=20 border=\"0\"></a><br>"; print "</center>\n"; Print::print_html_footer(); return 0; } sub export { my $block = Args::get_block(); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $len = Args::get_len(); my $bs = Args::get_unitsize(); Print::print_oct_header( "$vol" . "-" . "$Fs::addr_unit{$ftype}" . "$block" . ".raw"); Print::log_host_inv( "$Caseman::vol2sname{$vol}: Saving contents of data unit $block (unit size: $bs number: $len)" ); local *OUT; if ($ftype eq 'dls') { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype -u $bs -o $offset -i $imgtype $img $block $len" ); } else { Exec::exec_pipe(*OUT, "'$::TSKDIR/dcat' -f $ftype -o $offset -i $imgtype $img $block $len" ); } print "$_" while ($_ = Exec::read_pipe_data(*OUT, 512)); close(OUT); Print::print_oct_footer(); return 0; } # Blank Page sub blank { Print::print_html_header("Data Unit Blank Page"); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; print "<center><h3>Data Unit Mode</h3><br>\n" . "Here you can view the contents of any $Fs::addr_unit{$ftype} in the file system.<br>\n" . "Enter the address in the field on the left.\n"; Print::print_html_footer(); return 0; }