# # $Date: 2006/05/08 18:46:57 $ # # File name 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. # Updated 1/15 package File; # If the order of these views are changed, then the checks in main # must be as well $File::BLANK = 0; $File::FRAME = 1; $File::DIR_LIST = 2; $File::FILE_LIST_DIR = 3; $File::FILE_LIST_FILE = 4; $File::FILE_LIST_DEL = 5; $File::FILE_LIST = 6; $File::CONT = 7; $File::CONT_FR = 8; $File::CONT_MENU = 9; $File::REPORT = 10; $File::EXPORT = 11; $File::MD5LIST = 12; $File::CONT_IMG = 13; $File::REC_NO = 0; $File::REC_YES = 1; sub main { # By default, show the main frame $Args::args{'view'} = $Args::enc_args{'view'} = $File::FRAME unless (exists $Args::args{'view'}); Args::check_view(); my $view = Args::get_view(); if ($view == $File::BLANK) { blank(); return 0; } # Check Basic Args Args::check_vol('vol'); # These windows don't need the meta data address if ($view < $File::FILE_LIST) { if ($view == $File::FRAME) { return frame(); } Args::check_dir(); if ($view == $File::DIR_LIST) { return dir_list(); } elsif ($view == $File::FILE_LIST_DIR) { return file_list_dir(); } elsif ($view == $File::FILE_LIST_DEL) { return file_list_del(); } elsif ($view == $File::FILE_LIST_FILE) { return file_list_file(); } } # These windows need the meta data address Args::check_dir(); Args::check_meta('meta'); if ($view < $File::REPORT) { if ($view == $File::FILE_LIST) { return file_list(); } elsif ($view == $File::CONT) { return content(); } elsif ($view == $File::CONT_FR) { return content_fr(); } elsif ($view == $File::CONT_MENU) { return content_menu(); } } else { if ($view == $File::REPORT) { return report(); } elsif ($view == $File::EXPORT) { return export(); } elsif ($view == $File::MD5LIST) { return md5list(); } elsif ($view == $File::CONT_IMG) { return content_img(); } } Print::print_check_err("Invalid File View"); } # Sorting and display types my $FIL_SORT_ASC = 0; my $FIL_SORT_STR = 1; my $FIL_SORT_HEX = 2; # Methods of sorting the file listings my $SORT_DTYPE = 0; # type according to dentry my $SORT_ITYPE = 1; # type according to meta my $SORT_NAME = 2; my $SORT_MOD = 3; my $SORT_ACC = 4; my $SORT_CHG = 5; my $SORT_SIZE = 6; my $SORT_GID = 7; my $SORT_UID = 8; my $SORT_META = 9; my $SORT_DEL = 10; my $DIRMODE_SHOW = 1; my $DIRMODE_NOSHOW = 2; # # Make the three frames and fill them in # sub frame { my $vol = Args::get_vol('vol'); my $mnt = $Caseman::vol2mnt{$vol}; my $ftype = $Caseman::vol2ftype{$vol}; # If we were not given the meta, then look up the root unless (exists $Args::args{'meta'}) { $Args::args{'meta'} = $Args::enc_args{'meta'} = $Fs::root_meta{$ftype}; } unless (exists $Args::args{'dir'}) { $Args::enc_args{'dir'} = $Args::args{'dir'} = "/"; } Args::check_meta('meta'); Args::check_dir(); my $meta = Args::get_meta('meta'); my $dir = Args::get_dir(); Print::print_html_header_frameset("$mnt$dir on $Args::args{'vol'}"); my $sort = $SORT_NAME; $sort = $Args::args{'sort'} if (exists $Args::args{'sort'}); my $dirmode = $DIRMODE_NOSHOW; $dirmode = $Args::args{'dirmode'} if (exists $Args::args{'dirmode'}); print "\n"; # Directory Listing on Left my $url = "$::PROGNAME?$Args::baseargs&dir=$dir&" . "sort=$sort&dirmode=$dirmode"; print "\n"; # File frameset on right print "\n"; # File Listings on top print "\n"; # File Contents print "\n" . "\n" . "\n"; Print::print_html_footer_frameset(); return 0; } # # Print the directory names for the lhs frame and other # Search forms # sub dir_list { Args::check_sort(); Args::check_dirmode(); Print::print_html_header(""); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $sort = Args::get_sort(); my $dirmode = Args::get_dirmode(); my $mnt = $Caseman::vol2mnt{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $lcldir = ""; my $prev_plus = ""; # previous number of '+' directory spacers my $prev_fname = ""; my $prev_meta = ""; # Field to enter a directory into: print "

\n" . "
Directory Seek

" . "Enter the name of a directory that you want to view.
" . "$mnt" . "\n" . "\n" . "\n" . "\n" . "\n" . "\n" . Args::make_hidden() . # View Button "
\n"; # Field to enter a name into: print "

\n" . "
File Name Search

" . "Enter a Perl regular expression for the file names you want to find.

\n" . "\n" . "\n" . "\n" . "\n" . "\n" . "\n" . Args::make_hidden() . "
\n" . # Search Button "
\n"; print "


\n"; my $base_url = "$::PROGNAME?$Args::baseargs&sort=$sort"; # All deleted files button print "" . "" . "

\n"; # The dirmode arg shows if we should expand the whole directory listing # or not if ($dirmode == $DIRMODE_NOSHOW) { print "" . "\"Expand


\n"; return; } else { print "" . "\"Hide


\n"; } $base_url .= "&dirmode=$dirmode"; Print::log_host_inv("$Args::args{'vol'}: List of all directories"); # We need to maintain state to create dir and this is done by # counting the + marks. local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/fls' -f $ftype -ruD -o $offset -i $imgtype $img"); # Print root my $url = "$base_url&mod=$::MOD_FILE&view=$File::FILE_LIST&" . "meta=$Fs::root_meta{$ftype}&dir="; print "

$mnt
\n"; while ($_ = Exec::read_pipe_line(*OUT)) { if ( /^(\*)?(\+*)\s*[\-d]\/[\-d]\s*(\d+)\-?\d*\-?\d*\s*(\(realloc\))?:\t(.+)$/ ) { my $del = $1; my $plus = $2; my $meta = $3; my $re = $4; my $fname = $5; # Adjust the dir value using the '++' values to determine # how "deep" we are unless ($prev_plus eq $plus) { # are we in 1 more if ($plus eq $prev_plus . '+') { $lcldir .= ($prev_fname . "/"); } # we are back (at least one) elsif (defined $plus) { my @dirs = split('/', $lcldir); my $idx = -1; $lcldir = ""; while (($idx = index($plus, '+', $idx + 1)) != -1) { $lcldir .= ($dirs[$idx] . "/"); } } } $prev_plus = $plus; $prev_fname = $fname; $prev_meta = $meta; $url = "$base_url&mod=$::MOD_FILE&view=$File::FILE_LIST&" . "meta=$meta&dir=" . Args::url_encode($lcldir . $fname . "/"); print "" if defined $del; print "+$plus/$fname
\n"; print "
" if defined $del; } } close(OUT); Print::print_html_footer(); return 0; }; # end of FIL_DIR # Print the files and directories for the upper rhs frame # These can be sorted in any format # # We need to find a way to cache this data # sub file_list { Args::check_sort(); Args::check_dirmode(); my $vol = Args::get_vol('vol'); my $sort = Args::get_sort(); my $ftype = $Caseman::vol2ftype{$vol}; my $meta = Args::get_meta('meta'); my $mnt = $Caseman::vol2mnt{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $fname = "$mnt$Args::args{'dir'}"; $fname =~ s/\/\//\//g; my $sp = "  "; Print::print_html_header("Entries in $fname"); my (@itype, @dtype, @name, @mod, @acc, @chg, @size, @gid, @uid, @meta); my (@dir, @entry, @del, @realloc, @meta_int); my $tz = ""; $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); Print::log_host_inv( "$Caseman::vol2sname{$vol}: Directory listing of $fname ($meta)"); local *OUT; # execute command # NTFS does not look at deleted files - it will use ifind later if ($ftype eq "ntfs") { Exec::exec_pipe(*OUT, "'$::TSKDIR/fls' -f $ftype -lau $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" ); } else { Exec::exec_pipe(*OUT, "'$::TSKDIR/fls' -f $ftype -la $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" ); } # Make the big table, small table, and start the current directory my $iurl = "$::PROGNAME?$Args::baseargs&dirmode=$Args::enc_args{'dirmode'}&sort=$sort"; print < EOF3 # Make the Table and Headers my $url = "$::PROGNAME?mod=$::MOD_FILE&view=$File::FRAME&" . "$Args::baseargs&meta=$Args::enc_args{'meta'}" . "&dir=$Args::enc_args{'dir'}&dirmode=$Args::enc_args{'dirmode'}"; print "\n"; # Print the Headers - If the sorting mode is set to it, then don't # make it a link and print a different button if ($sort == $SORT_DEL) { print " \n"; } else { $iurl = $url . "&sort=$SORT_DEL"; print " \n"; } # type only gets one column for two 'types' print " \n" . " \n"; } else { $iurl = $url . "&sort=$SORT_ITYPE"; print "in\n"; } print " \n"; if ($sort == $SORT_NAME) { print " \n"; } else { $iurl = $url . "&sort=$SORT_NAME"; print " \n"; } print " \n"; # Modified / Written if ($sort == $SORT_MOD) { print " \n"; } else { $iurl = $url . "&sort=$SORT_MOD"; print " \n"; } print " \n"; # Accessed if ($sort == $SORT_ACC) { print " \n"; } else { $iurl = $url . "&sort=$SORT_ACC"; print " \n"; } print " \n"; # Change / Create if ($sort == $SORT_CHG) { print " \n"; } else { $iurl = $url . "&sort=$SORT_CHG"; print " \n"; } print " \n"; # Size if ($sort == $SORT_SIZE) { print " \n"; } else { $iurl = $url . "&sort=$SORT_SIZE"; print " \n"; } print " \n"; # UID if ($sort == $SORT_UID) { print " \n"; } else { $iurl = $url . "&sort=$SORT_UID"; print " \n"; } print " \n"; # GID if ($sort == $SORT_GID) { print " \n"; } else { $iurl = $url . "&sort=$SORT_GID"; print " \n"; } print " \n"; # meta if ($sort == $SORT_META) { print " \n"; } else { $iurl = $url . "&sort=$SORT_META"; print " \n"; } print "\n"; my $cnt = 0; my %seen; # sort into arrays while ($_ = Exec::read_pipe_line(*OUT)) { if ( /^($::REG_MTYPE)\/($::REG_MTYPE)\s*(\*?)\s*($::REG_META)(\(realloc\))?:\t(.+?)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o ) { my $lcldir = $Args::args{'dir'}; $dtype[$cnt] = $1; $itype[$cnt] = $2; $del[$cnt] = $3; $meta[$cnt] = $4; $realloc[$cnt] = ""; $realloc[$cnt] = $5 if (defined $5); $name[$cnt] = $6; $mod[$cnt] = $7; $acc[$cnt] = $8; $chg[$cnt] = $9; $size[$cnt] = $10; $gid[$cnt] = $11; $uid[$cnt] = $12; if ($meta[$cnt] =~ /^(\d+)(-\d+(-\d+)?)?$/) { $meta_int[$cnt] = $1; } else { $meta_int[$cnt] = $meta[$cnt]; } # See if we have already seen this file yet if (exists $seen{"$name[$cnt]-$meta[$cnt]"}) { my $prev_cnt = $seen{"$name[$cnt]-$meta[$cnt]"}; # If we saw it while it was deleted, & it # is now undel, then update it if ( ($del[$cnt] eq "") && ($del[$prev_cnt] eq '*')) { $del[$prev_cnt] = $del[$cnt]; } next; # Add it to the seen list } else { $seen{"$name[$cnt]-$meta[$cnt]"} = $cnt; } # We must adjust the dir for directories if ($itype[$cnt] eq 'd') { # special cases for .. and . if ($name[$cnt] eq '..') { my @dirs = split('/', $lcldir); my $i; $lcldir = ""; for ($i = 0; $i < $#dirs; $i++) { $lcldir .= ($dirs[$i] . '/'); } } elsif ($name[$cnt] ne '.') { $lcldir .= ($name[$cnt] . '/'); } $name[$cnt] .= '/'; } else { $lcldir .= $name[$cnt]; } # format the date so that the time and time zone are on the # same line $mod[$cnt] = "$1 $2" if ($mod[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $acc[$cnt] = "$1 $2" if ($acc[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $chg[$cnt] = "$1 $2" if ($chg[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $dir[$cnt] = Args::url_encode($lcldir); $entry[$cnt] = $cnt; $cnt++; } # We missed it for some reason else { print "\n"; } } close(OUT); # ntfs runs 'ifind' to find the orphan MFT entries if ($ftype eq "ntfs") { Exec::exec_pipe(*OUT, "'$::TSKDIR/ifind' -f $ftype -l $tz -p $meta -o $offset -i $imgtype $img" ); while ($_ = Exec::read_pipe_line(*OUT)) { if ( /^($::REG_MTYPE)\/($::REG_MTYPE)\s*(\*?)\s*($::REG_META)(\(realloc\))?:\t(.+?)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o ) { my $lcldir = $Args::args{'dir'}; $dtype[$cnt] = $1; $itype[$cnt] = $2; $del[$cnt] = $3; $meta[$cnt] = $4; $realloc[$cnt] = ""; $realloc[$cnt] = $5 if (defined $5); $name[$cnt] = $6; $mod[$cnt] = $7; $acc[$cnt] = $8; $chg[$cnt] = $9; $size[$cnt] = $10; $gid[$cnt] = $11; $uid[$cnt] = $12; if ($meta[$cnt] =~ /^(\d+)(-\d+(-\d+)?)?$/) { $meta_int[$cnt] = $1; } else { $meta_int[$cnt] = $meta[$cnt]; } # See if we have already seen this file yet if (exists $seen{"$name[$cnt]-$meta[$cnt]"}) { next; # Add it to the seen list } else { $seen{"$name[$cnt]-$meta[$cnt]"} = $cnt; } # We must adjust the dir for directories if ($itype[$cnt] eq 'd') { # special cases for .. and . if ($name[$cnt] eq '..') { my @dirs = split('/', $lcldir); my $i; $lcldir = ""; for ($i = 0; $i < $#dirs; $i++) { $lcldir .= ($dirs[$i] . '/'); } } elsif ($name[$cnt] ne '.') { $lcldir .= ($name[$cnt] . '/'); } $name[$cnt] .= '/'; } else { $lcldir .= $name[$cnt]; } # format the date so that the time and time zone are on the # same line $mod[$cnt] = "$1 $2" if ($mod[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $acc[$cnt] = "$1 $2" if ($acc[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $chg[$cnt] = "$1 $2" if ($chg[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $dir[$cnt] = Args::url_encode($lcldir); $entry[$cnt] = $cnt; $cnt++; } # We missed it for some reason else { print "\n"; } } close(OUT); } # End NTFS ONLY if ($cnt == 0) { print "
\n" . " \n"; # Add Note Button $iurl = "&$Args::baseargs&dir=$Args::enc_args{'dir'}&meta=$Args::enc_args{'meta'}"; if ($::USE_NOTES == 1) { print < EOF2 } # Generate MD5 List Button print < \"Generate
Current Directory: $mnt  EOF1 # Each file in the path will get its own link $iurl .= "&mod=$::MOD_FILE&view=$File::FILE_LIST_DIR"; my $path = ""; my @dir_split = split('/', $Args::args{'dir'}); while (scalar @dir_split > 1) { my $d = shift @dir_split; next if ($d eq ''); $path .= "$d/"; print " /${d}/ \n"; } print " /$dir_split[0]/ \n" if (scalar @dir_split == 1); print "
\"Add

" . "" . "" . "" . "" . "$sp" . "  Type  
"; if ($sort == $SORT_DTYPE) { print "dir"; } else { $iurl = $url . "&sort=$SORT_DTYPE"; print "dir"; } print " / "; if ($sort == $SORT_ITYPE) { print "in
$sp" . "" . "" . "" . "" . "$sp"; if ($Fs::mtime_str{$ftype} eq 'Modified') { print ""; } else { print ""; } print "" . ""; if ($Fs::mtime_str{$ftype} eq 'Modified') { print ""; } else { print ""; } print "$sp" . "" . "" . "" . "" . "$sp"; if ($Fs::ctime_str{$ftype} eq 'Changed') { print ""; } else { print ""; } print "" . ""; if ($Fs::ctime_str{$ftype} eq 'Changed') { print ""; } else { print ""; } print "$sp" . "" . "" . "" . "" . "$sp" . "" . "" . "" . "" . "$sp" . "" . "" . "" . "" . "$sp" . "" . "" . "" . "" . "
Error Parsing File (Invalid Characters?):
$_
Error Parsing File (Invalid Characters?):
$_
\n

No Contents
\n"; return 0; } # Sort the above array based on the sort argument my @sorted; # an array of indices if ($sort == $SORT_DTYPE) { @sorted = sort { $dtype[$a] cmp $dtype[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_ITYPE) { @sorted = sort { $itype[$a] cmp $itype[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_NAME) { @sorted = sort { lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_MOD) { @sorted = sort { $mod[$a] cmp $mod[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_ACC) { @sorted = sort { $acc[$a] cmp $acc[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_CHG) { @sorted = sort { $chg[$a] cmp $chg[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_SIZE) { @sorted = sort { $size[$a] <=> $size[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_UID) { @sorted = sort { $uid[$a] <=> $uid[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_GID) { @sorted = sort { $gid[$a] <=> $gid[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_META) { @sorted = sort { $meta_int[$a] <=> $meta_int[$b] or lc($name[$a]) cmp lc($name[$b]) } @entry; } elsif ($sort == $SORT_DEL) { @sorted = sort { $del[$b] cmp $del[$a] or lc($name[$a]) cmp lc($name[$b]) } @entry; } # print them based on sorting my $row = 0; foreach my $i (@sorted) { my $url; my $target; my $color; my $lcolor; if ($del[$i] eq '*') { $color = ""; $lcolor = $color; } else { $color = ""; $lcolor = ""; } # directories have different targets and view values if ($itype[$i] eq 'd') { $target = "list"; $url = "$::PROGNAME?mod=$::MOD_FILE&view=$File::FILE_LIST&" . "$Args::baseargs&meta=$meta_int[$i]" . "&sort=$sort&dir=$dir[$i]&dirmode=$Args::enc_args{'dirmode'}"; } else { $target = "content"; $url = "$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&" . "$Args::baseargs&meta=$meta[$i]" . "&sort=$sort&dir=$dir[$i]&dirmode=$Args::enc_args{'dirmode'}"; if ($del[$i] eq '*') { $url .= "&recmode=$File::REC_YES"; } else { $url .= "&recmode=$File::REC_NO"; } } if (($row % 2) == 0) { print "\n "; } else { print "\n "; } print "\n" if ($del[$i] eq '*'); print "\n" . " $sp\n" . " ${color}$dtype[$i] / $itype[$i]\n" . " $sp\n"; # for valid files and directories make a link if ( ($meta_int[$i] >= $Fs::first_meta{$ftype}) && ($size[$i] > 0) && (($itype[$i] eq 'r') || ($itype[$i] eq 'd'))) { print " $lcolor"; } else { print " $color"; } print "$name[$i]\n" . " $sp\n" . " ${color}$mod[$i]\n" . " $sp\n" . " ${color}$acc[$i]\n" . " $sp\n" . " ${color}$chg[$i]\n" . " $sp\n" . " ${color}$size[$i]\n" . " $sp\n" . " ${color}$uid[$i]\n" . " $sp\n" . " ${color}$gid[$i]\n" . " $sp\n"; # for a valid meta, make a link to meta browsing mode if ($meta_int[$i] >= $Fs::first_meta{$ftype}) { my $iurl = "$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&meta=$meta[$i]"; print "$lcolor"; } else { print "$color"; } print "$meta[$i] $realloc[$i]\n\n"; $row++; } print "\n"; Print::print_html_footer(); return 0; }; #end of FIL_LIST # This takes a directory name as an argument and converts it to # the meta value and calls FIL_LIST # # The meta value can be anything when this is run, it will be # overwritten sub file_list_dir { my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $dir = Args::get_dir(); my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; Print::log_host_inv( "$Args::args{'vol'}: Finding meta data address for $dir"); # Use 'ifind -n' to get the meta data address for the given name local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/ifind' -f $ftype -n '$dir' -o $offset -i $imgtype $img"); my $meta; while ($_ = Exec::read_pipe_line(*OUT)) { $meta = $1 if (/^($::REG_META)$/); } close(OUT); Print::print_check_err("Error finding meta data address for $dir") unless (defined $meta); Print::print_check_err( "Error finding meta data address for $dir$dir ( meta $meta) is not a directory.

\"view EOF Print::print_html_footer(); return 1; } # List the files that meet a certain pattern sub file_list_file { Args::check_sort(); Args::check_dirmode(); Args::check_dir(); my $vol = Args::get_vol('vol'); my $mnt = $Caseman::vol2mnt{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $ftype = $Caseman::vol2ftype{$vol}; my $meta = $Fs::root_meta{$ftype}; my $sort = Args::get_sort(); my $dirmode = Args::get_dirmode(); my $dir = Args::get_dir(); Print::print_html_header( "Filtered files on $Caseman::vol2sname{$vol} $mnt"); my $tz = ""; $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); my $sp = "  "; Print::log_host_inv( "$Caseman::vol2sname{$vol}: Listing all files with $dir"); local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/fls' -f $ftype -lpr $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" ); print "All files with \'$dir\' in the name

\n" . "" . "\n" . "


" . "\n" . "\n"; # deleted print "\n" . "\n"; # Type print "" . "\n"; # Name print " \n" . "\n"; # Mod / Written print " \n" . "\n"; # Access print " \n" . "\n"; # Change / Create print " \n" . "\n"; # Size print " \n" . "\n"; # UID print " \n" . "\n"; # GID print " \n" . "\n"; # Meta print " \n" . "\n"; my $row = 0; while ($_ = Exec::read_pipe_line(*OUT)) { if ( /^($::REG_MTYPE)\/($::REG_MTYPE)\s*(\*?)\s*($::REG_META)(\(realloc\))?:\t(.+?)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o ) { # We have to remove the / from the beginning of the file name so # save all values so they aren't lost my $dt = $1; my $it = $2; my $d = $3; my $i = $4; my $r = 0; $r = 1 if (defined $5); my $n = $6; my $m = $7; my $a = $8; my $c = $9; my $s = $10; my $g = $11; my $u = $12; if ($n =~ /^\/(.*)/) { $n = $1; } my $p = ""; my $f = $n; if ($n =~ /^(.+?)\/([^\/]+)$/) { $p = $1; $f = $2; } next unless ($f =~ /$dir/i); my $enc_n = Args::url_encode($n); my $iurl = "$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&meta=$i"; my $i_int = $i; $i_int = $1 if ($i =~ /(\d+)-\d+-\d+/); if (($row % 2) == 0) { print "\n"; } else { print "\n"; } print ""; print "" . "\n"; if ($it eq 'd') { my $url = "$::PROGNAME?mod=$::MOD_FILE&" . "view=$File::FILE_LIST&$Args::baseargs&meta=$i" . "&sort=$sort&dir=$enc_n&dirmode=$dirmode"; print "" . "\n"; } else { my $url = "$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&" . "$Args::baseargs&meta=$i&sort=$sort&dir=$enc_n"; if ($d eq '*') { $url .= "&recmode=$File::REC_YES"; } else { $url .= "&recmode=$File::REC_NO"; } print "" . "\n"; } $m = "$1 $2" if ($m =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $a = "$1 $2" if ($a =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $c = "$1 $2" if ($c =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); print "" . "\n" . "" . "\n" . "" . "\n" . "" . "\n" . "" . "\n" . "" . "\n"; print "\n"; } else { print "Error Parsing File (invalid characters?)
: $_\n
"; } $row++; } close(OUT); print "
" . "\"Deleted" . "$sp  Type  
" . "dir / in
$sp" . "$sp"; } else { print "src=\"pict/file_h_wr_link.jpg\" " . "width=\"60\" " . "alt=\"Written Time\">"; } print "$sp" . "$sp"; } else { print "src=\"pict/file_h_cre_link.jpg\" " . "width=\"59\" height=20 " . "alt=\"Create Time\">"; } print "$sp" . "$sp" . "$sp" . "$sp" . "$sp
\n"; my $color; my $lcolor; if ($d eq '*') { $color = ""; $lcolor = $color; print "\n"; } else { $color = ""; $lcolor = ""; print " "; } print "$sp$color" . "$dt / $it$sp"; if ($i_int >= $Fs::first_meta{$ftype}) { print "$lcolor"; } else { print "$color"; } print "$mnt$n$sp"; if (($i_int >= $Fs::first_meta{$ftype}) && ($it eq 'r')) { print "$lcolor"; } else { print "$color"; } print "$mnt$n$sp$color$m$sp$color$a$sp$color$c$sp$color$s$sp$color$g$sp$color$u$sp"; if ($i_int >= $Fs::first_meta{$ftype}) { print ""; print "$lcolor$i"; } else { print "$color$i"; } print " (realloc)" if $r; print "
\n"; print "
No files found with that pattern
\n" if ($row == 0); Print::print_html_footer(); return 0; } # display deleted files only # # Sorting should be added to this sub file_list_del { Args::check_sort(); Args::check_dirmode(); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $mnt = $Caseman::vol2mnt{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $meta = $Fs::root_meta{$ftype}; my $sort = Args::get_sort(); my $dirmode = Args::get_dirmode(); Print::print_html_header("Deleted files on $Caseman::vol2sname{$vol} $mnt"); my $tz = ""; $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); my $sp = "  "; Print::log_host_inv("$Caseman::vol2sname{$vol}: Listing all deleted files"); local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/fls' -f $ftype -ldr $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" ); print "All Deleted Files


" . "\n" . "\n"; # Type print "" . "\n"; # Name print " \n" . "\n"; # Mod / Written print " \n" . "\n"; # Access print " \n" . "\n"; # Change / Create print " \n" . "\n"; # Size print " \n" . "\n"; # UID print " \n" . "\n"; # GID print " \n" . "\n"; # Meta print " \n" . "\n"; my $row = 0; while ($_ = Exec::read_pipe_line(*OUT)) { if ( /^($::REG_MTYPE)\/($::REG_MTYPE)\s*(\*?)\s*($::REG_META)(\(realloc\))?:\t(.+?)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o ) { # We have to remove the / from the beginning of the file name so # save all values so they aren't lost my $dt = $1; my $it = $2; my $d = $3; my $i = $4; my $r = 0; $r = 1 if (defined $5); my $n = $6; my $m = $7; my $a = $8; my $c = $9; my $s = $10; my $g = $11; my $u = $12; if ($n =~ /^\/(.*)/) { $n = $1; } my $enc_n = Args::url_encode($n); my $iurl = "$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&meta=$i"; my $i_int = $i; $i_int = $1 if ($i =~ /(\d+)-\d+-\d+/); if (($row % 2) == 0) { print "\n"; } else { print "\n"; } print "" . "\n"; if ($it eq 'd') { my $url = "$::PROGNAME?mod=$::MOD_FILE&" . "view=$File::FILE_LIST&$Args::baseargs&meta=$i" . "&sort=$sort&dir=$enc_n&dirmode=$dirmode"; print "" . "\n"; } else { my $url = "$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&" . "$Args::baseargs&meta=$i&sort=$sort&dir=$enc_n" . "&recmode=$File::REC_YES"; print "" . "\n"; } $m = "$1 $2" if ($m =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $a = "$1 $2" if ($a =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); $c = "$1 $2" if ($c =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); print "" . "\n" . "" . "\n" . "" . "\n" . "" . "\n" . "" . "\n" . "" . "\n"; print "\n"; } else { print "Error Parsing File (invalid characters?)
: $_\n
"; } $row++; } close(OUT); print "
  Type  
" . "dir / in
$sp" . "$sp"; } else { print "src=\"pict/file_h_wr_link.jpg\" " . "width=\"60\" " . "alt=\"Written Time\">"; } print "$sp" . "$sp"; } else { print "src=\"pict/file_h_cre_link.jpg\" " . "width=\"59\" height=20 " . "alt=\"Create Time\">"; } print "$sp" . "$sp" . "$sp" . "$sp" . "$sp
" . "$dt / $it$sp"; if ($i_int >= $Fs::first_meta{$ftype}) { print ""; } print "" . "$mnt$n$sp"; if (($i_int >= $Fs::first_meta{$ftype}) && ($it eq 'r')) { print ""; } print "" . "$mnt$n$sp$m$sp$a$sp$c$sp$s$sp$g$sp$u$sp"; if ($i_int >= $Fs::first_meta{$ftype}) { print ""; } print "$i"; print " (realloc)" if $r; print "
\n"; print "
None
\n" if ($row == 0); Print::print_html_footer(); return 0; } # Content Frame # This creates two frames for the lower rhs frame # sub content_fr { Print::print_html_header_frameset(""); my $meta = Args::get_meta('meta'); 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 "\n"; my $recmode = $File::REC_NO; if (exists $Args::enc_args{'recmode'}) { $recmode = $Args::enc_args{'recmode'}; } else { # We need to get the allocation status of this structure my $meta_int = $meta; $meta_int = $1 if ($meta_int =~ /(\d+)-\d+(-\d+)?/); local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/ils' -f $ftype -e -o $offset -i $imgtype $img $meta_int" ); while ($_ = Exec::read_pipe_line(*OUT)) { chop; next unless ($_ =~ /^$meta/); if ($_ =~ /^$meta\|f/) { $recmode = $File::REC_YES; } elsif ($_ =~ /^$meta\|a/) { $recmode = $File::REC_NO; } else { Print::print_check_err("Error parsing ils output: $_"); } } } close(OUT); # Get the file type so we can show the thumb nails automatically if ($recmode == $File::REC_YES) { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" ); } else { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" ); } my $apptype = Exec::read_pipe_line(*OUT); close(OUT); $apptype = "Error getting file type" if ((!defined $apptype) || ($apptype eq "")); # The menu for the different viewing options print "\n"; # Print the image thumbnail if (($apptype =~ /image data/) || ($apptype =~ /PC bitmap data/)) { print "\n"; } else { # Where the actual content will be displayed print "\n"; } Print::print_html_footer_frameset(); return 0; } # This is the index for the lower rhs frame # Choose the content display type here sub content_menu { Args::check_sort(); Args::check_recmode(); Print::print_html_header(""); my $meta = Args::get_meta('meta'); 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 $recmode = Args::get_recmode(); # Get the file type if ($recmode == $File::REC_YES) { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" ); } else { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" ); } my $apptype = Exec::read_pipe_line(*OUT); close(OUT); $apptype = "Error getting file type" if ((!defined $apptype) || ($apptype eq "")); # We already have the path in the content window below, so save space # print "
$mnt$Args::args{'dir'}\n"; print "
\n"; my $url = "&$Args::baseargs&dir=$Args::enc_args{'dir'}" . "&meta=$Args::enc_args{'meta'}&recmode=$recmode"; # Print the options for output display print "\n\n" . "\n" . "\n" . "\n" . "\n" . "\n" . "\n" . "\n"; # if the file is either image or HTML, then let them view it if ( ($apptype =~ /image data/) || ($apptype =~ /PC bitmap data/)) { print "\n\n"; } elsif ($apptype =~ /HTML document text/) { print "\n\n"; } print "\n" . "\n" if ($::USE_NOTES == 1); print "
ASCII (display - " . "report)*Hex (" . "display - " . "report)*ASCII Strings (" . "display - " . "report)*" . "Export*View*View*" . "Add Note
\n"; print "File Type: $apptype\n"; print "
Deleted File Recovery Mode\n" if ($recmode == $File::REC_YES); print "
\n"; Print::print_html_footer(); return 0; } # # Display the actual content here # # NOTE: This has a media type of raw text # sub content { Args::check_sort(); Args::check_recmode(); Print::print_text_header(); my $sort = Args::get_sort(); my $meta = Args::get_meta('meta'); my $vol = Args::get_vol('vol'); my $mnt = $Caseman::vol2mnt{$vol}; my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $recflag = ""; $recflag = " -r " if (Args::get_recmode() == $File::REC_YES); my $fname = "$mnt$Args::args{'dir'}"; $fname =~ s/\/\//\//g; local *OUT; if ($sort == $FIL_SORT_ASC) { Print::log_host_inv( "$Caseman::vol2sname{$vol}: Viewing $fname ($meta) as ASCII"); Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" ); print "Contents Of File: $fname\n\n\n"; Print::print_output($_) while ($_ = Exec::read_pipe_data(*OUT, 1024)); close(OUT); } elsif ($sort == $FIL_SORT_HEX) { Print::log_host_inv( "$Caseman::vol2sname{$vol}: Viewing $fname ($meta) as Hex"); Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" ); print "Hex Contents Of File: $fname\n\n\n"; my $offset = 0; while ($_ = Exec::read_pipe_data(*OUT, 1024)) { Print::print_hexdump($_, $offset * 1024); $offset++; } close(OUT); } elsif ($sort == $FIL_SORT_STR) { Print::log_host_inv( "$Caseman::vol2sname{$vol}: Viewing $fname ($meta) as strings"); Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a" ); print "ASCII String Contents Of File: $fname\n\n\n\n"; Print::print_output($_) while ($_ = Exec::read_pipe_line(*OUT)); close(OUT); } Print::print_text_footer(); return 0; } sub content_img { Print::print_html_header("image content"); my $vol = Args::get_vol('vol'); my $mnt = $Caseman::vol2mnt{$vol}; my $fname = "$mnt$Args::args{'dir'}"; $fname =~ s/\/\//\//g; my $url = "&$Args::baseargs&meta=$Args::enc_args{'meta'}" . "&dir=$Args::enc_args{'dir'}&" . "cell_mode=2&recmode=$Args::enc_args{'recmode'}"; print "$fname

\n" . "\n" . "\n" . "\n" . "
" . "Thumbnail:
" . "
" . "View Full Size Image
\n
\n"; Print::print_html_footer(); return 0; } # Export the contents of a file sub export { my $meta = Args::get_meta('meta'); my $vol = Args::get_vol('vol'); my $mnt = $Caseman::vol2mnt{$vol}; my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $fname = "$mnt$Args::args{'dir'}"; $fname =~ s/\/\//\//g; my $recflag = ""; $recflag = " -r " if ( (exists $Args::enc_args{'recmode'}) && ($Args::enc_args{'recmode'} == $File::REC_YES)); Print::log_host_inv( "$Caseman::vol2sname{$vol}: Saving contents of $fname ($meta)"); local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" ); # We can't trust the mnt and dir values (since there # could be bad ASCII values, so only allow basic chars into name $fname =~ tr/a-zA-Z0-9\_\-\@\,/\./c; $fname = $1 if ($fname =~ /^\.(.*)$/); Print::print_oct_header("$vol-${fname}"); print "$_" while ($_ = Exec::read_pipe_data(*OUT, 1024)); Print::print_oct_footer(); return 0; } # Display a report for a file # This is intended to have its own window # sub report { Args::check_sort(); my $sort = Args::get_sort(); my $vol = Args::get_vol('vol'); my $meta = Args::get_meta('meta'); my $mnt = $Caseman::vol2mnt{$vol}; my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $type; my $fname = "$mnt$Args::args{'dir'}"; $fname =~ s/\/\//\//g; my $tz = ""; $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); my $recflag = ""; $recflag = " -r " if ( (exists $Args::enc_args{'recmode'}) && ($Args::enc_args{'recmode'} == $File::REC_YES)); # We can't trust the mnt and dir values (since there # could be bad ASCII values, so only allow basic chars into name $fname =~ tr/a-zA-Z0-9\_\-\@\,/\./c; $fname = $1 if ($fname =~ /^\.+(.*)$/); $fname = $1 if ($fname =~ /^(.*?)\.+$/); Print::print_text_header("filename=$Args::args{'vol'}-${fname}.txt"); $fname = "$mnt$Args::args{'dir'}"; if ($sort == $FIL_SORT_ASC) { Print::log_host_inv( "$Caseman::vol2sname{$vol}: Generating ASCII report for $fname ($meta)" ); $type = "ASCII"; } elsif ($sort == $FIL_SORT_HEX) { Print::log_host_inv( "$Args::args{'vol'}: Generating Hex report for $fname ($meta)"); $type = "Hex"; } elsif ($sort == $FIL_SORT_STR) { Print::log_host_inv( "$Args::args{'vol'}: Generating ASCII strings report for $fname ($meta)" ); $type = "string"; } else { print "\n\ninvalid sort value"; return 1; } # NOTE: There is a space in the beginning of the separator lines in # order to make clear@stamper.itconsult.co.uk time stamping happy # I think it confuses the lines that begin at the lhs with PGP # headers and will remove the second line. # print " Autopsy $type Report\n\n" . "-" x 70 . "\n" . " GENERAL INFORMATION\n\n" . "File: $fname\n"; # Calculate the MD5 value local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/md5'" ); my $md5 = Exec::read_pipe_line(*OUT); close(OUT); $md5 = "Error getting MD5 Value" if ((!defined $md5) || ($md5 eq "")); chomp $md5; if ($recflag eq "") { print "MD5 of file: $md5\n"; } else { print "MD5 of recovered file: $md5\n"; } Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/sha1'" ); my $sha1 = Exec::read_pipe_line(*OUT); close(OUT); $sha1 = "Error getting SHA-1 Value" if ((!defined $sha1) || ($sha1 eq "")); chomp $sha1; if ($recflag eq "") { print "SHA-1 of file: $sha1\n"; } else { print "SHA-1 of recovered file: $sha1\n"; } if ($sort == $FIL_SORT_STR) { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a | '$::TSKDIR/md5'" ); $md5 = Exec::read_pipe_line(*OUT); close(OUT); $md5 = "Error getting MD5 Value" if ((!defined $md5) || ($md5 eq "")); chomp $md5; print "MD5 of ASCII strings: $md5\n"; Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a | '$::TSKDIR/sha1'" ); $sha1 = Exec::read_pipe_line(*OUT); close(OUT); $sha1 = "Error getting SHA-1 Value" if ((!defined $sha1) || ($sha1 eq "")); chomp $sha1; print "SHA-1 of ASCII strings: $sha1\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\n" . "-" x 70 . "\n" . " META DATA INFORMATION\n\n"; # Get the meta details Exec::exec_pipe(*OUT, "'$::TSKDIR/istat' -f $ftype $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" ); print "$_" while ($_ = Exec::read_pipe_line(*OUT)); close(OUT); # File Type Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" ); my $apptype = Exec::read_pipe_line(*OUT); close(OUT); $apptype = "Error getting file type" if ((!defined $apptype) || ($apptype eq "")); print "\nFile Type: $apptype"; print "\n" . "-" x 70 . "\n"; if ($sort == $FIL_SORT_ASC) { print " CONTENT (Non-ASCII data may not be shown)\n\n"; } else { print " CONTENT\n\n"; } if ($sort == $FIL_SORT_ASC) { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" ); Print::print_output($_) while ($_ = Exec::read_pipe_data(*OUT, 1024)); close(OUT); } elsif ($sort == $FIL_SORT_HEX) { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" ); my $offset = 0; while ($_ = Exec::read_pipe_data(*OUT, 1024)) { Print::print_hexdump($_, $offset * 1024); $offset++; } close(OUT); } elsif ($sort == $FIL_SORT_STR) { Exec::exec_pipe(*OUT, "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a" ); Print::print_output($_) while ($_ = Exec::read_pipe_line(*OUT)); 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; } # Generate the MD5 value for every file in a given directory and save # them to a text file sub md5list { my $vol = Args::get_vol('vol'); my $meta = Args::get_meta('meta'); my $mnt = $Caseman::vol2mnt{$vol}; my $ftype = $Caseman::vol2ftype{$vol}; my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $fname = "$mnt$Args::args{'dir'}"; $fname = 'root' if ($fname eq '/'); $fname =~ s/\/\//\//g; # We can't trust the mnt and dir values (since there # could be bad ASCII values, so only allow basic chars into name $fname =~ tr/a-zA-Z0-9\_\-\@\,/\./c; # remove .'s at beginning and end $fname = $1 if ($fname =~ /^\.+(.*)$/); $fname = $1 if ($fname =~ /^(.*?)\.+$/); Print::print_text_header("filename=$fname.md5"); $fname = "$mnt$Args::args{'dir'}"; $fname =~ s/\/\//\//g; local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/fls' -f $ftype -Fu -o $offset -i $imgtype $img $meta"); print "MD5 Values for files in $fname ($Caseman::vol2sname{$vol})\n\n"; while ($_ = Exec::read_pipe_line(*OUT)) { # area for allocated files if ( (/r\/[\w\-]\s+([\d\-]+):\s+(.*)$/) || (/-\/r\s+([\d\-]+):\s+(.*)$/)) { my $in = $1; my $name = $2; local *OUT_MD5; Exec::exec_pipe(*OUT_MD5, "'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $in | '$::TSKDIR/md5'" ); my $md5out = Exec::read_pipe_line(*OUT_MD5); $md5out = "Error calculating MD5" if ((!defined $md5out) || ($md5out eq "")); chomp $md5out; print "$md5out\t$name\n"; close(OUT_MD5); } elsif (/[\w\-]\/[\w\-]\s+([\d\-]+):\s+(.*)$/) { # ignore, non-file types such as sockets or symlinks that do not have # MD5 values that make sense } # Hmmmm else { print "Error parsing file (invalid characters?): $_\n"; } } close(OUT); Print::print_text_footer(); return 0; } # Blank Page sub blank { Print::print_html_header(""); print "

File Browsing Mode


\n" . "

In this mode, you can view file and directory contents.

\n" . "

File contents will be shown in this window.
\n" . "More file details can be found using the Metadata link at the end of the list (on the right).
\n" . "You can also sort the files using the column headers

\n"; Print::print_html_footer(); return 0; }