home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 2004-01-29 | 266.3 KB | 10,314 lines
# # autopsyfunc.pm # Autopsy Forensic Browser # # This file requires The Sleuth Kit # www.sleuthkit.org # # version 1.71+ # Brian Carrier [carrier@sleuthkit.org] # Copyright (c) 2003 by Brian Carrier. All rights reserved # # version 1.5, 1.6, 1.7 # Copyright (c) 2001-2003 by Brian Carrier, @stake Inc. All rights reserved # # version 1.0 # Brian Carrier [carrier@cerias.purdue.edu] # Copyright (c) 2001 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 NOT AFFILIATED WITH PURDUE UNIVERSITY OR THE CENTER FOR # EDUCATION IN INFORMATION ASSURANCE AND SECURITY (CERIAS) AND THEY BEAR # NO RESPONSIBILITY FOR ITS USE OR MISUSE. # # # 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. # # # This file has become a huge mess! The history behind this is that it # was originally designed as a single CGI script. The basic flow is that # every HTML page or frameset has a different 'func' value in the URL. # There is an array of functions and the 'func' value is the index into # that array. Every request is first sent to 'autopsy_main' where basic # arguments are checked and then the specific function is called. It # checks the specific arguments (using the check_*() functions) and the # proper data is displayed to STDOUT, which is the socket. # use lib './'; use strict; use POSIX; # needed for tzset require 'conf.pl'; require 'fs.pl'; require 'define.pl'; require 'search.pl'; # Get rid of insecure settings $ENV{PATH} = ""; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; # import variables from conf.pl use vars '$PROGNAME', '$TASKDIR', '$LOCKDIR'; use vars '$VER', '$GREP_EXE', '$STRINGS_EXE'; use vars '$SANITIZE_TAG'; use vars '$AUT_HOME_PAGE', '$MD5_FILE'; use vars '$USE_NOTES', '$USE_LOG'; use vars '$IMGDIR', '$DATADIR', '$LOGDIR', '$REPDIR'; use vars '$NSRLDB', '$HTTP_NL'; use vars '%first_inode', '%root_inode', '%addr_unit', '%first_addr'; use vars '%ctime_str', '%mtime_str', '%auto_srch', '%auto_srch_reg'; use vars '%auto_srch_csense', '%meta_str'; # Formats for regular expressions # Year.Mon.Day Hr:Min:Sec (TZ) my $REG_DAY = '\d\d\d\d.\d\d.\d\d'; my $REG_TIME = '\d\d:\d\d:\d\d'; my $REG_ZONE1 = '[\w\+\-]+'; my $REG_ZONE2 = '\([\w\+\-]+\)'; my $REG_DATE = "$REG_DAY".'\s+'."$REG_TIME".'\s+'."$REG_ZONE2"; my $REG_FTYPE = '[\w\-]+'; my $REG_SKEW = '[\+\-]?\d+'; my $REG_FILE = '[\w\-\_\.]+'; my $REG_IMG = "$REG_FILE".'/'."$REG_FILE"; my $REG_IMG_PATH = '/[\w\-\_\.\/]+'; my $REG_CASE = $REG_FILE; my $REG_HOST = $REG_FILE; my $REG_FNAME = $REG_FILE; my $REG_MNT = '[\w\-\_\.\/\:\\\\]+'; my $REG_SEQ_FILE = '[\w\s\-\_\.\/\:\\\\]+'; my $REG_HASHDB = '[\w\-\_\.\,\/]+'; my $REG_BODY = $REG_FILE; my $REG_TL = $REG_FILE; my $REG_INODE = '[\d-]+'; my $REG_MD5 = '[0-9a-fA-F]{32,32}'; my $REG_INVESTIG = '[\w]+'; my $HELP_URL = "help/index.html"; # Give new directories user and group write permissions my $MKDIR_MASK = 0775; # constants for different functions (the func argument) my $WELCOME = 0x00; my $BLANK = 0x01; my $MAIN_FR = 0x02; my $MAIN_LO = $MAIN_FR; my $MAIN_TABS = 0x03; my $MAIN_MSG = 0x04; my $MAIN_HI = $MAIN_MSG; my $SORTER_MAIN = 0x06; my $SORTER_LO = $SORTER_MAIN; my $SORTER_LIST = 0x07; my $SORTER_ENT = 0x08; my $SORTER_DOIT = 0x09; my $SORTER_HI = $SORTER_DOIT; my $NOTES_READ = 0x0A; my $NOTES_LO = $NOTES_READ; my $NOTES_MAIN = $NOTES_READ; my $NOTES_WRITE = 0x0B; my $NOTES_ENT = 0x0C; my $NOTES_SEQ_READ = 0x0D; my $NOTES_SEQ_WRITE = 0x0E; my $NOTES_HI = $NOTES_SEQ_WRITE; ################################################# # File Mode my $FIL_LO = 0x10; my $FIL_MAIN = $FIL_LO + 0; my $FIL_DIR = $FIL_LO + 1; my $FIL_LIST = $FIL_LO + 2; my $FIL_CONT = $FIL_LO + 3; my $FIL_REP = $FIL_LO + 4; my $FIL_CMENU_FR = $FIL_LO + 5; my $FIL_CMENU = $FIL_LO + 6; my $FIL_DEL = $FIL_LO + 7; my $FIL_SAVE = $FIL_LO + 8; my $FIL_MD5 = $FIL_LO + 9; my $FIL_NAME = $FIL_LO + 10; my $FIL_HI = $FIL_LO + 10; # Sorting and display types my $FIL_SORT_ASC=0; my $FIL_SORT_STR=1; # Methods of sorting the file listings my $SORT_DTYPE=0; # type according to dentry my $SORT_ITYPE=1; # type according to inode 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_INODE=9; my $SORT_DEL=10; my $DMODE_SHOW = 1; my $DMODE_NOSHOW = 2; ################################################# # Data Mode my $BLK_MAIN = 0x20; my $BLK_LO=$BLK_MAIN; my $BLK_ENT = 0x21; my $BLK_CONT = 0x22; my $BLK_REP = 0x23; my $BLK_CMENU_FR = 0x24; my $BLK_CMENU = 0x25; my $BLK_DLS = 0x26; my $BLK_SAVE = 0x27; my $BLK_HI=$BLK_SAVE; # Display types that use the sort variable my $BLK_SORT_ASC=0; my $BLK_SORT_HEX=1; my $BLK_SORT_STR=2; # Types of block numbers my $BTYPE_DD=0; my $BTYPE_DLS=1; ################################################# # Hash Database my $HASH_LO = 0x2A; my $HASH_LOOKUP = $HASH_LO + 0; my $HASH_INDEX = $HASH_LO + 1; my $HASH_MAIN = $HASH_LO + 2; my $HASH_HI = $HASH_LO + 2; ################################################# # Search Mode my $SRCH_ENT = 0x30; my $SRCH_MAIN = $SRCH_ENT; my $SRCH_LO = $SRCH_ENT; my $SRCH_RMAIN = 0x31; my $SRCH_DOSRCH = 0x32; my $SRCH_READSRCH = 0x33; my $SRCH_HI = $SRCH_READSRCH; # Types of modes for fname (i.e. can we overwrite it if it exists) my $FNAME_MODE_INIT=0; my $FNAME_MODE_OVER=1; ################################################# # Sanitized Environment for picts and HTML my $CELL_LO = 0x38; my $CELL_MAIN = $CELL_LO + 0; my $CELL_MENU = $CELL_LO + 1; my $CELL_CONT = $CELL_LO + 2; my $CELL_HI = $CELL_LO + 2; ################################################# # Inode / Meta Mode my $INO_MAIN = 0x40; my $INO_LO = $INO_MAIN; my $INO_ENT = 0x41; my $INO_CONT = 0x42; my $INO_SAVE = 0x43; my $INO_REP = 0x44; my $INO_ILS = 0x45; my $INO_FFIND = 0x46; my $INO_HI = $INO_FFIND; ################################################ # File System my $FS_STAT = 0x50; my $FS_LO = $FS_STAT; my $FS_MAIN = $FS_STAT; my $FS_HI = $FS_STAT; ################################################ # Integrity my $INT_CHECK = 0x56; my $INT_MAIN = $INT_CHECK; my $INT_LO = $INT_CHECK; my $INT_CREATE = 0x57; my $INT_LIST_FR = 0x58; my $INT_LIST = 0x59; my $INT_HI = $INT_LIST; ################################################ # Timeline my $TL_LO = 0x60; my $TL_MAIN = $TL_LO + 0; my $TL_BODY_ENT = $TL_LO + 1; my $TL_BODY_DOIT = $TL_LO + 2; my $TL_TL_ENT = $TL_LO + 3; my $TL_TL_DOIT = $TL_LO + 4; my $TL_VIEW_MENU = $TL_LO + 5; my $TL_VIEW_FR = $TL_LO + 6; my $TL_VIEW_IDX = $TL_LO + 7; my $TL_VIEW_SUM = $TL_LO + 8; my $TL_VIEW = $TL_LO + 9; my $TL_TABS = $TL_LO + 10; my $TL_HI = $TL_LO + 10; ################################################ # Setup / Menu values my $CASE_OPEN = 0x70; my $CASE_LO = $CASE_OPEN; my $CASE_OPEN_LOG = 0x71; my $CASE_NEW = 0x72; my $CASE_NEW_DOIT = 0x73; my $CASE_DETAILS = 0x74; my $CASE_DEL = 0x75; my $CASE_HI = $CASE_DEL; my $HOST_OPEN = 0x76; my $HOST_LO = $HOST_OPEN; my $HOST_OPEN_LOG = 0x77; my $HOST_ADD = 0x78; my $HOST_ADD_DOIT = 0x79; my $HOST_DETAILS = 0x7A; my $HOST_DEL = 0x7B; my $HOST_HI = $HOST_DEL; my $IMG_OPEN = 0x7C; my $IMG_LO = $IMG_OPEN; my $IMG_OPEN_LOG = 0x7D; my $IMG_ADD = 0x7E; my $IMG_ADD_DOIT = 0x7F; my $IMG_DETAILS = 0x80; my $IMG_DEL = 0x81; my $IMG_MAKESTR = 0x82; my $IMG_MAKEDLS = 0x83; my $IMG_HI = $IMG_MAKEDLS; my $IMG_ADD_SYM = 0x1; my $IMG_ADD_COPY = 0x2; my $IMG_ADD_MOVE = 0x3; my $BACK_COLOR="#CCCC99"; my $BACK_COLOR_TABLE="#CCCCCC"; my @DEL_COLOR; $DEL_COLOR[0] = "red"; $DEL_COLOR[1] = "#800000"; # used when inode has been reallocated my $NORM_COLOR = ""; my $LINK_COLOR = "blue"; my $YEL_PIX = "pict/back_pix.jpg"; my @funcs; # Array for function references my %args; # Arguments that are decoded my %enc_args; # Arguments that are encoded my $baseargs; # Arguments that never change such as case,host,mnt and img my $baseargs_noimg; # baseargs w/out img info my %img2mnt; # Mapping for mount point, given the image name my %img2ftype; # Mapping for file system type, given the image name my %mod2img; # Mapping for image, given the strings or dls my %img2str; # Mapping for strings file, given the image name my %img2dls; # Mapping for dls file, given the image name # hash databases # NSRL is global my $exclude_db = ""; my $alert_db = ""; my $tz = ""; my $ts = 0; # time skew (in seconds) my $host_desc = ""; my $host_dir = ""; my $case_dir = ""; my $is_html = 0; my $is_body = 0; # Main Menu # # Display the title page $funcs[$WELCOME] = sub { print_javascript_header("Autopsy Forensic Browser"); print "<CENTER>\n"; if ($] >= 5.008) { print "<P><FONT COLOR=\"red\">Warning: You are using Perl v5.8.</FONT><BR>\n". " Some buffer problems have been reported with Autopsy and Perl 5.8 ". "where output is not shown.<BR>\n". "Perl 5.6 should be used if available.\n". "If data is missing, reload the page<BR><HR>\n"; } print <<EOF; <TABLE CELLSPACING=0 CELLPADDING=2 WIDTH=600 HEIGHT=350 BORDER=0> <TR> <TD COLSPAN=\"3\" ALIGN=\"CENTER\" VALIGN=\"MIDDLE\"> <A HREF=\"./about\"> <IMG SRC=\"pict/logo.jpg\" BORDER=0> </A> </TD> </TR> <TR> <TD COLSPAN=\"3\" ALIGN=\"CENTER\" VALIGN=\"MIDDLE\"> <A HREF=$AUT_HOME_PAGE> <TT>$AUT_HOME_PAGE</TT> </A> </TD> </TR> <TR><TD COLSPAN=3> </TD></TR> <TR> <TD ALIGN=CENTER WIDTH=200 VALIGN=\"MIDDLE\"> <A HREF=\"$PROGNAME?func=$CASE_OPEN\"> <IMG SRC=\"pict/menu_b_copen.jpg\" ALT=\"Open Case\" WIDTH=176 HEIGHT=20 BORDER=0> </A> </TD> <TD ALIGN=CENTER WIDTH=200 VALIGN=\"MIDDLE\"> <A HREF=\"$PROGNAME?func=$CASE_NEW\"> <IMG SRC=\"pict/menu_b_cnew.jpg\" ALT=\"New Case\" WIDTH=176 HEIGHT=20 BORDER=0> </A> </TD> <TD ALIGN=CENTER WIDTH=200 VALIGN=\"MIDDLE\"> <A HREF=\"$HELP_URL\" TARGET=\"_blank\"> <IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" WIDTH=167 HEIGHT=20 BORDER=0> </A> </TD> </TR> </TABLE> EOF return; }; # create the frame for the tabs on top and the generic message on the bottom $funcs[$MAIN_FR] = sub { print_html_header_frameset("$args{'case'}:$args{'host'}:$args{'img'}"); my $mode = $MAIN_FR; $mode = get_mode() if (exists $args{'mode'}); # Print the rest of the frames my $str = ""; if ($mode == $MAIN_FR) { $mode = $MAIN_MSG; } elsif ($mode == $FIL_MAIN) { $str .= "&inode=$args{'inode'}" if (exists $args{'inode'}); $str .= "&dir=$args{'dir'}" if (exists $args{'dir'}); $str .= "&sort=$args{'sort'}" if (exists $args{'sort'}); $str .= "&dmode=$args{'dmode'}" if (exists $args{'dmode'}); } elsif ($mode == $BLK_MAIN) { $str .= "&block=$args{'block'}" if (exists $args{'block'}); $str .= "&len=$args{'len'}" if (exists $args{'len'}); } elsif ($mode == $INO_MAIN) { $str .= "&inode=$args{'inode'}" if (exists $args{'inode'}); } # elsif ($mode == $FS_MAIN) # elsif ($mode == $SRCH_MAIN) # elsif ($mode == $INT_MAIN) # elsif ($mode == $NOTES_MAIN) print <<EOF; <FRAMESET ROWS=\"40,*\"> <FRAME SRC=\"$PROGNAME?func=$MAIN_TABS&$baseargs&mode=$mode\"> <FRAME SRC=\"$PROGNAME?func=$mode&$baseargs$str\"> </FRAMESET> <NOFRAMES> <CENTER> Autopsy requires a browser that supports frames. </CENTER> </NOFRAMES> EOF return; }; # Display a message when the image is opened (below the tabs) $funcs[$MAIN_MSG] = sub { print_html_header("Main Message"); print <<EOF; <CENTER> <BR><BR><BR><BR><BR><BR><BR> (select an analysis type) </CENTER> EOF return; }; $funcs[$MAIN_TABS] = sub { check_mode(); print_html_header_tabs("Mode Tabs"); my $mode = get_mode(); my $special = 0; $special = 1 if (($img2ftype{$args{'img'}} eq "strings") || ($img2ftype{$args{'img'}} eq "dls") || ($img2ftype{$args{'img'}} eq "swap") || ($img2ftype{$args{'img'}} eq "raw")) ; print "<CENTER><TABLE WIDTH=\"800\" BORDER=\"0\" CELLSPACING=\"0\" ". "CELLPADDING=\"0\"><TR>\n"; # Files print "<TD ALIGN=\"CENTER\" WIDTH=116>"; if ($special == 0) { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$FIL_MAIN&$baseargs\"". "TARGET=\"_top\">"; # Current if ($mode == $FIL_MAIN) { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_fil_cur.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"File Analysis (Current Mode)\"></A>"; } # Link else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_fil_link.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"File Analysis\"></A>"; } # non-link } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_fil_org.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"File Analysis (not available)\">"; } # Search print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=116>"; print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$SRCH_MAIN&$baseargs\"". " TARGET=\"_top\">"; if ($mode == $SRCH_MAIN) { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_srch_cur.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Keyword Search Mode (Current Mode)\"></A>"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_srch_link.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Keyword Search Mode\"></A>"; } # File Type print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=116>"; if ($special == 0) { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$SORTER_MAIN&$baseargs\"". " TARGET=\"_top\">"; # Current if ($mode == $SORTER_MAIN) { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_ftype_cur.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"File Type (Current Mode)\"></A>"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_ftype_link.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"File Type\"></A>"; } } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_ftype_org.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"File Type (not available)\">"; } # File System print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=116>"; if ($special == 0) { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$FS_MAIN&$baseargs\"". " TARGET=\"_top\">"; if ($mode == $FS_MAIN) { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_img_cur.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Image Details Mode (Current Mode)\"></A>"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_img_link.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Image Details Mode\"></A>"; } } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_img_org.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Image Details Mode (not available)\">"; } # Meta Data print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=116>"; if ($special == 0) { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$INO_MAIN&$baseargs\"". " TARGET=\"_top\">"; if ($mode == $INO_MAIN) { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_met_cur.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Meta Data Mode (Current Mode)\"></A>"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_met_link.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Meta Data Mode\"></A>"; } } else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_met_org.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Meta Data Mode (not available)\">"; } # Data Units print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=116>"; print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$BLK_MAIN&$baseargs\"". " TARGET=\"_top\">"; # Current if ($mode == $BLK_MAIN) { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_dat_cur.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Data Units Mode (Current Mode)\"></A>"; } # Link else { print "<IMG BORDER=0 ". "SRC=\"pict/main_t_dat_link.jpg\" ". "WIDTH=116 HEIGHT=38 ". "ALT=\"Data Units Mode\"></A>"; } # Help - set to current mode print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=52>". "<A HREF=\"$HELP_URL\"". " TARGET=\"_blank\">". "<IMG BORDER=0 ". "SRC=\"pict/tab_help.jpg\" ". "WIDTH=52 ". "ALT=\"Help\">". "</A></TD>\n"; # Close print "<TD ALIGN=\"CENTER\" WIDTH=52>". "<A HREF=\"$PROGNAME?func=$IMG_OPEN&$baseargs_noimg\"". " TARGET=\"_top\">". "<IMG BORDER=0 ". "SRC=\"pict/tab_close.jpg\" ". "WIDTH=52 ". "ALT=\"Close Image\">". "</A></TD>\n"; print "</TR></TABLE>\n"; return; }; # The tabs / button images in timeline view $funcs[$TL_TABS] = sub { check_mode(); print_html_header_tabs("Timeline Mode Tabs"); my $mode = get_mode(); print "<CENTER><TABLE WIDTH=\"800\" BORDER=\"0\" ". "CELLSPACING=\"0\" CELLPADDING=\"0\"><TR>\n"; # Create Datafile print "<TD ALIGN=\"CENTER\" WIDTH=174>". "<A HREF=\"$PROGNAME?func=$TL_MAIN&mode=$TL_BODY_ENT&$baseargs\" ". "TARGET=\"_top\">"; if ($mode == $TL_BODY_ENT) { print "<IMG BORDER=0 ". "SRC=\"pict/tl_t_data_cur.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"Create Data File (Current Mode)\"></A>\n"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/tl_t_data_link.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"Create Data File\"></A>\n"; } print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=174>". "<A HREF=\"$PROGNAME?func=$TL_MAIN&mode=$TL_TL_ENT&$baseargs\" ". "TARGET=\"_top\">"; # Create Timeline if ($mode == $TL_TL_ENT) { print "<IMG BORDER=0 ". "SRC=\"pict/tl_t_tl_cur.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"Create Timeline (Current Mode)\"></A>\n"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/tl_t_tl_link.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"Create Timeline\"></A>\n"; } print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=174>". "<A HREF=\"$PROGNAME?func=$TL_MAIN&mode=$TL_VIEW_MENU&$baseargs\" ". "TARGET=\"_top\">"; # View Timeline if (($mode == $TL_VIEW_FR) || ($mode == $TL_VIEW_MENU)) { print "<IMG BORDER=0 ". "SRC=\"pict/tl_t_view_cur.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"View Timeline (Current Mode)\"></A>\n"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/tl_t_view_link.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"View Timeline\"></A>\n"; } # Notes print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=174>"; if ($USE_NOTES == 1) { print "<A HREF=\"$PROGNAME?func=$NOTES_MAIN&${baseargs_noimg}\" ". "TARGET=\"_blank\">". "<IMG BORDER=0 ". "SRC=\"pict/tl_t_notes_link.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"View Notes\"></A></TD>\n"; } else { print "<IMG BORDER=0 ". "SRC=\"pict/tl_t_notes_org.jpg\" ". "WIDTH=174 HEIGHT=38 ". "ALT=\"View Notes\"></A></TD>\n"; } # Help - set to current mode print "<TD ALIGN=\"CENTER\" WIDTH=52>". "<A HREF=\"$HELP_URL\" ". "TARGET=\"_blank\">". "<IMG BORDER=0 ". "SRC=\"pict/tab_help.jpg\" ". "WIDTH=52 ". "ALT=\"Help\"></A></TD>\n"; # Close print "<TD ALIGN=\"CENTER\" WIDTH=52>". "<A HREF=\"$PROGNAME?func=$IMG_OPEN&$baseargs\" ". "TARGET=\"_top\">". "<IMG BORDER=0 ". "SRC=\"pict/tab_close.jpg\" ". "WIDTH=52 ". "ALT=\"Exit to Host Manager\"></A></TD>\n". "</TR></TABLE>\n"; return; }; #################################################################### # General menu Functions sub print_menu_tabs { print "<B>Case:</B> $args{'case'}" if (exists $args{'case'}); print "<BR>\n"; print "<B>Host:</B> $args{'host'}" if (exists $args{'host'}); print "<BR>\n"; print "<CENTER>\n"; print "<TABLE WIDTH=\"600\" HEIGHT=\"60\" BACKGROUND=\"$YEL_PIX\" ". "BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">\n<TR>\n". "<TD ALIGN=\"CENTER\" WIDTH=\"200\">"; # Case Gallery if ($args{'func'} == $CASE_OPEN) { print "<IMG BORDER=0 ". "SRC=\"pict/menu_t_cg_cur.jpg\" ". "WIDTH=200 HEIGHT=65 ". "ALT=\"Case Gallery (Current Mode)\">\n"; } else { print "<A HREF=\"$PROGNAME?func=$CASE_OPEN\">". "<IMG BORDER=0 ". "SRC=\"pict/menu_t_cg_link.jpg\" ". "WIDTH=200 HEIGHT=65 ". "ALT=\"Case Gallery\"></A>\n"; } print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=\"200\">"; # Host Gallery # Current if ($args{'func'} == $HOST_OPEN) { print "<IMG BORDER=0 ". "SRC=\"pict/menu_t_hg_cur.jpg\" ". "WIDTH=200 HEIGHT=65 ". "ALT=\"Host Gallery (Current Mode)\">\n"; } # Link elsif ($args{'func'} == $IMG_OPEN) { print "<A HREF=\"$PROGNAME?func=$HOST_OPEN&case=$args{'case'}\">". "<IMG BORDER=0 ". "SRC=\"pict/menu_t_hg_link.jpg\" ". "WIDTH=200 HEIGHT=65 ". "ALT=\"Host Gallery\"></A>\n"; } # non-link else { print "<IMG BORDER=0 ". "SRC=\"pict/menu_t_hg_org.jpg\" ". "WIDTH=200 HEIGHT=65 ". "ALT=\"Host Gallery (Not Available)\">\n"; } print "</TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=\"200\">"; # Host Manager # Current if ($args{'func'} == $IMG_OPEN) { print "<IMG BORDER=0 ". "SRC=\"pict/menu_t_hm_cur.jpg\" ". "WIDTH=200 HEIGHT=65 ". "ALT=\"Host Manager (Current Mode)\">\n"; } # non-link else { print "<IMG BORDER=0 ". "SRC=\"pict/menu_t_hm_org.jpg\" ". "WIDTH=200 HEIGHT=65 ". "ALT=\"Host Manager (Not Available)\">\n"; } print "</TD>\n". "</TABLE>\n"; }; #################################################################### # Case Functions $funcs[$CASE_NEW] = sub { print_html_header("Create A New Case"); print <<EOF; <BR> <BR> <CENTER> <IMG SRC=\"pict/menu_h_cnew.jpg\" ALT=\"New Case\"> <BR><BR><BR> <TABLE WIDTH=\"600\" BACKGROUND=\"$YEL_PIX\" CELLSPACING=\"0\" CELLPADDING=\"2\" BORDER=0> <FORM ACTION=\"$PROGNAME\" METHOD=\"GET\"> <INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$CASE_NEW_DOIT\"> <TR> <TD COLSPAN=2 ALIGN=center> 1. Enter Case Name (directory name): <INPUT TYPE=\"text\" NAME=\"case\"> </TD> </TR> <TR><TD COLSPAN=2> </TD></TR> <TR> <TD COLSPAN=2 ALIGN=center> 2. Enter Description (one line, optional): <INPUT TYPE=\"text\" NAME=\"desc\"> </TD> </TR> <TR><TD COLSPAN=2> </TD></TR> <TR> <TD COLSPAN=2 ALIGN=center> 3. Enter Investigator Logins (no spaces): </TD> </TR> <TR> <TD ALIGN=CENTER>a. <INPUT TYPE=\"text\" NAME=\"inv1\"></TD> <TD ALIGN=CENTER>b. <INPUT TYPE=\"text\" NAME=\"inv2\"></TD> </TR> <TR> <TD ALIGN=CENTER>c. <INPUT TYPE=\"text\" NAME=\"inv3\"></TD> <TD ALIGN=CENTER>d. <INPUT TYPE=\"text\" NAME=\"inv4\"></TD> </TR> <TR> <TD ALIGN=CENTER>e. <INPUT TYPE=\"text\" NAME=\"inv5\"></TD> <TD ALIGN=CENTER>f. <INPUT TYPE=\"text\" NAME=\"inv6\"></TD> </TR> <TR> <TD ALIGN=CENTER>g. <INPUT TYPE=\"text\" NAME=\"inv7\"></TD> <TD ALIGN=CENTER>h. <INPUT TYPE=\"text\" NAME=\"inv8\"></TD> </TR> <TR> <TD ALIGN=CENTER>i. <INPUT TYPE=\"text\" NAME=\"inv9\"></TD> <TD ALIGN=CENTER>j. <INPUT TYPE=\"text\" NAME=\"inv10\"></TD> </TR> </TABLE> <BR><BR> <TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\"> <TR> <TD ALIGN=CENTER> <INPUT TYPE=\"image\" SRC=\"pict/menu_b_cnew.jpg\" ALT=\"Create Case\" WIDTH=\"176\" HEIGHT=20 BORDER=0> </TD> </FORM> <TD ALIGN=CENTER> <FORM ACTION=\"$PROGNAME\" METHOD=\"GET\"> <INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$CASE_OPEN\"> <INPUT TYPE=\"image\" SRC=\"pict/menu_b_cancel.jpg\" ALT=\"Cancel\" WIDTH=\"167\" HEIGHT=20 BORDER=0> </FORM> </TD> <TD ALIGN=CENTER><A HREF=\"$HELP_URL\" TARGET=\"_blank\"> <IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" WIDTH=\"167\" HEIGHT=20 BORDER=0></A> </TD> </TR> </TABLE> EOF return; }; # Create the directory and case configuration file # Gets the input from CASE_NEW $funcs[$CASE_NEW_DOIT] = sub { check_case(); print_html_header("Creating Case: $args{'case'}"); print "<H3>Creating Case: <TT>$args{'case'}</TT></H3>\n"; # Make the directory if (-d "$case_dir") { print_err ("Error: $case_dir already exists<BR>Please remove the directory and its contents and try again"); } unless (mkdir $case_dir, $MKDIR_MASK) { print_err ("Error making directory $case_dir: $!"); } print "Case directory (<TT>$case_dir</TT>) created<BR>\n"; log_case_info ("Case $args{'case'} created"); my $fname = case_config_fname(); open CASE_CONFIG, ">$fname" or die "Can't open case config: $fname"; print CASE_CONFIG "# Autopsy case config file\n". "# Case: $args{'case'}\n\n". "created ".localtime()."\n"; if ((exists $args{'desc'}) && ($args{'desc'} ne "")){ print_err ("Invalid Description") if ($args{'desc'} =~ /\n/); print CASE_CONFIG "desc $args{'desc'}\n"; } print CASE_CONFIG "images $IMGDIR\n"; print CASE_CONFIG "data $DATADIR\n"; print CASE_CONFIG "log $LOGDIR\n"; print CASE_CONFIG "reports $REPDIR\n"; close CASE_CONFIG; print "Configuration file (<TT>$fname</TT>) created<BR>\n"; write_invest ($args{'inv1'}) if ((exists $args{'inv1'}) && ($args{'inv1'} ne "")); write_invest ($args{'inv2'}) if ((exists $args{'inv2'}) && ($args{'inv2'} ne "")); write_invest ($args{'inv3'}) if ((exists $args{'inv3'}) && ($args{'inv3'} ne "")); write_invest ($args{'inv4'}) if ((exists $args{'inv4'}) && ($args{'inv4'} ne "")); write_invest ($args{'inv5'}) if ((exists $args{'inv5'}) && ($args{'inv5'} ne "")); write_invest ($args{'inv6'}) if ((exists $args{'inv6'}) && ($args{'inv6'} ne "")); write_invest ($args{'inv7'}) if ((exists $args{'inv7'}) && ($args{'inv7'} ne "")); write_invest ($args{'inv8'}) if ((exists $args{'inv8'}) && ($args{'inv8'} ne "")); write_invest ($args{'inv9'}) if ((exists $args{'inv9'}) && ($args{'inv9'} ne "")); write_invest ($args{'inv10'}) if ((exists $args{'inv10'}) && ($args{'inv10'} ne "")); print "Investigators added<BR>\n"; log_session_info ("Case $args{'case'} created"); print "<BR><BR><A HREF=\"$PROGNAME?func=$CASE_OPEN\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\"></A>\n"; return; }; # Open a Case # This provides a form with a list of options $funcs[$CASE_OPEN] = sub { print_html_header("Open A Case"); print_menu_tabs(); print "<TABLE WIDTH=\"600\" BACKGROUND=\"$YEL_PIX\" ". " CELLSPACING=\"0\" CELLPADDING=\"2\" BORDER=0>\n"; # Read the directories of the Evidence Locker into an array # Verify that there is a config file in the directory my @cases; opendir CASES, $LOCKDIR or die "Can't open $LOCKDIR directory: $!"; foreach my $c (readdir CASES) { next if (($c eq '.') || ($c eq '..')); my $cfile = case_config_fname($c); push @cases, $c if ((-d "${LOCKDIR}$c") && (-e "$cfile")); } closedir CASES; # Were there any cases? if (scalar @cases == 0) { print "<TR><TD ALIGN=\"CENTER\">". "No cases exist in <TT>$LOCKDIR</TT>". "</TD></TR>\n"; } else { print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$CASE_OPEN_LOG\">\n". make_hidden(). "<TR><TH>Name</TH>". "<TH>Description</TH>". "<TD> </TD></TR>\n"; my $first = 0; foreach my $c (@cases) { print "<TR><TD ALIGN=\"left\">". "<INPUT TYPE=\"radio\" NAME=\"case\" VALUE=$c"; if ($first == 0) { print " CHECKED"; $first = 1; } print ">$c</TD>"; my %cvals = read_case_config($c); print "<TD>$cvals{'desc'}</TD>". "<TD ALIGN=center>". "<A HREF=\"$PROGNAME?func=$CASE_DETAILS&case=$c\">". "details</A></TD>". "</TR>\n"; } } print "</TABLE>\n"; print "<BR><BR>". "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR>\n"; # Print the OK button if there were cases if (scalar @cases != 0) { print "<TD ALIGN=CENTER>". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_ok.jpg\" ". "WIDTH=167 HEIGHT=20 ALT=\"Ok\" BORDER=0>". "</FORM></TD>\n\n"; } # Print a 'New Case' Button print "<TD ALIGN=CENTER>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$CASE_NEW\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_cnew.jpg\" ". "WIDTH=167 HEIGHT=20 ALT=\"New Case\" BORDER=0>\n". "</FORM></TD>". # Print a Menu Button "<TD ALIGN=CENTER>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_menu.jpg\" ". "WIDTH=167 HEIGHT=20 ALT=\"Main Menu\" BORDER=0>\n". "</FORM></TD></TR></TABLE>\n"; print "<TABLE WIDTH=600 CELLSPACING=\"0\" CELLPADDING=\"2\">\n<TR>". "<TD> </TD>\n". "<TD ALIGN=CENTER WIDTH=200><A HREF=\"$HELP_URL\" ". " TARGET=\"_blank\">". "<IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" ". "WIDTH=\"167\" HEIGHT=20 BORDER=0>". "</A></TD>". "<TD> </TD>\n". "</TR>\n". "</TABLE>"; return; }; # Log that a given case was opened and then proceed to open a host $funcs[$CASE_OPEN_LOG] = sub { log_session_info ("Case $args{'case'} opened"); log_case_info ("Case $args{'case'} opened"); $args{'func'} = $enc_args{'func'} = $HOST_OPEN; & {$funcs[$HOST_OPEN]}; }; # Display Case Details $funcs[$CASE_DETAILS] = sub { check_case(); print_html_header("Details of $args{'case'}"); my %cvals = read_case_config(); $cvals{'desc'} = " " unless (exists $cvals{'desc'}); $cvals{'created'} = " " unless (exists $cvals{'created'}); print "<BR><BR>". "<CENTER>". "<IMG SRC=\"pict/menu_h_cdet.jpg\" ALT=\"Case Details\">". "<BR><BR><BR>\n". "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" BACKGROUND=\"$YEL_PIX\" ". "CELLPADDING=\"2\" BORDER=0>\n". " <TR><TD ALIGN=\"RIGHT\" WIDTH=300><B>Name:</B></TD>". "<TD ALIGN=\"LEFT\" WIDTH=300><TT>$args{'case'}</TT></TD></TR>\n". # Description " <TR><TD ALIGN=\"RIGHT\"><B>Description:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$cvals{'desc'}</TT></TD></TR>\n". " <TR><TD ALIGN=\"RIGHT\"><B>Created:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$cvals{'created'}</TT></TD></TR>\n". # Directories " <TR><TD ALIGN=\"RIGHT\"><B>Directory:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$case_dir</TT></TD></TR>\n". " <TR><TD COLSPAN=\"2\"> </TD></TR>\n". " <TR><TD ALIGN=\"RIGHT\"><B>Images Dir:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$cvals{'images'}</TT></TD></TR>\n". " <TR><TD ALIGN=\"RIGHT\"><B>Output Dir:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$cvals{'data'}</TT></TD></TR>\n". " <TR><TD ALIGN=\"RIGHT\"><B>Report Dir:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$cvals{'reports'}</TT></TD></TR>\n". " <TR><TD ALIGN=\"RIGHT\"><B>Log Dir:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$cvals{'log'}</TT></TD></TR>\n"; # Display the valid investigators my @invs = read_invest(); my $cnt = 0; print " <TR><TD COLSPAN=\"2\"> </TD></TR>\n" if (scalar @invs > 0); foreach my $i (@invs) { if ($cnt == 0) { print " <TR><TD ALIGN=\"RIGHT\"><B>Investigators:</B></TD>"; $cnt++; } else { print " <TR><TD> </TD>"; } print "<TD ALIGN=\"LEFT\"><TT>$i</TT></TD></TR>\n"; } print "</TABLE>\n". "<P><A HREF=\"$PROGNAME?func=$CASE_OPEN\">". "<IMG SRC=\"pict/menu_b_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"167\" HEIGHT=20 BORDER=\"0\"></A>"; return; }; #################################################################### # Host Functions $funcs[$HOST_ADD] = sub { print_html_header("Add A New Host To $args{'case'}"); print "<B>Case: </B> $args{'case'}<BR><BR>\n"; print "<CENTER>". "<IMG SRC=\"pict/menu_h_hnew.jpg\" ALT=\"Add Host\">". "<BR><BR><BR>\n"; print "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" BACKGROUND=\"$YEL_PIX\" ". "CELLPADDING=\"2\" BORDER=0>\n". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HOST_ADD_DOIT\">\n". make_hidden(). "<TR><TD COLSPAN=\"2\"> </TD></TR>". "<TR><TD ALIGN=\"right\">1. Host Name (directory name):</TD>". "<TD ALIGN=\"left\"><INPUT TYPE=\"text\" NAME=\"host\"></TD></TR>\n". "<TR><TD ALIGN=\"right\">2. Description (one line, optional):</TD>". "<TD ALIGN=\"left\">". "<INPUT TYPE=\"text\" NAME=\"desc\" SIZE=32 MAXLENGTH=32></TD></TR>\n". "<TR><TD COLSPAN=\"2\"> </TD></TR>". "<TR><TD ALIGN=\"right\">3. Timezone:</TD>". "<TD ALIGN=\"left\">". "<INPUT TYPE=\"text\" NAME=\"tz\" SIZE=10 MAXLENGTH=16></TD></TR>\n". "<TR><TD ALIGN=\"right\">4. Timeskew (in +/- seconds):</TD>". "<TD ALIGN=\"left\">". "<INPUT TYPE=\"text\" NAME=\"ts\" SIZE=8 MAXLENGTH=16 VALUE=\"0\">". "</TD></TR>\n". "<TR><TD COLSPAN=\"2\"> </TD></TR>". "<TR><TD ALIGN=\"right\">5. Path of Alert Hash Database (optional)<BR>i.e. known bad files:</TD>". "<TD ALIGN=\"left\">". "<INPUT TYPE=\"text\" NAME=\"alert_db\" SIZE=32 MAXLENGTH=512>". "</TD></TR>\n". "<TR><TD ALIGN=\"right\">6. Path of Ignore Hash Database (optional)<BR>i.e. known good files:</TD>". "<TD ALIGN=\"left\">". "<INPUT TYPE=\"text\" NAME=\"exclude_db\" SIZE=32 MAXLENGTH=512>". "</TD></TR>\n". "<TR><TD COLSPAN=\"2\"> </TD></TR>". "</TABLE>\n"; # Ok Button print "<BR><BR><TABLE WIDTH=\"600\" CELLSPACING=\"8\" CELLPADDING=\"2\">\n". "<TR><TD ALIGN=CENTER>". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_hnew.jpg\" ". "WIDTH=167 HEIGHT=20 ALT=\"Add Host\" BORDER=0>\n". "</FORM></TD>\n". # Cancel Button "<TD ALIGN=CENTER>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HOST_OPEN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"case\" VALUE=\"$args{'case'}\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_cancel.jpg\" ". "ALT=\"Cancel\" WIDTH=\"167\" HEIGHT=20 BORDER=0>\n". "</FORM></TD>\n". # Help Button "<TD ALIGN=CENTER><A HREF=\"$HELP_URL\" ". "TARGET=\"_blank\">". "<IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" ". "WIDTH=\"167\" HEIGHT=20 BORDER=0></A>". "</TD></TR>\n". "</TABLE>"; return; }; # Make the directories and config files for a host $funcs[$HOST_ADD_DOIT] = sub { check_host(); check_tz(); check_ts(); print_html_header("Adding Host $args{'host'} to $args{'case'}"); print "<H3>Adding host: <TT>$args{'host'}</TT> to ". "case <TT>$args{'case'}</TT></H3>\n"; # Do some sanity checks before we start making the directories and such if ((exists $args{'alert_db'}) && ($args{'alert_db'} ne "")) { unless ($args{'alert_db'} =~ /^$REG_HASHDB$/o) { print "Invalid Alert Database path\n". "<P><A HREF=\"$PROGNAME?func=$HOST_ADD&case=$args{'case'}\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\"></A>\n"; return 1; } unless (-e "$args{'alert_db'}") { print "Alert Database Not Found: $args{'alert_db'}". "<P><A HREF=\"$PROGNAME?func=$HOST_ADD&case=$args{'case'}\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\"></A>\n"; return 1; } } if ((exists $args{'exclude_db'}) && ($args{'exclude_db'} ne "")) { unless ($args{'exclude_db'} =~ /^$REG_HASHDB$/o) { print "Invalid Exclude Database path\n". "<P><A HREF=\"$PROGNAME?func=$HOST_ADD&case=$args{'case'}\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\"></A>\n"; return 1; } unless (-e "$args{'exclude_db'}") { print "Exclude Database Not Found: $args{'exclude_db'}". "<P><A HREF=\"$PROGNAME?func=$HOST_ADD&case=$args{'case'}\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\"></A>\n"; return 1; } } # Make the directory if (-d "$host_dir") { print_err ("Error: $host_dir already exists<BR>Please remove the ". "directory and its contents and try again"); } unless (mkdir $host_dir, $MKDIR_MASK) { print_err ("Error making directory $host_dir: $!"); } print "Host Directory (<TT>$host_dir</TT>) created<P>\n"; log_case_info ("Host $args{'host'} added to case"); # @@@ READ CASE CONFIG FOR DIR NAMES # Images directory unless (mkdir "${host_dir}$IMGDIR", $MKDIR_MASK) { rmdir "${host_dir}"; print_err ("Error making ${host_dir}$IMGDIR"); } # Output Directory unless (mkdir "${host_dir}$DATADIR", $MKDIR_MASK) { rmdir "${host_dir}$IMGDIR"; rmdir "${host_dir}"; print_err ("Error making ${host_dir}$DATADIR"); } # Log Directory unless (mkdir "${host_dir}$LOGDIR", $MKDIR_MASK) { rmdir "${host_dir}$DATADIR"; rmdir "${host_dir}$IMGDIR"; rmdir "${host_dir}"; print_err ("Error making ${host_dir}$LOGDIR"); } # Reports directory unless (mkdir "${host_dir}$REPDIR", $MKDIR_MASK) { rmdir "${host_dir}$LOGDIR"; rmdir "${host_dir}$DATADIR"; rmdir "${host_dir}$IMGDIR"; rmdir "${host_dir}"; print_err ("Error making ${host_dir}$REPDIR"); } # Make a directory for mounting the image in loopback unless (mkdir "${host_dir}mnt", $MKDIR_MASK) { rmdir "${host_dir}$REPDIR"; rmdir "${host_dir}$LOGDIR"; rmdir "${host_dir}$DATADIR"; rmdir "${host_dir}$IMGDIR"; rmdir "${host_dir}"; print_err ("Error making ${host_dir}mnt"); } log_host_info ("Host $args{'host'} added to case $args{'case'}"); # Create config file my $fname = host_config_fname(); open HOST_CONFIG, ">$fname" or die "Can't open host config: $fname"; print HOST_CONFIG "# Autopsy host config file\n". "# Case: $args{'case'} Host: $args{'host'}\n". "# Created: ".localtime()."\n\n"; if ((exists $args{'desc'}) && ($args{'desc'} ne "")) { print_err ("Invalid Description") if ($args{'desc'} =~ /\n/); print HOST_CONFIG "desc $args{'desc'}\n"; } print HOST_CONFIG "timezone ".get_tz()."\n"; print HOST_CONFIG "timeskew ".get_ts()."\n"; if ((exists $args{'alert_db'}) && ($args{'alert_db'} ne "")) { # Index it if it is not unless (-e "$args{'alert_db'}-md5.idx") { print "Alert Database has not been indexed - it will be as an md5sum file<BR>\n"; print "<HR>\n"; hash_index_md5sum ($args{'alert_db'}); print "<HR>\n"; } # only print it if it was successful print HOST_CONFIG "alert_db \'$args{'alert_db'}\'\n" if (-e "$args{'alert_db'}-md5.idx"); } if ((exists $args{'exclude_db'}) && ($args{'exclude_db'} ne "")) { # Index it if it is not unless (-e "$args{'exclude_db'}-md5.idx") { print "Exclude Database has not been indexed - it will be as an md5sum file<BR>\n"; print "<HR>\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}hfind' -i md5sum '$args{'exclude_db'}'"); print "$_<BR>" while (<OUT>); close (OUT); print "<HR>\n"; } # only print it if it was successful print HOST_CONFIG "exclude_db \'$args{'exclude_db'}\'\n" if (-e "$args{'exclude_db'}-md5.idx"); } close HOST_CONFIG; print "Configuration file (<TT>$fname</TT>) created<BR><BR>\n"; print "<A HREF=\"$PROGNAME?func=$HOST_OPEN&case=$args{'case'}\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\"></A>\n"; return; }; # Open a host in the given case $funcs[$HOST_OPEN] = sub { print_html_header("Open Host In $args{'case'}"); print_menu_tabs(); print "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\" ". "BACKGROUND=\"$YEL_PIX\" BORDER=0>\n"; # Create an array of directories in the case, verifying that there is # a config file my @hosts; opendir HOSTS, $case_dir or die "Can't open $case_dir directory: $!"; foreach my $h (readdir HOSTS) { next if (($h eq '.') || ($h eq '..')); my $hfile = host_config_fname($h); push @hosts, $h if ((-d "${case_dir}$h") && (-e "$hfile")); } closedir HOSTS; if (scalar @hosts == 0) { print "<TR><TD COLSPAN=\"4\" ALIGN=CENTER>". "No hosts have been added to case yet". "</TD></TR></TABLE>\n"; } else { print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HOST_OPEN_LOG\">\n". make_hidden(). "<TR><TH>Name</TH>". "<TH>Description</TH><TH> </TH></TR>\n"; my $first = 0; foreach my $h (@hosts) { print "<TR><TD ALIGN=\"left\">". "<INPUT TYPE=\"radio\" NAME=\"host\" VALUE=$h"; if ($first == 0) { print " CHECKED"; $first = 1; } print "> $h </TD>"; my $fname = host_config_fname($h); open CONFIG, "<$fname" or die "Can't open host config file ($fname)"; my $desc = "None Provided"; while (<CONFIG>) { s/^\s+//; s/\s+$//; if (/^desc\s+(.*)$/) { $desc = $1; last; } } close CONFIG; print "<TD ALIGN=left>$desc</TD>". "<TD ALIGN=center>". "<A HREF=\"$PROGNAME?func=$HOST_DETAILS&$baseargs&". "host=$h\">details</A></TD></TR>\n"; } print "</TABLE>\n"; # Display pulldown of investigators print "<BR>Investigator (for reports only): "; my @invs = read_invest(); if (scalar @invs == 0) { print "None Provided<BR>\n". "<INPUT TYPE=\"hidden\" NAME=\"inv\" VALUE=\"unknown\">\n"; } else { my $cur_inv = ""; $cur_inv = $args{'inv'} if (exists $args{'inv'}); print "<SELECT NAME=\"inv\" SIZE=\"1\">\n"; if (($cur_inv eq "") && (scalar @invs != 1)) { print "<OPTION VALUE=\"\" SELECTED>Select One". "</OPTION>\n"; } foreach my $i (@invs) { print "<OPTION VALUE=\"$i\""; print " SELECTED" if ($cur_inv eq $i); print ">$i</OPTION>\n"; } print "</SELECT>\n"; } } print "<BR><BR><TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR>\n"; # Make a table for the buttons. The table will either be 3 or 2 # entries wide, depending on if there is an 'Ok' button or not unless (scalar @hosts == 0) { print "<TD ALIGN=CENTER>". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_ok.jpg\" ". "ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=0>\n". "</FORM>\n</TD>\n"; } # Add Host print "<TD ALIGN=CENTER>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HOST_ADD\">\n". "<INPUT TYPE=\"hidden\" NAME=\"case\" VALUE=\"$args{'case'}\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_hnew.jpg\" ". "ALT=\"Add Host\" WIDTH=\"176\" HEIGHT=20 BORDER=0>\n". "</FORM></TD>". # Close Button "<TD ALIGN=CENTER>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$CASE_OPEN\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_ccls.jpg\" ". "ALT=\"Close Case\" WIDTH=\"176\" HEIGHT=20 BORDER=0>\n". "</FORM></TD></TR></TABLE>\n"; print "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR><TD> </TD>". "<TD ALIGN=CENTER><A HREF=\"$HELP_URL\" ". " TARGET=\"_blank\">". "<IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" ". "WIDTH=\"167\" HEIGHT=20 BORDER=0>". "</A></TD><TD> </TD></TR>\n". "</TABLE>\n"; return; }; # Log that a given host was opened and then proceed to open an image $funcs[$HOST_OPEN_LOG] = sub { unless ((exists $args{'inv'}) && ($args{'inv'} ne "")) { print_html_header("Missing Investigator"); print "<BR>An investigator must be selected<P>\n". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HOST_OPEN_LOG\">\n". make_hidden(); print "Select one of the following:"; my @invs = read_invest(); print "<SELECT NAME=\"inv\" SIZE=\"1\">\n"; print "<OPTION VALUE=\"\" SELECTED>Select One". "</OPTION>\n"; foreach my $i (@invs) { print "<OPTION VALUE=\"$i\">$i</OPTION>\n"; } print "</SELECT><P>\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=43 HEIGHT=20 BORDER=\"0\">\n". "</FORM>\n"; return; } check_inv(); log_case_info ("Host $args{'host'} opened by $args{'inv'}"); log_host_info ("Host $args{'host'} opened by $args{'inv'}"); log_host_inv ("Host $args{'host'} opened"); $args{'func'} = $enc_args{'func'} = $IMG_OPEN; & {$funcs[$IMG_OPEN]}; }; # Provide details about the configuration of a host. This window is # a link from the HOST_OPEN window $funcs[$HOST_DETAILS] = sub { print_html_header("Details of $args{'case'}:$args{'host'}"); print "<B>Case: </B>$args{'case'}<BR><BR>". "<CENTER>". "<IMG SRC=\"pict/menu_h_hdet.jpg\" ALT=\"Host Details\">". "<BR><BR><BR>\n". "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\" ". "BACKGROUND=\"$YEL_PIX\" BORDER=0>\n". # Name "<TR><TD ALIGN=\"RIGHT\" WIDTH=300><B>Name:</B></TD>". "<TD ALIGN=\"LEFT\" WIDTH=300><TT>$args{'host'}</TT></TD></TR>\n". # Description "<TR><TD ALIGN=\"RIGHT\"><B>Description:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>". (($host_desc ne "") ? $host_desc : " "). "</TT></TD></TR>\n". # Timezone "<TR><TD ALIGN=\"RIGHT\"><B>Timezone: </B></TD>". "<TD ALIGN=\"LEFT\"><TT>$tz</TT></TD></TR>\n". # Timeskew "<TR><TD ALIGN=\"RIGHT\"><B>Timeskew:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$ts</TT></TD></TR>\n". "<TR><TD COLSPAN=2> </TD></TR>\n". # Actual Directory "<TR><TD ALIGN=\"RIGHT\"><B>Directory:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$host_dir</TT></TD></TR>\n". "<TR><TD COLSPAN=2> </TD></TR>\n". # Alert Database "<TR><TD ALIGN=\"RIGHT\"><B>Alert Hash Database:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>". (($alert_db ne "") ? $alert_db : " "). "</TT></TD></TR>\n". # Exclude Database "<TR><TD ALIGN=\"RIGHT\"><B>Exclude Hash Database:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>". (($exclude_db ne "") ? $exclude_db : " "). "</TT></TD></TR>\n". "</TABLE>\n"; # Final Button print "<BR><BR><FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HOST_OPEN\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/menu_b_ok.jpg\" ". "ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=\"0\">\n</FORM>"; return; }; #################################################################### # Image Functions # Open an image that has been configured $funcs[$IMG_OPEN] = sub { print_html_header("Open Image In $args{'case'}:$args{'host'}"); print_menu_tabs(); print "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\" ". "BACKGROUND=\"$YEL_PIX\" BORDER=0>\n"; # the images have been loaded from reading the host config file in # autopsy_main if (scalar (keys %img2ftype) == 0) { print "</TABLE>No images have been added to this host yet<BR>\n"; goto EGRESS; } # We want to sort by mounting point, so rearrange the hash my %mnt2img; # Cycle through each image we read from the host config foreach my $i (keys %img2ftype) { next if (($img2ftype{$i} eq "dls") || ($img2ftype{$i} eq "strings") || ($img2ftype{$i} eq "body") || ($img2ftype{$i} eq "timeline") ); if (($img2ftype{$i} eq "raw") || ($img2ftype{$i} eq "swap")) { $mnt2img{"$img2ftype{$i}--AUTOPSY--$i"} = $i; } else { $mnt2img{"$img2mnt{$i}--AUTOPSY--$i"} = $i; } } # sort via mount point (which includes the name) my @mnt = sort { lc($a) cmp lc($b) } keys %mnt2img; # It is possible to have only the dls image and not the original # We need to search for those now because they will not be in the # list that we just made (which are arranged via mount point) my @orphan_dls; # cycle through each image and check its type and original foreach my $k (keys %img2ftype) { if (($img2ftype{$k} eq "dls") && (!defined $mod2img{$k})) { push @orphan_dls, $k; } } print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_OPEN_LOG\">\n". make_hidden(). "<TR><TH ALIGN=LEFT>mount</TH>". # mnt "<TH> </TH>". # img button and unalloc "<TH ALIGN=LEFT>name</TH><TH> </TH></TR>\n"; # img name for (my $i = 0; $i <= $#mnt; $i++) { print "<TR>"; my $img = $mnt2img{$mnt[$i]}; # Mount Point # If we have the dummy string at the end of the duplicate # entry, then take it off and print the original $mnt[$i] = $1 if ($mnt[$i] =~ /^(.*?)--AUTOPSY--$REG_IMG$/o); print "<TD><TT>$mnt[$i]</TT></TD>"; # Image button print "<TD><INPUT TYPE=\"radio\" ". "NAME=\"img\" VALUE=$img"; print " CHECKED" if ($i == 0); print ">"; # if there is a corresponding dls entry, make an unalloc button if (defined $img2dls{$img}) { print " (<INPUT TYPE=\"radio\" NAME=\"img\" ". "VALUE=$img2dls{$img}> unalloc)</TD>"; } else { print "</TD>"; } # image name and ftype print "<TD><TT>$img</TT></TD>". "<TD ALIGN=center><A HREF=\"$PROGNAME?func=$IMG_DETAILS&$baseargs&". "img=$img&mnt=$mnt[$i]\">details</A></TD>". "</TR>\n"; } # If we are done with the regular images and have some orphan # dls images, print them my @sort = sort @orphan_dls; for (my $i = 0; $i <= $#sort; $i++) { print "<TR><TD> </TD><TD> </TD><TD>(<INPUT TYPE=\"radio\" NAME=\"img\" ". "VALUE=$sort[$i]"; print " CHECKED" if ($#mnt == 0); print "> unalloc)</TD><TD><TT>$sort[$i]</TT></TD></TR>\n"; } # Begin Button print "</TABLE>\n"; EGRESS: print "<BR><BR>". "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\"><TR>\n"; my $width = 300; unless (scalar (keys %img2ftype) == 0) { $width = 200; print "<TD ALIGN=CENTER WIDTH=$width>". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_ok.jpg\" ". "ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=0>\n". "</FORM></TD>\n"; } print "<TD ALIGN=CENTER WIDTH=$width>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_ADD\">\n". make_hidden(). "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_inew.jpg\" ". "ALT=\"Add Image\" WIDTH=167 HEIGHT=20 BORDER=0></FORM></TD>\n". "<TD ALIGN=CENTER WIDTH=$width>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HOST_OPEN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"case\" VALUE=\"$args{'case'}\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_hcls.jpg\" ". "WIDTH=167 HEIGHT=20 ALT=\"Close Host\" BORDER=0>\n". "</FORM></TD></TR>\n</TABLE>\n"; print "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR><TD> </TD>\n". "<TD ALIGN=CENTER WIDTH=200><A HREF=\"$HELP_URL\" ". " TARGET=\"_blank\">". "<IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" ". "WIDTH=\"167\" HEIGHT=20 BORDER=0>". "</A></TD><TD> </TD></TR>\n". "</TABLE>\n"; # Other features that can be done on a host print "<HR><P>". "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR>\n"; # Timeline of file activity print "<TD ALIGN=\"CENTER\" WIDTH=200>". "<A HREF=\"$PROGNAME?${baseargs_noimg}&func=$TL_MAIN\">". "<IMG BORDER=0 ". "SRC=\"pict/menu_b_tl.jpg\" ". "WIDTH=\"167\" HEIGHT=20 ". "ALT=\"File Activity Timelines\"></A></TD>\n"; # verify the integrity of the images print "<TD ALIGN=\"CENTER\" WIDTH=200>". "<A HREF=\"$PROGNAME?${baseargs_noimg}&func=$INT_LIST_FR\">". "<IMG BORDER=0 ". "SRC=\"pict/menu_b_int.jpg\" ". "WIDTH=\"167\" HEIGHT=20 ". "ALT=\"Image Integrity\"></A></TD>\n". "<TD ALIGN=\"CENTER\" WIDTH=200>". "<A HREF=\"$PROGNAME?${baseargs_noimg}&func=$HASH_MAIN\">". "<IMG BORDER=0 ". "SRC=\"pict/menu_b_hashdb.jpg\" ". "WIDTH=\"167\" HEIGHT=20 ". "ALT=\"Hash Databases\"></A></TD>\n". "</TR></TABLE>\n"; # Notes if ($USE_NOTES == 1) { print "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR>\n". "<TD ALIGN=\"CENTER\" WIDTH=300>". "<A HREF=\"$PROGNAME?${baseargs_noimg}&func=$NOTES_READ\">". "<IMG BORDER=0 ". "SRC=\"pict/menu_b_note.jpg\" ". "WIDTH=\"167\" HEIGHT=20 ". "ALT=\"View Notes\"></A></TD>\n". "<TD WIDTH=300 ALIGN=\"CENTER\">". "<A HREF=\"$PROGNAME?${baseargs_noimg}&func=$NOTES_SEQ_READ\">". "<IMG BORDER=0 ". "SRC=\"pict/menu_b_seq.jpg\" ". "WIDTH=\"167\" HEIGHT=20 ". "ALT=\"Event Sequencer\"></A></TD>\n". "</TR>\n". "</TABLE>\n"; } # check if the permissions are ok # if (((stat("$host_dir/$IMGDIR"))[2]) & 0000222) { # print "<BR><BR><BR>". # "<FONT COLOR=\"$DEL_COLOR[0]\">". # "NOTE: The images directory allows for writes.<BR> It is ". # "recommended that these permissions be turned off</FONT><BR>\n"; #} return; }; # Log in the host log that a given image was opened by what user # then open the main window $funcs[$IMG_OPEN_LOG] = sub { log_host_info ("Image $args{'img'} opened by $args{'inv'}"); log_host_inv ("$args{'img'}: Image opened"); $args{'func'} = $enc_args{'func'} = $MAIN_FR; & {$funcs[$MAIN_FR]}; }; my $MD5_NOTHING = 1; my $MD5_CALC = 2; my $MD5_ADD = 3; # Menu to add a new image to the host # # The list of new images is determined by looking in the images directory # and seeing which is not yet configured # $funcs[$IMG_ADD] = sub { print_html_header("Add Image To $args{'case'}:$args{'host'}"); print "<B>Case:</B> $args{'case'}<BR>\n". "<B>Host:</B> $args{'host'}<BR>\n"; print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_ADD_DOIT\">\n". make_hidden(); print <<EOF1; <CENTER> <IMG SRC=\"pict/menu_h_inew.jpg\" ALT=\"Add Image\"> <BR><BR><BR> <TABLE WIDTH=\"600\" CELLPADDING=\"2\" CELLSPACING=\"0\" BACKGROUND=\"$YEL_PIX\" BORDER=0> <TR> <TD COLSPAN=2> </TD> </TR> <TR> <TD ALIGN=CENTER COLSPAN=2> <B>Image Details</B> </TD> </TR> <TR> <TD WIDTH=300 ALIGN=RIGHT>Location (starting with /): </TD> <TD WIDTH=300 ALIGN=LEFT> <INPUT TYPE=\"text\" NAME=\"img_path\" SIZE=36 MAXLENGTH=256> </TD> </TR> <TR> <TD WIDTH=300 ALIGN=RIGHT>Import Method:</TD> <TD WIDTH=300 ALIGN=LEFT> <INPUT TYPE=\"radio\" NAME=\"sort\" VALUE=$IMG_ADD_SYM CHECKED> Symlink to Evidence Locker </TD> </TR> <TR> <TD WIDTH=300 ALIGN=RIGHT> </TD> <TD WIDTH=300 ALIGN=LEFT> <INPUT TYPE=\"radio\" NAME=\"sort\" VALUE=$IMG_ADD_COPY> Copy to Evidence Locker </TD> </TR> <TR> <TD WIDTH=300 ALIGN=RIGHT> </TD> <TD WIDTH=300 ALIGN=LEFT> <INPUT TYPE=\"radio\" NAME=\"sort\" VALUE=$IMG_ADD_MOVE> Move to Evidence Locker (<FONT COLOR="red">Warning</FONT>: image loss could occur during a system failure) </TD> </TR> EOF1 # Show the file system types that we know of print "<TR><TD ALIGN=RIGHT>File System Type: </TD>". "<TD ALIGN=LEFT><SELECT NAME=\"ftype\">\n"; foreach my $fs (sort keys %root_inode) { print "<OPTION VALUE=\"$fs\">$fs</OPTION>\n"; } # The following do not have 'inodes' but should be in the list print "<OPTION VALUE=\"\">======</OPTION>\n"; print "<OPTION VALUE=\"raw\">raw</OPTION>\n"; print "<OPTION VALUE=\"swap\">swap</OPTION>\n"; print "</SELECT></TD></TR>\n"; # Enter the mounting point and MD5 print <<EOF2; <TR> <TD ALIGN=RIGHT>Original Mount Point (i.e. <TT>C:\\</TT>): </TD> <TD ALIGN=LEFT><INPUT TYPE=\"text\" NAME=\"mnt\"></TD> </TR> <TR> <TD ALIGN=RIGHT> </TD> <TD ALIGN=LEFT>Note: Mounting point not required for swap or raw types</TD> </TR> <TR> <TD COLSPAN=2> </TD> </TR> <TR> <TD ALIGN=CENTER COLSPAN=2> <B>Image Integrity Check Options (i.e. MD5)</B> </TD> </TR> <TR> <TD ALIGN=RIGHT>Calculate Now:</TD> <TD ALIGN=LEFT> <INPUT TYPE=\"radio\" NAME=\"do_md5\" VALUE=\"$MD5_CALC\" CHECKED> </TD> </TR> <TR> <TD ALIGN=RIGHT>Ignore:</TD> <TD ALIGN=LEFT> <INPUT TYPE=\"radio\" NAME=\"do_md5\" VALUE=\"$MD5_NOTHING\"> </TD> </TR> <TR> <TD ALIGN=RIGHT>Add:</TD> <TD ALIGN=LEFT> <INPUT TYPE=\"radio\" NAME=\"do_md5\" VALUE=\"$MD5_ADD\"> </TD> </TR> <TR> <TD ALIGN=RIGHT>MD5: </TD> <TD ALIGN=LEFT> <INPUT TYPE=\"text\" NAME=\"md5\" SIZE=36 MAXLENGTH=32> </TD> </TR> <TR> <TD ALIGN=RIGHT> </TD> <TD ALIGN=LEFT> <INPUT TYPE=\"checkbox\" NAME=\"ver_md5\" VALUE=\"1\"> Verify MD5 After Importing? </TD> </TR> <TR> <TD COLSPAN=2> </TD> </TR> </TABLE> <BR><BR> <TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\"> <TR> <TD ALIGN=CENTER> <INPUT TYPE=\"image\" SRC=\"pict/menu_b_inew.jpg\" ALT=\"Add Image\" WIDTH=\"167\" HEIGHT=20 BORDER=0> </TD> </FORM> EOF2 print " <TD ALIGN=CENTER>\n". " <FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". " <INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_OPEN\">\n". make_hidden(). " <INPUT TYPE=\"image\" SRC=\"pict/menu_b_cancel.jpg\" ". "ALT=\"Cancel\" WIDTH=\"167\" HEIGHT=20 BORDER=0></FORM>\n". " </TD>\n". # HELP " <TD ALIGN=CENTER>\n". " <A HREF=\"$HELP_URL\" TARGET=\"_blank\">\n". " <IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" ". "WIDTH=\"167\" HEIGHT=20 BORDER=0></A>\n". " </TD>\n". "</TR>\n". "</TABLE>\n"; return; }; # Add the image to the configuration by adding it to the host config file # and the md5.txt file if that data was provided $funcs[$IMG_ADD_DOIT] = sub { check_img_path(); check_ftype(); check_sort(); check_do_md5(); check_mnt() if (($args{'ftype'} ne 'raw') && ($args{'ftype'} ne 'swap')); print_html_header("Add a new image to an Autopsy Case"); my $mnt = get_mnt(); my $fstype = get_ftype(); my $img_path = get_img_path(); my $import_type = get_sort(); # Test the File System if (($fstype ne 'swap') && ($fstype ne 'raw')) { local *OUT; my $out; # Run 'fsstat' and see if there is any output - else there was # an error and the data went to STDERR exec_pipe(*OUT, "'${TASKDIR}fsstat' -f $fstype '$img_path'"); unless (read (OUT, $out, 1)) { print "<P>The image is not a <TT>$fstype</TT> file system<BR>\n". "<P><A HREF=\"$PROGNAME?func=$IMG_ADD&$baseargs\">". "<IMG SRC=\"pict/but_ok.jpg\" BORDER=\"0\" ". "WIDTH=\"43\" HEIGHT=20 ALT=\"Ok\">". "</A>\n"; return; } close (OUT); } # The get the images directory and file name my $img = ""; if ($img_path =~ /\/($REG_FILE)$/) { $img = "$IMGDIR/$1"; } else { print_err ("Error Parsing Image Path ($img_path)"); } # Get the full path of the destination my $img_dst = "$host_dir/$img"; if ((-e "$img_dst") || (-l "$img_dst")) { print_err ("Image by the same name already exists in the Host directory ($img)"); } my $orig_size = (stat("$img_path"))[7]; # Copy, Move, or link it if ($import_type == $IMG_ADD_SYM) { log_host_info ("Sym Linking image $img_path into $args{'case'}:$args{'host'}"); print_err ("ERROR: /bin/ln missing") unless (-x '/bin/ln'); print "Linking <TT>$img_path</TT> to <TT>$img_dst</TT><BR>\n"; exec_sys ("/bin/ln -s '$img_path' '$img_dst'"); } elsif ($import_type == $IMG_ADD_COPY) { log_host_info ("Copying image $img_path into $args{'case'}:$args{'host'}"); print_err ("ERROR: /bin/cp missing") unless (-x '/bin/cp'); print "Copying <TT>$img_path</TT> to <TT>$img_dst</TT><BR>\n"; exec_sys ("/bin/cp '$img_path' '$img_dst'"); } elsif ($import_type == $IMG_ADD_MOVE) { log_host_info ("Moving image $img_path into $args{'case'}:$args{'host'}"); print_err ("ERROR: /bin/mv missing") unless (-x '/bin/mv'); print "Moving <TT>$img_path</TT> to <TT>$img_dst</TT><BR>\n"; exec_sys ("/bin/mv '$img_path' '$img_dst'"); } else { print_err ("Invalid Import Type: $import_type"); } my $new_size = (stat("$img_dst"))[7]; if ($new_size != $orig_size) { print_err ("Original image size ($orig_size) is not the same as the destination size ($new_size)"); } my $do_md5 = get_do_md5(); unless ($do_md5 == $MD5_NOTHING) { my $act_md5 = ""; # Do we need to calculate an MD5? if (($do_md5 == $MD5_CALC) || (($do_md5 == $MD5_ADD) && (exists $args{'ver_md5'}) && ($args{'ver_md5'} == 1) ) ) { print "<P>Calculating MD5 of <TT>$img</TT> ". "(this could take a while)<BR>\n"; $act_md5 = calc_md5($img_dst); unless ($act_md5 =~ /^$REG_MD5$/o) { print "Error calculating MD5<BR>\n"; return 1; } print "Current MD5: <TT>$act_md5</TT><BR>\n"; } # And md5 value was given so we can add it to the md5.txt file if (($do_md5 == $MD5_ADD) && (exists $args{'md5'})) { my $md5 = $args{'md5'}; unless ($md5 =~ /^$REG_MD5$/o) { if ($md5 eq "") { print "MD5 value missing<BR>\n"; } else { print "Invalid MD5 value (32 numbers or letters a-f)<BR>\n"; } print "<P><A HREF=\"$PROGNAME?func=$IMG_ADD&$baseargs\">". "<IMG SRC=\"pict/but_ok.jpg\" BORDER=\"0\" ". "WIDTH=\"43\" HEIGHT=20 ALT=\"Ok\">". "</A>\n"; return 1; } $md5 =~ tr/[a-f]/[A-F]/; # They also want us to validate the MD5 if ((exists $args{'ver_md5'}) && ($args{'ver_md5'} == 1) ) { if ($act_md5 eq $md5) { print "Integrity Check Passed<BR>\n"; log_host_info ("Integrity check passed on new image ($img)"); } else { print "<FONT COLOR=\"$DEL_COLOR[0]\">". "Integrity Check Failed<BR></FONT><BR>\n". "Provided: <TT>$md5</TT><BR>\n"; log_host_info ("Integrity check failed on new image ($img)"); return 1; } } # set the act_md5 value to what was given and verified $act_md5 = $md5; } update_md5 ("$img", "$act_md5"); } if ($fstype eq 'swap') { update_host_config ("swap", "$img"); } elsif ($fstype eq 'raw') { update_host_config ("raw", "$img"); } else { update_host_config ("image", "$img", "$fstype $mnt"); } print "<P>Image: <TT>$img_path</TT> added to config file as <TT>$img</TT>\n"; print <<EOF; <P> <CENTER> <TABLE WIDTH=600> <TR> <TD WIDTH=300 ALIGN=CENTER> <A HREF=\"$PROGNAME?func=$IMG_OPEN&${baseargs_noimg}\"> <IMG SRC=\"pict/menu_b_ok.jpg\" ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=\"0\"> </A> </TD> <TD WIDTH=300 ALIGN=CENTER> <A HREF=\"$PROGNAME?func=$IMG_ADD&${baseargs_noimg}\"> <IMG SRC=\"pict/menu_b_inew.jpg\" ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=\"0\"> </A> </TD> </TR> </TABLE> </CENTER> EOF return; }; # Display details of image based on config values # provides links to remove the config of the image and to get the file # system details $funcs[$IMG_DETAILS] = sub { check_img('img'); check_ftype(); check_mnt(); print_html_header("Details of $args{'img'}"); my $mnt = get_mnt(); my $ftype = get_ftype(); print "<CENTER>". "<IMG SRC=\"pict/menu_h_idet.jpg\" ALT=\"Image Details\">". "<BR><BR><BR>\n". "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\" ". "BACKGROUND=\"$YEL_PIX\" BORDER=0>\n". " <TR><TD COLSPAN=\"2\"> </TD></TR>\n". # Name " <TR><TD ALIGN=\"RIGHT\" WIDTH=\"300\"><B>Name:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$args{'img'}</TT></TD></TR>\n". # Mount " <TR><TD ALIGN=\"RIGHT\"><B>Mounting Point:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$mnt</TT></TD></TR>\n". # Type " <TR><TD ALIGN=\"RIGHT\"><B>File System Type:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$ftype</TT></TD></TR>\n"; my $md5 = lookup_md5($args{'img'}); print " <TR><TD ALIGN=\"RIGHT\"><B>MD5:</B></TD><TD><TT>". (($md5 =~ /^$REG_MD5$/o)? $md5 : " "). "</TT></TD></TR>\n". # Host Directory " <TR><TD ALIGN=\"RIGHT\"><B>Host Directory:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>$host_dir</TT></TD></TR>\n". " <TR><TD COLSPAN=\"2\"> </TD></TR>\n". # Strings File " <TR><TD ALIGN=\"RIGHT\"><B>Strings File:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>". ((exists $img2str{$args{'img'}}) ? $img2str{$args{'img'}} : " "). "</TT></TD></TR>\n"; if (($ftype ne "raw") && ($ftype ne "swap")) { # dls file print " <TR><TD ALIGN=\"RIGHT\"><B>Unallocated $addr_unit{$ftype}s (dls) File:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>". ((exists $img2dls{$args{'img'}}) ? $img2dls{$args{'img'}} : " "). "</TT></TD></TR>\n"; # Strings of dls print " <TR><TD ALIGN=\"RIGHT\"><B>Strings of Unallocated $addr_unit{$ftype}s File:</B></TD>". "<TD ALIGN=\"LEFT\"><TT>". ( ( (exists $img2dls{$args{'img'}}) && (exists $img2str{$img2dls{$args{'img'}}})) ? $img2str{$img2dls{$args{'img'}}} : " "). "</TT></TD></TR>\n"; } print " <TR><TD COLSPAN=\"2\"> </TD></TR>\n". "</TABLE>\n"; # Section for Strings file and 'dls' file if ( (!(defined $img2str{$args{'img'}})) || (!(defined $img2dls{$args{'img'}})) || ((defined $img2dls{$args{'img'}}) && (!(defined $img2str{$img2dls{$args{'img'}}})))) { print "<HR><TABLE WIDTH=600>\n<TR>"; } # Strings File if (!(defined $img2str{$args{'img'}})) { (my $img_dir, my $str_img) = split (/\//,$args{'img'}); print "<TD ALIGN=\"CENTER\" WIDTH=300><H3>Generate Strings File</H3>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "File Name: <INPUT TYPE=\"text\" NAME=\"fname\" ". "VALUE=\"$str_img.str\"><BR><BR>\n". "Generate MD5? ". "<INPUT TYPE=\"checkbox\" NAME=\"md5\" VALUE=\"1\" CHECKED><BR><BR>". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_MAKESTR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_str.jpg\" ". "ALT=\"Extract Strings\" BORDER=\"0\">\n</FORM></TD>\n"; } if (($ftype eq 'dls') || ($ftype eq 'swap') || ($ftype eq 'raw')) { # Place holder for types that have no notion of unallocated } # Unallocated Space File elsif (!(defined $img2dls{$args{'img'}})) { print "<TD ALIGN=\"CENTER\" WIDTH=300><H3>Create File of Unallocated $addr_unit{$ftype}s</H3>". "(Note: This Does Not Include Slack Space)<BR>\n". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "File Name: <INPUT TYPE=\"text\" NAME=\"fname\" "; (my $img_dir, my $dls_img) = split (/\//,$args{'img'}); if ($dls_img =~ /^(.*?)\.dd$/) { print "VALUE=\"$1.dls\"><BR><BR>\n"; } else { print "VALUE=\"${dls_img}.dls\"><BR><BR>\n"; } print "Generate MD5? ". "<INPUT TYPE=\"checkbox\" NAME=\"md5\" VALUE=\"1\" CHECKED><BR><BR>". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_MAKEDLS\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_un.jpg\" ". "ALT=\"Extract Unallocated Data\" BORDER=\"0\">\n<BR></FORM>\n"; } # strings of 'dls' elsif (!(defined $img2str{$img2dls{$args{'img'}}})) { (my $img_dir, my $str_img) = split (/\//,$img2dls{$args{'img'}}); print "<TD ALIGN=\"CENTER\" WIDTH=300><H3>Generate Strings File of Unallocated $addr_unit{$ftype}s</H3>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "File Name: <INPUT TYPE=\"text\" NAME=\"fname\" ". "VALUE=\"$str_img.str\"><BR><BR>\n". "Generate MD5? ". "<INPUT TYPE=\"checkbox\" NAME=\"md5\" VALUE=\"1\" CHECKED><BR><BR>". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_MAKESTR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$img2dls{$args{'img'}}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_str.jpg\" ". "ALT=\"Extract Strings\" BORDER=\"0\">\n</FORM></TD>\n"; } if ( (!(defined $img2str{$args{'img'}})) || (!(defined $img2dls{$args{'img'}})) || ((defined $img2dls{$args{'img'}}) && (!(defined $img2str{$img2dls{$args{'img'}}})))) { print "</TR></TABLE><HR>\n"; } print "<P>". "<TABLE WIDTH=\"600\" CELLSPACING=\"0\" CELLPADDING=\"2\">\n". # Ok "<TR><TD ALIGN=CENTER WIDTH=200>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_OPEN\">\n". make_hidden(). "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_ok.jpg\" ". "ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=0></FORM></TD>\n"; print "<TD ALIGN=CENTER WIDTH=200>"; if (($ftype ne "raw") && ($ftype ne "swap")) { # File System Details print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_blank\">\n". make_hidden(). "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$MAIN_FR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mode\" VALUE=\"$FS_MAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mnt\" VALUE=\"$args{'mnt'}\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_fs.jpg\" ". "WIDTH=167 HEIGHT=20 ". "ALT=\"File System\" BORDER=0></FORM></TD>\n"; } else { print " </TD>\n"; } # Remove Image print "<TD ALIGN=CENTER WIDTH=200>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_DEL\">\n". make_hidden(). "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mnt\" VALUE=\"$args{'mnt'}\">\n". "<INPUT TYPE=\"image\" SRC=\"pict/menu_b_rem.jpg\" ". "WIDTH=167 HEIGHT=20 ". "ALT=\"Remove\" BORDER=0></FORM></TD>\n". "</TR></TABLE>\n"; return; }; # remove the config files $funcs[$IMG_DEL] = sub { check_img('img'); check_ftype(); print_html_header("Removing Configuration Settings for $args{'img'}"); update_host_config("", $args{'img'}, ""); update_md5($args{'img'}, ""); print "Settings for <TT>$args{'img'}</TT> removed from ". "<TT>$args{'case'}:$args{'host'}</TT>.\n". "<P>NOTE: The actual file still exists in the host directory.\n"; print "<P><A HREF=\"$PROGNAME?func=$IMG_OPEN&${baseargs_noimg}\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\"></A>\n"; return(); }; ################################################################### # Blank Page $funcs[$BLANK] = sub { print_html_header(""); print "<!-- This Page Intentionally Left Blank -->\n"; return 0; }; # ###################### FILE MODE ################### # # # Make the three frames and fill them in # $funcs[$FIL_MAIN] = sub { # If we were not given the inode, then look up the root unless (exists $args{'inode'}) { my $ftype = get_ftype(); $args{'inode'} = $enc_args{'inode'} = $root_inode{$ftype}; } unless (exists $args{'dir'}) { $args{'dir'} = "/"; } check_inode('inode'); check_dir(); print_html_header_frameset("$args{'mnt'}$args{'dir'} on $args{'img'}"); my $sort = $SORT_NAME; $sort = $args{'sort'} if (exists $args{'sort'}); my $dmode = $DMODE_NOSHOW; $dmode = $args{'dmode'} if (exists $args{'dmode'}); print "<FRAMESET COLS=\"175,*\">\n"; # Directory Listing on Left my $url = "$PROGNAME?$baseargs&dir=$enc_args{'dir'}&". "sort=$sort&dmode=$dmode&inode=$enc_args{'inode'}"; print "<FRAME SRC=\"$url&func=$FIL_DIR\">\n"; # File frameset on right print "<FRAMESET ROWS=\"50%,50%\">\n"; # File Listings on top print "<FRAME SRC=\"$url&func=$FIL_LIST\" ". "NAME=\"list\">\n"; # File Contents print "<FRAME SRC=\"$PROGNAME?func=$BLANK&$baseargs\" ". "NAME=\"content\">\n". "</FRAMESET>\n". "</FRAMESET>\n"; return 0; }; # # Print the directory names for the lhs frame # # THIS NEEDS TO IMPROVE TO BECOME MORE USABLE # $funcs[$FIL_DIR] = sub { check_dir(); check_sort(); check_dmode(); print_html_header(""); my $ftype = get_ftype(); my $sort = get_sort(); my $dmode = get_dmode(); my $lcldir = ""; my $prev_plus = ""; # previous number of '+' directory spacers my $prev_fname = ""; my $prev_meta = ""; my $img = get_img('img'); # Field to enter a directory into: print "<P><FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"list\">\n". "<B>View Directory:</B><BR><TT>$args{'mnt'}</TT>". "<INPUT TYPE=\"text\" NAME=\"dir\" SIZE=24 MAXLENGTH=100>\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$FIL_NAME\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mnt\" VALUE=\"$args{'mnt'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"sort\" VALUE=\"$args{'sort'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"dmode\" VALUE=\"$args{'dmode'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"inode\" VALUE=\"0\">\n". make_hidden(). # Ok Button "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\"></FORM>\n"; print "<P><HR><P>\n"; my $base_url = "$PROGNAME?$baseargs&sort=$sort"; # All deleted files button print "<A HREF=\"$base_url&func=$FIL_DEL&inode=$root_inode{$ftype}&dir=\" ". "TARGET=\"list\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_b_alldel.jpg\" ". "WIDTH=\"127\" ". "ALT=\"Show All Deleted Files\">". "</A><P>\n"; # The dmode arg shows if we should expand the whole directory listing # or not if ($dmode == $DMODE_NOSHOW) { print "<A HREF=\"$base_url&func=$FIL_MAIN&dmode=$DMODE_SHOW\" ". "TARGET=\"_parent\">". "<IMG SRC=\"pict/file_b_expand.jpg\" ALT=\"Expand All Directories\" ". "BORDER=\"0\"></A><P><HR>\n"; return; } else { print "<A HREF=\"$base_url&func=$FIL_MAIN&dmode=$DMODE_NOSHOW\" ". "TARGET=\"_parent\">". "<IMG SRC=\"pict/file_b_hide.jpg\" ALT=\"Hide All Directories\" ". "BORDER=\"0\"></A><P><HR>\n"; } $base_url .= "&dmode=$dmode"; log_host_inv ("$args{'img'}: List of all directories"); # We need to maintain state to create dir and this is done by # counting the + marks. local *OUT; exec_pipe(*OUT, "'${TASKDIR}fls' -f $ftype -ruD '$img'"); # Print root my $url = "$base_url&func=$FIL_LIST&inode=$root_inode{$ftype}&dir="; print "<P><A HREF=\"$url\" TARGET=\"list\">$args{'mnt'}</A><BR>\n"; while (<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&func=$FIL_LIST&inode=$meta". "&dir=".url_encode($lcldir.$fname."/"); print "<FONT COLOR=\"$DEL_COLOR[0]\">" if defined $del; print "+$plus<A HREF=\"$url\" TARGET=\"list\"><TT>/$fname</TT></A><BR>\n"; print "</FONT>" if defined $del; } } close (OUT); 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 # $funcs[$FIL_LIST] = sub { check_inode('inode'); check_dir(); check_sort(); check_dmode(); my $fname = "$args{'mnt'}$args{'dir'}"; my $sp = " "; print_html_header("Entries in $fname"); my (@itype, @dtype, @name, @mod, @acc, @chg, @size, @gid, @uid, @inode); my (@dir, @entry, @del, @realloc, @inode_int); my $sort = get_sort(); my $ftype = get_ftype(); my $inode = get_inode('inode'); my $img = get_img('img'); log_host_inv ("$args{'img'}: Directory listing of $fname ($inode)"); # execute command local *OUT; exec_pipe(*OUT, "'${TASKDIR}fls' -f $ftype -la -z '$tz' -s $ts '$img' $inode"); # Make the big table, small table, and start the current directory my $iurl = "$PROGNAME?$baseargs&dmode=$enc_args{'dmode'}&sort=$sort"; print <<EOF1; <!-- Big Table --> <TABLE CELLSPACING=\"0\" CELLPADDING=\"2\" BORDER=0> <!-- Small Table --> <TR> <TD COLSPAN=19> <TABLE BORDER=0 ALIGN=\"left\" CELLSPACING=\"0\" CELLPADDING=\"2\" WIDTH=500> <TR> <TD COLSPAN=2><B>Current Directory:</B> <TT> <A HREF=\"${iurl}&func=$FIL_LIST&inode=$root_inode{$ftype}&dir=\">$args{'mnt'}</A> EOF1 # Each file in the path will get its own link $iurl .= "&func=$FIL_NAME&inode=0"; my $path = ""; my @dir_split = split ('/', $args{'dir'}); while (scalar @dir_split > 1) { my $d = shift @dir_split; next if ($d eq ''); $path .= "$d/"; print " <A HREF=\"${iurl}&dir=$path\">/${d}/</A> \n"; } print " /$dir_split[0]/ \n" if (scalar @dir_split == 1); print " </TT></TD>\n". " </TR>\n"; # Add Note Button $iurl = "&$baseargs&dir=$enc_args{'dir'}&inode=$enc_args{'inode'}"; if ($USE_NOTES == 1) { print <<EOF2; <TR> <TD WIDTH=\"100\" ALIGN=LEFT> <A HREF=\"$PROGNAME?func=$NOTES_ENT$iurl\" TARGET=\"_blank\"> <IMG BORDER=\"0\" SRC=\"pict/but_addnote.jpg\" WIDTH=\"89\" HEIGHT=20 ALT=\"Add Note About Directory\"> </A> </TD> EOF2 } # Generate MD5 List Button print <<EOF3; <TD WIDTH=\"206\" ALIGN=LEFT> <A HREF=\"$PROGNAME?func=$FIL_MD5$iurl\" TARGET=\"_blank\"> <IMG BORDER=\"0\" SRC=\"pict/file_b_md5list.jpg\" WIDTH=\"206\" ALT=\"Generate list of MD5 values\"> </A> </TD> </TR> <!-- END of Little Table --> </TABLE> </TD> </TR> <TR> <TD COLSPAN=19><HR></TD> </TR> EOF3 # Make the Table and Headers my $url="$PROGNAME?func=$FIL_MAIN&$baseargs&inode=$enc_args{'inode'}". "&dir=$enc_args{'dir'}&dmode=$enc_args{'dmode'}"; print "<TR VALIGN=\"MIDDLE\" ". "BACKGROUND=\"$YEL_PIX\">\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 " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_del_cur.jpg\" ". "WIDTH=\"49\" HEIGHT=20 ". "ALT=\"Deleted Files\">". "</TD>\n"; } else { $iurl = $url."&sort=$SORT_DEL"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_del_link.jpg\" ". "WIDTH=\"28\" HEIGHT=20 ". "ALT=\"Deleted Files\">". "</A></TD>\n"; } # type only gets one column for two 'types' print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n". " <TH ALIGN=\"CENTER\" BACKGROUND=\"$YEL_PIX\">". " Type <BR>"; if ($sort == $SORT_DTYPE) { print "dir"; } else { $iurl = $url."&sort=$SORT_DTYPE"; print "<A HREF=\"$iurl\" TARGET=\"_parent\">dir</A>"; } print " / "; if ($sort == $SORT_ITYPE) { print "in</TH>\n"; } else { $iurl = $url."&sort=$SORT_ITYPE"; print "<A HREF=\"$iurl\" TARGET=\"_parent\">in</A></TH>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; if ($sort == $SORT_NAME) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_nam_cur.jpg\" ". "WIDTH=\"76\" HEIGHT=20 ". "ALT=\"File Name\">". "</TD>\n"; } else { $iurl = $url."&sort=$SORT_NAME"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_nam_link.jpg\" ". "WIDTH=\"50\" HEIGHT=20 ". "ALT=\"File Name\">". "</A></TD>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; # Modified / Written if ($sort == $SORT_MOD) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">"; if ($mtime_str{$ftype} eq 'Modified') { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_mod_cur.jpg\" ". "WIDTH=\"84\" HEIGHT=20 ". "ALT=\"Modified Time\">"; } else { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_wr_cur.jpg\" ". "WIDTH=\"89\" HEIGHT=20 ". "ALT=\"Written Time\">"; } print "</TD>\n"; } else { $iurl = $url."&sort=$SORT_MOD"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">"; if ($mtime_str{$ftype} eq 'Modified') { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_mod_link.jpg\" ". "WIDTH=\"62\" HEIGHT=20 ". "ALT=\"Modified Time\">"; } else { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_wr_link.jpg\" ". "WIDTH=\"60\" HEIGHT=20 ". "ALT=\"Written Time\">"; } print "</A></TD>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; # Accessed if ($sort == $SORT_ACC) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_acc_cur.jpg\" ". "WIDTH=\"90\" HEIGHT=20 ". "ALT=\"Access Time\">". "</TD>\n"; } else { $iurl = $url."&sort=$SORT_ACC"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_acc_link.jpg\" ". "WIDTH=\"66\" HEIGHT=20 ". "ALT=\"Access Time\">". "</A></TD>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; # Change / Create if ($sort == $SORT_CHG) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">"; if ($ctime_str{$ftype} eq 'Changed') { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_chg_cur.jpg\" ". "WIDTH=\"90\" HEIGHT=20 ". "ALT=\"Change Time\">"; } else { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_cre_cur.jpg\" ". "WIDTH=\"84\" HEIGHT=20 ". "ALT=\"Create Time\">"; } print "</TD>\n"; } else { $iurl = $url."&sort=$SORT_CHG"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">"; if ($ctime_str{$ftype} eq 'Changed') { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_chg_link.jpg\" ". "WIDTH=\"62\" HEIGHT=20 ". "ALT=\"Change Time\">"; } else { print "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_cre_link.jpg\" ". "WIDTH=\"59\" HEIGHT=20 ". "ALT=\"Create Time\">"; } print "</A></TD>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; # Size if ($sort == $SORT_SIZE) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_siz_cur.jpg\" ". "WIDTH=\"53\" HEIGHT=20 ". "ALT=\"Size\">". "</TD>\n"; } else { $iurl = $url."&sort=$SORT_SIZE"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_siz_link.jpg\" ". "WIDTH=\"31\" HEIGHT=20 ". "ALT=\"Size\">". "</A></TD>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; # UID if ($sort == $SORT_UID) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_uid_cur.jpg\" ". "WIDTH=\"49\" HEIGHT=20 ". "ALT=\"UID\">". "</TD>\n"; } else { $iurl = $url."&sort=$SORT_UID"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_uid_link.jpg\" ". "WIDTH=\"27\" HEIGHT=20 ". "ALT=\"UID\">". "</A></TD>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; # GID if ($sort == $SORT_GID) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_gid_cur.jpg\" ". "WIDTH=\"49\" HEIGHT=20 ". "ALT=\"GID\">". "</TD>\n"; } else { $iurl = $url."&sort=$SORT_GID"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_gid_link.jpg\" ". "WIDTH=\"28\" HEIGHT=20 ". "ALT=\"GID\">". "</A></TD>\n"; } print " <TD BACKGROUND=\"$YEL_PIX\">$sp</TD>\n"; # Inode if ($sort == $SORT_INODE) { print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_meta_cur.jpg\" ". "WIDTH=\"62\" HEIGHT=20 ". "ALT=\"Meta\">". "</TD>\n"; } else { $iurl = $url."&sort=$SORT_INODE"; print " <TD ALIGN=\"LEFT\" BACKGROUND=\"$YEL_PIX\">". "<A HREF=\"$iurl\" TARGET=\"_parent\">". "<IMG BORDER=\"0\" ". "SRC=\"pict/file_h_meta_link.jpg\" ". "WIDTH=\"41\" HEIGHT=20 ". "ALT=\"Meta\">". "</A></TD>\n"; } print "</TR>\n"; my $cnt = 0; # sort into arrays while (<OUT>) { if (/^([\?dfcbrlsw-])\/([\?dfcbrlsw-])\s*(\*?)\s*($REG_INODE)(\(realloc\))?:\t(.+?)\t($REG_DATE)\t($REG_DATE)\t($REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o) { my $lcldir = $args{'dir'}; $dtype[$cnt] = $1; $itype[$cnt] = $2; $del[$cnt] = $3; $inode[$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 ($inode[$cnt] =~ /^(\d+)(-\d+(-\d+)?)?$/) { $inode_int[$cnt] = $1; } else { $inode_int[$cnt] = $inode[$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] = url_encode($lcldir); $entry[$cnt] = $cnt; $cnt++; } # We missed it for some reason else { print "<TR><TD COLSPAN=10>Error Parsing File (Invalid Characters?):<BR>$_</TD></TR>\n"; } } if ($cnt == 0) { print "</TABLE>\n<CENTER>No Contents</CENTER>\n"; return 0; } close (OUT); # 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_INODE) { @sorted = sort { $inode_int[$a] <=> $inode_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 $func; my $color; my $lcolor; if ($del[$i] eq '*') { $color = "<FONT COLOR=\"".$DEL_COLOR[$realloc[$i] ne ""]."\">"; $lcolor = $color; } else { $color = "<FONT COLOR=\"$NORM_COLOR\">"; $lcolor = "<FONT COLOR=\"$LINK_COLOR\">"; } # directories have different targets and func values if ($itype[$i] eq 'd') { $target = "list"; $url="$PROGNAME?func=$FIL_LIST&$baseargs&inode=$inode_int[$i]". "&sort=$sort&dir=$dir[$i]&dmode=$enc_args{'dmode'}"; } else { $target = "content"; $url="$PROGNAME?func=$FIL_CMENU_FR&$baseargs&inode=$inode[$i]". "&sort=$sort&dir=$dir[$i]&dmode=$enc_args{'dmode'}"; } if (($row % 2) == 0) { print "<TR VALIGN=\"TOP\" BGCOLOR=\"$BACK_COLOR\">\n <TD ALIGN=\"CENTER\">"; } else { print "<TR VALIGN=\"TOP\" BGCOLOR=\"$BACK_COLOR_TABLE\">\n <TD ALIGN=\"CENTER\">"; } print "<IMG SRC=\"pict/file_b_check.jpg\" BORDER=\"0\">\n" if ($del[$i] eq '*') ; print "</TD>\n". " <TD>$sp</TD>\n". " <TD ALIGN=\"CENTER\">${color}$dtype[$i] / $itype[$i]</TD>\n". " <TD>$sp</TD>\n"; # for valid files and directories make a link if ( ($inode_int[$i] >= $first_inode{$ftype}) && ($size[$i] > 0) && (($itype[$i] eq 'r') || ($itype[$i] eq 'd'))) { print " <TD><A HREF=\"$url\" TARGET=\"$target\">$lcolor"; } else { print " <TD>$color"; } print "<TT>$name[$i]</TT></TD>\n". " <TD>$sp</TD>\n". " <TD>${color}$mod[$i]</TD>\n". " <TD>$sp</TD>\n". " <TD>${color}$acc[$i]</TD>\n". " <TD>$sp</TD>\n". " <TD>${color}$chg[$i]</TD>\n". " <TD>$sp</TD>\n". " <TD>${color}$size[$i]</TD>\n". " <TD>$sp</TD>\n". " <TD>${color}$uid[$i]</TD>\n". " <TD>$sp</TD>\n". " <TD>${color}$gid[$i]</TD>\n". " <TD>$sp</TD>\n"; # for a valid inode, make a link to inode browsing mode if ($inode_int[$i] >= $first_inode{$ftype}) { my $iurl="$PROGNAME?func=$MAIN_FR&mode=$INO_MAIN&$baseargs&inode=$inode[$i]"; print "<TD><A HREF=\"$iurl\" TARGET=\"_blank\">$lcolor"; } else { print "<TD>$color"; } print "$inode[$i]</A> $realloc[$i]</TD>\n</TR>\n"; $row++; } print "</TABLE>\n"; return 0; }; #end of FIL_LIST # This takes a directory name as an argument and converts it to # the inode value and calls FIL_LIST # # The inode value can be anything when this is run, it will be # overwritten $funcs[$FIL_NAME] = sub { check_dir(); my $ftype = get_ftype(); my $img = get_img('img'); my $dir = get_dir(); log_host_inv ("$args{'img'}: Finding meta data address for $dir"); # Use 'ifind -n' to get the inode local *OUT; exec_pipe(*OUT, "'${TASKDIR}ifind' -f $ftype -n '$dir' '$img'"); my $inode; while (<OUT>) { $inode = $1 if (/^($REG_INODE)$/); } close (OUT); unless ($inode =~ /^$REG_INODE$/) { print_check_err ("Error finding meta data address for $dir: $inode"); } # Verify it is a directory with istat exec_pipe(*OUT, "'${TASKDIR}istat' -f $ftype '$img' $inode"); while (<OUT>) { # This is a directory if ((/mode:\s+d/) || (/DOS Mode: Directory/)) { close (OUT); # Set the inode variables $enc_args{'inode'} = $args{'inode'} = $inode; $args{'dir'} .= "/" unless ($args{'dir'} =~ /.*?\/$/); $enc_args{'dir'} .= "/" unless ($enc_args{'dir'} =~ /.*?\/$/); # List the directory contents & {$funcs[$FIL_LIST]}; return 0; } } close (OUT); # This is not a directory, so just give a link print_html_header(""); print <<EOF; <TT>$dir</TT> ( <A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$INO_MAIN&$baseargs&inode=$inode\" TARGET=_blank> inode $inode</A>) is not a directory. <P> <A HREF=\"$PROGNAME?func=$FIL_CMENU_FR&$baseargs&inode=$inode&dir=$dir\" TARGET=\"content\"> <IMG SRC=\"pict/but_view.jpg\" HEIGHT=20 WIDTH=123 ALT=\"view contents\" BORDER=\"0\"> </A> EOF return 1; }; # Content Frame # This creates two frames for the lower rhs frame # $funcs[$FIL_CMENU_FR] = sub { check_inode('inode'); check_dir(); print_html_header_frameset(""); print "<FRAMESET ROWS=\"65,*\">\n"; print "<FRAME SRC=\"$PROGNAME?func=$FIL_CMENU&$baseargs". "&dir=$enc_args{'dir'}&inode=$enc_args{'inode'}". "&sort=$FIL_SORT_ASC\">\n"; print "<FRAME SRC=\"$PROGNAME?func=$FIL_CONT&$baseargs". "&dir=$enc_args{'dir'}&inode=$enc_args{'inode'}". "&sort=$FIL_SORT_ASC\" NAME=\"cont2\">\n</FRAMESET>"; return 0; }; # This is the index for the lower rhs frame # Choose the content display type here $funcs[$FIL_CMENU] = sub { check_inode('inode'); check_dir(); check_sort(); print_html_header(""); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); # get the type of contents local *OUT; exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode | '${TASKDIR}file' -z -b -"); my $file_type = <OUT>; close (OUT); $file_type = "Error getting file type" if ((!defined $file_type) || ($file_type eq "")); # We already have the path in the content window below, so save space # print "<CENTER><TT>$args{'mnt'}$args{'dir'}</TT>\n"; print "<CENTER>\n"; my $url = "&$baseargs&dir=$enc_args{'dir'}&inode=$enc_args{'inode'}"; # Print the options for output display print "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\">\n<TR>\n". "<TD>ASCII (<A HREF=\"$PROGNAME?func=$FIL_CONT&sort=$FIL_SORT_ASC$url\"". "TARGET=\"cont2\">display</A> - ". "<A HREF=\"$PROGNAME?func=$FIL_REP&sort=$FIL_SORT_ASC$url\"". "TARGET=\"_blank\">report</A>)</TD>\n". "<TD>*</TD>\n". "<TD>Strings (". "<A HREF=\"$PROGNAME?func=$FIL_CONT&sort=$FIL_SORT_STR$url\"". "TARGET=\"cont2\">display</A> - ". "<A HREF=\"$PROGNAME?func=$FIL_REP&sort=$FIL_SORT_STR$url\"". "TARGET=\"_blank\">report</A>)</TD>\n". "<TD>*</TD>\n". "<TD><A HREF=\"$PROGNAME?func=$FIL_SAVE&$url\">". "Export</A></TD>\n"; # if the file is either image or HTML, then let them view it if (($file_type =~ /image data/) || ($file_type =~ /HTML document text/) || ($file_type =~ /PC bitmap data/)) { print "<TD>*</TD>\n<TD><A HREF=\"$PROGNAME?func=$CELL_MAIN$url\"". "TARGET=\"_blank\">View</A></TD>\n"; } print "<TD>*</TD>\n". "<TD><A HREF=\"$PROGNAME?func=$NOTES_ENT$url\" TARGET=\"_blank\">". "Add Note</A></TD>\n" if ($USE_NOTES == 1); print "</TR></TABLE>\n"; print "File Type: $file_type"; print "</CENTER>"; return 0; }; # display deleted files only # # Sorting should be added to this $funcs[$FIL_DEL] = sub { check_inode('inode'); check_dir(); check_sort(); print_html_header("Deleted files on $args{'img'} $args{'mnt'}"); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); my $sort = get_sort(); my $sp = " "; log_host_inv ("$args{'img'}: Listing all deleted files"); local *OUT; exec_pipe(*OUT, "'${TASKDIR}fls' -f $ftype -ldr -z '$tz' -s $ts '$img' $inode"); print "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\" BORDER=0>\n". "<TR VALIGN=\"MIDDLE\" ALIGN=\"LEFT\" ". "BACKGROUND=\"$YEL_PIX\">\n"; # Type print "<TH ALIGN=\"CENTER\"> Type  <BR>". "dir / in</TH>". "<TD>$sp</TD>\n"; # Name print " <TD><IMG BORDER=\"0\" ". "SRC=\"pict/file_h_nam_link.jpg\" ". "WIDTH=\"50\" HEIGHT=20 ". "ALT=\"File Name\">". "</TD>\n". "<TD>$sp</TD>\n"; # Mod / Written print " <TD><IMG BORDER=\"0\" "; if ($mtime_str{$ftype} eq 'Modified') { print "SRC=\"pict/file_h_mod_link.jpg\" ". "WIDTH=\"62\" HEIGHT=20 ". "ALT=\"Modified Time\">"; } else { print "SRC=\"pict/file_h_wr_link.jpg\" ". "WIDTH=\"60\" ". "ALT=\"Written Time\">"; } print "</TD>\n". "<TD>$sp</TD>\n"; # Access print " <TD><IMG BORDER=\"0\" ". "SRC=\"pict/file_h_acc_link.jpg\" ". "WIDTH=\"66\" HEIGHT=20 ". "ALT=\"Access Time\">". "</TD>\n". "<TD>$sp</TD>\n"; # Change / Create print " <TD><IMG BORDER=\"0\" "; if ($ctime_str{$ftype} eq 'Changed') { print "SRC=\"pict/file_h_chg_link.jpg\" ". "WIDTH=\"62\" HEIGHT=20 ". "ALT=\"Change Time\">"; } else { print "SRC=\"pict/file_h_cre_link.jpg\" ". "WIDTH=\"59\" HEIGHT=20 ". "ALT=\"Create Time\">"; } print "</TD>\n". "<TD>$sp</TD>\n"; # Size print " <TD><IMG BORDER=\"0\" ". "SRC=\"pict/file_h_siz_link.jpg\" ". "WIDTH=\"31\" HEIGHT=20 ". "ALT=\"Size\">". "</TD>\n". "<TD>$sp</TD>\n"; # UID print " <TD><IMG BORDER=\"0\" ". "SRC=\"pict/file_h_uid_link.jpg\" ". "WIDTH=\"27\" HEIGHT=20 ". "ALT=\"UID\">". "</TD>\n". "<TD>$sp</TD>\n"; # GID print " <TD><IMG BORDER=\"0\" ". "SRC=\"pict/file_h_gid_link.jpg\" ". "WIDTH=\"28\" HEIGHT=20 ". "ALT=\"GID\">". "</TD>\n". "<TD>$sp</TD>\n"; # Inode print " <TD><IMG BORDER=\"0\" ". "SRC=\"pict/file_h_meta_link.jpg\" ". "WIDTH=\"41\" HEIGHT=20 ". "ALT=\"Meta\">". "</TD>\n". "<TD>$sp</TD>\n"; my $row = 0; while (<OUT>) { if (/^([\?dfcbrlsw-])\/([\?dfcbrlsw-])\s*(\*?)\s*($REG_INODE)(\(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 = url_encode($n); my $iurl="$PROGNAME?func=$INO_CONT&$baseargs&inode=$i"; my $i_int = $i; $i_int = $1 if ($i =~ /(\d+)-\d+-\d+/); if (($row % 2) == 0) { print "<TR VALIGN=\"TOP\" BGCOLOR=\"$BACK_COLOR\">\n"; } else { print "<TR VALIGN=\"TOP\" BGCOLOR=\"$BACK_COLOR_TABLE\">\n"; } print "<TD ALIGN=\"CENTER\"><FONT COLOR=\"$DEL_COLOR[$r]\">". "$dt / $it</TD>". "<TD>$sp</TD>\n"; if ($it eq 'd') { my $url="$PROGNAME?func=$FIL_LIST&$baseargs&inode=$i". "&sort=$sort&dir=$enc_n"; print "<TD>"; if ($i_int >= $first_inode{$ftype}) { print "<A HREF=\"$url\" target=\"_self\">"; } print "<FONT COLOR=\"$DEL_COLOR[$r]\"><TT>". "$args{'mnt'}$n</TT></TD>". "<TD>$sp</TD>\n"; } else { my $url="$PROGNAME?func=$FIL_CMENU_FR&$baseargs&inode=$i". "&sort=$sort&dir=$enc_n"; print "<TD>"; if (($i_int >= $first_inode{$ftype}) && ($it eq 'r')) { print "<A HREF=\"$url\" target=\"content\">"; } print "<FONT COLOR=\"$DEL_COLOR[$r]\"><TT>". "$args{'mnt'}$n</TT></TD>". "<TD>$sp</TD>\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 "<TD><FONT COLOR=\"$DEL_COLOR[$r]\">$m</TD>". "<TD>$sp</TD>\n". "<TD><FONT COLOR=\"$DEL_COLOR[$r]\">$a</TD>". "<TD>$sp</TD>\n". "<TD><FONT COLOR=\"$DEL_COLOR[$r]\">$c</TD>". "<TD>$sp</TD>\n". "<TD><FONT COLOR=\"$DEL_COLOR[$r]\">$s</TD>". "<TD>$sp</TD>\n". "<TD><FONT COLOR=\"$DEL_COLOR[$r]\">$g</TD>". "<TD>$sp</TD>\n". "<TD><FONT COLOR=\"$DEL_COLOR[$r]\">$u</TD>". "<TD>$sp</TD>\n"; print "<TD>"; if ($i_int >= $first_inode{$ftype}) { print "<A HREF=\"$iurl\" target=\"content\">"; } print "<FONT COLOR=\"$DEL_COLOR[$r]\">$i</A>"; print " (realloc)" if $r; print "</TD></TR>\n"; } else { print "Error Parsing File (invalid characters?)<BR>: $_\n<BR>"; } $row++; } close(OUT); print "</TABLE>\n"; if ($row == 0) { print "<CENTER>None</CENTER>\n"; return 0; } }; # # Display the actual content here # # NOTE: This has a media type of raw text # $funcs[$FIL_CONT] = sub { check_inode('inode'); check_dir(); check_sort(); print_text_header(); print "\n"; my $sort = get_sort(); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); my $fname = "$args{'mnt'}$args{'dir'}"; local *OUT; if ($sort == $FIL_SORT_ASC) { log_host_inv ("$args{'img'}: Viewing $fname ($inode) as ASCII"); exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype -H '$img' $inode"); print "Contents Of File: $fname\n\n\n\n"; print_output ($_) while (<OUT>); close (OUT); } elsif ($sort == $FIL_SORT_STR) { log_host_inv ("$args{'img'}: Viewing $fname ($inode) as strings"); exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype -H '$img' $inode | '$STRINGS_EXE' -a"); print "String Contents Of File: $fname\n\n\n\n"; print_output ($_) while (<OUT>); close (OUT); } return 0; }; # Export the contents of a file $funcs[$FIL_SAVE] = sub { check_inode('inode'); check_dir(); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); my $fname = "$args{'mnt'}$args{'dir'}"; log_host_inv ("$args{'img'}: Saving contents of $fname ($inode)"); local *OUT; exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode"); print_oct_header(); # 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 "Content-Disposition: inline; ". "filename=${args{'img'}}-${fname};\n\n"; print "$_" while(<OUT>); close (OUT); # we exit instead of return so that we don't get two \n\n at the end exit(0); }; # Display a report for a file # This is intended to have its own window # $funcs[$FIL_REP] = sub { check_inode('inode'); check_dir(); check_sort(); print_text_header(); my $sort = get_sort(); my $img = get_img('img'); my $inode = get_inode('inode'); my $ftype = get_ftype(); my $type; my $fname = "$args{'mnt'}$args{'dir'}"; # 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 "Content-Disposition: inline; ". "filename=${args{'img'}}-${fname}.txt;\n\n"; $fname = "$args{'mnt'}$args{'dir'}"; if ($sort == $FIL_SORT_ASC) { log_host_inv ("$args{'img'}: Generating ASCII report for $fname ($inode)"); $type = "ascii"; }elsif ($sort == $FIL_SORT_STR) { log_host_inv ("$args{'img'}: Generating strings report for $fname ($inode)"); $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 (ver $VER)\n\n". "-" x 62 ."\n". "File: $fname\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype -H '$img' $inode | '${TASKDIR}md5'"); my $md5 = <OUT>; close (OUT); $md5 = "Error getting MD5 Value" if ((!defined $md5) || ($md5 eq "")); chomp $md5; print "MD5 of file: $md5\n"; if ($sort == $FIL_SORT_STR) { exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype -H '$img' $inode | '$STRINGS_EXE' -a | '${TASKDIR}md5'"); $md5 = <OUT>; close (OUT); $md5 = "Error getting MD5 Value" if ((!defined $md5) || ($md5 eq "")); chomp $md5; print "MD5 of strings: $md5\n"; } print "Image: $img\n"; print "Image Type: $ftype\n"; my $date = localtime(); print "Date Generated: $date\n". "Investigator: $args{'inv'}\n". "-" x 62 ."\n"; # Get the inode details exec_pipe(*OUT, "'${TASKDIR}istat' -f $ftype -z '$tz' -s $ts '$img' $inode"); print "$_" while (<OUT>); close (OUT); # File Type exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode | '${TASKDIR}file' -z -b -"); my $file_type = <OUT>; close (OUT); $file_type = "Error getting file type" if ((!defined $file_type) || ($file_type eq "")); print "\nFile Type: $file_type"; print "\n"."-" x 62 ."\n"; if ($sort == $FIL_SORT_ASC) { exec_pipe (*OUT, "'${TASKDIR}icat' -f $ftype -H '$img' $inode"); } elsif ($sort == $FIL_SORT_STR) { exec_pipe (*OUT, "'${TASKDIR}icat' -f $ftype -H '$img' $inode | '$STRINGS_EXE' -a"); } print_output($_) while (<OUT>); close (OUT); return 0; }; # Generate the MD5 value for every file in a given directory and save # them to a text file $funcs[$FIL_MD5] = sub { check_inode('inode'); check_dir(); print_text_header(); my $img = get_img('img'); my $inode = get_inode('inode'); my $ftype = get_ftype(); my $fname = "$args{'mnt'}$args{'dir'}"; $fname = 'root' if ($fname eq '/'); # 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 "Content-Disposition: inline; ". "filename=$fname.md5;\n\n"; $fname = "$args{'mnt'}$args{'dir'}"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}fls' -f $ftype -Fu '$img' $inode"); print "MD5 Values for files in $fname ($args{'img'})\n\n"; while (<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_pipe(*OUT_MD5, "'${TASKDIR}icat' -f $ftype '$img' $in | '${TASKDIR}md5'"); my $md5out = <OUT_MD5>; $md5out = "Error getting 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); }; ################# BLOCKS ########################## # Generate the 2 frames for block browsing $funcs[$BLK_MAIN] = sub { print_html_header_frameset("Data Browse on $args{'img'}"); print "<FRAMESET COLS=\"20%,80%\">\n"; # Data: Listings print "<FRAME SRC=\"$PROGNAME?func=$BLK_ENT&$baseargs". "&block=$enc_args{'block'}\">\n"; # Data Contents if (exists $args{'block'}) { my $len = get_len(); print "<FRAME SRC=\"$PROGNAME?func=$BLK_CMENU_FR&". "block=$enc_args{'block'}&$baseargs&len=$len\" ". "NAME=\"content\">\n</FRAMESET>\n"; } else { print "<FRAME SRC=\"$PROGNAME?func=$BLANK&$baseargs\" ". "NAME=\"content\">\n</FRAMESET>\n"; } return 0; }; # Frame to enter the data into $funcs[$BLK_ENT] = sub { print_html_header(""); my $ftype = get_ftype(); my $bs = get_unitsize(); print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" ". "TARGET=\"content\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$BLK_CMENU_FR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". make_hidden(). # Address "<B>$addr_unit{$ftype} Number:</B><BR> ". "<INPUT TYPE=\"text\" NAME=\"block\" SIZE=12 MAXLENGTH=12"; print " VALUE=\"$enc_args{'block'}\"" if (exists $args{'block'}); print ">\n"; # Number of units print "<P><B>Number of ${addr_unit{$ftype}}s:</B>". "<BR> ". "<INPUT TYPE=\"text\" NAME=\"len\" VALUE=\"1\" SIZE=6 MAXLENGTH=6>\n"; print "<P><B>${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')) { print "<P><B>Address Type:</B><BR> ". "<SELECT NAME=\"btype\" SIZE=1>\n". "<OPTION VALUE=\"$BTYPE_DD\" SELECTED>Regular (dd)</OPTION>\n". "<OPTION VALUE=\"$BTYPE_DLS\">Unallocated (dls)</OPTION>\n". "</SELECT>\n"; } else { print "<INPUT TYPE=\"hidden\" NAME=\"btype\" VALUE=\"$BTYPE_DD\">\n"; } # Lazarus print "<P><B>Lazarus Addr:</B> ". "<INPUT TYPE=\"checkbox\" NAME=\"btype2\">\n". "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n". "</FORM>\n"; print "<P>". "<A HREF=\"$PROGNAME?func=$BLK_DLS&$baseargs\" TARGET=\"content\">". "<IMG SRC=\"pict/but_alloc_list.jpg\" BORDER=\"0\" ". "WIDTH=113 HEIGHT=20 ALT=\"Allocation List\"></A><BR>\n" unless (($ftype eq 'dls') || ($ftype eq 'swap') || ($ftype eq 'raw')); if ( ($ftype ne 'dls') && (exists $img2dls{$args{'img'}}) ) { print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$MAIN_FR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mode\" VALUE=\"$BLK_MAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$img2dls{$args{'img'}}\">\n". make_hidden(). "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_lun.jpg\" ". "ALT=\"Load Unallocated Image\" BORDER=\"0\">\n<BR></FORM>\n"; } elsif ( ($ftype eq 'dls') && (exists $mod2img{$args{'img'}}) ) { print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$MAIN_FR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mode\" VALUE=\"$BLK_MAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$mod2img{$args{'img'}}\">\n". make_hidden(). "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_lorig.jpg\" ". "ALT=\"Load Original Image\" BORDER=\"0\">\n<BR></FORM>\n"; } return 0; }; # generate frame for block content $funcs[$BLK_CMENU_FR] = sub { check_block(); print_html_header_frameset(""); my $sort = $BLK_SORT_ASC; $sort = $1 if ((exists $args{'sort'}) && ($args{'sort'} =~ /^(\d+)$/)); my $len = get_len(); my $blk; my $ifind = get_ifind(); # off is 1 if a lazarus block number as they are off by one my $off = 0; $off = -1 if (exists $args{'btype2'}); # Do we need to convert from dls value to dd value ? if ((exists $args{'btype'}) && ($args{'btype'} == $BTYPE_DLS)) { my $img = get_img('img'); my $b = get_block() + $off; my $ftype = get_ftype(); local *OUT; exec_pipe(*OUT, "'${TASKDIR}dcalc' -f $ftype -u $b '$img'"); $blk = <OUT>; close (OUT); $blk = "Error getting block" if ((!defined $blk) || ($blk eq "")); if ($blk !~ /^\d+$/) { print "$blk\n"; return 1; } } else { $blk = get_block() + $off; } print "<FRAMESET ROWS=\"25%,75%\">\n". "<FRAME SRC=\"$PROGNAME?func=$BLK_CMENU&$baseargs". "&block=$blk&sort=$sort&len=$len&ifind=$ifind\">\n". "<FRAME SRC=\"$PROGNAME?func=$BLK_CONT&$baseargs". "&block=$blk&sort=$sort&len=$len\" NAME=\"cont2\">\n". "</FRAMESET>"; return 0; }; sub print_ifind { my $block = get_block(); my $img = get_img('img'); my $ftype = get_ftype(); log_host_inv ("$args{'img'}: Finding $meta_str{$ftype} for data unit $block"); local *OUT; exec_pipe (*OUT, "'${TASKDIR}ifind' -f $ftype -d $block '$img'"); my $inode = <OUT>; close (OUT); $inode = "Error getting inode" if ((!defined $inode) || ($inode eq "")); if ($inode =~ /^($REG_INODE)$/o) { $inode = $1; my $tmpr = $args{'mnt'}; print "<B>Pointed to by $meta_str{$ftype}:</B> ". "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$INO_MAIN&$baseargs&". "inode=$inode\" TARGET=\"_blank\">$inode</A><BR>\n"; print "<B>Pointed to by file:</B><BR>\n"; exec_pipe(*OUT, "'${TASKDIR}ffind' -f $ftype -a '$img' $inode"); while (<OUT>) { chop ; # Make it red if it is deleted if (/^(\*)\s+\/*(.*)$/) { 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_output("<TT>$tmpr$1</TT><BR>\n"); # this must be an error } else { print_output("$_<BR>\n"); } } close (OUT); } else { print "$inode\n"; } } # Generate index for block content $funcs[$BLK_CMENU] = sub { check_block(); print_html_header(""); my $block = get_block(); my $prev = $block - 1; my $next = $block + 1; my $sort = get_sort(); my $ftype = get_ftype(); my $img = get_img('img'); my $ifind = get_ifind(); my $len = get_len(); my $bs = get_unitsize(); my $len_str = $bs * $len; print "<CENTER><FONT SIZE=3>"; my $url = "$PROGNAME?func=$BLK_CMENU_FR&$baseargs&sort=$sort&len=$len". "&ifind=$ifind"; # Next and Previous pointers print "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR>\n"; # Previous if ($prev < $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?func=$BLK_SAVE&$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?func=$NOTES_ENT&$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 == $BLK_SORT_ASC) { print "display - "; } else { print "<A HREF=\"$PROGNAME?func=$BLK_CMENU_FR&$baseargs&". "sort=$BLK_SORT_ASC&block=$block&len=$len\" TARGET=\"_parent\">". "display</A> - \n"; } print "<A HREF=\"$PROGNAME?func=$BLK_REP&$baseargs&sort=$BLK_SORT_ASC". "&block=$block&len=$len\" TARGET=\"_blank\">report</A>)</TD>\n". "<TD>*</TD>\n"; print "<TD>Hex ("; if ($sort == $BLK_SORT_HEX) { print "display - "; } else { print "<A HREF=\"$PROGNAME?func=$BLK_CMENU_FR&$baseargs&". "sort=$BLK_SORT_HEX&block=$block&len=$len\" TARGET=\"_parent\">". "display</A> - \n"; } print "<A HREF=\"$PROGNAME?func=$BLK_REP&$baseargs&sort=$BLK_SORT_HEX". "&block=$block&len=$len\" TARGET=\"_blank\">report</A>)</TD>\n". "<TD>*</TD>\n"; print "<TD>Strings ("; if ($sort == $BLK_SORT_STR) { print "display - "; } else { print "<A HREF=\"$PROGNAME?func=$BLK_CMENU_FR&$baseargs&". "sort=$BLK_SORT_STR&block=$block&len=$len\" TARGET=\"_parent\">". "display</A> - \n"; } print "<A HREF=\"$PROGNAME?func=$BLK_REP&$baseargs&sort=$BLK_SORT_STR". "&block=$block&len=$len\" TARGET=\"_blank\">report</A>)</TD>\n". "</TR></TABLE>\n"; # Special case for 'dls' b.c. dcat does not have a dls type local *OUT; if ($ftype eq 'dls') { exec_pipe(*OUT, "'${TASKDIR}dcat' -f raw '$img' $block | '${TASKDIR}file' -z -b -"); } else { exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype '$img' $block | '${TASKDIR}file' -z -b -"); } my $file_type = <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"; print "<B>$addr_unit{$ftype}</B> $block<BR>\n"; if (($ftype ne "swap") && ($ftype ne "raw") && ($ftype ne "dls")) { exec_pipe(*OUT, "'${TASKDIR}dstat' -f $ftype '$img' $block"); my $cnt = 0; while (<OUT>) { if ($_ =~ /((Not )?Allocated)/) { print "<FONT COLOR=\"$DEL_COLOR[0]\">" if (defined $2); print "<B>$1</B><BR>"; print "</FONT>" if (defined $2); } elsif ($_ =~ /Group: (\d+)/) { print "<B>Group:</B> $1<BR>\n"; } $cnt++; } close (OUT); if ($cnt == 0) { print "Invalid $addr_unit{$ftype} address<BR>\n"; return; } # Make ifind an option $url = "$PROGNAME?func=$BLK_CMENU&$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(); } } if ($ftype eq 'dls') { if (exists $mod2img{$args{'img'}}) { print "<A HREF=\"$PROGNAME?func=$BLK_CMENU_FR&". "${baseargs_noimg}". "mnt=&img=$mod2img{$args{'img'}}&". "block=$block&sort=$sort&len=$len&btype=$BTYPE_DLS\" ". "TARGET=\"_parent\">View Original</A><BR>\n"; } } return 0; }; #Display actual block content $funcs[$BLK_CONT] = sub { check_block(); check_sort(); print_text_header(); print "\n"; my $sort = get_sort(); my $block = get_block(); my $img = get_img('img'); my $ftype = get_ftype(); my $len = get_len(); my $bs = get_unitsize(); my $len_str = $bs * $len; my $str = "Contents of $addr_unit{$ftype} $block ($len_str bytes) in $args{'img'}\n\n\n"; my $log_str = "contents of $addr_unit{$ftype} $block ($len_str bytes)"; local *OUT; if ($sort == $BLK_SORT_HEX) { print "Hex ".$str; log_host_inv ("$args{'img'}: Displaying Hex $log_str"); exec_pipe(*OUT,"'${TASKDIR}dcat' -f $ftype -h '$img' $block $len_str"); } elsif ($sort == $BLK_SORT_ASC) { print "ASCII ".$str; log_host_inv ("$args{'img'}: Displaying ASCII $log_str"); exec_pipe(*OUT,"'${TASKDIR}dcat' -f $ftype -a '$img' $block $len_str"); } elsif ($sort == $BLK_SORT_STR) { print "String ".$str; log_host_inv ("$args{'img'}: Displaying string $log_str"); exec_pipe(*OUT,"'${TASKDIR}dcat' -f $ftype '$img' $block $len_str | '$STRINGS_EXE' -a"); } print $_ while (<OUT>); close (OUT); return 0; }; $funcs[$BLK_REP] = sub { check_block(); check_sort(); print_text_header(); my $sort = get_sort(); my $img = get_img('img'); my $block = get_block(); my $ftype = get_ftype(); my $len = get_len(); my $type; my $bs = get_unitsize(); my $len_str = $len * $bs; print "Content-Disposition: inline; ". "filename=$args{'img'}-$addr_unit{$ftype}$args{'block'}.txt;\n\n"; if ($sort == $BLK_SORT_ASC) { log_host_inv ("$args{'img'}: Generating ASCII report on data unit $block"); $type = "ascii"; } elsif ($sort == $BLK_SORT_STR) { log_host_inv ("$args{'img'}: Generating strings report on data unit $block"); $type = "string"; } elsif ($sort == $BLK_SORT_HEX) { log_host_inv ("$args{'img'}: Generating hex report on data unit $block"); $type = "hex"; } else { print "\n\n"; print "invalid sort value"; return 1; } print " Autopsy $type $addr_unit{$ftype} Report (ver $VER)\n\n". "-" x 62 ."\n"; if (($ftype ne 'dls') && ($ftype ne 'raw') && ($ftype ne 'swap')) { print "$addr_unit{$ftype}: $args{'block'}\n"; print "Length: $len_str bytes\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}ifind' -f $ftype -d $block '$img'"); my $inode = <OUT>; close (OUT); $inode = "Error getting inode" if ((!defined $inode) || ($inode eq "")); if ($inode =~ /^($REG_INODE)$/o) { my $tmpi = $1; print "Pointed to by $meta_str{$ftype}: $tmpi\n"; my $tmpr = $args{'mnt'}; print "Pointed to by files:\n"; exec_pipe(*OUT, "'${TASKDIR}ffind' -f $ftype -a '$img' $tmpi"); while (<OUT>) { chop ; if (/^(\*)\s+\/*(.*)$/) { print_output(" $tmpr$2 (deleted)\n"); } elsif (/^\/(.*)$/) { print_output(" $tmpr$1\n"); } else { print_output(" $_\n"); } } close(OUT); } else { print "Not allocated to any meta data structures\n"; } } # not dls else { print "$args{'block'}\n"; print "Length: $len_str bytes\n"; } exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype '$img' $block $len_str | '${TASKDIR}md5'"); my $md5 = <OUT>; close(OUT); $md5 = "Error getting md5" if ((!defined $md5) || ($md5 eq "")); chop $md5; print "MD5 of raw $addr_unit{$ftype}: $md5\n"; if ($sort == $BLK_SORT_HEX) { exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype -h '$img' $block $len_str | '${TASKDIR}md5'"); } elsif ($sort == $BLK_SORT_ASC) { exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype -a '$img' $block $len_str | '${TASKDIR}md5'"); } elsif ($sort == $BLK_SORT_STR) { exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype '$img' $block $len_str | '$STRINGS_EXE' -a | '${TASKDIR}md5'"); } $md5 = <OUT>; close(OUT); $md5 = "Error getting md5" if ((!defined $md5) || ($md5 eq "")); chop $md5; print "MD5 of $type output: $md5\n"; print "Image: $img\n"; print "Image Type: $ftype\n"; my $date = localtime(); print "Date Generated: $date\n". "Investigator: $args{'inv'}\n". "-" x 62 ."\n"; if ($sort == $BLK_SORT_HEX) { exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype -h '$img' $block $len_str"); } elsif ($sort == $BLK_SORT_ASC) { exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype -a '$img' $block $len_str"); } elsif ($sort == $BLK_SORT_STR) { exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype '$img' $block $len_str | '$STRINGS_EXE' -a"); } print_output($_) while (<OUT>); close (OUT); return 0; }; # # Display the block allocation list # $funcs[$BLK_DLS] = sub { print_html_header("Block Allocation List"); my $DLS_GAP = 500; my $img = get_img('img'); my $ftype = get_ftype(); my $min = 0; $min = get_min() if (exists $args{'min'}); my $max = $min + $DLS_GAP - 1; # set fmin to the minimum for the file system my $fmin = $min; $fmin = $first_addr{$ftype} if ($min < $first_addr{$ftype}); log_host_inv ("$args{'img'}: Block Allocation List for $min to $max"); print "<CENTER><H2>$addr_unit{$ftype}: $min - $max</H2>"; my $tmp; print "<FONT SIZE=3>\n"; if ($min - $DLS_GAP >= 0) { $tmp = $min - $DLS_GAP; print "<A HREF=\"$PROGNAME?func=$BLK_DLS&$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?func=$BLK_DLS&$baseargs&min=$tmp\">". "<IMG SRC=\"pict/but_next.jpg\" ALT=\"next\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A><BR>"; print "</FONT></CENTER>\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}dls' -elb -f $ftype '$img' $fmin-$max"); while (<OUT>) { if (/^(\d+)\|([af])/) { print "<A HREF=\"$PROGNAME?func=$BLK_CMENU_FR&$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><FONT SIZE=3>\n"; if ($min - $DLS_GAP >= 0) { $tmp = $min - $DLS_GAP; print "<A HREF=\"$PROGNAME?func=$BLK_DLS&$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?func=$BLK_DLS&$baseargs&min=$tmp\">". "<IMG SRC=\"pict/but_next.jpg\" ALT=\"next\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A><BR>"; print "</FONT></CENTER>\n"; }; $funcs[$BLK_SAVE] = sub { check_block(); print_oct_header(); my $block = get_block(); my $img = get_img('img'); my $ftype = get_ftype(); my $len = get_len(); my $bs = get_unitsize(); my $len_str = $len * $bs; log_host_inv ("$args{'img'}: Saving contents of data unit $block ($len_str bytes)"); print "Content-Disposition: inline; filename=$args{'img'}". "-$addr_unit{$ftype}$block.raw;\n\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype '$img' $block $len_str"); print "$_" while (<OUT>); close (OUT); # we exit instead of return so that we don't get two \n\n at the end exit(0); }; ########################### INODE #################### $funcs[$INO_MAIN] = sub { print_html_header_frameset("Meta Data Browse on $args{'img'}"); print "<FRAMESET COLS=\"20%,80%\">\n"; # Inode Enter Location print "<FRAME SRC=\"$PROGNAME?func=$INO_ENT&$baseargs". "&inode=$enc_args{'inode'}\">\n"; # Inode Contents if (exists $enc_args{'inode'}) { print "<FRAME SRC=\"$PROGNAME?func=$INO_CONT&". "inode=$enc_args{'inode'}&$baseargs\" ". "NAME=\"content\">\n</FRAMESET>\n"; } else { print "<FRAME SRC=\"$PROGNAME?func=$BLANK&$baseargs\" ". "NAME=\"content\">\n</FRAMESET>\n"; } return 0; }; # Generate the frame to enter the data into $funcs[$INO_ENT] = sub { print_html_header(""); my $ftype = get_ftype(); # Address print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"content\">\n". "<B>$meta_str{$ftype} Number:</B><BR>   ". "<INPUT TYPE=\"text\" NAME=\"inode\" SIZE=12 MAXLENGTH=12"; print " VALUE=\"$enc_args{'inode'}\"" if exists ($args{'inode'}); print ">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$INO_CONT\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". make_hidden(). # Ok Button "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\"></FORM>\n"; # Allocation List print "<P>". "<A HREF=\"$PROGNAME?func=$INO_ILS&$baseargs\" TARGET=\"content\">". "<IMG SRC=\"pict/but_alloc_list.jpg\" BORDER=\"0\" ". "WIDTH=113 HEIGHT=20 ALT=\"Allocation List\">". "</A>\n"; return 0; }; # Display the contents of inode $funcs[$INO_CONT] = sub { check_inode('inode'); print_html_header(""); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); log_host_inv ("$args{'img'}: Displaying details of $meta_str{$ftype} $inode"); my $inode_int = $inode; $inode_int = $1 if ($inode =~ /^(\d+)-\d+(-\d)?/); my $prev = $inode_int - 1; my $next = $inode_int + 1; print "<FONT SIZE=3><CENTER>\n"; print "<A HREF=\"$PROGNAME?func=$INO_CONT&$baseargs&inode=$prev\">". "<IMG SRC=\"pict/but_prev.jpg\" ALT=\"previous\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A>\n" unless ($prev < $first_inode{$ftype}); print "<A HREF=\"$PROGNAME?func=$INO_CONT&$baseargs&inode=$next\">". "<IMG SRC=\"pict/but_next.jpg\" ALT=\"next\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A>\n<BR>"; print "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\">\n<TR>". "<TD><A HREF=\"$PROGNAME?func=$INO_REP&$baseargs&inode=$inode\"". " TARGET=\"_blank\">". "<IMG SRC=\"pict/but_report.jpg\" ALT=\"report\" ". "WIDTH=88 HEIGHT=20 BORDER=\"0\">". "</A></TD>\n". "<TD><A HREF=\"$PROGNAME?func=$FIL_CMENU_FR&$baseargs&inode=$inode&". "dir=$args{'img'}-inode-$inode\" TARGET=\"_blank\">". "<IMG SRC=\"pict/but_view.jpg\" ALT=\"view contents\" ". "WIDTH=123 HEIGHT=20 BORDER=\"0\">". "</A></TD>\n". "<TD><A HREF=\"$PROGNAME?func=$INO_SAVE&$baseargs&inode=$inode&\">". "<IMG SRC=\"pict/but_export.jpg\" ALT=\"export\" ". "WIDTH=123 HEIGHT=20 BORDER=\"0\">". "</A></TD>"; print "<TD><A HREF=\"$PROGNAME?func=$NOTES_ENT&$baseargs&inode=$inode&\" ". "TARGET=\"_blank\">". "<IMG SRC=\"pict/but_addnote.jpg\" ALT=\"Add Note\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\">". "</A></TD>" if ($USE_NOTES == 1); print "</TR></TABLE>\n</FONT></CENTER>\n<FONT SIZE=3>"; my $tmpr = $args{'mnt'}; if ($ftype =~ /fat/) { print "<A HREF=\"$PROGNAME?func=$INO_FFIND&$baseargs&". "inode=$inode\" TARGET=\"_blank\">Find File</A><BR>"; } else { print "<B>Pointed to by file:</B><BR>\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}ffind' -f $ftype -a '$img' $inode"); my $cnt = 0; while (<OUT>) { chop ; if (/^(\*)\s+\/*(.*)$/) { print_output("<TT><FONT COLOR=\"$DEL_COLOR[0]\">$tmpr$2</FONT></TT> (deleted)<BR>\n"); } elsif (/^\/(.*)$/) { print_output("<TT>$tmpr$1</TT><BR>\n"); } else { print_output("$_<BR>\n"); } $cnt++; } close (OUT); if ($cnt == 0) { print "<BR>Invalid $meta_str{$ftype} value<BR>\n"; return; } } exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode | '${TASKDIR}file' -z -b -"); my $file_type = <OUT>; close (OUT); $file_type = "Error getting file type" if ((!defined $file_type) || ($file_type eq "")); print "<B>File Type:</B><BR>$file_type<BR>\n"; # MD5 Value exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode | '${TASKDIR}md5'"); my $md5out = <OUT>; close (OUT); $md5out = "Error getting MD5" if ((!defined $md5out) || ($md5out eq "")); chomp $md5out; print "<B>MD5:</B><BR><TT>$md5out</TT><BR>\n"; # Hash Database Lookups if ((($NSRLDB ne "") || ($alert_db ne "") || ($exclude_db ne "")) && ($md5out =~ /^$REG_MD5$/o)) { print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_blank\">\n". make_hidden(). "<INPUT TYPE=\"hidden\" NAME=\"md5\" VALUE=\"$md5out\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HASH_LOOKUP\">\n". "<TABLE CELLPADDING=\"2\" CELLSPACING=\"8\"><TR>\n"; if ($NSRLDB ne "") { print "<TD ALIGN=\"left\">". "<INPUT TYPE=\"checkbox\" NAME=\"hash_nsrl\" VALUE=\"1\" CHECKED>". "NSRL</TD>\n"; } if ($alert_db ne "") { print "<TD ALIGN=\"left\">". "<INPUT TYPE=\"checkbox\" NAME=\"hash_alert\" VALUE=\"1\" CHECKED>". "Alert Database</TD>\n"; } if ($exclude_db ne "") { print "<TD ALIGN=\"left\">". "<INPUT TYPE=\"checkbox\" NAME=\"hash_exclude\" VALUE=\"1\" CHECKED>". "Exclude Database</TD>\n"; } print "<TD ALIGN=\"left\">". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">". "</TD></TR></TABLE>\n</FORM>\n"; } # istat output print "<B>Details:</B><BR>\n"; my $mode = 0; # set to 1 when showing blocks my $force = 0; # set to 1 if size of inode is 0 my @output; if (exists ($args{'force'})) { my $f = get_force(); exec_pipe(*OUT, "'${TASKDIR}istat' -f $ftype -z '$tz' -s $ts -b $f '$img' $inode"); } else { exec_pipe(*OUT, "'${TASKDIR}istat' -f $ftype -z '$tz' -s $ts '$img' $inode"); } while (<OUT>) { if ($mode == 1) { if (/^Indirect Blocks/) { print "$_<BR>\n"; next; } elsif (/^Type: (\S+) \((\d+\-\d+)\) (.*)$/) { print "Type: $1 (". "<A HREF=\"$PROGNAME?func=$FIL_CMENU_FR&$baseargs". "&inode=$inode_int-$2&dir=$args{'img'}-inode-$inode_int-$2\" ". "TARGET=\"_blank\">$2</A>) $3<BR>\n"; next; } my $blk; foreach $blk (split (/ /, $_)) { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$BLK_MAIN&". "$baseargs&block=$blk\" TARGET=\"_blank\">$blk</A> "; } print "<BR>\n"; } else { if (/^Not Allocated$/) { print "<FONT COLOR=\"$DEL_COLOR[0]\">$_</FONT><BR>\n"; } else { print "$_<BR>\n"; } $mode = 1 if (/^Direct Blocks|^Sectors/); $mode = 1 if (/^Attributes/); if ((/^size: (\d+)/) && ($1 == 0)) { $force = 1; } } } close (OUT); # display a text box to force X number of blocks to be displayed if ($force == 1) { print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". make_hidden(). "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"inode\" VALUE=\"$inode\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$INO_CONT\">\n"; print "Enter number of $addr_unit{$ftype}s to display: <INPUT TYPE=\"TEXT\" ". "VALUE=5 NAME=\"force\" SIZE=\"3\">\n"; print "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_force.jpg\" ". "WIDTH=53 HEIGHT=20 ALT=\"Force\" BORDER=\"0\"> (because the size is 0)\n</FORM>\n"; } }; $funcs[$INO_FFIND] = sub { check_inode('inode'); print_html_header("Find File"); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); my $tmpr = $args{'mnt'}; print "<B>Pointed to by file:</B><BR>\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}ffind' -f $ftype -a '$img' $inode"); while (<OUT>) { chop ; if (/(\*)\s+\/*(.*)/) { print_output("<TT><FONT COLOR=\"$DEL_COLOR[0]\">$tmpr$2</FONT></TT> (deleted)<BR>\n"); } elsif (/^\/(.*)$/) { print_output("<TT>$tmpr$1</TT><BR>\n"); } else { print_output("$_<BR>\n"); } } close (OUT); }; $funcs[$INO_SAVE] = sub { check_inode('inode'); print_oct_header(); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); log_host_inv ("$args{'img'}: Saving contents of $meta_str{$ftype} $inode"); print "Content-Disposition: inline; filename=$args{'img'}". "-inode$inode.raw;\n\n"; local *OUT; exec_pipe(*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode"); print "$_" while (<OUT>); close (OUT); # exit instead of return so we don't get \n\n at the end exit(0); }; $funcs[$INO_REP] = sub { check_inode('inode'); print_text_header(); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); log_host_inv ("$args{'img'}: Generating report for $meta_str{$ftype} $inode"); print "Content-Disposition: inline; ". "filename=$args{'img'}-inode$inode.txt;\n\n"; print " Autopsy $meta_str{$ftype} Report (ver $VER)\n\n". "-" x 62 ."\n". "$meta_str{$ftype}: $args{'inode'}\n"; print "Pointed to by file:\n"; my $tmpr = $args{'mnt'}; local *OUT; exec_pipe(*OUT, "'${TASKDIR}ffind' -f $ftype -a '$img' $inode"); while (<OUT>) { chop ; if (/^(\*)\s+\/*(.*)$/) { print_output(" $tmpr$2 (deleted)\n"); } elsif (/^\/(.*)$/) { print_output(" $tmpr$1\n"); } else { print_output(" $_\n"); } } close(OUT); exec_pipe(*OUT, "'${TASKDIR}istat' -f $ftype -z '$tz' -s $ts '$img' $inode | '${TASKDIR}md5'"); my $md5 = <OUT>; close (OUT); $md5 = "Error getting MD5 Value" if ((!defined $md5) || ($md5 eq "")); chop $md5; print "MD5 of istat output: $md5\n"; print "Image: $img\n"; print "Image Type: $ftype\n"; my $date = localtime(); print "Date Generated: $date\n". "Investigator: $args{'inv'}\n". "-" x 62 ."\n"; exec_pipe(*OUT, "'${TASKDIR}istat' -f $ftype -z '$tz' -s $ts '$img' $inode"); while (<OUT>) { print "$_"; } close (OUT); exec_pipe (*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode | '${TASKDIR}file' -z -b -"); my $file_type = <OUT>; close (OUT); $file_type = "Error getting file type" if ((!defined $file_type) || ($file_type eq "")); print "\nFile Type: $file_type"; print "\n"."-" x 62 ."\n"; return 0; }; # Display the Inode Allocation Table $funcs[$INO_ILS] = sub { my $ILS_GAP = 500; my $ftype = get_ftype(); my $img = get_img('img'); my $min = 0; $min = get_min() if (exists $args{'min'}); my $max = $min + $ILS_GAP - 1; # Because we can not use inodes 0 and 1 for most FS, set fmin to the # minimum for this fs my $fmin = $min; $fmin = $first_inode{$ftype} if ($min < $first_inode{$ftype}); print_html_header("$meta_str{$ftype} Allocation List $fmin -> $max"); log_host_inv ("$args{'img'}: $meta_str{$ftype} Allocation List for $min to $max"); print "<CENTER><H2>$meta_str{$ftype}: $fmin - $max</H2>"; # Display next and previous links my $tmp; print "<FONT SIZE=3>\n"; if ($min > $first_inode{$ftype}) { $tmp = $min - $ILS_GAP; print "<A HREF=\"$PROGNAME?func=$INO_ILS&$baseargs&min=$tmp\">". "<IMG SRC=\"pict/but_prev.jpg\" ALT=\"previous\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A> "; } $tmp = $min + $ILS_GAP; print " <A HREF=\"$PROGNAME?func=$INO_ILS&$baseargs&min=$tmp\">". "<IMG SRC=\"pict/but_next.jpg\" ALT=\"next\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A><BR>"; print "</FONT></CENTER>\n"; # The list local *OUT; exec_pipe (*OUT, "'${TASKDIR}ils' -e -s $ts -f $ftype '$img' $fmin-$max"); while (<OUT>) { if (/^($REG_INODE)\|([af])\|\d+\|\d+\|\d+\|\d+\|\d+\|/o) { print "<A HREF=\"$PROGNAME?func=$INO_CONT&$baseargs&inode=$1\">". "$1:</A> "; if ($2 eq "a") { print "allocated<BR>\n"; } else { print "<FONT COLOR=\"$DEL_COLOR[0]\">free</FONT><BR>\n"; } } } close (OUT); # Display next and previous links print "<CENTER><FONT SIZE=3>\n"; if ($min > $first_inode{$ftype}) { $tmp = $min - $ILS_GAP; print "<A HREF=\"$PROGNAME?func=$INO_ILS&$baseargs&min=$tmp\">". "<IMG SRC=\"pict/but_prev.jpg\" ALT=\"previous\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A> "; } $tmp = $min + $ILS_GAP; print " <A HREF=\"$PROGNAME?func=$INO_ILS&$baseargs&min=$tmp\">". "<IMG SRC=\"pict/but_next.jpg\" ALT=\"next\" ". "WIDTH=\"89\" HEIGHT=20 BORDER=\"0\"></A><BR>"; print "</FONT></CENTER>\n"; }; ############ SEARCHING ################## my $CASE_INSENS = 1; my $CASE_SENS = 0; my $REG_EXP = 1; my $STRING = 0; # Form to enter search data $funcs[$SRCH_ENT] = sub { print_html_header("Search on $args{'img'}"); print "<CENTER><H3>Keyword Search on <TT>$args{'img'}</TT></H3>\n"; print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "Enter String: <INPUT TYPE=\"text\" NAME=\"str\"><BR><BR>\n". make_hidden(). "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$SRCH_RMAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"checkbox\" NAME=\"srch_case\" VALUE=\"$CASE_INSENS\">". "Case Insensitive\n". "<INPUT TYPE=\"checkbox\" NAME=\"regexp\" VALUE=\"$REG_EXP\">". "Regular Expression<BR><BR>\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_srch.jpg\" ". "ALT=\"Search\" BORDER=\"0\">\n</FORM>\n"; my $ftype = get_ftype(); print "<TABLE WIDTH=600><TR>\n"; # If we are a non-dls image and one exists - make a button to load it if ( ($ftype ne 'dls') && (exists $img2dls{$args{'img'}}) ) { print "<TD ALIGN=CENTER WIDTH=200>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$MAIN_FR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mode\" VALUE=\"$SRCH_MAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$img2dls{$args{'img'}}\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_lun.jpg\" ". "ALT=\"Load Unallocated Image\" BORDER=\"0\">\n<BR></FORM></TD>\n"; } # If we are a dls and the original exists - make a button to load it elsif ( ($ftype eq 'dls') && (exists $mod2img{$args{'img'}}) ) { print "<TD ALIGN=CENTER WIDTH=200>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$MAIN_FR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mode\" VALUE=\"$SRCH_MAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$mod2img{$args{'img'}}\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_lorig.jpg\" ". "ALT=\"Load Original Image\" BORDER=\"0\">\n<BR></FORM></TD>\n"; } # Strings Button if (!(exists $img2str{$args{'img'}})) { my $dest_img = $args{'img'}; $dest_img = $mod2img{$args{'img'}} if exists ($mod2img{$args{'img'}}); print "<TD ALIGN=CENTER WIDTH=200>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_DETAILS\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$dest_img\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_str.jpg\" ". "ALT=\"Extract Strings\" BORDER=\"0\">\n<BR></FORM></TD>\n"; } # Unallocated Space Button if (($ftype ne 'dls') && ($ftype ne 'swap') && ($ftype ne 'raw') && (!(exists $img2dls{$args{'img'}}))) { print "<TD ALIGN=CENTER WIDTH=200>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_DETAILS\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/srch_b_un.jpg\" ". "ALT=\"Extract Unallocated Space\" BORDER=\"0\">\n<BR></FORM></TD>\n"; } print "</TR></TABLE>\n"; print "<A HREF=\"help/grep.html\" TARGET=\"_new\">". "grep cheat sheet</A>\n<BR><BR>\n"; print "<P><FONT COLOR=\"red\">NOTE:</FONT> The keyword search runs ". "<TT>grep</TT> on the image.<BR>\n". "A list of what will and ". "what will not be found is available ". "<A HREF=\"help/grep_lim.html\" TARGET=\"_new\">here</A>.<BR>\n"; # Section for previous searches my $srch_name = get_srch_file(0); if (-e $srch_name) { print "<HR><H3>Previous Searches</H3>\n". "<TABLE WIDTH=600>\n"; my $row_idx = 0; # Cycle through the files for (my $srch_idx = 0; ;$srch_idx++) { $srch_name = get_srch_file($srch_idx); last unless (-e $srch_name); # Open the file to get the string and count unless (open (SRCH, "$srch_name")) { print "Error opening search file: $srch_name\n"; return 1; } my $prev_str = ""; my $prev_cnt = 0; while (<SRCH>) { unless (/^(\d+)\|(.*?)?\|(.*)$/) { print "Error pasing header of search file: $srch_name\n"; return 1; } $prev_cnt = $1; $prev_str = $3; if (length ($prev_str) > 32) { $prev_str = substr($prev_str, 0, 32); $prev_str .= "..."; } last; } close (SRCH); print "<TR>\n" if ($row_idx == 0); print " <TD ALIGN=CENTER WIDTH=150>\n". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$SRCH_RMAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"srchidx\" VALUE=\"$srch_idx\">\n". make_hidden(); print "<INPUT TYPE=\"SUBMIT\" VALUE=\"$prev_str ($prev_cnt)\">". "<BR></FORM>\n"; if ($row_idx == 3) { print "</TR>\n"; $row_idx = 0; } else { $row_idx++; } } print "</TABLE>\n"; } # Predefined expressions from search.pl print "<HR><H3>Predefined Searches</H3>\n"; print "<TABLE WIDTH=600>\n"; my $row_idx = 0; my $r; foreach $r (keys %auto_srch) { $auto_srch_reg{$r} = 0 unless (defined $auto_srch_reg{$r}); $auto_srch_csense{$r} = 1 unless (defined $auto_srch_csense{$r}); print "<TR>\n" if ($row_idx == 0); print " <TD ALIGN=CENTER WIDTH=150>\n". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$SRCH_RMAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"str\" VALUE=\"$auto_srch{$r}\">\n". make_hidden(); if ($auto_srch_reg{$r} == 1) { print "<INPUT TYPE=\"hidden\" NAME=\"regexp\" VALUE=\"$REG_EXP\">\n"; } if ($auto_srch_csense{$r} == 0) { print "<INPUT TYPE=\"hidden\" NAME=\"srch_case\" VALUE=\"$CASE_INSENS\">\n"; } print "<INPUT TYPE=\"SUBMIT\" VALUE=\"$r\"><BR></FORM>\n". " </TD>\n"; if ($row_idx == 3) { print "</TR>\n"; $row_idx = 0; } else { $row_idx++; } } print "</TABLE>\n"; return 0; }; # MAIN WITH RESULTS # Page that makes frame with the results on left and data units on right $funcs[$SRCH_RMAIN] = sub { # A string was given for a new search if (exists $args{'str'}) { check_str(); print_html_header_frameset("Search on $args{'img'} for $args{'str'}"); print "<FRAMESET COLS=\"35%,65%\">\n"; my $srch_case = ""; $srch_case = "&srch_case=$args{'srch_case'}" if (exists $args{'srch_case'}); my $regexp = ""; $regexp = "®exp=$args{'regexp'}" if (exists $args{'regexp'}); # Block List print "<FRAME SRC=\"$PROGNAME?func=$SRCH_DOSRCH&". "$baseargs$srch_case$regexp&str=$enc_args{'str'}\">\n"; } elsif (exists $args{'srchidx'}) { check_srchidx(); print_html_header_frameset("Search on $args{'img'} for Index $args{'idx'}"); print "<FRAMESET COLS=\"35%,65%\">\n"; # Block List print "<FRAME SRC=\"$PROGNAME?func=$SRCH_READSRCH&". "$baseargs&srchidx=$enc_args{'srchidx'}\">\n"; } # Block Contents print "<FRAME SRC=\"$PROGNAME?func=$BLANK&$baseargs\" NAME=\"content\">\n". "</FRAMESET>\n"; return 0; }; # Find an empty file to save the keyword searches to sub find_srch_file { my $tmp_img = $args{'img'}; $tmp_img =~ tr/\//\-/; my $out_name = "${host_dir}${DATADIR}/$tmp_img"; my $i; for ($i = 0; -e "${out_name}-${i}.srch"; $i++) { } return "${out_name}-${i}.srch"; } # Pass the index and get the full path of the file returned sub get_srch_file { my $idx = shift; my $tmp_img = $args{'img'}; $tmp_img =~ tr/\//\-/; return "${host_dir}${DATADIR}/$tmp_img-${idx}.srch"; } $funcs[$SRCH_READSRCH] = sub { check_srchidx(); print_html_header(""); my $srch_name = get_srch_file($args{'srchidx'}); unless (open (SRCH, "$srch_name")) { print "Error opening search file: $srch_name\n"; return 1; } my @results; my $prev_str = ""; my $grep_flag = ""; while (<SRCH>) { if ($. == 1) { unless (/^(\d+)\|(.*?)?\|(.*)$/) { print "Error pasing header of search file: $srch_name\n"; return 1; } $grep_flag = $2; $prev_str = $3; } else { push @results, "$_"; } } close (SRCH); print_srch_results($prev_str, $grep_flag, \@results, $srch_name); return 0; }; # performs actual search, saves hits to file, and calls method to print $funcs[$SRCH_DOSRCH] = sub { check_str(); print_html_header(""); my $img = get_img('img'); my $ftype = get_ftype(); my $orig_str = get_str(); my $grep_str = $orig_str; # we will escape some values in the grep ver # Check for a search string if ($orig_str eq "") { print "You must enter a string value to search<BR>\n"; print "<B><A HREF=\"$PROGNAME?func=$SRCH_ENT&$baseargs\" ". "TARGET=\"_parent\">New Search</A></B>\n<P>"; return 1; } my $log = ""; # Log entry string my $grep_flag = ""; # Flags to pass to grep # Check if search is case insensitive my $case = 0; if ((exists $args{'srch_case'}) && ($args{'srch_case'} == $CASE_INSENS)) { $grep_flag = "-i"; $case = 1; $log .= "Case Insensitive "; } # Check if search is a regular expression my $regexp = 0; if ((exists $args{'regexp'}) && ($args{'regexp'} == $REG_EXP)) { $grep_flag .= " -E"; $regexp = 1; $log .= "Regular Expression "; } # if not a reg-exp, we need to escape some special values that # 'grep' will misinterpret else { $grep_str =~ s/\\/\\\\/g; # \ $grep_str =~ s/\./\\\./g; # . $grep_str =~ s/\[/\\\[/g; # [ $grep_str =~ s/\^/\\\^/g; # ^ $grep_str =~ s/\$/\\\$/g; # $ $grep_str =~ s/\*/\\\*/g; # * # We need to add ' to end begin and end of the search as well if ($grep_str =~ /\'/) { $grep_str =~ s/\'/\\\'/g; # ' $grep_str = "'$grep_str'"; } $grep_str =~ s/^\-/\\\-/; # starting with - (mistakes for an arg) } log_host_inv ("$args{'img'}: ${log}search for $grep_str"); # Get the addressable unit of image my $bs = get_unitsize(); local *OUT; my $hit_cnt = 0; $SIG{ALRM} = sub { if (($hit_cnt++ % 5) == 0) { print "+"; } else { print "-"; } alarm(5); }; alarm(5); print "<B>Searching</B>: "; # if the string is less than 4 chars, then it will not be in the # strings file so it will be searched for the slow way if (length($orig_str) < 4) { my $ltmp = length ($orig_str); exec_pipe (*OUT, "'$STRINGS_EXE' -t d -n $ltmp '$img' | '$GREP_EXE' $grep_flag '$grep_str'"); } # Use the strings file if it exists elsif (defined $img2str{$args{'img'}}) { my $str_img = "${host_dir}/$img2str{$args{'img'}}"; exec_pipe (*OUT, "'$GREP_EXE' $grep_flag '$grep_str' '$str_img'"); } # Run strings on the image first and then grep that else { exec_pipe (*OUT, "'$STRINGS_EXE' -a -t d '$img' | '$GREP_EXE' $grep_flag '$grep_str'"); } # $norm_str is normalized to find the "hit" in the output my $norm_str = $orig_str; # make this lowercase if we are doing case insens $norm_str =~ tr/[A-Z]/[a-z]/ if ($case == 1); my $norm_str_len = length ($norm_str); # array to pass to printing method my @results; # Cycle through the results and put them in an array while (<OUT>) { # print "." if (scalar (@results) % $STATUS == 0); # Parse out the byte offset and hit string if (/^\s*(\d+)\s+(.+)$/) { my $off = $1; my $hit_str_orig = $2; my $idx = 0; # Make a copy that we can modify & play with my $hit_str = $hit_str_orig; $hit_str =~ tr/[A-Z]/[a-z]/ if ($case == 1); # How long was the string that we hit? my $hit_str_len = length ($hit_str); # I'm not sure how to find a grep re in the hit yet, so # for now we do not get the exact offset if ($regexp) { my $b = int ($off / $bs); my $o = int ($off % $bs); # $hit =~ s/\n//g; push @results, "${b}|${o}|"; next; } # There could be more than one keyword in the string # so cylcle through all of them my $psize = scalar (@results); while (($idx = index ($hit_str, $norm_str, $idx)) > -1) { my $b = int (($off + $idx) / $bs); my $o = int (($off + $idx) % $bs); # The summary of the hit starts 5 chars before it my $sum_min = $idx - 5; $sum_min = 0 if ($sum_min < 0); # Goto 5 after, if there is still space my $sum_max = $idx + $norm_str_len + 5; $sum_max = $hit_str_len if ($sum_max > $hit_str_len); my $sum_hit = substr ($hit_str_orig, $sum_min, $sum_max - $sum_min); # remove new lines $sum_hit =~ s/\n/ /g; push @results, "${b}|${o}|$sum_hit"; # advance index to find next hit $idx++; } # If we did not find a term, then just print what # was found-this occurs bc index does not find it # sometimes. if ($psize == scalar(@results)) { my $b = int ($off / $bs); my $o = int ($off % $bs); # $hit =~ s/\n//g; push @results, "${b}|${o}|"; next; } } # A negative offset is common on FreeBSD with large images elsif (/^\s*(\-\d+):?\s*(.+)$/) { print "ERROR: Negative byte offset ($1) Your version of ". "strings likely does not support large files: $2<BR>\n"; } else { print "Error parsing grep result: $_<BR>\n"; } } close (OUT); $SIG{ALRM} = 'DEFAULT'; print " <B>Done</B><BR>"; print "<B>Saving</B>: "; # Find a file to save the results to my $srch_name = find_srch_file(); unless (open(IDX, ">$srch_name")) { print "Error opening $srch_name\n"; return (1); } # Print the header my $cnt = scalar(@results); print IDX "$cnt|${grep_flag}|${orig_str}\n"; for (my $i = 0; $i < $cnt; $i++) { # print "." if ($i % $STATUS == 0); print IDX "$results[$i]\n"; } close (IDX); print " <B>Done</B><HR>\n"; print_srch_results($grep_str, $grep_flag, \@results, $srch_name); return 0; }; # Args are search string, grep flags, and array of hits sub print_srch_results { if (scalar (@_) != 4) { print "Missing Args for print_srch_results()\n"; return 1; } my $grep_str = shift(); my $grep_flag = shift(); my @results = @{shift()}; my $srch_name = shift(); my $cnt = scalar(@results); my $ftype = get_ftype(); my $addr_str = $addr_unit{$ftype}; print "<B><A HREF=\"$PROGNAME?func=$SRCH_ENT&$baseargs\" ". "TARGET=\"_parent\">New Search</A></B>\n<P>"; my $grep_str_html = html_encode($grep_str); if ($cnt == 0) { print "<B><TT>$grep_str_html</TT> was not found</B><BR>\n"; } elsif ($cnt == 1) { print "<B>1 occurrence of <TT>$grep_str_html</TT> was found</B><BR>\n"; } else { print "<B>$cnt occurrences of <TT>$grep_str_html</TT> were found</B><BR>\n"; } print "Search Options:<BR>\n"; if ($grep_flag =~ /\-i/) { print " Case Insensitive<BR>\n"; } else { print " Case Sensitive<BR>\n"; } if ($grep_flag =~ /\-E/) { print " Regular Expression<BR>\n"; } print "<HR>\n"; if ($cnt > 1000) { print "There were more than <U>1000</U> hits.<BR>\n"; print "Please revise the search to a managable amount.\n"; print "<P>The $cnt hits can be found in: <TT>$srch_name</TT><BR>\n"; print "<P><B><A HREF=\"$PROGNAME?func=$SRCH_ENT&$baseargs\" ". "TARGET=\"_parent\">New Search</A></B>\n<P>"; return 0; } my $prev = -1; for (my $i = 0; $i < $cnt; $i++) { unless ($results[$i] =~ /^(\d+)\|(\d+)\|(.*)?$/) { print "Error parsing search array: $results[$i]\n"; return 1; } my $blk = $1; my $off = $2; my $str = $3; if ($blk != $prev) { my $url="$PROGNAME?func=$BLK_CMENU_FR&$baseargs&block=$blk"; print "<BR>\n$addr_str $blk (<A HREF=\"$url&sort=$BLK_SORT_HEX\" ". "TARGET=content>Hex</A> - ". "<A HREF=\"$url&sort=$BLK_SORT_ASC\" TARGET=content>". "Ascii</A>"; print " - <A HREF=\"$PROGNAME?$baseargs&func=$BLK_CMENU_FR&". "mnt=$enc_args{'mnt'}&img=$mod2img{$args{'img'}}&". "btype=$BTYPE_DLS&block=$blk\" TARGET=content>Original</A>" if (($ftype eq 'dls') && (exists $mod2img{$args{'img'}})); print ")<BR>"; $prev = $blk; } my $occ = $i + 1; if ($str ne "") { $str = html_encode($str); print "$occ: $off (<TT>$str</TT>)<BR>\n"; } else { print "$occ: $off<BR>\n"; } } return 0; } # Make a strings -t d file for the image to decrease the search time $funcs[$IMG_MAKESTR] = sub { check_fname(); check_fname_mode(); print_html_header(""); my $fname = get_fname(); my $fname_rel = get_fname_rel(); my $mode = $args{'fname_mode'}; my $ftype = get_ftype(); if ((-e "$fname") && ($FNAME_MODE_INIT == $mode)) { print "File Already Exists: $fname_rel\n"; my $hidden = "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_MAKESTR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". make_hidden(); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"md5\" VALUE=\"$args{'md5'}\">\n" if (exists $args{'md5'}); print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "New Name: <INPUT TYPE=\"text\" NAME=\"fname\">\n". "<TABLE CELLSPACING=\"30\" CELLPADDING=\"2\"><TR><TD>". "$hidden". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_new_name.jpg\" ". "WIDTH=79 HEIGHT=20 ALT=\"Use New Name\" BORDER=\"0\">\n". "</FORM></TD>\n"; print "<TD><FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "$hidden". "<INPUT TYPE=\"hidden\" NAME=\"fname\" VALUE=\"$args{'fname'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_OVER\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_replace.jpg\" ". "WIDTH=66 HEIGHT=20 ALT=\"Replace\" BORDER=\"0\">\n". "</FORM></TD></TR></TABLE>"; return 0; } my $img = get_img('img'); print "Extracting strings from <TT>$args{'img'}</TT> and saving to ". "<TT>$args{'fname'}</TT><BR><BR>\n"; log_host_inv ("$args{'img'}: Saving ASCII strings to $fname_rel"); local *OUT; exec_pipe (*OUT, "'$STRINGS_EXE' -a -t d '$img' > '$fname'"); print $_ while (<OUT>); close (OUT); # Verify that it worked unless (open (STR, "$fname")) { print "Error opening $fname<BR>\n". "Either an error occurred while generating the file or ". "no ASCII strings exist"; return (1); } my $sz = 0; while (<STR>) { unless (/^\s*\d+\s+\S.*$/) { print ("Error making strings file: $_"); return (1); } $sz = 1; last; } if ($sz == 0) { print "Strings file has no valid entries, there could be no ASCII". " strings in the original image"; print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_DETAILS\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>"; return (1); } close (STR); # append to config update_host_config("strings", $fname_rel, "$args{'img'}"); print "<TT>$fname_rel</TT> added to host config file<BR><BR>"; $img2ftype{$fname_rel} = "strings"; $mod2img{$fname_rel} = $args{'img'}; $img2str{$args{'img'}} = $fname_rel; # Calculate MD5 if ((exists $args{'md5'}) && ($args{'md5'} == 1)) { print "Calculating MD5 Value<BR><BR>\n"; my $m = int_create_wrap ($fname, $fname_rel); print "MD5 Value: <TT>$m</TT><BR><BR>\n"; } my $dest_img = $args{'img'}; # We need to return with a real image to IMG_DETAILS so check the mod $dest_img = $mod2img{$args{'img'}} if (defined $mod2img{$args{'img'}}); print "<A HREF=\"$PROGNAME?$baseargs_noimg&func=$IMG_DETAILS&". "img=$dest_img\" TARGET=_top>Image Details</A><P>\n"; print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$SRCH_MAIN&$baseargs\"". " TARGET=\"_top\">Keyword Search</A>\n"; return 0; }; $funcs[$IMG_MAKEDLS] = sub { check_fname(); check_fname_mode(); print_html_header(""); my $fname = get_fname(); my $fname_rel = get_fname_rel(); my $mode = $args{'fname_mode'}; if ((-e "$fname") && ($FNAME_MODE_INIT == $mode)) { print "File Already Exists: $fname_rel\n"; my $hidden = "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$IMG_MAKEDLS\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". make_hidden(); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"md5\" VALUE=\"$args{'md5'}\">\n" if (exists $args{'md5'}); print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "New Name: <INPUT TYPE=\"text\" NAME=\"fname\"> ". "<TABLE CELLSPACING=\"30\" CELLPADDING=\"2\"><TR><TD>". "$hidden". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_new_name.jpg\" ". "WIDTH=79 HEIGHT=20 ALT=\"Use New Name\" BORDER=\"0\">\n". "</FORM></TD>\n"; print "<TD><FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_replace.jpg\" ". "WIDTH=66 HEIGHT=20 ALT=\"Replace\" BORDER=\"0\"><BR>\n". "$hidden". "<INPUT TYPE=\"hidden\" NAME=\"fname\" VALUE=\"$args{'fname'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_OVER\">\n". "</FORM></TD></TR></FORM>"; return 0; } my $img = get_img('img'); my $ftype = get_ftype(); log_host_inv ("$args{'img'}: Saving unallocated data to $fname_rel"); print "Extracting unallocated data from <TT>$args{'img'}</TT> and ". "saving to <TT>$fname_rel</TT><BR><BR>\n"; local *OUT; exec_pipe (*OUT, "'${TASKDIR}dls' -f $ftype '$img' > '$fname'"); print "$_" while (<OUT>); close (OUT); # append to fsmorgue update_host_config("dls", $fname_rel, $args{'img'}); print "<TT>$fname_rel</TT> added to host config file<BR><BR>"; $img2ftype{$fname_rel} = "dls"; $mod2img{$fname_rel} = $args{'img'}; $img2dls{$args{'img'}} = $fname_rel; # Calculate MD5 if ((exists $args{'md5'}) && ($args{'md5'} == 1)) { print "Calculating MD5 Value<BR><BR>\n"; my $m = int_create_wrap ($fname, $fname_rel); print "MD5 Value: <TT>$m</TT><BR><BR>\n"; } print "<A HREF=\"$PROGNAME?$baseargs&func=$IMG_DETAILS\"". " TARGET=_top>Image Details</A><P>\n"; print "<A HREF=\"$PROGNAME?func=$MAIN_FR&mode=$SRCH_MAIN&$baseargs_noimg&". "img=$fname_rel\" TARGET=\"_top\">Keyword Search</A>\n"; return 0; }; ############ FILE SYSTEM ################## $funcs[$FS_STAT] = sub { print_html_header("File System Status"); log_host_inv ("$args{'img'}: Displaying file system details"); my $img = get_img('img'); my $ftype = get_ftype(); my $fat = 0; local *OUT; exec_pipe (*OUT, "'${TASKDIR}fsstat' -f $ftype '$img'"); while (<OUT>) { # Special case for FAT # We will be giving hyperlinks in the FAT table dump if ($fat == 1) { # Ignore the divider if (/\-\-\-\-\-\-\-\-\-\-/) { print "$_<BR>"; next; } if (/^((\d+)\-\d+\s+\((\d+)\)) \-\> ([\w]+)$/) { my $full = $1; my $blk = $2; my $len = $3; my $next = $4; # Print the tag so that other FAT entries can link to it print "<A NAME=\"$blk\">\n"; print "<A HREF=\"$PROGNAME?$baseargs&func=$MAIN_FR&mode=$BLK_MAIN&". "block=$blk&len=$len\" TARGET=\"_blank\">$full</A> -> "; if ($next eq 'EOF') { print "EOF<BR>\n"; } else { print "<A HREF=\"#$next\">$next</A><BR>\n"; } } else { $fat = 0; print "$_<BR>"; } } else { print "$_<BR>"; } # Set the flag if we reach the FAT $fat = 1 if (($ftype =~ /fat/) && ($_ =~ /FAT CONTENTS/)); } close (OUT); }; ############ INTEGRITY CHECKS ################## # Special func for printing integrity check menu # We show any file that we have a reference for # pass the md5 hash (from md5.txt) and then the sorted array sub int_menu_print { my %md5s = %{$_[0]}; my @sort = @{$_[1]}; for (my $i = 0; $i <= $#sort; $i++) { print "<TR><TD ALIGN=\"right\"><TT><B>$sort[$i]</B></TT></TD>\n"; # It already exists, so make verify button if (exists $md5s{$sort[$i]}) { print "<TD><TT>$md5s{$sort[$i]}</TT></TD>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"cont\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$sort[$i]\">\n". make_hidden(). "<TD><INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$INT_CHECK\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/int_b_valid.jpg\" ". "ALT=\"Validate\" BORDER=\"0\">\n". "</FORM></TD></TR>\n"; } # Generate New button else { print "<TD> </TD><TD>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"cont\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$sort[$i]\">\n". make_hidden(). "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$INT_CREATE\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/int_b_calc.jpg\" ". "ALT=\"Calculate\" BORDER=\"0\">\n". "</FORM></TD></TR>\n"; } } return; }; # Create a frame with two rows, one with the list of images to check # and then the bottom actually does it. $funcs[$INT_LIST_FR] = sub { print_html_header_frameset("$args{'case'}:$args{'host'} Integrity Check"); print "<FRAMESET ROWS=\"80%,20%\">\n"; # Block List print "<FRAME SRC=\"$PROGNAME?func=$INT_LIST&$baseargs\">\n"; print "<FRAME SRC=\"$PROGNAME?func=$BLANK\" NAME=\"cont\">\n"; print "</FRAMESET>\n"; return 0; }; # Reads the MD5 file to fill in the MENU list for the integrity # check mode $funcs[$INT_LIST] = sub { print_html_header("Image Integrity Menu"); my %md5s; my @dls; my @str; my @fs; my @body; my @tl; # Read the known values if the file exists if (open (FILE, "${host_dir}${IMGDIR}/$MD5_FILE")) { # Read the md5 values into a hash while (<FILE>) { s/^\s+//; s/\s+$//; if (/($REG_MD5)\s+(.*)/o) { $md5s{"$2"} = $1; $md5s{"$2"} =~ tr/[a-f]/[A-F]/; } else { print "Error reading line $. of $MD5_FILE: $_<BR>\n"; return 1; } } close (FILE); } if (open (FILE, "${host_dir}${DATADIR}/$MD5_FILE")) { # Read the md5 values into a hash while (<FILE>) { s/^\s+//; s/\s+$//; if (/($REG_MD5)\s+(.*)/o) { $md5s{"$2"} = $1; $md5s{"$2"} =~ tr/[a-f]/[A-F]/; } else { print "Error reading line $. of $MD5_FILE: $_<BR>\n"; return 1; } } close (FILE); } # sort the images into the different types foreach my $k (keys %img2ftype) { if ($img2ftype{$k} eq "dls") { push @dls, $k; } elsif ($img2ftype{$k} eq "strings") { push @str, $k; } elsif ($img2ftype{$k} eq "body") { push @body, $k; } elsif ($img2ftype{$k} eq "timeline") { push @tl, $k; } else { push @fs, $k; } } print "<CENTER><TABLE CELLSPACING=\"10\" CELLPADDING=\"2\">"; # File system images if (scalar @fs > 0) { print "<TR><TH COLSPAN=3>". "<IMG SRC=\"pict/int_h_img.jpg\" ALT=\"File System Images\">". "</TH></TR>\n"; my @sort = sort {$a cmp $b} @fs; int_menu_print (\%md5s, \@sort); } # Unallocated (dls) images if (scalar @dls > 0) { print "<TR><TH COLSPAN=3> </TH></TR>\n". "<TR><TH COLSPAN=3>". "<IMG SRC=\"pict/int_h_unalloc.jpg\" ALT=\"Unallocated Data Files\">". "</TH></TR>\n"; my @sort = sort {$a cmp $b} @dls; int_menu_print (\%md5s, \@sort); } # Strings files (of dls or fs images) if (scalar @str > 0) { print "<TR><TH COLSPAN=3> </TH></TR>\n". "<TR><TH COLSPAN=3>". "<IMG SRC=\"pict/int_h_str.jpg\" ALT=\"Strings of Images\">". "</TH></TR>\n"; my @sort = sort {$a cmp $b} @str; int_menu_print (\%md5s, \@sort); } # timeline body files if (scalar @body > 0) { print "<TR><TH COLSPAN=3> </TH></TR>\n". "<TR><TH COLSPAN=3>". "<IMG SRC=\"pict/int_h_data.jpg\" ALT=\"Timeline Data Files\">". "</TH></TR>\n"; my @sort = sort {$a cmp $b} @body; int_menu_print (\%md5s, \@sort); } # timeline files if (scalar @tl > 0) { print "<TR><TH COLSPAN=3> </TH></TR>\n". "<TR><TH COLSPAN=3>". "<IMG SRC=\"pict/int_h_tl.jpg\" ALT=\"Timelines\">". "</TH></TR>\n"; my @sort = sort {$a cmp $b} @tl; int_menu_print (\%md5s, \@sort); } print <<EOF; </TABLE> <P> <TABLE CELLSPACING=20 WIDTH=600 CELLPADDING=2> <TR> <TD><A HREF=\"$PROGNAME?$baseargs&func=$IMG_OPEN\" TARGET=\"_top\"> <IMG SRC=\"pict/menu_b_ok.jpg\" ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=\"0\"> </A> </TD> <TD><A HREF=\"$PROGNAME?$baseargs&func=$INT_LIST_FR\" TARGET=\"_top\"> <IMG SRC=\"pict/menu_b_ref.jpg\" ALT=\"Refresh\" WIDTH=\"167\" HEIGHT=20 BORDER=\"0\"> </A> </TD> <TD ALIGN=CENTER> <A HREF=\"$HELP_URL\" TARGET=\"_blank\"> <IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" WIDTH=\"167\" HEIGHT=20 BORDER=0> </A> </TD> </TR> </TABLE> EOF return; }; # Pass the relative path (images/xyz) of the file. The MD5 is # returned (or NULL) (in all caps) sub lookup_md5 { my $img = shift; my $md5 = ""; (my $img_dir) = split (/\//,$img); my $md5_file = "${host_dir}${img_dir}/$MD5_FILE"; if (-e "$md5_file") { unless (open (FILE, $md5_file)) { print "Error opening $md5_file<BR>\n"; return ""; } while (<FILE>) { s/^\s+//; s/\s+$//; if (/($REG_MD5)\s+(.*)/o) { my $m = $1; if ($2 =~ /$img$/) { $md5 = $m; $md5 =~ tr/[a-f]/[A-F]/; last; } } else { print "Error reading line $. of $md5_file: $_<BR>\n"; return ""; } } close (FILE); } return $md5; }; $funcs[$INT_CHECK] = sub { # we do a check_img because it was skipped in the main function check_img('img'); print_html_header("Image Integrity Check"); my $md5 = lookup_md5($args{'img'}); if ($md5 eq "") { print "The MD5 value of <TT>$args{'img'}</TT> was not found<BR>". "It can be calculated by pressing the button below.". "<BR><BR>\n<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$INT_CREATE\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/int_b_calc.jpg\" ". "ALT=\"Calculate\" BORDER=\"0\">\n</FORM>"; return 1; } log_host_inv ("$args{'img'}: Checking image integrity"); print "<FONT SIZE=3>Original MD5: <TT>$md5</TT><BR>\n"; # We have the original value, now get the new one my $img = get_img('img'); my $cur = calc_md5($img); if ($cur =~ /^$REG_MD5$/o) { print "Current MD5: <TT>$cur</TT><BR><BR>\n"; if ($cur eq $md5) { print "Pass<BR>\n"; log_host_inv ("$args{'img'}: Image integrity check PASSED"); } else { print "<FONT COLOR=\"$DEL_COLOR[0]\">Fail: Restore from backup". "</FONT><BR>\n"; log_host_inv ("$args{'img'}: Image integrity check FAILED"); } return 0; } else { print "$cur<BR>\n"; return 1; } }; # Calculate the MD5 value of a file (given the full path) # return the value in upper case sub calc_md5 { my $img = shift; my $hit_cnt = 0; $SIG{ALRM} = sub { if (($hit_cnt++ % 5) == 0) { print "+"; } else { print "-"; } alarm(5); }; alarm(5); local *OUT; exec_pipe (*OUT, "'${TASKDIR}md5' '$img'"); my $out = <OUT>; close (OUT); $SIG{ALRM} = 'DEFAULT'; print "\n" if ($hit_cnt > 0); $out = "Error getting MD5" if ((!defined $out) || ($out eq "")); if ($out =~ /($REG_MD5)\s+$img/) { my $m = $1; $m =~ tr/[a-f]/[A-F]/; return $m; } else { return $out; } } # Pass it the full path and the short name # and it adds it to md5.txt and returns the MD5 sub int_create_wrap { my $img = shift; my $name = shift; my $m = calc_md5 ($img); update_md5 ($name, $m) if ($m =~ /^$REG_MD5$/o); return $m; } $funcs[$INT_CREATE] = sub { print_html_header("Image Integrity Creation"); print "Calculating MD5 value for <TT>$args{'img'}</TT><BR>\n"; log_host_inv ("$args{'img'}: Calculating MD5 value"); my $img = get_img('img'); my $m = int_create_wrap ($img, $args{'img'}); print "MD5: <TT>$m</TT><BR>\n"; (my $img_dir) = split (/\//,$args{'img'}); print "<BR>Value added to <TT>${host_dir}${img_dir}/$MD5_FILE</TT><BR><BR>\n"; }; #################################################################### # TIME LINE my %m2d = ("Jan", 1, "Feb", 2, "Mar", 3, "Apr", 4, "May", 5, "Jun", 6, "Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12); my @d2m = ("", "Jan","Feb","Mar","Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); # Call the appropriate function based on the value of sort $funcs[$TL_MAIN] = sub { print_html_header_frameset("Timeline: $args{'case'}:$args{'host'}"); print "<FRAMESET ROWS=\"38,*\">\n"; my $mode = $TL_MAIN; $mode = get_mode() if (exists $args{'mode'}); # Listing print "<FRAME SRC=\"$PROGNAME?func=$TL_TABS&$baseargs&mode=$mode\">\n"; my $str = ""; # Contents if ($mode == $TL_MAIN) { print "<FRAME SRC=\"$PROGNAME?func=$BLANK\" ". "NAME=\"content\">\n</FRAMESET>\n"; return; } # elsif ($mode == $TL_BODY_ENT) elsif ($mode == $TL_TL_ENT) { $str .= "&body=$args{'body'}" if (exists $args{'body'}); } elsif ($mode == $TL_VIEW_FR) { $str .= "&tl=$args{'tl'}" if (exists $args{'tl'}); } # elsif ($mode == $NOTES_MAIN) print "<FRAME SRC=\"$PROGNAME?func=$mode&$baseargs$str\" ". "NAME=\"content\">\n</FRAMESET>\n"; return 0; }; $funcs[$TL_BODY_ENT] = sub { print_html_header(""); my $i; my %mnt2img; # Cycle through each image we read from fsmorgue foreach $i (keys %img2mnt) { next if (($img2ftype{$i} eq "strings") || ($img2ftype{$i} eq "dls") || ($img2ftype{$i} eq "raw") || ($img2ftype{$i} eq "swap")); $mnt2img{"$img2mnt{$i}--$i"} = $i; } # sort via ftype and then mount point (which includes the name) my @mnt = sort { lc($img2ftype{$mnt2img{$a}}) cmp lc($img2ftype{$mnt2img{$b}}) or lc($a) cmp lc($b) } keys %mnt2img; print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_BODY_DOIT\">\n". make_hidden(). "<P>1. Select one or more of the following images to collect data from:\n". "<TABLE CELLSPACING=\"8\" CELLPADDING=\"2\">"; for (my $i = 0; $i <= $#mnt; $i++) { my $img = $mnt2img{$mnt[$i]}; print "<TR><TD><INPUT TYPE=\"checkbox\" NAME=\"$img\" VALUE=\"1\">". "</TD><TD><TT>$img2mnt{$img}</TT></TD><TD><TT>$img</TT></TD>". "<TD>$img2ftype{$img}</TD>\n"; } print "</TABLE><P>2. Select the data types to gather:<BR>\n". "<TABLE CELLSPACING=\"8\" CELLPADDING=\"2\"><TR>". "<TD><INPUT TYPE=\"checkbox\" NAME=\"al_file\" VALUE=\"1\" CHECKED>". "</TD><TD>Allocated Files</TD>". "<TD><INPUT TYPE=\"checkbox\" NAME=\"unal_file\" VALUE=\"1\" CHECKED>". "</TD><TD>Unallocated Files</TD>". "<TD><INPUT TYPE=\"checkbox\" NAME=\"unal_inode\" VALUE=\"1\" CHECKED>". "</TD><TD>Unallocated Meta Data Structures</TD></TR></TABLE>\n". "<P>3. Enter name of output file (<TT>body</TT>):<BR>". "<TT>$DATADIR/</TT>". "<INPUT TYPE=\"text\" NAME=\"fname\" VALUE=\"body\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n". "<P>4. Generate MD5 Value? ". "<INPUT TYPE=\"checkbox\" NAME=\"md5\" VALUE=\"1\" CHECKED>"; print "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\"></FORM>\n"; }; $funcs[$TL_BODY_DOIT] = sub { check_fname(); check_fname_mode(); print_html_header(""); my $fname_rel = get_fname_rel(); my $fname = get_fname(); my $mode = $args{'fname_mode'}; if ((-e "$fname") && ($FNAME_MODE_INIT == $mode)) { print "File Already Exists: $fname_rel\n"; my $hidden = make_hidden(); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"func\" ". "VALUE=\"$TL_BODY_DOIT\">\n"; my $i; foreach $i (%img2mnt) { $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"$i\" VALUE=\"1\">\n" if (exists $args{$i}); } $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"al_file\" ". "VALUE=\"$args{'al_file'}\">\n" if (exists $args{'al_file'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"unal_file\" ". "VALUE=\"$args{'unal_file'}\">\n" if (exists $args{'unal_file'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"unal_inode\" ". "VALUE=\"$args{'unal_inode'}\">\n" if (exists $args{'unal_inode'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"md5\" ". "VALUE=\"$args{'md5'}\">\n" if (exists $args{'md5'}); # Make a new name print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "New Name: <INPUT TYPE=\"text\" NAME=\"fname\">". "<TABLE CELLSPACING=\"30\" CELLPADDING=\"2\"><TR><TD>". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\" >\n". "$hidden". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_new_name.jpg\" ". "WIDTH=79 HEIGHT=20 ALT=\"Use New Name\" BORDER=\"0\">\n". "</FORM></TD>\n"; # Overwrite it print "<TD><FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_replace.jpg\" ". "WIDTH=66 HEIGHT=20 ALT=\"Replace\" BORDER=\"0\"><BR>\n". "<INPUT TYPE=\"hidden\" NAME=\"fname\" VALUE=\"$args{'fname'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_OVER\" >\n". "$hidden". "</FORM></TD></TR></TABLE>"; return 0; } # we will be appending to the file so we should del it now if (-e "$fname") { unlink ($fname); } my $log_files = ""; my $log_type = ""; my $al_file = 0; if (exists $args{'al_file'}) { $al_file = $args{'al_file'}; $log_type .= "Allocated Files"; } my $unal_file = 0; if (exists $args{'unal_file'}) { $unal_file = $args{'unal_file'}; $log_type .= ", " if ($log_type ne ""); $log_type .= "Unallocated Files"; } my $unal_inode = 0; if (exists $args{'unal_inode'}) { $unal_inode = $args{'unal_inode'}; $log_type .= ", " if ($log_type ne ""); $log_type .= "Unallocated Meta Data Structures"; } if (($unal_inode == 0) && ($unal_file == 0) && ($al_file == 0)) { print "No data types were selected. You must select at least one.<BR>\n"; return 1; } my $i; my $found = 0; local *OUT; foreach $i (keys %img2mnt) { if (exists $args{$i}) { $found = 1; my $ftype = $img2ftype{$i}; my $img = $host_dir.$i; my $mnt = $img2mnt{$i}; $log_files .= ", " if ($log_files ne ""); $log_files .= "$i"; if (($al_file) && ($unal_file)) { print "Running <TT>fls -r -m</TT> on <TT>$i</TT><BR>\n"; exec_pipe (*OUT, "'${TASKDIR}fls' -z '$tz' -s $ts -m '$mnt' -f $ftype -r '$img' >> '$fname'"); print "$_<BR>\n" while (<OUT>); close (OUT); } elsif ($al_file) { print "Running <TT>fls -ru -m</TT> on <TT>$i</TT><BR>\n"; exec_pipe (*OUT, "'${TASKDIR}fls' -z '$tz' -s $ts -m '$mnt' -f $ftype -ru '$img' >> '$fname'"); print "$_<BR>\n" while (<OUT>); close (OUT); } elsif ($unal_file) { print "Running <TT>fls -rd -m</TT> on <TT>$i</TT><BR>\n"; exec_pipe (*OUT, "'${TASKDIR}fls' -z '$tz' -s $ts -m '$mnt' -f $ftype -rd '$img' >> '$fname'"); print "$_<BR>\n" while (<OUT>); close (OUT); } if ($unal_inode) { print "Running <TT>ils -m</TT> on <TT>$i</TT><BR>\n"; my $tz_back = ""; $tz_back = $ENV{TZ} if (exists $ENV{TZ}); $ENV{TZ} = $tz; POSIX::tzset(); exec_pipe (*OUT, "'${TASKDIR}ils' -s $ts -m -f $ftype '$img' >> '$fname'"); print "$_<BR>\n" while (<OUT>); close (OUT); $ENV{TZ} = $tz_back; POSIX::tzset(); } } } unless ($found) { print "No images were given for analysis. At least one must be selected.<BR>\n"; return 1; } log_host_inv ("Saving timeline data for $log_type for $log_files to $fname_rel"); # append to host config update_host_config ("body", $fname_rel); print "<BR>Body file saved to <TT>$fname</TT><BR><BR>\n". "Entry added to host config file<BR><BR>\n"; # Calculate MD5 if ((exists $args{'md5'}) && ($args{'md5'} == 1)) { print "Calculating MD5 Value<BR><BR>\n"; my $m = int_create_wrap ($fname, $fname_rel); print "MD5 Value: <TT>$m</TT><BR><BR>\n"; } print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"body\" VALUE=\"$args{'fname'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_MAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mode\" VALUE=\"$TL_TL_ENT\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n"; return 0; }; $funcs[$TL_TL_ENT] = sub { print_html_header(""); my @body; # Find the body files if we will be looking for them unless (exists $args{'body'}) { foreach my $k (keys %img2ftype) { if ($img2ftype{$k} eq "body") { push @body, $k; } } if (scalar(@body) == 0) { print "There are currently no <TT>body</TT> files ". "for this host.<BR>You must create the intermediate ". "data file before you can perform this step<BR>\n". "<P><A TARGET=\"_top\" ". "HREF=\"$PROGNAME?$baseargs&func=$TL_MAIN&mode=$TL_BODY_ENT\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\">". "</A>\n"; return 1; } } print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_TL_DOIT\">\n". make_hidden(). "1. Select the data input file (<TT>body</TT>):\n". "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\">"; # if the body file was specified then just print it if (exists $args{'body'}) { print "<TR><TD><INPUT TYPE=\"radio\" NAME=\"body\" ". "VALUE=\"$args{'body'}\" CHECKED>". "</TD><TD>$args{'body'}</TD>\n"; } else { my @body_sort = sort {lc($a) cmp lc($b)} @body; for (my $i = 0; $i <= $#body_sort; $i++) { (my $img_dir, my $str_img) = split (/\//,$body_sort[$i]); print "<TR><TD><INPUT TYPE=\"radio\" NAME=\"body\" ". "VALUE=\"$str_img\"></TD><TD>$str_img</TD>\n"; } } my $cur_mon = 1 + (localtime())[4]; my $cur_year = 1900 + (localtime())[5]; # STARTING DATE print "</TABLE>\n". "<P>2. Enter the starting date:<BR>\n". "None: <INPUT TYPE=\"radio\" NAME=\"st_none\" VALUE=\"1\" CHECKED><BR>". "Specify: <INPUT TYPE=\"radio\" NAME=\"st_none\" VALUE=\"0\"> ". "<SELECT NAME=\"st_mon\" SIZE=\"1\">"; for my $i (1 .. 12) { if ($i == $cur_mon) { print "<OPTION SELECTED VALUE=\"$i\">$d2m[$i]</OPTION>\n"; } else { print "<OPTION VALUE=\"$i\">$d2m[$i]</OPTION>\n"; } } print "</SELECT>". "<SELECT NAME=\"st_day\" SIZE=\"1\">". "<OPTION SELECTED>1</OPTION>\n"; for my $i (2 .. 31) { print "<OPTION VALUE=\"$i\">$i</OPTION>\n"; } print "</SELECT>". "<INPUT TYPE=\"text\" NAME=\"st_year\" SIZE=\"6\" VALUE=\"$cur_year\">\n"; # END DATE print "<P>3. Enter the ending date:<BR>\n". "None: <INPUT TYPE=\"radio\" NAME=\"end_none\" VALUE=\"1\" CHECKED><BR>\n". "Specify: <INPUT TYPE=\"radio\" NAME=\"end_none\" VALUE=\"0\"> \n". "<SELECT NAME=\"end_mon\" SIZE=\"1\">\n"; for my $i (1 .. 12) { if ($i == $cur_mon) { print "<OPTION SELECTED VALUE=\"$i\">$d2m[$i]</OPTION>\n"; } else { print "<OPTION VALUE=\"$i\">$d2m[$i]</OPTION>\n"; } } print "</SELECT>\n". "<SELECT NAME=\"end_day\" SIZE=\"1\">\n". "<OPTION SELECTED VALUE=\"1\">1</OPTION>\n"; for my $i (2 .. 31) { print "<OPTION VALUE=\"$i\">$i</OPTION>\n"; } print "</SELECT>". "<INPUT TYPE=\"text\" NAME=\"end_year\" SIZE=\"6\" VALUE=\"$cur_year\">\n"; # FILE NAME print "<P>4. Enter the file name to save as:<BR>". "<TT>$DATADIR/</TT><INPUT TYPE=\"text\" SIZE=36 NAME=\"fname\"><BR>\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n"; # Get only the UNIX images - since only they have /etc/passwd and group my @unix_imgs; my $root_img = ""; foreach my $i (keys %img2ftype) { my $f = $img2ftype{$i}; next unless (($f =~ /^linux/) || ($f =~ /bsd$/) || ($f =~ /^solaris$/) || ($f =~ /^bsdi$/)) ; push @unix_imgs, $i; # Keep a reference to an image with '/' as the mounting point $root_img = $i if ($img2mnt{$i} eq '/'); } if (scalar @unix_imgs > 0) { print "<P>5. Select the UNIX image that contains the /etc/passwd and /etc/group files:<BR>\n"; print "<SELECT NAME=\"pw_img\">\n"; # If we did not find an image that has a / mounting point, then # we will use none as the default. if ($root_img eq "") { print "<OPTION VALUE=\"\" SELECTED>None</OPTION>\n"; } else { print "<OPTION VALUE=\"\">None</OPTION>\n"; } foreach my $img (@unix_imgs) { if ($root_img eq $img) { print "<OPTION VALUE=\"$img\" SELECTED>$img ($img2mnt{$img})". "</OPTION>\n"; } else { print "<OPTION VALUE=\"$img\">$img ($img2mnt{$img})</OPTION>\n"; } } print "</SELECT>\n"; print "<P>6. Generate MD5 Value? "; } else { print "<P>5. Generate MD5 Value? "; } print "<INPUT TYPE=\"checkbox\" NAME=\"md5\" VALUE=\"1\" CHECKED>\n"; # Create Button print "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n"; return 0; }; $funcs[$TL_TL_DOIT] = sub { check_fname(); check_body(); print_html_header(""); my $body = get_body(); my $fname = get_fname(); my $fname_rel = get_fname_rel(); my $mode = $args{'fname_mode'}; if ((-e "$fname") && ($FNAME_MODE_INIT == $mode)) { print "File Already Exists: <TT>$fname_rel</TT><BR>\n"; my $hidden = "<INPUT TYPE=\"hidden\" NAME=\"body\" VALUE=\"$args{'body'}\">". make_hidden(); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"st_none\" ". "VALUE=\"$args{'st_none'}\">\n" if (exists $args{'st_none'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"st_year\" ". "VALUE=\"$args{'st_year'}\">\n" if (exists $args{'st_year'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"st_day\" ". "VALUE=\"$args{'st_day'}\">\n" if (exists $args{'st_day'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"st_mon\" ". "VALUE=\"$args{'st_mon'}\">\n" if (exists $args{'st_mon'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"end_none\" ". "VALUE=\"$args{'end_none'}\">\n" if (exists $args{'end_none'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"end_year\" ". "VALUE=\"$args{'end_year'}\">\n" if (exists $args{'end_year'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"end_day\" ". "VALUE=\"$args{'end_day'}\">\n" if (exists $args{'end_day'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"end_mon\" ". "VALUE=\"$args{'end_mon'}\">\n" if (exists $args{'end_mon'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"tz\" ". "VALUE=\"$args{'tz'}\">\n" if (exists $args{'tz'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"pw_img\" ". "VALUE=\"$args{'pw_img'}\">\n" if (exists $args{'pw_img'}); $hidden .= "<INPUT TYPE=\"hidden\" NAME=\"md5\" ". "VALUE=\"$args{'md5'}\">\n" if (exists $args{'md5'}); # Make a new name print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "New Name: <INPUT TYPE=\"text\" NAME=\"fname\">". "<TABLE CELLSPACING=\"30\" CELLPADDING=\"2\"><TR><TD>". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_TL_DOIT\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_INIT\">\n". "$hidden\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_new_name.jpg\" ". "WIDTH=79 HEIGHT=20 ALT=\"Use New Name\" BORDER=\"0\">\n". "</FORM></TD>\n"; # Overwrite it print "<TD><FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_replace.jpg\" ". "WIDTH=66 HEIGHT=20 ALT=\"Replace\" BORDER=\"0\"><BR>\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_TL_DOIT\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname\" VALUE=\"$args{'fname'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"fname_mode\" VALUE=\"$FNAME_MODE_OVER\" >\n". "$hidden\n". "</FORM></TD></TR></TABLE>"; return 0; } my $mon; my $day; my $year; my $date = ""; # Get the start date unless ((exists $args{'st_none'}) && ($args{'st_none'} == 1)) { if (exists $args{'st_mon'}) { check_st_mon(); $mon = get_st_mon(); } if (exists $args{'st_year'}) { check_st_year(); $year = get_st_year(); } if ((exists $args{'st_day'}) && ($args{'st_day'} =~ /^(\d\d?)$/)) { $day = $1; if (($day < 1) || ($day > 31)) { print ("Invalid start day\n"); return 1; } } else { print ("Invalid start day\n"); return 1; } $date = "$mon/$day/$year"; } unless ((exists $args{'end_none'}) && ($args{'end_none'} == 1)) { if ($date eq "") { print "Begin date must be given if ending date is given<BR>"; return 1; } if ((exists $args{'end_mon'}) && ($args{'end_mon'} =~ /^(\d\d?)$/)) { $mon = $1; if (($mon < 1) || ($mon > 12)) { print ("Invalid end month\n"); return 1; } } else { print ("Invalid end month\n"); return 1; } if ((exists $args{'end_year'}) && ($args{'end_year'} =~ /^(\d\d\d\d)$/)) { $year = $1; if (($year < 1970) || ($year > 2020)) { print ("Invalid ending year\n"); return 1; } } else { print ("Invalid end year\n"); return 1; } if ((exists $args{'end_day'}) && ($args{'end_day'} =~ /^(\d\d?)$/)) { $day = $1; if (($day < 1) || ($day > 31)) { print ("Invalid end day\n"); return 1; } } else { print ("Invalid end day\n"); return 1; } $date .= "-$mon/$day/$year"; } # temp strings for the password and group files my $pw_tmp = ""; my $gr_tmp = ""; my $mac_args = ""; my $log = ""; local *OUT; # Password and Group Files if ((exists $args{'pw_img'}) && ($args{'pw_img'} ne "")) { check_img('pw_img'); my $pw_img = get_img('pw_img'); my $ftype = $img2ftype {$args{'pw_img'}}; $log .= "Password & Group File ($pw_img) "; # Get the passwd file inode and copy the file exec_pipe (*OUT, "'${TASKDIR}ifind' -f $ftype -n 'etc/passwd' '$pw_img'"); my $pwi = <OUT>; close (OUT); $pwi = "Error getting inode for passwd" if ((!defined $pwi) || ($pwi eq "")); # Do the Taint Checking if ($pwi =~ /^($REG_INODE)$/) { $pwi = $1; $log .= "Password Inode ($pwi) "; # Find a temp name that we can call it my $i; for ($i = 0; ; $i++) { unless (-e "$fname.pw-$i") { $pw_tmp = "$fname.pw-$i"; last; } } exec_sys("'${TASKDIR}icat' -f $ftype '$pw_img' $pwi > '$pw_tmp'"); $mac_args .= " -p \'$pw_tmp\' "; } else { print ("Error finding /etc/passwd inode in $pw_img ($pwi)<BR>"); log_host_inv ("$pw_img: /etc/passwd file not found for timeline"); } # Get the group file inode and copy the file exec_pipe (*OUT, "'${TASKDIR}ifind' -f $ftype -n 'etc/group' '$pw_img'"); my $gri = <OUT>; close (OUT); $gri = "Error getting inode for group" if ((!defined $gri) || ($gri eq "")); # Do the Taint Checking if ($gri =~ /^($REG_INODE)$/) { $gri = $1; $log .= "Group Inode ($gri) "; # Find a temp name that we can call it my $i; for ($i = 0; ; $i++) { unless (-e "$fname.gr-$i") { $gr_tmp = "$fname.gr-$i"; last; } } exec_sys("'${TASKDIR}icat' -f $ftype '$pw_img' $gri > '$gr_tmp'"); $mac_args .= " -g \'$gr_tmp\' "; } else { print ("Error finding /etc/group inode in $pw_img ($gri)<BR>"); log_host_inv ("$pw_img: /etc/group file not found for timeline"); } } if ($date eq "") { print "Creating Timeline using all dates (Time Zone: $tz)<BR>\n"; log_host_inv ("$args{'body'}: Creating timeline using all dates (TZ: $tz) ${log}to $fname_rel"); } else { print "Creating Timeline for $date (Time Zone: $tz)<BR>\n"; log_host_inv ("$args{'body'}: Creating timeline for $date (TZ: $tz) ${log}to $fname_rel"); } # mactime needs the path to run the 'date' command $ENV{PATH} = "/bin:/usr/bin"; local *OUT; exec_pipe (*OUT, "LANG=C LC_ALL=C '${TASKDIR}mactime' -b '$body' -z '$tz' -i day '${fname}.sum' $mac_args $date > '$fname'"); print "$_<BR>\n" while (<OUT>); close (OUT); $ENV{PATH} = ""; # Remove the password and group files unlink ("$pw_tmp") if ($pw_tmp ne ""); unlink ("$gr_tmp") if ($gr_tmp ne ""); print "<BR>Timeline saved to <TT>$fname</TT><BR><BR>\n"; # append to fsmorgue update_host_config ("timeline", $fname_rel); print "Entry added to host config file<BR><BR>\n"; # Calculate MD5 if ((exists $args{'md5'}) && ($args{'md5'} == 1)) { print "Calculating MD5 Value<BR><BR>\n"; my $m = int_create_wrap ($fname, $fname_rel); print "MD5 Value: <TT>$m</TT><BR><BR>\n"; } print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_top\">\n". "<INPUT TYPE=\"hidden\" NAME=\"tl\" VALUE=\"$args{'fname'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_MAIN\">\n". "<INPUT TYPE=\"hidden\" NAME=\"mode\" VALUE=\"$TL_VIEW_FR\">\n". make_hidden(). "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n". "(NOTE: It is easier to view the timeline in a text editor than here)"; return 0; }; $funcs[$TL_VIEW_MENU] = sub { print_html_header(""); my @tl; # Find the timelines in the images hash foreach my $k (keys %img2ftype) { if ($img2ftype{$k} eq "timeline") { push @tl, $k; } } if (scalar(@tl) == 0) { print "There are currently no timeline files in the ". "host config file.<BR>One must first be created before you ". "can view it<BR>\n"; print "<P><A TARGET=\"_top\" ". "HREF=\"$PROGNAME?$baseargs&func=$TL_MAIN&mode=$TL_TL_ENT\">". "<IMG SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=\"43\" HEIGHT=20 BORDER=\"0\">". "</A>\n"; return 1; } print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_VIEW_FR\">\n". make_hidden(). "1. Select the timeline file:\n". "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\">\n"; my @tl_sort = sort {lc($a) cmp lc($b)} @tl; for (my $i = 0; $i <= $#tl_sort; $i++) { (my $img_dir, my $str_img) = split (/\//,$tl_sort[$i]); print "<TR><TD><INPUT TYPE=\"radio\" NAME=\"tl\" ". "VALUE=\"$str_img\"></TD><TD>$str_img</TD>\n"; } print "</TABLE>\n". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n"; return 0; }; $funcs[$TL_VIEW_FR] = sub { check_tl(); print_html_header_frameset(""); my $tl = get_tl(); my $url = ""; unless (exists $args{'st_mon'}) { # get the start point (this design is not efficient at ALL) if (-z "$tl") { print("Timeline has no entries"); return (1); } unless (open (TL, "$tl")) { print("Error opening $tl"); return (1); } my $beg_mon; my $beg_year; while (<TL>) { if (/^(?:\w\w\w )?(\w\w\w)\s+\d\d\s+(\d\d\d\d)\s+\d\d:\d\d:\d\d/) { $url = "tl=$enc_args{'tl'}&st_mon=$m2d{$1}&st_year=$2"; } last; } close (TL); if ($url eq "") { print "Invalid Timeline<BR>\n"; return 1; } } else { $url = "tl=$enc_args{'tl'}&st_mon=$enc_args{'st_mon'}&". "st_year=$enc_args{'st_year'}"; } print "<FRAMESET ROWS=\"65,*\">\n". "<FRAME SRC=\"$PROGNAME?$baseargs&func=$TL_VIEW_IDX&$url\">\n". "<FRAME SRC=\"$PROGNAME?$baseargs&func=$TL_VIEW&$url\">\n</FRAMESET>"; return 0; }; $funcs[$TL_VIEW_IDX] = sub { check_st_mon(); check_st_year();check_tl(); print_html_header(""); my $mon = get_st_mon(); my $year = get_st_year(); my $tl = get_tl(); print "<CENTER><FONT SIZE=3>"; my $url = "$PROGNAME?$baseargs&func=$TL_VIEW_FR&tl=$enc_args{'tl'}"; # Next and Previous pointers my $pyear = $year; my $pmon = $mon - 1; if ($pmon == 0) { $pmon = 12; $pyear--; } print "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR><TD ALIGN=\"CENTER\">". "<A HREF=\"$url&st_mon=$pmon&st_year=$pyear\" TARGET=\"_parent\">". "<- $d2m[$pmon] $pyear</A></TD>\n". "<TD> </TD>\n"; if (-e "${tl}.sum") { print "<TD><A HREF=\"$PROGNAME?$baseargs&func=$TL_VIEW_SUM&". "tl=$enc_args{'tl'}\" TARGET=\"_parent\">". "Summary</TD>\n". "<TD> </TD>\n"; } my $nyear = $year; my $nmon = $mon + 1; if ($nmon == 13) { $nmon = 1; $nyear++; } print "<TD ALIGN=\"CENTER\">". "<A HREF=\"$url&st_mon=$nmon&st_year=$nyear\" TARGET=\"_parent\">". "$d2m[$nmon] $nyear -></A></TD></TR></TABLE>\n"; # Make a form to enter the next month and year to show. # it defaults to the current location print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\" TARGET=\"_parent\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$TL_VIEW_FR\">\n". "<INPUT TYPE=\"hidden\" NAME=\"tl\" VALUE=\"$enc_args{'tl'}\">\n". make_hidden(). "<TABLE CELLSPACING=\"0\" CELLPADDING=\"2\">\n". "<TR><TD ALIGN=\"CENTER\"><SELECT NAME=\"st_mon\" SIZE=\"1\">\n"; for my $i (1 .. 12) { if ($i == $mon) { print "<OPTION SELECTED VALUE=\"$i\">$d2m[$i]</OPTION>\n"; } else { print "<OPTION VALUE=\"$i\">$d2m[$i]</OPTION>\n"; } } print "</SELECT></TD>". "<TD ALIGN=\"CENTER\">". "<INPUT TYPE=\"text\" NAME=\"st_year\" SIZE=\"6\" VALUE=\"$year\">". "</TD>". "<TD ALIGN=\"CENTER\">". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=43 HEIGHT=20 BORDER=\"0\"></TD>\n". "</TR></TABLE></FORM>\n"; return 0; }; # Display the contents of the summary file (hits per day) and show # it as hits per month $funcs[$TL_VIEW_SUM] = sub { check_tl(); print_html_header(""); my $tl = get_tl(); $tl .= ".sum"; unless (-e "$tl") { print_err ("Summary of timeline file not found (<TT>$tl</TT>)<BR>The timeline must be created with The Sleuth Kit version 1.61 or greater to have a summary\n"); } open (TL, "<$tl") or die "Can not open $tl"; my $url = "$PROGNAME?$baseargs&func=$TL_VIEW_FR&tl=$enc_args{'tl'}"; print "<P>This page provides a monthly summary of activity.". "Each day that has activity is noted with the number of events<BR>\n"; my $p_year = ""; my $p_mon = ""; print "<P><TABLE CELLSPACING=2 BORDER=0>\n"; while (<TL>) { my @a = split(/ /, $_); next unless (scalar (@a) == 5); my $mon = $m2d{$a[1]}; my $year = $a[3]; $year = $1 if ($year =~ /^(\d{4,4}):$/); if (($p_year ne $year) || ($p_mon ne $mon)) { print "<TR><TD COLSPAN=6 ALIGN=LEFT>". "<A HREF=\"$url&st_mon=$mon&st_year=$year\">". "$a[1] $year</A></TD></TR>\n"; $p_year = $year; $p_mon = $mon; } print "<TR><TD> </TD><TD>$a[0]</TD>". "<TD>$a[1]</TD><TD>$a[2]</TD><TD>$year</TD><TD>($a[4])</TD></TR>\n"; } print "</TABLE>\n"; close (TL); return 0; }; # display a given month of the timeline $funcs[$TL_VIEW] = sub { check_tl(); check_st_mon(); check_st_year(); print_html_header(""); my $tl = get_tl(); my $st_mon = get_st_mon(); my $st_year = get_st_year(); unless (open (TL, "$tl")) { print("Error opening $tl"); return (1); } log_host_inv ("$args{'tl'}: Viewing timeline for $d2m[$st_mon] $st_year"); print "<TABLE CELLSPACING=\"5\" CELLPADDING=\"2\" WIDTH=100%>\n"; # zone identifies if we should be printing or not my $zone = 0; my $row = 0; while (<TL>) { if (/^(?:(\w\w\w\s+)?(\w\w\w\s+\d\d\s+\d\d\d\d)\s+(\d\d:\d\d:\d\d))?\s+(\d+)\s+([mac\.]+)\s+([-\/\?\w]+)\s+([\d\w\/]+)\s+([\d\w\/]+)\s+($REG_INODE)\s+(.*)$/o) { my $day = ""; $day = $1 if (defined $1); my $date = ""; $date = $2 if (defined $2); my $time = ""; $time = $3 if (defined $3); my $sz = $4; my $mac = $5; my $p = $6; my $u = $7; my $g = $8; my $i = $9; my $f = $10; # we must break this down to see if we can skip it or not if ($date ne "") { if ($date =~ /^(\w\w\w)\s+\d\d\s+(\d\d\d\d)$/) { if ($2 < $st_year) { next; } elsif (($2 == $st_year) && ($m2d{$1} < $st_mon)) { next; } elsif ($2 > $st_year) { last; } elsif (($2 == $st_year) && ($m2d{$1} > $st_mon)) { last; } else { $zone = 1; } } } # we need to print this entry if ($zone) { # the deleted inode <blah-dead-2> entries screw up in HTML $f = "<$1 >" if ($f =~ /^<(.*?)>$/); if (($row % 2) == 0) { print "<TR VALIGN=\"TOP\" BGCOLOR=\"$BACK_COLOR\">\n"; } else { print "<TR VALIGN=\"TOP\" BGCOLOR=\"$BACK_COLOR_TABLE\">\n"; } print "<TD>$day $date $time</TD>". "<TD>$sz</TD><TD>$mac</TD><TD>$p</TD>". "<TD>$u</TD><TD>$g</TD><TD>$i</TD><TD>$f</TD></TR>\n"; $row++; } } else { print "Error parsing timeline: $_<BR>\n"; } } close (TL); print "</TABLE>"; return 0; }; ############ Notes ################## # window that allows one to make a note # use the vars that were passed to determine what a comment is being # made about (file, inode, block) # $funcs[$NOTES_ENT] = sub { my $str; my $hidden; if ($USE_NOTES == 0) { print_html_header("Error"); print "Notes Option is not enabled\n"; return; } my $ftype = get_ftype(); # if the inode arg exists, it is either an inode note or a file name note if (exists $args{'inode'}) { my $inode = get_inode('inode'); my $fname = ""; if (exists $args{'dir'}) { my $fname = "$args{'mnt'}$args{'dir'}"; print_html_header("Notes for file $fname"); print "<CENTER><B>Enter a note for <TT>$fname</TT> ($inode):</B>". "<BR><BR>\n"; } else { print_html_header("Notes for $meta_str{$ftype} $inode"); print "<CENTER><B>Enter a note for $meta_str{$ftype} $inode:</B>". "<BR><BR>\n"; } print "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<TEXTAREA ROWS=10 COLS=50 WRAP=\"virtual\" NAME=\"note\">". "</TEXTAREA><BR>\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$NOTES_WRITE\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"inode\" VALUE=\"$inode\">\n". make_hidden(); print "<INPUT TYPE=\"hidden\" NAME=\"dir\" VALUE=\"$args{'dir'}\">\n" if (exists $args{'dir'}); # Option to add a normal note print "<INPUT TYPE=\"checkbox\" NAME=\"norm_note\" VALUE=\"1\" CHECKED>\n". " Add a Standard Note<BR>\n"; # Sequencer notes $ENV{TZ} = $tz; POSIX:tzset(); my $ftype = get_ftype(); my $img_path = get_img('img'); my $inode_int = $inode; $inode_int = $1 if ($inode_int =~ /(\d+)-\d+(-\d+)?/); local *OUT; exec_pipe (*OUT, "'${TASKDIR}ils' -f $ftype -e '$img_path' $inode_int"); # Get the fourth line my $tmp = <OUT>; $tmp = <OUT>; $tmp = <OUT>; $tmp = <OUT>; unless ((defined $tmp) && ($tmp =~ /^$REG_INODE\|\w\|\d+\|\d+\|(\d+)\|(\d+)\|(\d+)\|/o)) { print "Error parsing 'ils' output:<BR>\n"; return 1; } my $mtime = $1; my $atime = $2; my $ctime = $3; close (OUT); $mtime = localtime($mtime); $atime = localtime($atime); $ctime = localtime($ctime); print "<BR><B>Add a Sequencer Event:</B><BR>\n". "<INPUT TYPE=\"checkbox\" NAME=\"mtime\" VALUE=\"1\">". " M-Time (<TT>$mtime</TT>)<BR>\n". "<INPUT TYPE=\"checkbox\" NAME=\"atime\" VALUE=\"1\">". " A-Time (<TT>$atime</TT>)<BR>\n". "<INPUT TYPE=\"checkbox\" NAME=\"ctime\" VALUE=\"1\">". " C-Time (<TT>$ctime</TT>)<BR>\n"; print "<BR><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n"; } # data unit comment elsif (exists $args{'block'}) { my $block = get_block(); my $len = get_len(); print_html_header("Notes for $addr_unit{$ftype} $block"); print "<CENTER><B>Enter a note for $addr_unit{$ftype} $block</B><BR><BR>\n". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<TEXTAREA ROWS=10 COLS=50 WRAP=\"virtual\" NAME=\"note\">". "</TEXTAREA><BR>\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$NOTES_WRITE\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". "<INPUT TYPE=\"hidden\" NAME=\"block\" VALUE=\"$block\">\n". "<INPUT TYPE=\"hidden\" NAME=\"len\" VALUE=\"$len\">\n". "<INPUT TYPE=\"hidden\" NAME=\"norm_note\" VALUE=\"1\">\n". make_hidden(). "<BR><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n"; } else { print_html_header ("ERROR"); print "Unknown note type\n"; return; } return; }; # Write the note to the note file # # we tell what kind of note it is based on what args are passed # # if inode is passed it is either a dir, file, or inode and if block is # passed it is a block # If the dir arg is passed it is a file or directory and if the dir arg # ends with a '/' then it is a directory # # This function also writes the sequencer events from files and inodes # but the NOTES_SEQ_WRITE does the manual ones # $funcs[$NOTES_WRITE] = sub { if ($USE_NOTES == 0) { print_html_header("Error"); print "Notes Option is not enabled\n"; return; } check_note(); # Get rid of carriage returns that Netscape adds $args{'note'} =~ tr/\r//d; my $ftype = get_ftype(); my $inode = ""; my $fname = ""; my $block = ""; my $len = ""; my $type = ""; if (exists $args{'inode'}) { $inode = get_inode('inode'); if (exists $args{'dir'}) { $args{'dir'} .= "/" if ($args{'dir'} eq ""); $fname = "$args{'mnt'}$args{'dir'}"; if (($args{'dir'} =~ /\/$/) || ($args{'dir'} eq "")) { log_host_inv ("$args{'img'}: Creating note for directory $fname ($inode)"); $type = "dir"; } else { log_host_inv ("$args{'img'}: Creating note for file $fname ($inode)"); $type = "file"; } } else { log_host_inv ("$args{'img'}: Creating note for $meta_str{$ftype} $inode"); $type = "$meta_str{$ftype}"; } } elsif (exists $args{'block'}) { $block = get_block(); $len = get_len(); log_host_inv ("$args{'img'}: Creating note for $addr_unit{$ftype} $block"); $type = "$addr_unit{$ftype}"; } else { print_html_header ("ERROR"); print "Unknown note type\n"; return; } print_text_header(); print "\n"; # Create the notes # Create a "normal" note if ((exists $args{'norm_note'}) && ($args{'norm_note'} == 1)) { my $notes_file = investig_notes_fname(); open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; print "Note added to $notes_file:\n\n"; # Date my $tmp = localtime(); print NOTES "$tmp\n"; print "$tmp\n"; # We have a file name if ($fname ne "") { if ($type eq 'dir') { print NOTES "Directory: $fname\n"; print "Directory: $fname\n"; } else { print NOTES "File: $fname\n"; print "File: $fname\n"; } } if ($inode ne "") { print NOTES "Image: $args{'img'} Inode: $inode\n"; print "Image: $args{'img'} Inode: $inode\n"; } if ($block ne "") { print NOTES "Image: $args{'img'} $addr_unit{$ftype}: $block Len: $len\n"; print "Image: $args{'img'} $addr_unit{$ftype}: $block Len: $len\n"; } # The actual notes and a line at the bottom print NOTES "\n$args{'note'}\n\n". "-" x 62 ."\n"; print "\n$args{'note'}\n\n"; close (NOTES); } return 0 unless (exists $args{'inode'}); # Create a sequencer event return 0 unless ( ((exists $args{'mtime'}) && ($args{'mtime'} == 1)) || ((exists $args{'atime'}) && ($args{'atime'} == 1)) || ((exists $args{'ctime'}) && ($args{'ctime'} == 1)) ); my $img_path = get_img('img'); # Get the times for the inode # Set the timezone to the host zone $ENV{TZ} = "$tz"; POSIX::tzset(); my $inode_int = $inode; $inode_int = $1 if ($inode_int =~ /(\d+)-\d+(-\d+)?/); local *OUT; exec_pipe (*OUT, "'${TASKDIR}ils' -f $ftype -e '$img_path' $inode_int"); # Skip to the fourth line my $tmp = <OUT>; $tmp = <OUT>; $tmp = <OUT>; $tmp = <OUT>; unless ((defined $tmp) && ($tmp =~ /^$REG_INODE\|\w\|\d+\|\d+\|(\d+)\|(\d+)\|(\d+)\|/o)) { print "Error parsing 'ils' output<BR>\n"; return 1; } my $mtime = $1; my $atime = $2; my $ctime = $3; close (OUT); # Get rid of the carriage returns $args{'note'} =~ s/\n/<BR>/gs; my $notes_file = investig_seq_notes_fname(); open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; if ((exists $args{'mtime'}) && ($args{'mtime'} == 1)) { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($mtime); $year += 1900; $mon += 1; $mday = "0$mday" if ($mday < 10); $hour = "0$hour" if ($hour < 10); $min = "0$min" if ($min < 10); $sec = "0$sec" if ($sec < 10); print NOTES "'$year','$mon','$mday','$hour','$min','$sec',". "'$args{'host'}','$args{'img'}','$fname','$inode','$block',". "'$type','[M-Time]$args{'note'}'\n"; log_host_inv ("$args{'img'}: M-Time note added for inode $args{'inode'}"); print "M-Time sequence event added\n"; } if ((exists $args{'atime'}) && ($args{'atime'} == 1)) { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($atime); $year += 1900; $mon += 1; $mday = "0$mday" if ($mday < 10); $hour = "0$hour" if ($hour < 10); $min = "0$min" if ($min < 10); $sec = "0$sec" if ($sec < 10); print NOTES "'$year','$mon','$mday','$hour','$min','$sec',". "'$args{'host'}','$args{'img'}','$fname','$inode','$block',". "'$type','[A-Time]$args{'note'}'\n"; log_host_inv ("$args{'img'}: A-Time note added for inode $args{'inode'}"); print "A-Time sequence event added\n"; } if ((exists $args{'ctime'}) && ($args{'ctime'} == 1)) { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($ctime); $year += 1900; $mon += 1; $mday = "0$mday" if ($mday < 10); $hour = "0$hour" if ($hour < 10); $min = "0$min" if ($min < 10); $sec = "0$sec" if ($sec < 10); print NOTES "'$year','$mon','$mday','$hour','$min','$sec',". "'$args{'host'}','$args{'img'}','$fname','$inode','$block',". "'$type','[C-Time]$args{'note'}'\n"; log_host_inv ("$args{'img'}: C-Time note added for inode $args{'inode'}"); print "C-Time sequence event added\n"; } close (NOTES); return 0; }; # Display the contents of the "normal" notes file $funcs[$NOTES_READ] = sub { if ($USE_NOTES == 0) { print_html_header("Error"); print "Notes Option is not enabled\n"; return; } print_html_header("Contents of Notes File"); my $notes_file = investig_notes_fname(); log_host_inv ("Viewing contents of notes file ($notes_file)"); if ((!(-e "$notes_file")) || (-z "$notes_file")) { print "No notes have been entered yet<BR>\n"; return; } open NOTES, "<$notes_file" or die "Can't open log: $notes_file"; my $file = ""; my $dir = ""; print "<TABLE WIDTH=100%>\n". "<TR BGCOLOR=$BACK_COLOR><TD ALIGN=LEFT>\n"; my $row=0; # This will need to change whenever the log format changes while (<NOTES>) { # we need to extract mnt from here $file = $1 if (/File: (.*)/); $dir = $1 if (/Directory: (.*)/); # Reset the $file if we are at the end of the current note if (/^\-+$/) { $file = ""; $dir = ""; if (($row++ % 2) == 0) { print "</TD></TR>\n<TR BGCOLOR=$BACK_COLOR_TABLE><TD ALIGN=LEFT>\n"; } else { print "</TD></TR>\n<TR BGCOLOR=$BACK_COLOR><TD ALIGN=LEFT>\n"; } } else { print "$_<BR>"; } if (/Image: ($REG_IMG) Inode: ([0-9\-]+)/o) { my $img = $1; my $inode = $2; # if we can't find this image, then it likely means that the # comment pertains to a different case, so we can not give # any links unless (exists $img2mnt{$img}) { next; } # file note if ($file ne "") { # extract the prepended mnt value my $mnt = $img2mnt{$img}; my $fname = ""; $fname = $1 if ($file =~ /^$mnt\/?(.*)$/); print "<A HREF=\"$PROGNAME?$baseargs&func=$FIL_CMENU_FR". "&img=$img&inode=$inode&dir=$fname\" TARGET=\"_blank\">View</A><BR>\n"; } # directory note elsif ($dir ne "") { # extract the prepended mnt value my $mnt = $img2mnt{$img}; my $fname = ""; $fname = $1 if ($dir =~ /^$mnt\/?(.*)$/); print "<A HREF=\"$PROGNAME?func=$MAIN_FR&". "mode=$FIL_MAIN&img=$img&". "$baseargs&inode=$inode&dir=$fname\" TARGET=\"_blank\">". "View</A><BR>\n"; } # inode note else { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&". "mode=$INO_MAIN&img=$img". "&$baseargs&inode=$inode\" TARGET=\"_blank\">View</A><BR>\n"; } } # block note elsif (/Image: ($REG_IMG) \w+: ([0-9]+) Len: (\d+)/o) { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&". "mode=$BLK_MAIN&img=$1&". "block=$2&len=$3&$baseargs\"". " TARGET=\"_blank\">View</A><BR>\n"; } } print "</TR></TABLE>\n"; # Ok and refresh buttons print "<P><CENTER><TABLE WIDTH=600>\n". "<TR><TD WIDTH=300 ALIGN=CENTER>\n". "<A HREF=\"$PROGNAME?func=$IMG_OPEN&$baseargs\">". "<IMG BORDER=0 SRC=\"pict/menu_b_ok.jpg\" ". "WIDTH=167 HEIGHT=20></A>\n". "</TD><TD WIDTH=300 ALIGN=CENTER>\n". "<A HREF=\"$PROGNAME?func=$NOTES_READ&$baseargs\">". "<IMG BORDER=0 SRC=\"pict/menu_b_ref.jpg\" ". "WIDTH=167 HEIGHT=20></A>\n". "</TD></TR></TABLE>\n"; close (NOTES); return; }; ######################################################################### # Sequencer Code # Write a sequence event that was manually entered $funcs[$NOTES_SEQ_WRITE] = sub { if ($USE_NOTES == 0) { print_html_header("Error"); print "Notes Option is not enabled\n"; return; } check_note(); print_html_header("Writing Sequencer Event"); # Get rid of carriage returns that Netscape adds $args{'note'} =~ tr/\r//d; $args{'note'} =~ s/\n/<BR>/gs; if ($args{'note'} eq "") { print "A comment must be given for the event<BR>\n". "<P><A HREF=\"$PROGNAME?func=$NOTES_SEQ_READ&$baseargs\">". "<IMG BORDER=0 SRC=\"pict/menu_b_ok.jpg\" ". "WIDTH=167 HEIGHT=20></A>\n"; return 1; } # Check the args and add them to the final string that will be written my $str = ""; unless ((exists $args{'year'}) && ($args{'year'} =~ /^(\d\d\d\d)$/)) { print "Invalid year<BR>\n"; return 1; } $str .= "'$1',"; unless ((exists $args{'mon'}) && ($args{'mon'} =~ /^(\d\d?)$/)) { print "Invalid month<BR>\n"; return 1; } $str .= "'$1',"; unless ((exists $args{'day'}) && ($args{'day'} =~ /^(\d\d?)$/)) { print "Invalid day<BR>\n"; return 1; } $str .= "'$1',"; unless ((exists $args{'hour'}) && ($args{'hour'} =~ /^(\d\d?)$/)) { print "Invalid hour<BR>\n"; return 1; } $str .= "'$1',"; unless ((exists $args{'min'}) && ($args{'min'} =~ /^(\d\d?)$/)) { print "Invalid min<BR>\n"; return 1; } $str .= "'$1',"; unless ((exists $args{'sec'}) && ($args{'sec'} =~ /^(\d\d?)$/)) { print "Invalid sec<BR>\n"; return 1; } $str .= "'$1',"; # There are no image, inode, file name, or data unit for this type $str .= "'$args{'host'}','','','','',"; unless ((exists $args{'src'}) && ($args{'src'} =~ /^(\w+)$/)) { print "Invalid src<BR>\n"; return 1; } $str .= "'$1','$args{'note'}'\n"; # Write the string to the notes file my $notes_file = investig_seq_notes_fname(); open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; print NOTES $str; close (NOTES); # Send a message to the user print "Event Added to Sequencer file:<BR><BR>\n". "$d2m[$args{'mon'}] $args{'day'}, $args{'year'} ". "$args{'hour'}:$args{'min'}:$args{'sec'}<BR><BR>\n". "$args{'note'}<BR>\n". "<P><A HREF=\"$PROGNAME?func=$NOTES_SEQ_READ&$baseargs&". "year=$enc_args{'year'}&mon=$enc_args{'mon'}&day=$enc_args{'day'}&". "hour=$enc_args{'hour'}&min=$enc_args{'min'}&sec=$enc_args{'sec'}\">". "<IMG BORDER=0 SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=43 HEIGHT=20></A>\n"; return 0; }; # View the sequencer file $funcs[$NOTES_SEQ_READ] = sub { if ($USE_NOTES == 0) { print_html_header("Error"); print "Notes Option is not enabled\n"; return; } print_html_header("Event Sequencer"); print "<CENTER>\n". "<H3>Event Sequencer</H3>\n"; my $cnt = 0; my @entry; my (@year, @mon, @day, @hour, @min, @sec, @host, @img, @fname, @inode, @data, @type, @note); # Read the sequencer file into arrays that will be sorted my $notes_file = investig_seq_notes_fname(); if (-e $notes_file) { open NOTES, "$notes_file" or die "Can't open log: $notes_file"; while (<NOTES>) { unless (/^'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?($REG_HOST)'?,'?($REG_IMG)?'?,'?(.*?)?'?,'?($REG_INODE)?'?,'?(\d+)?'?,'?([\w\s]+)'?,'?(.*?)'?$/) { print "Error parsing sequence event entry: $_\n"; return 1; } $year[$cnt] = $1; $mon[$cnt] = $2; $day[$cnt] = $3; $hour[$cnt] = $4; $min[$cnt] = $5; $sec[$cnt] = $6; $host[$cnt] = $7; $img[$cnt] = $8; $fname[$cnt] = $9; $inode[$cnt] = $10; $data[$cnt] = $11; $type[$cnt] = $12; $note[$cnt] = $13; $entry[$cnt] = $cnt; $cnt++; } close (NOTES); # Sort the values by date, source, and then note my @sorted = sort { $year[$a] <=> $year[$b] or $mon[$a] <=> $mon[$b] or $day[$a] <=> $day[$b] or $hour[$a] <=> $hour[$b] or $min[$a] <=> $min[$b] or $sec[$a] <=> $sec[$b] or lc($type[$a]) cmp lc($type[$b]) or lc($note[$a]) cmp lc($note[$b]) } @entry; # Table and header print "<TABLE WIDTH=800 BORDER=1>\n". "<TR BACKGROUND=\"$YEL_PIX\">\n". "<TH>Date & Time</TH>\n". "<TH>Source</TH>\n". "<TH>Event & Note</TH></TR>\n"; # Cycle through the sorted events my $row = 0; foreach my $i (@sorted) { # Alternate row colors if (($row % 2) == 0) { print "<TR BGCOLOR=\"$BACK_COLOR\">\n"; } else { print "<TR BGCOLOR=\"$BACK_COLOR_TABLE\">\n"; } # Date & Time print "<TD ALIGN=LEFT VALIGN=TOP>\n". "$d2m[$mon[$i]] $day[$i], $year[$i]". " $hour[$i]:$min[$i]:$sec[$i]</TD>"; my $img; if (defined $img[$i]) { $img = $img[$i]; } else { $img = ""; } print "<TD ALIGN=LEFT VALIGN=TOP>\n"; # IF there is as name, then we will show it if ((defined $fname[$i]) && ($fname[$i] ne "")) { if (($img ne "") && (exists $img2mnt{$img}) && (defined $inode[$i])) { # extract the prepended mnt value my $mnt = $img2mnt{$img}; my $fname = ""; $fname = $1 if ($fname[$i] =~ /^$mnt\/?(.*)$/); # Check if it is a directory if ($type[$i] eq 'dir') { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&". "mode=$FIL_MAIN&img=$img[$i]&". "$baseargs&inode=$inode[$i]&dir=$fname\" ". "TARGET=\"_blank\">\n". "<TT>$fname[$i]</TT></A>\n"; } else { print "<A HREF=\"$PROGNAME?func=$FIL_CMENU_FR&". "img=$img[$i]&". "$baseargs&inode=$inode[$i]&dir=$fname\" ". "TARGET=\"_blank\">\n". "<TT>$fname[$i]</TT></A>\n"; } } else { print "<TT>$fname[$i]</TT>\n"; } } # Display the inode value if there was no name elsif (($img ne "") && (defined $inode[$i]) && ($inode[$i] ne "")) { my $ftype = $img2ftype{$img}; # Include a link if we can if (exists $img2mnt{$img}) { print "<A HREF=\"$PROGNAME?func=$MAIN_FR&". "mode=$INO_MAIN&img=$img". "&$baseargs&inode=$inode[$i]\" TARGET=\"_blank\">\n". "$meta_str{$ftype}: $inode[$i]</A>\n"; } else { print "$meta_str{$ftype}: $inode[$i]\n"; } } # Otherwise, just give the source type else { print "$type[$i]\n"; } print "</TD>\n"; # Print the actual note $note[$i] = " " if ($note[$i] eq ""); print "<TD ALIGN=LEFT>$note[$i]</TD></TR>\n"; $row++; } print "</TABLE>\n"; } # End of if file exists else { print "No events currently exist<BR>\n"; } # Ok and refresh buttons print "<P><TABLE WIDTH=600>\n". "<TR><TD WIDTH=300 ALIGN=CENTER>\n". "<A HREF=\"$PROGNAME?func=$IMG_OPEN&$baseargs\">". "<IMG BORDER=0 SRC=\"pict/menu_b_ok.jpg\" ". "WIDTH=167 HEIGHT=20></A>\n". "</TD><TD WIDTH=300 ALIGN=CENTER>\n". "<A HREF=\"$PROGNAME?func=$NOTES_SEQ_READ&$baseargs\">". "<IMG BORDER=0 SRC=\"pict/menu_b_ref.jpg\" ". "WIDTH=167 HEIGHT=20></A>\n". "</TD></TR></TABLE>\n"; # Manually add a new event print "<HR>\n". "<B>Add a New Event</B><BR><BR>\n". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<TEXTAREA ROWS=10 COLS=50 WRAP=\"virtual\" NAME=\"note\">". "</TEXTAREA><BR>\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$NOTES_SEQ_WRITE\">\n". make_hidden(); # Month print "<P>Date: ". "<SELECT NAME=\"mon\" SIZE=\"1\">\n"; my $prev = 1; $prev = $args{'mon'} if ((exists $args{'mon'}) && ($args{'mon'} =~ /^\d+$/)); for my $i (1 .. 12) { if ($i == $prev) { print "<OPTION VALUE=$i SELECTED>$d2m[$i]</OPTION>\n"; } else { print "<OPTION VALUE=\"$i\">$d2m[$i]</OPTION>\n"; } } print "</SELECT>\n"; # Day print " <SELECT NAME=\"day\" SIZE=\"1\">\n"; $prev = 1; $prev = $args{'day'} if ((exists $args{'day'}) && ($args{'day'} =~ /^\d+$/)); for my $i (1 .. 31) { my $dstr = $i; $dstr = "0$i" if ($i < 10); if ($prev eq $dstr) { print "<OPTION VALUE=\"$dstr\" SELECTED>$dstr</OPTION>\n"; } else { print "<OPTION VALUE=\"$dstr\">$dstr</OPTION>\n"; } } print "</SELECT>\n"; # Year $prev = 1900 + (localtime())[5]; $prev = $args{'year'} if ((exists $args{'year'}) && ($args{'year'} =~ /^\d+$/)); print " <INPUT TYPE=\"text\" VALUE=\"$prev\" ". "NAME=\"year\" SIZE=\"6\">\n"; # Hour print " <SELECT NAME=\"hour\" SIZE=\"1\">\n"; $prev = 0; $prev = $args{'hour'} if ((exists $args{'hour'}) && ($args{'hour'} =~ /^\d+$/)); for my $i (0 .. 23) { my $hstr = $i; $hstr = "0$i" if ($i < 10); if ($prev eq $hstr) { print "<OPTION VALUE=\"$hstr\" SELECTED>$hstr</OPTION>\n"; } else { print "<OPTION VALUE=\"$hstr\">$hstr</OPTION>\n"; } } print "</SELECT>\n"; # Min print ":<SELECT NAME=\"min\" SIZE=\"1\">\n"; $prev = 0; $prev = $args{'min'} if ((exists $args{'min'}) && ($args{'min'} =~ /^\d+$/)); for my $i (0 .. 59) { my $mstr = $i; $mstr = "0$i" if ($i < 10); if ($prev eq $mstr) { print "<OPTION VALUE=\"$mstr\" SELECTED>$mstr</OPTION>\n"; } else { print "<OPTION VALUE=\"$mstr\">$mstr</OPTION>\n"; } } print "</SELECT>\n"; # Sec print ":<SELECT NAME=\"sec\" SIZE=\"1\">\n"; $prev = 0; $prev = $args{'sec'} if ((exists $args{'sec'}) && ($args{'sec'} =~ /^\d+$/)); for my $i (0 .. 59) { my $sstr = $i; $sstr = "0$i" if ($i < 10); if ($prev eq $sstr) { print "<OPTION VALUE=\"$sstr\" SELECTED>$sstr</OPTION>\n"; } else { print "<OPTION VALUE=\"$sstr\">$sstr</OPTION>\n"; } } print "</SELECT>\n"; # Type print "<BR><BR>Source of Event: <SELECT NAME=\"src\" SIZE=1>\n". "<OPTION VALUE=\"firewall\">firewall</OPTION>\n". "<OPTION VALUE=\"ids\">ids</OPTION>\n". "<OPTION VALUE=\"isp\">isp</OPTION>\n". "<OPTION VALUE=\"log\">log</OPTION>\n". "<OPTION VALUE=\"other\" SELECTED>other</OPTION>\n". "<OPTION VALUE=\"person\">person</OPTION>\n". "</SELECT>\n"; print "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/menu_b_ok.jpg\" ". "WIDTH=167 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n"; return 0; }; ######################################################################### # # sorter # # sorter frameset $funcs[$SORTER_MAIN] = sub { print_html_header_frameset("Sorter on $args{'img'}"); print "<FRAMESET COLS=\"20%,80%\">\n"; # Block List print "<FRAME SRC=\"$PROGNAME?func=$SORTER_LIST&$baseargs\">\n"; # Blank print "<FRAME SRC=\"$PROGNAME?func=$BLANK&$baseargs\" NAME=\"content\">\n". "</FRAMESET>\n"; return 0; }; # The left-hand frame for running sorter $funcs[$SORTER_LIST] = sub { print_html_header("sorter menu"); print "<P><A HREF=\"$PROGNAME?func=$SORTER_ENT&$baseargs\" ". "TARGET=\"content\">Sort Files by Type</A>"; return 0; }; # Get the data and print the form so that sorter can be run $funcs[$SORTER_ENT] = sub { print_html_header("sorter - enter data to create"); print "<CENTER>". "<H3>File Type Sortings</H3></CENTER><BR>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">\n". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$SORTER_DOIT\">\n". "<INPUT TYPE=\"hidden\" NAME=\"img\" VALUE=\"$args{'img'}\">\n". make_hidden(); print <<EOF1; <P>The <B>sorter</B> tool will process an image and organize the files based on their file type. The files are organized into categories that are defined in configuration files. The categories will be saved in the <TT>${DATADIR}</TT> directory. <HR> EOF1 my $sort_dir = get_sorter_dir(); if (-d "$sort_dir") { print "WARNING: This will overwrite any existing data in:<BR>". " <TT>$sort_dir</TT><BR>\n"; } my $tab = " "; print <<EOF2; <P> <INPUT TYPE=\"checkbox\" NAME=\"sorter_cat\" VALUE=\"1\" CHECKED> Sort files into categories by type <P>$tab <INPUT TYPE=\"checkbox\" NAME=\"sorter_unk\" VALUE=\"1\"> Do not save data about <TT>unknown</TT> file types <P>$tab <INPUT TYPE=\"checkbox\" NAME=\"sorter_save\" VALUE=\"1\"> Save a copy of files in category directory (may require lots of disk space) <P>$tab <INPUT TYPE=\"checkbox\" NAME=\"sorter_img\" VALUE=\"1\"> Save ONLY graphic images and make thumbnails <BR> $tab (may require lots of disk space and will save to a different directory than sorting all file types) <P> <INPUT TYPE=\"checkbox\" NAME=\"sorter_ext\" VALUE=\"1\" CHECKED> Extension and File Type Validation EOF2 if (($NSRLDB ne "") && (-e "$NSRLDB")) { # @@@ Removed until it is easier to identify the known bad files in # NSRL # print # "<P><INPUT TYPE=\"checkbox\" NAME=\"sorter_nsrl\" VALUE=\"1\" CHECKED>". # "Exclude files in the <B>NIST NSRL</B>\n"; print "<P>The <B>NIST NSRL</B> option has been removed from this mode\n"; } if (($alert_db ne "") && (-e "$alert_db")) { print "<P><INPUT TYPE=\"checkbox\" NAME=\"sorter_alert\" VALUE=\"1\" CHECKED>". "Alert files that are found in the <B>Alert Hash Database</B>\n"; } if (($exclude_db ne "") && (-e "$exclude_db")) { print "<P><INPUT TYPE=\"checkbox\" NAME=\"sorter_exclude\" VALUE=\"1\" CHECKED>". "Ignore files that are found in the <B>Exclude Hash Database</B>\n"; } print "<P><INPUT TYPE=\"IMAGE\" SRC=\"pict/but_ok.jpg\" ". "WIDTH=43 HEIGHT=20 ALT=\"Ok\" BORDER=\"0\">\n</FORM>\n"; return; }; # Run sorter on the image $funcs[$SORTER_DOIT] = sub { print_html_header("sorter - create"); my $sort_args = ""; my $ext = 0; my $cat = 0; log_host_inv ("Running 'sorter' on ($args{'img'}"); $ext = 1 if ((exists $args{'sorter_ext'}) && ($args{'sorter_ext'} == 1)); $cat = 1 if ((exists $args{'sorter_cat'}) && ($args{'sorter_cat'} == 1)); if (($cat == 0) && ($ext == 0)) { print "At least one action must be selected\n". "<P><A HREF=\"$PROGNAME?func=$SORTER_ENT&$baseargs\">". "<IMG BORDER=0 SRC=\"pict/but_ok.jpg\" ALT=\"Ok\" ". "WIDTH=43 HEIGHT=20></A>\n"; return; } # If both actions are wanted then no flags are needed $sort_args .= "-e " if (($ext == 1) && ($cat == 0)); $sort_args .= "-i " if (($ext == 0) && ($cat == 1)); my $sort_dir = get_sorter_dir(); if ($cat == 1) { if ((exists $args{'sorter_img'}) && ($args{'sorter_img'} == 1)) { my $config = "${TASKDIR}/../share/sorter/images.sort"; print_err ("images configuration file not found ($config)") unless (-e "$config"); $sort_args .= "-C $config -s -U "; $sort_dir = get_sorter_graphics_dir(); } else { $sort_args .= "-s " if ((exists $args{'sorter_save'}) && ($args{'sorter_save'} == 1)); $sort_args .= "-U " if ((exists $args{'sorter_unk'}) && ($args{'sorter_unk'} == 1)); } } if ($NSRLDB ne "") { # @@@ Removed until the known bad can be identified in NSRL # $sort_args .= "-n \'$NSRLDB\' " # if ((exists $args{'sorter_nsrl'}) && ($args{'sorter_nsrl'} == 1)); } if ($alert_db ne "") { $sort_args .= "-a \'$alert_db\' " if ((exists $args{'sorter_alert'}) && ($args{'sorter_alert'} == 1)); } if ($exclude_db ne "") { $sort_args .= "-x \'$exclude_db\' " if ((exists $args{'sorter_exclude'}) && ($args{'sorter_exclude'} == 1)); } my $mnt = get_mnt(); my $fstype = get_ftype(); my $img = get_img('img'); unless (-d "$sort_dir") { unless (mkdir "$sort_dir", $MKDIR_MASK) { print_err ("Error making $sort_dir"); } } if (-e "$sort_dir/index.html") { unlink ("$sort_dir/index.html"); } my $exec = "-h -m '$mnt' -d '$sort_dir' -f $fstype $sort_args '$img'"; print "Executing: <TT>sorter $exec</TT><P>\n"; # Execute Sorter my $hit_cnt = 0; $SIG{ALRM} = sub { if (($hit_cnt++ % 5) == 0) { print "+"; } else { print "-"; } alarm(5); }; alarm(5); local *OUT; exec_pipe (*OUT, "LANG=C LC_ALL=C '${TASKDIR}sorter' $exec"); while (<OUT>) { print "$_<BR>\n"; $hit_cnt = 0; } $SIG{ALRM} = 'DEFAULT'; if (-e "$sort_dir/index.html") { print "<P>Output can be found by viewing: <TT>$sort_dir/index.html</TT><P>\n". "(Future versions of Autopsy will have built-in viewing capabilities)<BR>\n"; # Print the index.html file from the output print "<HR><CENTER><H3>Results Summary</H3></CENTER>\n"; open INDEX, "<$sort_dir/index.html" or die "Can't open sorter index file ($sort_dir/index.html)"; while (<INDEX>) { next if ((/^<HTML><HEAD><TITLE>/i) || (/^<BODY><CENTER><H2>/i)); # Extract out the symlinks to the categories if (/^\s*<li><A HREF="\.\/[\w\.]+">([\w\s]+)<\/a> \((\d+)\)\s*$/i) { print "<LI>$1 ($2)\n"; } # Skip the link on the thumbnails link elsif (/^\s*\(<A HREF=[\"\.\/\w]+>thumbnails<\/A>\)\s*$/) { print "(thumbnails)\n"; } else { print "$_"; } } close (INDEX); } return; }; ######################################################################### # # Hash Databases # sub hash_index_md5sum { my $db = shift; local *OUT; exec_pipe (*OUT, "'${TASKDIR}hfind' -i md5sum '$db'"); while (<OUT>) { print "$_<BR>\n"; } close (OUT); }; sub hash_index_nsrl { local *OUT; exec_pipe (*OUT, "'${TASKDIR}hfind' -i nsrl-md5 '$NSRLDB'"); while (<OUT>) { print "$_<BR>\n"; } close (OUT); }; # Window from HOST Manager $funcs[$HASH_MAIN] = sub { print_html_header("Hash Database Manager"); print <<EOF; Hash databases allow Autopsy to quickly identify known files. This includes files that are known to be good and those that are known to be bad. The 'hfind' tool is used to lookup entries in the databases and it needs an index file for each database. This window allows one to re-index the database after it has been updated. <P> To edit the location of the databases, you must manually edit the <TT>host.aut</TT> file in the host directory. <HR> <CENTER> <IMG SRC=\"pict/hashdb_h_alert.jpg\" ALT=\"Alert Database\" BORDER=\"0\"> </CENTER> <P><B>Overview</B><BR> These files are known to be <U>bad</U> and are the ones that you want to know about if they are in the image you are analyzing. For example, this database would include hashes of known attacker tools, rootkits, or photographs. EOF print "<P><B>Details</B><BR>\n"; if ($alert_db eq "") { print "Location: <TT>Not Configured</TT><BR>\n"; } elsif (-e "$alert_db") { print "Location: <TT>$alert_db</TT><BR>\n"; if (-e "${alert_db}-md5.idx") { print "Status: MD5 Index File Exists<BR>\n"; } else { print "Status: Database has not been MD5 indexed<BR>\n"; } # Index Button print "<P><A HREF=\"$PROGNAME?func=$HASH_INDEX&hash_alert=1&$baseargs\">". "<IMG SRC=\"pict/but_indexdb.jpg\" ALT=\"Index DB\" ". "WIDTH=116 HEIGHT=20 BORDER=\"0\">". "</A>\n"; # Lookup Button if (-e "${alert_db}-md5.idx") { print "<P><B>Lookup</B><BR>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HASH_LOOKUP\">\n". "<INPUT TYPE=\"hidden\" NAME=\"hash_alert\" VALUE=\"1\">\n". make_hidden(). "<TABLE CELLSPACING=\"10\" CELLPADDING=\"2\">\n<TR>\n". "<TD ALIGN=\"LEFT\">Enter MD5 Value: ". "<INPUT TYPE=\"text\" NAME=\"md5\" SIZE=40 MAXLENGTH=32></TD>\n". "<TD ALIGN=\"LEFT\">". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_lookup.jpg\" ALT=\"Ok\" ". "WIDTH=116 HEIGHT=20 BORDER=\"0\">\n". "</TD></TR>\n</TABLE>\n". "</FORM>"; } } else { print "Location: <TT>$alert_db</TT><BR>\n". "ERROR: Database not found<BR>\n"; } print <<EOF2; <HR> <CENTER> <IMG SRC=\"pict/hashdb_h_ig.jpg\" ALT=\"Ignore Database\" BORDER=\"0\"> </CENTER> <P><B>Overview</B><BR> These files are known to be <U>good</U> and are the ones that you can ignore if they are found in the image you are analyzing. For example, this database would include hashes of known system binaries and other documents that you do not want to waste time on when running 'sorter' or files that you want to confirm were not modified by an attacker. EOF2 print "<P><B>Details</B><BR>\n"; if ($exclude_db eq "") { print "Location: <TT>Not Configured</TT><BR>\n"; } elsif (-e "$exclude_db") { print "Location: <TT>$exclude_db</TT><BR>\n"; if (-e "${exclude_db}-md5.idx") { print "Status: MD5 Index File Exists<BR>\n"; } else { print "Status: Database has not been MD5 indexed<BR>\n"; } # Index Button print "<P><A HREF=\"$PROGNAME?func=$HASH_INDEX&hash_exclude=1&$baseargs\">". "<IMG SRC=\"pict/but_indexdb.jpg\" ALT=\"Index DB\" ". "WIDTH=116 HEIGHT=20 BORDER=\"0\">". "</A>\n"; # Lookup Button if (-e "${exclude_db}-md5.idx") { print "<P><B>Lookup</B><BR>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HASH_LOOKUP\">\n". "<INPUT TYPE=\"hidden\" NAME=\"hash_exclude\" VALUE=\"1\">\n". make_hidden(). "<TABLE CELLSPACING=\"10\" CELLPADDING=\"2\">\n<TR>\n". "<TD ALIGN=\"LEFT\">Enter MD5 Value: ". "<INPUT TYPE=\"text\" NAME=\"md5\" SIZE=40 MAXLENGTH=32></TD>\n". "<TD ALIGN=\"LEFT\">". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_lookup.jpg\" ALT=\"Ok\" ". "WIDTH=116 HEIGHT=20 BORDER=\"0\">\n". "</TD></TR>\n</TABLE>\n". "</FORM>"; } } else { print "Location: <TT>$exclude_db</TT><BR>\n". "ERROR: Database not found<BR>\n"; } print <<EOF3; <HR> <CENTER> <IMG SRC=\"pict/hashdb_h_nsrl.jpg\" ALT=\"NSRL Database\" BORDER=\"0\"> </CENTER> <P><B>Overview</B><BR> These files are known to be <U>good</U> and <U>bad</U>. It is currently difficult to distinguish between known good and known bad and therefore the NSRL is no longer used much in Autopsy until a better solution can be found. EOF3 print "<P><B>Details</B><BR>\n"; if ($NSRLDB eq "") { print "Location: <TT>Not Configured</TT><BR>\n"; } elsif (-e "$NSRLDB") { print "Location: <TT>$NSRLDB</TT><BR>\n"; if (-e "${NSRLDB}-md5.idx") { print "Status: MD5 Index File Exists<BR>\n"; } else { print "Status: Database has not been MD5 indexed<BR>\n"; } # Index Button print "<P><A HREF=\"$PROGNAME?func=$HASH_INDEX&hash_nsrl=1&$baseargs\">". "<IMG SRC=\"pict/but_indexdb.jpg\" ALT=\"Index DB\" ". "WIDTH=116 HEIGHT=20 BORDER=\"0\">". "</A>\n"; # Lookup Button if (-e "${NSRLDB}-md5.idx") { print "<P><B>Lookup</B><BR>". "<FORM ACTION=\"$PROGNAME\" METHOD=\"GET\">". "<INPUT TYPE=\"hidden\" NAME=\"func\" VALUE=\"$HASH_LOOKUP\">\n". "<INPUT TYPE=\"hidden\" NAME=\"hash_nsrl\" VALUE=\"1\">\n". make_hidden(). "<TABLE CELLSPACING=\"10\" CELLPADDING=\"2\">\n<TR>\n". "<TD ALIGN=\"LEFT\">Enter MD5 Value: ". "<INPUT TYPE=\"text\" NAME=\"md5\" SIZE=40 MAXLENGTH=32></TD>\n". "<TD ALIGN=\"LEFT\">". "<INPUT TYPE=\"IMAGE\" SRC=\"pict/but_lookup.jpg\" ". "ALT=\"Lookup\" WIDTH=116 HEIGHT=20 BORDER=0>\n". "</TD></TR>\n</TABLE>\n". "</FORM>"; } } else { print "Location: <TT>$NSRLDB</TT><BR>\n". "ERROR: Database not found<BR>\n"; } print <<EOF4; <HR><CENTER> <TABLE WIDTH=600 CELLSPACING=\"0\" CELLPADDING=\"2\"> <TR> <TD ALIGN=CENTER> <A HREF=\"$PROGNAME?func=$IMG_OPEN&$baseargs\"> <IMG SRC=\"pict/menu_b_ok.jpg\" ALT=\"Ok\" WIDTH=\"167\" HEIGHT=20 BORDER=\"0\"> </A> </TD> <TD ALIGN=CENTER> <A HREF=\"$HELP_URL\" TARGET=\"_blank\"> <IMG SRC=\"pict/menu_b_help.jpg\" ALT=\"Help\" WIDTH=\"167\" HEIGHT=20 BORDER=0> </A> </TD> </TR> </TABLE> EOF4 return; }; $funcs[$HASH_INDEX] = sub { print_html_header("Hash Database Indexing"); if ((exists $args{'hash_exclude'}) && ($args{'hash_exclude'} == 1) && ($exclude_db ne "")) { log_host_info ("Exclude Database Re-Indexed"); print "<HR><B>Exclude Database Indexing</B><P>\n"; hash_index_md5sum($exclude_db); } if ((exists $args{'hash_alert'}) && ($args{'hash_alert'} == 1) && ($alert_db ne "")) { log_host_info ("Alert Database Re-Indexed"); print "<HR><B>Alert Database Indexing</B><P>\n"; hash_index_md5sum($alert_db); } if ((exists $args{'hash_nsrl'}) && ($args{'hash_nsrl'} == 1) && ($NSRLDB ne "")) { log_host_info ("NSRL Database Re-Indexed"); print "<HR><B>NSRL Database Indexing</B><P>\n"; hash_index_nsrl(); } print "<P>Indexing Complete<BR>\n". "<HR><P>\n<A HREF=\"$PROGNAME?func=$HASH_MAIN&$baseargs\">\n". "<IMG SRC=\"pict/menu_b_hashdb.jpg\" WIDTH=\"167\" ". "HEIGHT=20 ALT=\"Hash Databases\" BORDER=\"0\"></A>\n"; return; }; # Lookup hashes in database $funcs[$HASH_LOOKUP] = sub { print_html_header("Hash Database Lookup"); unless ((exists $args{'md5'}) && ($args{'md5'} =~ /^$REG_MD5$/o)) { print_err("Invalid MD5 Argument"); } if ((exists $args{'hash_nsrl'}) && ($args{'hash_nsrl'} == 1) && ($NSRLDB ne "")) { print "<HR><B>NSRL Lookup</B><P>\n"; if (-e "$NSRLDB") { local *OUT; exec_pipe (*OUT, "'${TASKDIR}hfind' '$NSRLDB' $args{'md5'}"); print "$_<BR>\n" while (<OUT>); close (OUT); log_host_inv ("NSRL Lookup ($args{'md5'})"); } else { print "NSRL Database Missing<BR>\n"; log_host_inv ("NSRL Lookup ($args{'md5'}) - Database Missing"); } } if ((exists $args{'hash_exclude'}) && ($args{'hash_exclude'} == 1) && ($exclude_db ne "")) { print "<HR><B>Exclude Database Lookup</B><P>\n"; if (-e "$exclude_db") { local *OUT; exec_pipe (*OUT, "'${TASKDIR}hfind' '$exclude_db' $args{'md5'}"); print "$_<BR>\n" while (<OUT>); close (OUT); log_host_inv ("Exclude Database Lookup ($args{'md5'})"); } else { print "Exclude Database Missing<BR>\n"; log_host_inv ("Exclude Database Lookup ($args{'md5'}) - Database Missing"); } } if ((exists $args{'hash_alert'}) && ($args{'hash_alert'} == 1) && ($alert_db ne "")) { print "<HR><B>Alert Database Lookup</B><P>\n"; if (-e "$alert_db") { local *OUT; exec_pipe (*OUT, "'${TASKDIR}hfind' '$alert_db' $args{'md5'}"); print "$_<BR>\n" while (<OUT>); close (OUT); log_host_inv ("Alert Database Lookup ($args{'md5'})"); } else { print "Alert Database Missing<BR>\n"; log_host_inv ("Alert Database Lookup ($args{'md5'}) - Database Missing"); } } print "<HR><P>\n". "If any of the hash databases need to be re-indexed, use the ". "<U>Hash Database Manager</U><P>". "<A HREF=\"$PROGNAME?func=$HASH_MAIN&$baseargs\" TARGET=\"_blank\">\n". "<IMG SRC=\"pict/menu_b_hashdb.jpg\" WIDTH=\"167\" ". "HEIGHT=20 ALT=\"Hash Databases\" BORDER=\"0\"></A>\n"; return 0; }; ######################################################################### # # CELL - Sanitized Environment # my $CELL_MODE_SANIT = 1; my $CELL_MODE_NORM = 2; $funcs[$CELL_MAIN] = sub { check_inode('inode'); check_dir(); my $fname = "$args{'mnt'}$args{'dir'}"; print_html_header_frameset("Autopsy Cell"); print "<FRAMESET ROWS=\"15%,85%\">\n"; # if a mode was not given, then choose the Sanitized by default $args{'cell_mode'} = $CELL_MODE_SANIT unless ((exists $args{'cell_mode'}) && ($args{'cell_mode'} =~ /^\d$/)); my $url = "&$baseargs&inode=$enc_args{'inode'}&dir=$enc_args{'dir'}&". "cell_mode=$args{'cell_mode'}"; print "<FRAME SRC=\"$PROGNAME?func=${CELL_MENU}${url}\">\n". "<FRAME SRC=\"$PROGNAME?func=${CELL_CONT}${url}\">\n". "</FRAMESET>\n"; return 0; }; # Print the menu on top. This allows one to export the file and change modes $funcs[$CELL_MENU] = sub { check_inode('inode'); check_dir(); check_cell_mode(); print_html_header ("Cell Header"); my $cell_mode = $args{'cell_mode'}; my $url = "&$baseargs&inode=$enc_args{'inode'}&". "dir=$enc_args{'dir'}"; if ($cell_mode == $CELL_MODE_SANIT) { print <<EOF1; <CENTER> This file is currently being viewed in a <B>sanitized environment</B><BR> HTML files have been edited to disable scripts and links. Pictures have been replaced by place holders<BR> <TABLE WIDTH=300 CELLSPACING=\"0\" CELLPADDING=\"2\"> <TR> <TD ALIGN=CENTER> <A HREF=\"$PROGNAME?func=$CELL_MAIN$url&cell_mode=$CELL_MODE_NORM\" TARGET=\"_top\"> <IMG SRC=\"pict/sanit_b_norm.jpg\" ALT=\"Normal\" BORDER=\"0\"> </A> </TD> EOF1 } elsif ($cell_mode == $CELL_MODE_NORM) { print <<EOF2; <CENTER> This file is currently being viewed in a <B>normal environment</B><BR> HTML files are being viewed without modification.<BR> <TABLE WIDTH=300 CELLSPACING=\"0\" CELLPADDING=\"2\"> <TR> <TD ALIGN=CENTER> <A HREF=\"$PROGNAME?func=$CELL_MAIN$url&cell_mode=$CELL_MODE_SANIT\" TARGET=\"_top\"> <IMG SRC=\"pict/sanit_b_san.jpg\" ALT=\"Sanitized\" BORDER=\"0\"> </A> </TD> EOF2 } # Export the file print "<TD ALIGN=CENTER>\n". "<A HREF=\"$PROGNAME?func=$FIL_SAVE&$url\">". "<IMG SRC=\"pict/but_export.jpg\" ALT=\"export\" BORDER=\"0\" ". "WIDTH=123 HEIGHT=20>". "</A></TD></TR></TABLE>"; return; }; # Display safe and common things in the browser (pictures, basic html) $funcs[$CELL_CONT] = sub { check_inode('inode'); check_dir(); check_cell_mode(); my $inode = get_inode('inode'); my $img = get_img('img'); my $ftype = get_ftype(); my $fname = "$args{'mnt'}$args{'dir'}"; # identify what type it is local *OUT; exec_pipe (*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode | '${TASKDIR}file' -b -"); my $file_type = <OUT>; close (OUT); $file_type = "Error getting file type" if ((!defined $file_type) || ($file_type eq "")); if ($file_type =~ /JPEG image data/) { log_host_inv ("$args{'img'}: Viewing $fname ($inode) as JPEG"); print "Content-type: image/jpeg${HTTP_NL}${HTTP_NL}"; } elsif ($file_type =~ /GIF image data/) { log_host_inv ("$args{'img'}: Viewing $fname ($inode) as GIF"); print "Content-type: image/gif${HTTP_NL}${HTTP_NL}"; } elsif ($file_type =~ /PNG image data/) { log_host_inv ("$args{'img'}: Viewing $fname ($inode) as PNG"); print "Content-type: image/png${HTTP_NL}${HTTP_NL}"; } elsif ($file_type =~ /PC bitmap data/) { log_host_inv ("$args{'img'}: Viewing $fname ($inode) as BMP"); print "Content-type: image/bmp${HTTP_NL}${HTTP_NL}"; } elsif ($file_type =~ /HTML document text/) { log_host_inv ("$args{'img'}: Viewing $fname ($inode) as HTML"); print "Content-type: text/html${HTTP_NL}${HTTP_NL}"; } else { log_host_inv ("$args{'img'}: Unknown format of inode $inode "); print_html_header(""); print "Unknown File Type for Viewing: $file_type\n"; return 1; } local *OUT; exec_pipe (*OUT, "'${TASKDIR}icat' -f $ftype '$img' $inode"); while (<OUT>) { # Parse out bad "stuff" if (($file_type =~ /HTML document text/) && ($args{'cell_mode'} == $CELL_MODE_SANIT)) { $_ =~ s/\bSRC=/SRC=$SANITIZE_TAG\?/ig; $_ =~ s/\bHREF=/HREF=$SANITIZE_TAG\?/ig; $_ =~ s/<script/<$SANITIZE_TAG-script/ig; $_ =~ s/\bBACKGROUND=/BACKGROUND=$SANITIZE_TAG\?/ig; } print "$_"; } close (OUT); return 0; }; ##### Begin main ############ sub autopsy_main { # Parse arguments my $args = shift; foreach my $nam_val (split (/&/, $args)) { my ($name, $value) = split (/=/, $nam_val); if (defined $value) { my $dec_name = url_decode($name); $enc_args{$dec_name} = $value; $args{$dec_name} = url_decode($value); } } if (exists $args{'case'}) { check_case(); $case_dir = "${LOCKDIR}/".get_case()."/"; if (exists $args{'host'}) { check_host(); $host_dir = "$case_dir".get_host()."/"; read_host_config() if ($args{'func'} != $HOST_ADD_DOIT); } } if (check_func()) { # No func value was given or an invalid one was given if (exists $args{'func'}) { print_html_header(); print "Invalid func argument (positive numbers only)<BR>\n"; } else { # give the main menu if no func value was given & {$funcs[$WELCOME]}; } print "${HTTP_NL}${HTTP_NL}"; return 0; } # These functions do not need any arguments if ( ($args{'func'} == $WELCOME) || ($args{'func'} == $BLANK) || (($args{'func'} >= $CASE_LO) && ($args{'func'} <= $CASE_HI)) ) { } # need the case value elsif (($args{'func'} >= $HOST_LO) && ($args{'func'} <= $HOST_HI)) { check_case(); } # need the case and host elsif ( (($args{'func'} >= $IMG_LO) && ($args{'func'} <= $IMG_HI)) || (($args{'func'} >= $NOTES_LO) && ($args{'func'} <= $NOTES_HI)) || (($args{'func'} >= $TL_LO) && ($args{'func'} <= $TL_HI)) || (($args{'func'} >= $HASH_LO) && ($args{'func'} <= $HASH_HI)) || ($args{'func'} == $INT_LIST) || ($args{'func'} == $INT_LIST_FR)) { check_case(); check_inv(); check_host(); } # Int doesn't need the ftype because it gets messed up with body and # timelines and such elsif(($args{'func'} >= $INT_LO) && ($args{'func'} <= $INT_HI)) { check_case(); check_inv(); check_host(); check_img('img'); } # FIL, BLK, SRCH, INO, FS, INT, CASE else { check_case(); check_inv(); check_host(); check_img('img'); check_ftype(); } # special case of the strings and dls output if ((exists $img2ftype{$args{'img'}}) && (($img2ftype{$args{'img'}} eq "strings") || ($img2ftype{$args{'img'}} eq "raw") || ($img2ftype{$args{'img'}} eq "swap") || ($img2ftype{$args{'img'}} eq "dls")) ) { unless ( (($args{'func'} >= $SRCH_LO) && ($args{'func'} <= $SRCH_HI)) || (($args{'func'} >= $BLK_LO) && ($args{'func'} <= $BLK_HI)) || (($args{'func'} >= $NOTES_LO) && ($args{'func'} <= $NOTES_HI)) || (($args{'func'} >= $MAIN_LO) && ($args{'func'} <= $MAIN_HI)) || (($args{'func'} >= $IMG_LO) && ($args{'func'} <= $IMG_HI)) || ($args{'func'} == $BLANK) || (($args{'func'} >= $INT_LO) && ($args{'func'} <= $INT_HI)) ) { print_html_header(); print "Error: You selected a non-file system image ". "that can only be used for Searching and data unit browsing<BR>\n"; make_baseargs(); print "<BR><A HREF=\"$PROGNAME?$baseargs&func=$IMG_OPEN\"". "TARGET=\"_top\">Return to Host Manager</A><BR>"; exit 1; } $enc_args{'mnt'} = ""; } elsif ((exists $img2ftype{$args{'img'}}) && (($img2ftype{$args{'img'}} eq "body") || ($img2ftype{$args{'img'}} eq "timeline")) ) { # this is just a dummy section to exclude the timeline files # from the next check of mounting point } # if the mounting point was not found, then look it up elsif ((exists $args{'img'}) && (!exists $args{'mnt'})) { unless (exists $img2mnt{$args{'img'}}) { print_html_header(); print "Mounting point not found: $args{'img'}\n"; exit 1; } $args{'mnt'} = $img2mnt{$args{'img'}}; $enc_args{'mnt'} = url_encode($img2mnt{$args{'img'}}); } make_baseargs(); & {$funcs[$args{'func'}]}; print "\n</BODY>\n" if ($is_body == 1); print "\n</HTML>\n" if ($is_html == 1); print "${HTTP_NL}${HTTP_NL}"; return 0; } # This assumes that the checking of the types has been done and this just # makes a string of the key values if they exist # # case # host # img # Must add & after sub make_baseargs { $baseargs = ""; $baseargs .= "case=$enc_args{'case'}&" if ((exists $enc_args{'case'}) && ($enc_args{'case'} ne "")); $baseargs .= "host=$enc_args{'host'}&" if ((exists $enc_args{'host'}) && ($enc_args{'host'} ne "")); $baseargs .= "inv=$enc_args{'inv'}&" if ((exists $enc_args{'inv'}) && ($enc_args{'inv'} ne "")); $baseargs_noimg = $baseargs; $baseargs .= "img=$enc_args{'img'}&" if ((exists $enc_args{'img'}) && ($enc_args{'img'} ne "")); $baseargs .= "ftype=$enc_args{'ftype'}&" if ((exists $enc_args{'ftype'}) && ($enc_args{'ftype'} ne "")); $baseargs .= "mnt=$enc_args{'mnt'}&" if ((exists $enc_args{'mnt'}) && ($enc_args{'mnt'} ne "")); # remove the final '&' $baseargs_noimg = $1 if ($baseargs_noimg =~ /^(.*?)&$/); $baseargs = $1 if ($baseargs =~ /^(.*?)&$/); return; }; # Does not do mnt or img sub make_hidden { my $str = ""; $str .= "<INPUT TYPE=\"hidden\" NAME=\"host\" VALUE=\"$args{'host'}\">\n" if ((exists $args{'host'}) && ($args{'host'} ne "")); $str .= "<INPUT TYPE=\"hidden\" NAME=\"case\" VALUE=\"$args{'case'}\">\n" if ((exists $args{'case'}) && ($args{'case'} ne "")); $str .= "<INPUT TYPE=\"hidden\" NAME=\"inv\" VALUE=\"$args{'inv'}\">\n" if ((exists $args{'inv'}) && ($args{'inv'} ne "")); return $str; } #########################################################################3 # # Config Files # # # Return a hash of the keywords and the values sub read_case_config { my $case; if (scalar (@_) == 1) { $case = shift; } else { $case = get_case(); } my $fname = case_config_fname($case); open CONFIG, "<$fname" or die "Can't open case config file ($fname)"; my %vals; while (<CONFIG>) { next if ((/^\#/) || (/^\s+$/)); s/^\s+//; s/\s+$//; $vals{$1} = $2 if (/^(\S+)\s+(.*)$/); } close (CONFIG); $vals{'desc'} = "None Provided" unless (exists $vals{'desc'}); $vals{'created'} = "unknown" unless (exists $vals{'created'}); $vals{'images'} = $IMGDIR unless (exists $vals{'images'}); $vals{'data'} = $DATADIR unless (exists $vals{'data'}); $vals{'log'} = $LOGDIR unless (exists $vals{'log'}); $vals{'reports'} = $REPDIR unless (exists $vals{'reports'}); return %vals; }; # reads host config file and sets global hash values for images and other sub read_host_config { my $host = get_host(); my $cfile = host_config_fname(); unless (open (FILE, $cfile)) { print_check_err("Error opening $cfile"); } %img2mnt = (); %img2ftype = (); %mod2img = (); %img2str = (); %img2dls = (); $tz = ""; $ts = 0; $host_desc = ""; $exclude_db = ""; $alert_db = ""; while (<FILE>) { next if ((/^\#/) || (/^\s+$/)); # remove whitespace s/^\s+//; s/\s+$//; # normal file system image entry # # 'image images/hda1.dd openbsd /usr if (/^image\s+($REG_IMG)\s+([\w\-]+)\s+([\w\-\_\.\/:\\]+)$/o) { my $i = $1; my $t = $2; my $r = $3; unless (defined $root_inode{$t}) { print_check_err("Error: unknown type: $t in host config: $.". "<BR>Edit the file and refresh your browser"); } unless ((-e "${host_dir}${i}") || (-l "${host_dir}${i}")) { print_check_err("Error: image in ${host}.host:$. not found: ". "${host_dir}${i}<BR>Edit the config file and refresh your browser". "<BR>(Or your version of Perl does not support large files)"); } $img2ftype{$i} = $t; # Add trailing / to original mount point if needed if (($r !~ /.*?\/$/) && ($r !~ /.*?\\$/)) { $r .= '/'; } $img2mnt{$i} = $r; } # entry for a strings or dls file # # strings data/hda1.str images/hda1.dd elsif (/^strings\s+($REG_IMG)\s+($REG_IMG)$/o) { my $i = $1; my $o = $2; unless ((-e "${host_dir}${i}") || (-l "${host_dir}${i}")) { print_check_err("Error: strings file not found: ". "${host_dir}${i}<BR>Edit host config and refresh your browser"); } unless ((-e "${host_dir}${o}") || (-l "${host_dir}${o}")) { print_check_err("Error: strings original not found: ". "${host_dir}${o}<BR>Edit host config and refresh your browser"); } $img2ftype{$i} = "strings"; $mod2img{$i} = $o; $img2str{$o} = $i; } # dls entry # dls data/image.dls [images/image.dd] elsif (/^dls\s+($REG_IMG)\s*($REG_IMG)?$/o) { my $dls = $1; unless ((-e "${host_dir}${dls}") || (-l "${host_dir}${dls}")) { print_check_err("Error: dls file not found: ". "${host_dir}${dls}<BR>Edit host config and refresh your browser"); } $img2ftype{$dls} = "dls"; if (defined $2) { my $dd = $2; unless ((-e "${host_dir}${dd}") || (-l "${host_dir}${dd}")) { print_check_err("Error: dls original not found: ". "${host_dir}${dd}<BR>Edit host config and refresh your browser"); } $mod2img{$dls} = $dd; $img2dls{$dd} = $dls; } } # swap # swap images/hda3.dd elsif (/^swap\s+($REG_IMG)\s*$/o) { my $i = $1; unless ((-e "${host_dir}${i}") || (-l "${host_dir}${i}")) { print_check_err("Error: swap in ${host}.host:$. not found: ". "${host_dir}${i}<BR>Edit the config file and refresh your browser". "<BR>(Or your version of Perl does not support large files)"); } $img2ftype{$i} = "swap"; } # raw # raw images/hda3.dd elsif (/^raw\s+($REG_IMG)\s*$/o) { my $i = $1; unless ((-e "${host_dir}${i}") || (-l "${host_dir}${i}")) { print_check_err("Error: raw in ${host}.host:$. not found: ". "${host_dir}${i}<BR>Edit the config file and refresh your browser". "<BR>(Or your version of Perl does not support large files)"); } $img2ftype{$i} = "raw"; } # body data/body.txt elsif (/^body\s+($REG_IMG)$/o) { my $i = $1; unless ((-e "${host_dir}${i}") || (-l "${host_dir}${i}")) { print_check_err("Error: body file not found: ". "${host_dir}${i}<BR>Edit host config and refresh your browser"); } $img2ftype{$i} = "body"; } # timeline data/timeline.txt elsif (/^timeline\s+($REG_IMG)$/o) { my $i = $1; unless ((-e "${host_dir}${i}") || (-l "${host_dir}${i}")) { print_check_err("Error: timeline file not found: ". "${host_dir}${i}<BR>Edit host config and refresh your browser"); } $img2ftype{$i} = "timeline"; } # timezone XYZ elsif (/^timezone\s+($REG_ZONE1)$/o) { $tz = $1; } # timeskew XYZ elsif (/^timeskew\s+($REG_SKEW)$/o) { $ts = $1; } # desc XYZ elsif (/^desc\s+(.*)$/) { $host_desc = $1; } # hash databases elsif (/^alert_db\s+'(.*)'$/) { $alert_db = $1; } elsif (/^exclude_db\s+'(.*)'$/) { $exclude_db = $1; } else { my $msg = "Error: invalid entry in $cfile:$.". "<BR>\n". "image path fs_type mnt_point<BR>\n". "strings path orig_img<BR>\n". "dls path [orig_img]<BR>\n". "body path<BR>\n". "timeline path<BR>\n". "timezone TZ<BR>\n". "desc DESCRIPTION<BR>\n"; print_check_err($msg); } } close (FILE); if ($tz eq "") { print_check_err ("Missing Timezone Variable in Host Config"); } } # Remove any entries with the given image name from the host config # and add a new one # # If type is "", then nothing is written, just removed sub update_host_config { my $type = shift; my $img = shift; my $ref = shift; my $read = host_config_fname(); my $write = $read."-".rand(); unless (open (READ, "<$read")) { print "Error opening $read"; exit (1); } unless (open (WRITE, ">$write")) { print "Error opening $write"; exit (1); } while (<READ>) { s/^\s+//; s/\s+$//; print WRITE "$_\n" unless ((/^(\w+)\s+($REG_IMG)/o) && ($2 eq $img) && ($1 ne 'desc') && ($1 ne 'timezone')); } if ($type ne "") { if (defined $ref) { print WRITE "$type $img $ref\n"; } else { print WRITE "$type $img\n"; } } close (READ); close (WRITE); rename $write, $read; return; }; # Given the image and md5, it is saved to the MD5.txt file and any other # references to the image are removed # # if $md5 is "", then nothing is written sub update_md5 { my $img = shift; my $md5 = shift; $md5 =~ tr/[a-f]/[A-F]/; (my $img_dir) = split (/\//,$img); my $read = "${host_dir}/$img_dir/${MD5_FILE}"; my $write = $read."-".rand(); unless (open (WRITE, ">$write")) { print "Error opening $write"; exit (1); } if (-e "$read") { unless (open (READ, "<$read")) { print "Error opening $read"; exit (1); } while (<READ>) { s/^\s+//; s/\s+$//; print WRITE "$_\n" unless ((/^$REG_MD5\s+($REG_IMG)/o) && ($1 eq $img)); } close (READ); } print WRITE "$md5 $img\n" if ($md5 ne ""); close (WRITE); rename $write, $read; return; } # Write the login name to the investigators file sub write_invest { my $name = shift; my $fname = investig_fname(); open INVES, ">>$fname" or die "Can't open investigators file: $fname"; if ($name =~ /^$REG_INVESTIG$/o) { print INVES "$name\n"; } else { print_err ("Invalid investigator: $name"); } close (INVES); } # Read the investigators file and return a sorted list sub read_invest { my $fname = investig_fname(); open INVES, "<$fname" or return; my @investigs; while (<INVES>) { chomp; s/^\s+//; s/\s+$//; push @investigs, $_ if (/^$REG_INVESTIG$/o); } close (INVES); sort {lc($a) cmp lc($b)} @investigs; } #### END OF MAIN #### # if no args are passed, return case config using args{'case'}, # else use the case value passed # # Case config: # In case directory with case_name.case sub case_config_fname { if (scalar (@_) == 1) { my $c = shift; return "${LOCKDIR}$c/case.aut"; } else { return "${LOCKDIR}$args{'case'}/case.aut"; } } # Case log # In case directory with case_name.log sub case_log_fname { return "${case_dir}/case.log"; } # File of investigators name in list sub investig_fname { return "${case_dir}/investigators.txt"; } sub investig_notes_fname { return "${host_dir}/logs/".$args{'inv'}.".notes"; } sub investig_seq_notes_fname { return "${host_dir}/logs/".$args{'inv'}.".seq.notes"; } sub investig_log_fname { return "${host_dir}/$LOGDIR/$args{'inv'}.log"; } sub investig_exec_log_fname { return "${host_dir}/$LOGDIR/$args{'inv'}.exec.log"; } sub host_log_fname { return "${host_dir}/$LOGDIR/host.log"; } # if no args are passed, return host config using args{'host'}, # else use the host value passed sub host_config_fname { if (scalar (@_) == 1) { my $h = shift; return "${case_dir}$h/host.aut"; } else { return "${host_dir}host.aut"; } } ###################### COMMAND WRAPPERS ###################### # exec_pipe(HANDLE, CMD); sub exec_pipe { my $handle = shift(@_); my $cmd = shift(@_); die "Can't open pipe for exec_pipe" unless defined(my $pid = open ($handle , "-|") ); if ($pid) { # this sucks, but for some reason the buffers don't empty if # this isn't there and the output is missing sometimes sleep(1); return $handle; } else { $| = 1; log_host_inv_exec ("$cmd"); exec("$cmd") or die "Can't exec program: $!"; } } sub exec_sys { my $cmd = shift(@_); log_host_inv_exec ("$cmd"); system ($cmd); return; } ###################### INPUT CHECKS ###################### # # Arguments # sub check_func { if ((!exists $args{'func'}) || ($args{'func'} !~ /^\d+$/) || (!(defined $funcs[$args{'func'}])) ) { return 1; } return 0; } # We don't allow much for the image because this is an argument to # the TASK programs. We keep these files only in one # directory and for easy/simple security only allow basic names # Symbolic links are allowed if these simple names are not desired # # Allowed values are A-Za-z0-9_-. sub check_img { my $img = shift; if (!exists $args{$img}) { print_check_err ("Missing image ($img) argument"); } elsif ($args{$img} =~ /^$REG_IMG$/o) { # Check for its actual existence print_check_err("Missing image in host dir ($img): $args{$img}") unless ((-e "${host_dir}$args{$img}") || (-l "${host_dir}$args{$img}")); print_check_err("Invalid directory in image name") if (($args{$img} =~ /^\//) || ($args{$img} =~ /^\.\./)); } else { print_check_err ("Invalid image ($img) value (only letters, ". "numbers,-,.,_) [$args{$img}]"); } return 0; } # Return the full path of the image sub get_img { my $img_cat = shift; if ($args{$img_cat} =~ /^($REG_IMG)$/o) { return "${host_dir}$1"; } print_err("Invalid Image"); } # img_path is used when adding images - it is the full path to the # non-evidence locker copy of the image sub check_img_path { if (!exists $args{'img_path'}) { print_check_err ("Missing image (img_path) argument"); } elsif ($args{'img_path'} =~ /^$REG_IMG_PATH$/o) { # Check for its actual existence print_check_err("Image not found at $args{'img_path'}") unless ((-e "$args{'img_path'}") || (-l "$args{'img_path'}")); } else { print_check_err ("Invalid image path (only letters, ". "numbers,-,.,_/ and start with /) [$args{'img_path'}]"); } return 0; } sub get_img_path { if ($args{'img_path'} =~ /^($REG_IMG_PATH)$/o) { return "$1"; } print_err("Invalid Image Path"); } # Case name sub check_case { unless (exists $args{'case'}) { print_check_err ("Missing case argument"); } unless ($args{'case'} =~ /^$REG_CASE$/o) { print_check_err ("Invalid case value (letters, num, and symbols only"); } return 0; } sub get_case { if ($args{'case'} =~ /^($REG_CASE)$/o) { return $1; } print_err("Invalid Case Name"); } # Host name sub check_host { unless (exists $args{'host'}) { print_check_err ("Missing host argument"); } unless ($args{'host'} =~ /^$REG_HOST$/o) { print_check_err ("Invalid host value"); } return 0; } sub get_host { if ($args{'host'} =~ /^($REG_HOST)$/o) { return $1; } print_err("Invalid Host"); } sub check_inv { unless (exists $args{'inv'}) { print_check_err ("Missing inv argument"); } unless ($args{'inv'} =~ /^$REG_INVESTIG$/o) { print_check_err ("Invalid inv value (letters, num, and symbols only"); } return 0; } sub get_inv { if ($args{'inv'} =~ /^($REG_INVESTIG)$/o) { return $1; } print_err("Invalid Investigator"); } sub check_fname { unless (exists $args{'fname'}) { print_check_err ("Missing fname argument"); } unless ($args{'fname'} =~ /^$REG_FNAME$/o) { print_check_err ("Invalid fname value (only letters, ". "numbers,-,., and _)"); } return 0; } sub get_fname { if ($args{'fname'} =~ /^($REG_FNAME)$/o) { return "${host_dir}${DATADIR}/$1"; } print_err("Invalid File Name"); } # Return the relative fname sub get_fname_rel { if ($args{'fname'} =~ /^($REG_FNAME)$/o) { return "$DATADIR/$1"; } print_err("Invalid Relative File Name"); } sub check_body { unless (exists $args{'body'}) { print_check_err ("Missing body argument"); } unless ($args{'body'} =~ /^$REG_BODY$/o) { print_check_err ("Invalid body value (only letters, ". "numbers,-,., and _)"); } return 0; } sub get_body { if ($args{'body'} =~ /^($REG_BODY)$/o) { return "${host_dir}${DATADIR}/$1"; } print_err("Invalid Body"); } sub check_tl { if (!exists $args{'tl'}) { print_check_err ("Missing timeline argument"); } elsif ($args{'tl'} =~ /^($REG_TL)$/o) { # Check for its actual existence unless ((-e "${host_dir}${DATADIR}/$1") || (-l "${host_dir}${DATADIR}/$1")) { print_check_err("Missing timeline: ${host_dir}${DATADIR}/$1"); } } else { print_check_err ("Invalid timeline value (only letters, ". "numbers,-,., and _)"); } return 0; } sub get_tl { if ($args{'tl'} =~ /^($REG_TL)$/o) { return "${host_dir}${DATADIR}/$1"; } print_err("Invalid Timeline"); } sub check_fname_mode { if (!exists $args{'fname_mode'}) { print_check_err ("Missing fname_mode argument"); } unless ($args{'fname_mode'} =~ /^\d+$/) { print_check_err ("invalid mode: numbers only"); } return 0; } sub get_sorter_dir { if ($args{'img'} =~ /^.*?\/(.*)$/) { return "${host_dir}${DATADIR}/sorter-$1/"; } print_err("Invalid Sorter Directory"); } sub get_sorter_graphics_dir { if ($args{'img'} =~ /^.*?\/(.*)$/) { return "${host_dir}${DATADIR}/sorter-graphics-$1/"; } print_err("Invalid Sorter Graphics Directory"); } sub check_dir { if ((!exists $args{'dir'}) || ($args{'dir'} =~ /\/\.\.\//) || ($args{'dir'} =~ /\;/) ) { print_check_err("Invalid dir argument (valid file path only)"); } return 0; } sub get_dir { if ($args{'dir'} =~ /([^;]*)/o) { return $1; } print_err("Invalid Directory"); } sub check_mnt { my $ftype = get_ftype(); if (($ftype eq "dls") || ($ftype eq "swap") || ($ftype eq "raw")) { $args{'mnt'} = $ftype; } elsif (!exists $args{'mnt'}) { print_check_err("Missing mount point argument"); } elsif ($args{'mnt'} =~ /\/\.\.\//) { print_check_err("Invalid mount point argument (valid file path only)"); } unless ($args{'mnt'} =~ /^$REG_MNT$/o) { print_check_err("Invalid mount point argument (valid file path only)"); } return 0; } sub get_mnt { if ($args{'mnt'} =~ /($REG_MNT)/o) { return $1; } print_err("Invalid Mounting Point"); } sub check_inode { my $inode = shift; if ((!exists $args{$inode}) || ($args{$inode} !~ /^$REG_INODE$/o) || ($args{$inode} < 0)) { print_check_err("Invalid inode ($inode) argument (numbers >= 0 only)"); } return 0; } # We can only have positive numbers sub get_inode { my $inode = shift; if ($args{$inode} =~ /^($REG_INODE)$/o) { return $1; } print_err("Invalid Inode"); } sub get_force { if ($args{'force'} =~ /^(\d+)$/) { return $1; } print_err("Invalid Force Flag"); } sub check_block { if ((!exists $args{'block'}) || ($args{'block'} !~ /^\d+$/)) { print_check_err("Invalid block argument (positive numbers only)"); } return 0; } sub get_block { if ($args{'block'} =~ /^(\d+)$/) { return $1; } print_err("Invalid Block"); } sub check_cell_mode { if ((!exists $args{'cell_mode'}) || ($args{'cell_mode'} !~ /^\d$/o)) { print_check_err("Invalid cell_mode argument (numbers >= 0 only)"); } return 0; } sub check_len { if ((!exists $args{'len'}) || ($args{'len'} !~ /^\d+$/)) { print_check_err("Invalid len argument (positive numbers only)"); } return 0; } sub get_len { if ((exists $args{'len'}) && ($args{'len'} =~ /^(\d+)$/)) { return $1; } # return the default len of 1 if it is not defined return 1; } sub check_sort { if ((!exists $args{'sort'}) || ($args{'sort'} !~ /^\d+$/)) { print_check_err("Invalid sort argument (positive numbers only)"); } return 0; } sub get_sort { if ($args{'sort'} =~ /^(\d+)$/) { return $1; } print_err("Invalid sort flag"); } # ifind is optional and by default is 0 if not given sub get_ifind { if (!exists $args{'ifind'}) { return 0; } elsif ($args{'ifind'} =~ /^(\d+)$/) { return $1; } print_err("Invalid ifind flag"); } sub check_mode { if ((!exists $args{'mode'}) || ($args{'mode'} !~ /^\d+$/)) { print_check_err("Invalid mode argument (positive numbers only)"); } return 0; } sub get_mode { if ($args{'mode'} =~ /^(\d+)$/) { return $1; } print_err("Invalid Mode"); } sub check_dmode { if ((!exists $args{'dmode'}) || ($args{'dmode'} !~ /^\d+$/)) { print_check_err("Invalid dmode argument (positive numbers only)"); } return 0; } sub get_dmode { if ($args{'dmode'} =~ /^(\d+)$/) { return $1; } print_err("Invalid dmode"); } sub get_min { if ($args{'min'} =~ /^(\d+)$/) { return $1; } print_err("Invalid Minute"); } sub check_htype { if ((!exists $args{'htype'}) || ($args{'htype'} !~ /^\d+$/)) { print_check_err("Invalid htype argument (positive numbers only)"); } return 0; } sub get_htype { if ($args{'htype'} =~ /^(\d+)$/) { return $1; } print_err("Invalid htype"); } # This should be made more flexible sub check_str { if (!exists $args{'str'}) { print_check_err("Missing string argument"); } return 0; } # Get the string to search for with grep # This should be made more flexible sub get_str { if ($args{'str'} =~ /^\s*(.*)$/) { return $1; } print_err("Invalid String"); } # Index for previous keyword search sub check_srchidx { if ((!exists $args{'srchidx'}) || ($args{'srchidx'} !~ /^\d+$/)) { print_check_err("Invalid srchidx argument (positive numbers only)"); } return 0; } sub check_tz { if ((!exists $args{'tz'}) || ($args{'tz'} !~ /^$REG_ZONE1$/o)) { print_check_err("Missing time zone argument"); } return 0; } sub get_tz { if ($args{'tz'} =~ /^($REG_ZONE1)$/o) { return $1; } print_err("Invalid Timezone"); } sub check_do_md5 { if ((!exists $args{'do_md5'}) || ($args{'do_md5'} !~ /^\d+$/)) { print_check_err("Missing do_md5 argument"); } return 0; } sub get_do_md5 { if ($args{'do_md5'} =~ /^\s*(\d+)$/) { return $1; } print_err("Invalid MD5 Flag"); } sub check_ts { if ((!exists $args{'ts'}) || ($args{'ts'} !~ /^$REG_SKEW$/o)) { print_check_err("Missing time skew argument"); } return 0; } sub get_ts { if ($args{'ts'} =~ /^\s*($REG_SKEW)$/o) { return $1; } print_err("Invalid Time Skew"); } sub check_note { if (!exists $args{'note'}) { print_check_err("Missing note argument"); } return 0; } sub check_ftype { unless (((exists $img2ftype{$args{'img'}}) && ($img2ftype{$args{'img'}} =~ /^$REG_FTYPE$/o)) || ((exists $args{'ftype'}) && ($args{'ftype'} =~ /^$REG_FTYPE$/o)) ) { print_check_err("Missing or invalid ftype value"); } return 0; } sub get_ftype { unless ((exists $args{'img'}) && (exists $img2ftype{$args{'img'}})) { if (exists $args{'ftype'}) { if ($args{'ftype'} =~ /^($REG_FTYPE)$/o) { return $1; } return 0; } print_check_err("Missing ftype value"); } return $img2ftype{$args{'img'}}; } sub check_st_mon { if ((exists $args{'st_mon'}) && ($args{'st_mon'} =~ /^(\d\d?)$/)) { if (($1 < 1) || ($1 > 12)) { print ("Invalid start month\n"); return 1; } } else { print ("Invalid start month\n"); return 1; } } sub get_st_mon { if ($args{'st_mon'} =~ /^(\d\d?)$/) { return $1; } print_err("Invalid Month"); } sub check_st_year { if ((exists $args{'st_year'}) && ($args{'st_year'} =~ /^(\d\d\d\d?)$/)) { if (($1 < 1970) || ($1 > 2020)) { print ("Invalid start year\n"); return 1; } } else { print ("Invalid start year\n"); return 1; } } sub get_st_year { if ($args{'st_year'} =~ /^(\d\d\d\d)$/) { return $1; } print_err("Invalid Year"); } # sub get_unitsize { my $ftype = get_ftype(); my $dcat_out; if ($ftype eq 'dls') { if (exists $mod2img{$args{'img'}}) { my $orig = $mod2img{$args{'img'}}; local *OUT; exec_pipe(*OUT, "'${TASKDIR}dcat' -f $img2ftype{$orig} -s '$host_dir$orig'"); $dcat_out = <OUT>; close (OUT); } # We don't have the original image, so just set the size to 512 else { return 512; } } elsif ($ftype eq 'swap') { return 4096; } elsif ($ftype eq 'raw') { return 512; } else { my $img = get_img('img'); local *OUT; exec_pipe(*OUT, "'${TASKDIR}dcat' -f $ftype -s '$img'"); $dcat_out = <OUT>; close (OUT); } $dcat_out = "Error getting unit size" if ((!defined $dcat_out) || ($dcat_out eq "")); if ($dcat_out =~ /(\d+): Size of Addressable Unit/) { return $1; } else { print "Error identifying block size (dcat -s output)<BR>\n"; print "$dcat_out<BR>\n"; exit(1); } }; ############## URL UTILITIES ################## sub html_encode { my $text = shift; $text =~ s/&/&/gs; $text =~ s/</</gs; $text =~ s/>/>/gs; # @@@ LEADING SPACES and TABS # while ($text =~ s/^( )*\t/"$1 "/eig) {} # while ($text =~ s/^( )* /"$1 "/eig) {} return $text; } sub url_encode { my $text = shift; $text =~ s/([^a-z0-9_.!~*'() -])/sprintf "%%%02X", ord($1)/eig; $text =~ tr/ /+/; return $text; } sub url_decode { my $text = shift; $text =~ tr/\+/ /; $text =~ s/%([a-f0-9][a-f0-9])/chr( hex( $1 ) )/eig; return $text; } ############ LOGGING ######################## sub log_session_info { return unless ($USE_LOG == 1); my $str = shift; chomp $str; my $date = localtime; my $lname = "autopsy.log"; open AUTLOG, ">>${LOCKDIR}/$lname" or die "Can't open log: $lname"; print AUTLOG "$date: $str\n"; close (AUTLOG); return; }; sub log_case_info { return unless ($USE_LOG == 1); my $str = shift; chomp $str; my $date = localtime; my $fname = case_log_fname(); open CASELOG, ">>$fname" or die "Can't open log: $fname"; print CASELOG "$date: $str\n"; close (CASELOG); return; }; # log data to the general log file for the host sub log_host_info { return unless ($USE_LOG == 1); my $str = shift; chomp $str; my $date = localtime; my $fname = host_log_fname(); open HOSTLOG, ">>$fname" or die "Can't open log: $fname"; print HOSTLOG "$date: $str\n"; close (HOSTLOG); return; }; # Log data to the investigators specific log file sub log_host_inv { return unless ($USE_LOG == 1); my $str = shift; chomp $str; my $date = localtime; my $fname = investig_log_fname(); open HOSTLOG, ">>$fname" or die "Can't open log: $fname"; print HOSTLOG "$date: $str\n"; close (HOSTLOG); return; }; sub log_host_inv_exec { return unless ($USE_LOG == 1); my $str = shift; chomp $str; # We may not have a full host setup yet so check the reqs for the # exec log file return unless (defined $host_dir && $host_dir ne ""); return unless (exists $args{'inv'} && $args{'inv'} ne ""); my $date = localtime; my $fname = investig_exec_log_fname(); open HOSTLOG, ">>$fname" or die "Can't open log: $fname"; print HOSTLOG "$date: $str\n"; close (HOSTLOG); return; } ############ DISPLAY ######################## sub print_check_err { print_html_header(""); print shift()."<BR>\n"; sleep (1); exit 1; } sub print_err { print shift()."<BR>\n"; sleep (1); exit 1; } # The page that makes the frameset does not have a body statement # This routine is used to make the minimum required header statements sub print_html_header_frameset { my $text = shift; print "Content-type: text/html${HTTP_NL}${HTTP_NL}"; my $time = localtime(); print <<EOF; <HTML> <!-- Autopsy ver. $VER Forensic Browser --> <!-- Page created at: $time --> <HEAD> <TITLE>$text</TITLE> </HEAD> EOF $is_html = 1; } # Create the header information with the body tag sub print_html_header { print_html_header_frameset(shift); print "<BODY BGCOLOR=\"$BACK_COLOR\">\n\n"; $is_body = 1; } # Print the header with the margins set to 0 so that the tab buttons # are flush with the edges of the frame sub print_html_header_tabs { print_html_header_frameset(shift); print "<BODY MARGINHEIGHT=0 MARGINWIDTH=0 TOPMARGIN=0 ". "LEFTMARGIN=0 RIGHTMARGIN=0 BOTMARGIN=0 BGCOLOR=\"$BACK_COLOR\">\n\n"; $is_body = 1; } # Header for front page to warn about java script sub print_javascript_header { my $text = shift; print "Content-type: text/html${HTTP_NL}${HTTP_NL}"; my $time = localtime(); # The write line has to stay on one line print <<EOF; <HTML> <!-- Autopsy ver. $VER Forensic Browser --> <!-- Page created at: $time --> <HEAD> <TITLE>$text</TITLE> <SCRIPT language=\"JavaScript\"> <!-- hide script from old browsers document.write(\'<CENTER><FONT COLOR=\"red\"><P>WARNING: Your browser currently has Java Script enabled</FONT><P>You do not need Java Script to use Autopsy and it is recommended that it be turned off for security reasons<HR></CENTER>\'); //--> </SCRIPT> </HEAD> <BODY BGCOLOR=\"$BACK_COLOR\"> EOF $is_html = 1; $is_body = 1; } # For raw text outputs # This only has ONE newline at the end so that a Content-Disposition # can be added. A newline must be added if Disposition is not used. sub print_text_header { print "Content-type: text/plain${HTTP_NL}"; } # For forced save outputs # This only has ONE newline at the end so that a Content-Disposition # can be added. A newline must be added if Disposition is not used. sub print_oct_header { print "Content-type: application/octet-stream${HTTP_NL}"; } # remove control chars from printout sub print_output { while (my $out = shift) { foreach $_ (split (//, $out)) { if (($_ eq "\n") || ($_ eq "\r") || ($_ eq "\f") || ($_ eq "\t") ) { print "$_"; } elsif ((ord($_) < 0x20) || (ord($_) > 0x7e)) { print "^".ord($_); } else { print "$_"; } } } }