mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
4152 lines
131 KiB
Perl
4152 lines
131 KiB
Perl
#
|
|
# Case Management methods, including the windows and functions to read the
|
|
# config files
|
|
#
|
|
# Brian Carrier [carrier@sleuthkit.org]
|
|
# Copyright (c) 2001-2005 by Brian Carrier. All rights reserved
|
|
#
|
|
# This file is part of the Autopsy Forensic Browser (Autopsy)
|
|
#
|
|
# Autopsy is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Autopsy is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Autopsy; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
|
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
|
# MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
|
|
# IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
# (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR
|
|
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
package Caseman;
|
|
|
|
# If the order of these views are changed, then the order of the main
|
|
# function may have to be as well
|
|
|
|
# Case Views
|
|
$Caseman::CASE_NEW = 1;
|
|
$Caseman::CASE_NEW_DOIT = 2;
|
|
$Caseman::CASE_OPEN = 3;
|
|
$Caseman::CASE_OPEN_LOG = 4;
|
|
$Caseman::CASE_DETAILS = 5;
|
|
|
|
# $Caseman::CASE_DEL = 6;
|
|
my $CASE_MAX = 5;
|
|
|
|
# Host Views
|
|
$Caseman::HOST_ADD = 7;
|
|
$Caseman::HOST_ADD_DOIT = 8;
|
|
$Caseman::HOST_OPEN = 9;
|
|
$Caseman::HOST_OPEN_LOG = 10;
|
|
$Caseman::HOST_DETAILS = 11;
|
|
|
|
# $Caseman::HOST_DEL = 12;
|
|
my $HOST_MAX = 11;
|
|
|
|
# Image Views
|
|
$Caseman::IMG_ADD = 13;
|
|
$Caseman::IMG_ADD_PREP = 14;
|
|
$Caseman::IMG_ADD_DOIT = 15;
|
|
$Caseman::VOL_OPEN = 16;
|
|
$Caseman::VOL_OPEN_LOG = 17;
|
|
$Caseman::VOL_DETAILS = 18;
|
|
$Caseman::IMG_DEL = 19;
|
|
$Caseman::VOL_MAKESTR = 20;
|
|
$Caseman::VOL_MAKEBLKLS = 21;
|
|
my $IMG_MAX = 21;
|
|
|
|
# Module Variables
|
|
# %vol2par - Volume to parent volume (vol to img, str to vol)
|
|
# %vol2start - Starting sector of volume in image
|
|
# %vol2end - ending sector of volume in image
|
|
# %vol2cat - The big picture type of volume (part, disk, strings, blkls)
|
|
# %vol2ftype - The file system type (fat, dos, ntfs etc.)
|
|
# %vol2itype - The image file type (could be for a parent image)
|
|
# %vol2dtype- the disk type
|
|
# %mod2vol; # Mapping for image, given the strings or blkls
|
|
# %vol2mnt; # Mapping for mount point, given the vol name
|
|
# %vol2str; # Mapping for ASCII strings file, given the vol name
|
|
# %vol2uni; # Mapping for Unicode strings file, given the vol name
|
|
# %vol2blkls; # Mapping for blkls file, given the vol name
|
|
# %vol2path - full file path of volume
|
|
# %vol2sname - short name of volume
|
|
|
|
sub main {
|
|
|
|
# By default, show the case open window
|
|
$Args::args{'view'} = $Args::enc_args{'view'} = $Caseman::CASE_OPEN
|
|
unless (exists $Args::args{'view'});
|
|
|
|
Args::check_view();
|
|
my $view = Args::get_view();
|
|
|
|
# The only live function is for the open img
|
|
if ($::LIVE == 1) {
|
|
Args::check_inv();
|
|
if ($view == $Caseman::VOL_OPEN) {
|
|
return vol_open();
|
|
}
|
|
|
|
Args::check_vol('vol');
|
|
|
|
# Args::check_ftype();
|
|
# Args::check_mnt();
|
|
|
|
if ($view == $Caseman::VOL_OPEN_LOG) {
|
|
return vol_open_log();
|
|
}
|
|
else {
|
|
Print::print_check_err(
|
|
"Invalid Live Analysis Case Management View");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
# Case functions
|
|
if ($view <= $CASE_MAX) {
|
|
if ($view == $Caseman::CASE_OPEN) {
|
|
return case_open();
|
|
}
|
|
elsif ($view == $Caseman::CASE_NEW) {
|
|
return case_new();
|
|
}
|
|
|
|
Args::check_case();
|
|
$::case_dir = "$::LOCKDIR/" . Args::get_case() . "/";
|
|
$::case_dir =~ s/\/\//\//g;
|
|
|
|
if ($view == $Caseman::CASE_OPEN_LOG) {
|
|
return case_open_log();
|
|
}
|
|
elsif ($view == $Caseman::CASE_NEW_DOIT) {
|
|
return case_new_doit();
|
|
}
|
|
elsif ($view == $Caseman::CASE_DETAILS) {
|
|
return case_details();
|
|
}
|
|
}
|
|
|
|
Args::check_case();
|
|
$::case_dir = "$::LOCKDIR/" . Args::get_case() . "/";
|
|
$::case_dir =~ s/\/\//\//g;
|
|
|
|
# Host functions
|
|
if ($view <= $HOST_MAX) {
|
|
if ($view == $Caseman::HOST_OPEN) {
|
|
return host_open();
|
|
}
|
|
elsif ($view == $Caseman::HOST_ADD) {
|
|
return host_add();
|
|
}
|
|
|
|
Args::check_host();
|
|
$::host_dir = "$::case_dir" . Args::get_host() . "/";
|
|
$::host_dir =~ s/\/\//\//g;
|
|
if ($view == $Caseman::HOST_ADD_DOIT) {
|
|
return host_add_doit();
|
|
}
|
|
|
|
Caseman::read_host_config();
|
|
if ($view == $Caseman::HOST_OPEN_LOG) {
|
|
return host_open_log();
|
|
}
|
|
elsif ($view == $Caseman::HOST_DETAILS) {
|
|
return host_details();
|
|
}
|
|
}
|
|
|
|
Args::check_host();
|
|
$::host_dir = "$::case_dir" . Args::get_host() . "/";
|
|
$::host_dir =~ s/\/\//\//g;
|
|
Caseman::read_host_config();
|
|
Args::check_inv();
|
|
|
|
if ($view <= $IMG_MAX) {
|
|
if ($view == $Caseman::VOL_OPEN) {
|
|
return vol_open();
|
|
}
|
|
elsif ($view == $Caseman::IMG_ADD) {
|
|
return img_add();
|
|
}
|
|
elsif ($view == $Caseman::IMG_ADD_PREP) {
|
|
return img_add_prep();
|
|
}
|
|
elsif ($view == $Caseman::IMG_ADD_DOIT) {
|
|
return img_add_doit();
|
|
}
|
|
|
|
Args::check_vol('vol');
|
|
|
|
if ($view == $Caseman::VOL_OPEN_LOG) {
|
|
return vol_open_log();
|
|
}
|
|
elsif ($view == $Caseman::VOL_DETAILS) {
|
|
return vol_details();
|
|
}
|
|
|
|
# elsif ($view == $Caseman::IMG_DEL) {
|
|
# return img_del();
|
|
# }
|
|
elsif ($view == $Caseman::VOL_MAKESTR) {
|
|
return vol_makestr();
|
|
}
|
|
elsif ($view == $Caseman::VOL_MAKEBLKLS) {
|
|
return vol_makeblkls();
|
|
}
|
|
}
|
|
|
|
Print::print_check_err("Invalid Case Management View");
|
|
}
|
|
|
|
####################################################################
|
|
# General menu Functions
|
|
|
|
sub print_menu_tabs {
|
|
|
|
if ($::LIVE == 1) {
|
|
print "<h2>Live Analysis Mode</h2>\n";
|
|
}
|
|
|
|
print "<table width=\"600\" height=\"60\" background=\"$::YEL_PIX\" "
|
|
. "border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tr>\n"
|
|
. "<td align=\"center\" width=\"200\">";
|
|
|
|
my $view = Args::get_view();
|
|
|
|
# Case Gallery Tab
|
|
if ($view == $Caseman::CASE_OPEN) {
|
|
print "<img border=0 src=\"pict/menu_t_cg_cur.jpg\" "
|
|
. "width=200 height=65 alt=\"Case Gallery (Current Mode)\">\n";
|
|
}
|
|
elsif ($::LIVE == 1) {
|
|
print "<img border=0 src=\"pict/menu_t_cg_org.jpg\" "
|
|
. "width=200 height=65 alt=\"Case Gallery\">\n";
|
|
}
|
|
else {
|
|
print "<a href=\"$::PROGNAME?"
|
|
. "mod=$::MOD_CASEMAN&view=$Caseman::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 Tab
|
|
# Current
|
|
if ($view == $Caseman::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 (($view == $Caseman::VOL_OPEN) && ($::LIVE == 0)) {
|
|
print "<a href=\"$::PROGNAME?"
|
|
. "mod=$::MOD_CASEMAN&view=$Caseman::HOST_OPEN"
|
|
. "&case=$Args::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 Tab
|
|
# Current
|
|
if ($view == $Caseman::VOL_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</tr>\n" . "</table>\n";
|
|
}
|
|
|
|
####################################################################
|
|
# Case Functions
|
|
|
|
# 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::args{'case'}/case.aut";
|
|
}
|
|
}
|
|
|
|
# Read case config and save it to $Caseman::cvals
|
|
sub read_case_config {
|
|
return if ($::LIVE == 1);
|
|
|
|
my $case;
|
|
|
|
if (scalar(@_) == 1) {
|
|
$case = shift;
|
|
}
|
|
else {
|
|
$case = Args::get_case();
|
|
}
|
|
|
|
my $fname = case_config_fname($case);
|
|
|
|
%Caseman::cvals = ();
|
|
|
|
open CONFIG, "<$fname"
|
|
or die "Can't open case config file ($fname)";
|
|
|
|
while (<CONFIG>) {
|
|
next if ((/^\#/) || (/^\s+$/));
|
|
s/^\s+//;
|
|
s/\s+$//;
|
|
$Caseman::cvals{$1} = $2 if (/^(\S+)\s+(.*)$/);
|
|
}
|
|
close(CONFIG);
|
|
|
|
$Caseman::cvals{'desc'} = "None Provided"
|
|
unless (exists $Caseman::cvals{'desc'});
|
|
|
|
$Caseman::cvals{'created'} = "unknown"
|
|
unless (exists $Caseman::cvals{'created'});
|
|
}
|
|
|
|
sub case_new {
|
|
Print::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=\"mod\" value=\"$::MOD_CASEMAN\">
|
|
<input type=\"hidden\" name=\"view\" value=\"$Caseman::CASE_NEW_DOIT\">
|
|
<tr>
|
|
<td colspan=3 align=left>
|
|
1. <b>Case Name:</b> The name of this investigation. It can contain only letters, numbers, and symbols.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=2><input type=\"text\" name=\"case\"></td>
|
|
</tr>
|
|
|
|
<tr><td colspan=3> </td></tr>
|
|
|
|
<tr>
|
|
<td colspan=3 align=left>
|
|
2. <b>Description:</b> An optional, one line description of this case.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=2><input type=\"text\" name=\"desc\" size=32 maxlength=32></td>
|
|
</tr>
|
|
|
|
<tr><td colspan=3> </td></tr>
|
|
|
|
<tr>
|
|
<td colspan=3 align=left>
|
|
3. <b>Investigator Names:</b> The optional names (with no spaces) of the investigators for this case.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left><tt>a.</tt> <input type=\"text\" name=\"inv1\"></td>
|
|
<td align=left><tt>b.</tt> <input type=\"text\" name=\"inv2\"></td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left><tt>c.</tt> <input type=\"text\" name=\"inv3\"></td>
|
|
<td align=left><tt>d.</tt> <input type=\"text\" name=\"inv4\"></td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left><tt>e.</tt> <input type=\"text\" name=\"inv5\"></td>
|
|
<td align=left><tt>f.</tt> <input type=\"text\" name=\"inv6\"></td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left><tt>g.</tt> <input type=\"text\" name=\"inv7\"></td>
|
|
<td align=left><tt>h.</tt> <input type=\"text\" name=\"inv8\"></td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left><tt>i.</tt> <input type=\"text\" name=\"inv9\"></td>
|
|
<td align=left><tt>j.</tt> <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=\"mod\" value=\"$::MOD_CASEMAN\">
|
|
<input type=\"hidden\" name=\"view\" value=\"$Caseman::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
|
|
|
|
Print::print_html_footer();
|
|
return;
|
|
}
|
|
|
|
# Create the directory and case configuration file
|
|
# Gets the input from CASE_NEW
|
|
sub case_new_doit {
|
|
Print::print_html_header("Creating Case: $Args::args{'case'}");
|
|
my $case = $Args::args{'case'};
|
|
|
|
print "<h3>Creating Case: <tt>$case</tt></h3>\n";
|
|
|
|
# Make the directory
|
|
if (-d "$::case_dir") {
|
|
|
|
# we can't send all of this to print_err, bc it doesn't want HTML
|
|
print "Error: $::case_dir already exists<br>"
|
|
. "Please remove the directory and its contents and try again"
|
|
. "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::CASE_OPEN\">"
|
|
. "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" "
|
|
. "width=\"43\" height=20 border=\"0\"></a>\n";
|
|
Print::print_err("\n");
|
|
}
|
|
|
|
unless (mkdir "$::case_dir", $::MKDIR_MASK) {
|
|
Print::print_err("Error making directory $::case_dir: $!");
|
|
}
|
|
|
|
print "Case directory (<tt>$::case_dir</tt>) created<br>\n";
|
|
Print::log_case_info("Case $case created");
|
|
|
|
my $fname = Caseman::case_config_fname();
|
|
|
|
open CASE_CONFIG, ">$fname" or die "Can't open case config: $fname";
|
|
|
|
print CASE_CONFIG "# Autopsy case config file\n"
|
|
. "# Case: $case\n\n"
|
|
. "created "
|
|
. localtime() . "\n";
|
|
|
|
if ((exists $Args::args{'desc'}) && ($Args::args{'desc'} ne "")) {
|
|
Print::print_err(
|
|
"Invalid Description\n" . "Use the browser's back button to fix")
|
|
if ($Args::args{'desc'} =~ /\n/);
|
|
|
|
print CASE_CONFIG "desc $Args::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";
|
|
|
|
my $iname = investig_fname();
|
|
open INVES, ">>$iname" or die "Can't open investigators file: $iname";
|
|
|
|
my @invs;
|
|
if ( (exists $Args::args{'inv1'})
|
|
&& ($Args::args{'inv1'} ne "")
|
|
&& ($Args::args{'inv1'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv2'})
|
|
&& ($Args::args{'inv2'} ne "")
|
|
&& ($Args::args{'inv2'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv3'})
|
|
&& ($Args::args{'inv3'} ne "")
|
|
&& ($Args::args{'inv3'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv4'})
|
|
&& ($Args::args{'inv4'} ne "")
|
|
&& ($Args::args{'inv4'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv5'})
|
|
&& ($Args::args{'inv5'} ne "")
|
|
&& ($Args::args{'inv5'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv6'})
|
|
&& ($Args::args{'inv6'} ne "")
|
|
&& ($Args::args{'inv6'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv7'})
|
|
&& ($Args::args{'inv7'} ne "")
|
|
&& ($Args::args{'inv7'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv8'})
|
|
&& ($Args::args{'inv8'} ne "")
|
|
&& ($Args::args{'inv8'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv9'})
|
|
&& ($Args::args{'inv9'} ne "")
|
|
&& ($Args::args{'inv9'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
if ( (exists $Args::args{'inv10'})
|
|
&& ($Args::args{'inv10'} ne "")
|
|
&& ($Args::args{'inv10'} =~ /^\s*($::REG_INVESTIG)\s*$/o))
|
|
{
|
|
print INVES "$1\n";
|
|
push @invs, $1;
|
|
}
|
|
|
|
close(INVES);
|
|
|
|
Print::log_session_info("Case $case created");
|
|
|
|
print "<br><br>We must now create a host for this case.\n";
|
|
|
|
print "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_ADD\">\n"
|
|
. "<input type=\"hidden\" name=\"case\" value=\"$case\">\n";
|
|
|
|
if (scalar @invs == 0) {
|
|
print "<option hiddden name=\"inv\" value=\"unknown\">\n";
|
|
}
|
|
else {
|
|
print "<br><br>Please select your name from the list: "
|
|
. "<select name=\"inv\" size=\"1\">\n";
|
|
|
|
foreach $i (@invs) {
|
|
print "<option value=\"$i\">$i</option>\n";
|
|
}
|
|
print "</select>\n";
|
|
}
|
|
|
|
print "<br><br>"
|
|
. "<input type=\"image\" src=\"pict/menu_b_hnew.jpg\" alt=\"Add New Host\" "
|
|
. "height=20 border=\"0\"></form>\n";
|
|
|
|
Print::print_html_footer();
|
|
return;
|
|
}
|
|
|
|
# Open a Case
|
|
# This provides a form with a list of options
|
|
sub case_open {
|
|
Print::print_html_header("Open A Case");
|
|
|
|
# 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 = Caseman::case_config_fname($c);
|
|
|
|
push @cases, $c
|
|
if ((-d "$::LOCKDIR/$c") && (-e "$cfile"));
|
|
}
|
|
closedir CASES;
|
|
|
|
print "<br><br><center>";
|
|
|
|
# Were there any cases?
|
|
if (scalar @cases == 0) {
|
|
print "No cases exist in <tt>$::LOCKDIR</tt><br><br>\n"
|
|
. "Select the New Case button below to make one<br>\n";
|
|
}
|
|
else {
|
|
|
|
print "Select the case to open or create a new one<br>\n";
|
|
|
|
print_menu_tabs();
|
|
|
|
print "<table width=\"600\" background=\"$::YEL_PIX\" "
|
|
. " cellspacing=\"0\" cellpadding=\"2\" border=0>\n";
|
|
|
|
print "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::CASE_OPEN_LOG\">\n"
|
|
. Args::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>";
|
|
|
|
Caseman::read_case_config($c);
|
|
|
|
print "<td>$Caseman::cvals{'desc'}</td>"
|
|
. "<td align=center>"
|
|
. "<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::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=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::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>";
|
|
|
|
Print::print_html_footer();
|
|
return;
|
|
}
|
|
|
|
# Log that a given case was opened and then proceed to open a host
|
|
sub case_open_log {
|
|
Print::log_session_info("Case $Args::args{'case'} opened");
|
|
Print::log_case_info("Case $Args::args{'case'} opened");
|
|
$Args::args{'view'} = $Args::enc_args{'view'} = $Caseman::HOST_OPEN;
|
|
host_open();
|
|
}
|
|
|
|
# Display Case Details
|
|
sub case_details {
|
|
|
|
Print::print_html_header("Details of $Args::args{'case'}");
|
|
|
|
read_case_config();
|
|
|
|
$Caseman::cvals{'desc'} = " "
|
|
unless (exists $Caseman::cvals{'desc'});
|
|
$Caseman::cvals{'created'} = " "
|
|
unless (exists $Caseman::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::args{'case'}</tt></td></tr>\n"
|
|
.
|
|
|
|
# Description
|
|
" <tr><td align=\"right\"><b>Description:</b></td>"
|
|
. "<td align=\"left\"><tt>$Caseman::cvals{'desc'}</tt></td></tr>\n"
|
|
. " <tr><td align=\"right\"><b>Created:</b></td>"
|
|
. "<td align=\"left\"><tt>$Caseman::cvals{'created'}</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?mod=$::MOD_CASEMAN&view=$Caseman::CASE_OPEN\">"
|
|
. "<img src=\"pict/menu_b_ok.jpg\" alt=\"Ok\" "
|
|
. "width=\"167\" height=20 border=\"0\"></a>";
|
|
|
|
Print::print_html_footer();
|
|
return 0;
|
|
}
|
|
|
|
####################################################################
|
|
# Host Functions
|
|
|
|
# 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";
|
|
}
|
|
}
|
|
|
|
# Converts the original single image host config to the volume-based config
|
|
sub convert_host_config {
|
|
|
|
return if ($::LIVE == 1);
|
|
|
|
my $host = Args::get_host();
|
|
|
|
Print::log_host_info("Converting host config files");
|
|
print STDERR "Converting host config file to new format\n";
|
|
|
|
# The file to convert
|
|
my $cfile = host_config_fname();
|
|
unless (open(FILE, $cfile)) {
|
|
Print::print_check_err("Error opening $cfile");
|
|
}
|
|
|
|
my $tmpcfile = "$::host_dir" . "host-convert.aut";
|
|
unless (open(FILE_TMP, ">>$tmpcfile")) {
|
|
Print::print_check_err("Error opening $tmpcfile");
|
|
}
|
|
|
|
my $img_cnt = 0;
|
|
my $vol_cnt = 0;
|
|
$img2vol{'qazwsxedc'} = ""; # stores the image path to partition / file name
|
|
$img2vol2{'qazwsxedc'} =
|
|
""; # stores the image path to file name (no partitions)
|
|
|
|
while (<FILE>) {
|
|
if ((/^\#/) || (/^\s+$/)) {
|
|
print FILE_TMP $_;
|
|
next;
|
|
}
|
|
|
|
# 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;
|
|
|
|
# Add trailing / to original mount point if needed
|
|
if (($r !~ /.*?\/$/) && ($r !~ /.*?\\$/)) {
|
|
$r .= '/';
|
|
}
|
|
my $vnum = "vol" . $vol_cnt;
|
|
my $inum = "img" . $img_cnt;
|
|
$img2vol{$i} = $vnum;
|
|
$img2vol2{$i} = $inum;
|
|
|
|
print FILE_TMP "image $inum raw $i\n";
|
|
print FILE_TMP "part $vnum $inum 0 0 $t $r\n";
|
|
|
|
$img_cnt++;
|
|
$vol_cnt++;
|
|
}
|
|
|
|
# swap
|
|
# swap images/hda3.dd
|
|
elsif (/^swap\s+($::REG_IMG)\s*$/o) {
|
|
my $i = $1;
|
|
|
|
my $vnum = "vol" . $vol_cnt;
|
|
my $inum = "img" . $img_cnt;
|
|
$img2vol{$i} = $vnum;
|
|
$img2vol2{$i} = $inum;
|
|
|
|
print FILE_TMP "image $inum raw $i\n";
|
|
print FILE_TMP "part $vnum $inum 0 0 swap\n";
|
|
$img_cnt++;
|
|
$vol_cnt++;
|
|
|
|
}
|
|
|
|
# raw
|
|
# raw images/hda3.dd
|
|
elsif (/^raw\s+($::REG_IMG)\s*$/o) {
|
|
my $i = $1;
|
|
$img2vol{$i} = "vol" . $vol_cnt;
|
|
$img2vol2{$i} = "img" . $img_cnt;
|
|
|
|
print FILE_TMP "image img" . $img_cnt . " raw $i\n";
|
|
print FILE_TMP "part vol" . $vol_cnt . " img" . $img_cnt
|
|
. " 0 0 raw\n";
|
|
$img_cnt++;
|
|
$vol_cnt++;
|
|
}
|
|
|
|
# entry for a strings or blkls file
|
|
#
|
|
# strings data/hda1.str images/hda1.dd
|
|
elsif (/^strings\s+($::REG_IMG)\s+($::REG_IMG)$/o) {
|
|
my $i = $1;
|
|
my $o = $2;
|
|
|
|
if (exists $img2vol{$o}) {
|
|
my $vname = $img2vol{$o};
|
|
print FILE_TMP "strings vol" . $vol_cnt . " $vname $i\n";
|
|
$img2vol{$i} = "vol" . $vol_cnt;
|
|
$img2vol2{$i} = "vol" . $vol_cnt;
|
|
}
|
|
else {
|
|
print STDERR "Error: Volume for strings $o not found<br>\n";
|
|
}
|
|
$vol_cnt++;
|
|
}
|
|
|
|
# entry for a strings or blkls file
|
|
#
|
|
# unistrings data/hda1.str images/hda1.dd
|
|
elsif (/^unistrings\s+($::REG_IMG)\s+($::REG_IMG)$/o) {
|
|
my $i = $1;
|
|
my $o = $2;
|
|
|
|
if (exists $img2vol{$o}) {
|
|
my $vname = $img2vol{$o};
|
|
print FILE_TMP "unistrings vol" . $vol_cnt
|
|
. " $vname $i\n";
|
|
$img2vol{$i} = "vol" . $vol_cnt;
|
|
$img2vol2{$i} = "vol" . $vol_cnt;
|
|
}
|
|
else {
|
|
print STDERR
|
|
"Error: Volume for unicode strings $o not found<br>\n";
|
|
}
|
|
$vol_cnt++;
|
|
}
|
|
|
|
# blkls entry
|
|
# blkls data/image.blkls [images/image.dd]
|
|
elsif (/^blkls\s+($::REG_IMG)\s*($::REG_IMG)$/o) {
|
|
my $i = $1;
|
|
my $o = $2;
|
|
|
|
$img2vol{$i} = "vol" . $vol_cnt;
|
|
|
|
if (exists $img2vol{$o}) {
|
|
my $vname = $img2vol{$o};
|
|
print FILE_TMP "blkls vol" . $vol_cnt . " $vname $i\n";
|
|
$img2vol{$i} = "vol" . $vol_cnt;
|
|
$img2vol2{$i} = "vol" . $vol_cnt;
|
|
}
|
|
else {
|
|
print STDERR "Error: Volume for blkls $o not found<br>\n";
|
|
}
|
|
$vol_cnt++;
|
|
}
|
|
|
|
# body data/body.txt
|
|
elsif (/^body\s+($::REG_IMG)$/o) {
|
|
my $i = $1;
|
|
print FILE_TMP "body vol" . $vol_cnt . " $i\n";
|
|
$img2vol{$i} = "vol" . $vol_cnt;
|
|
$img2vol2{$i} = "vol" . $vol_cnt;
|
|
|
|
$vol_cnt++;
|
|
}
|
|
|
|
# timeline data/timeline.txt
|
|
elsif (/^timeline\s+($::REG_IMG)$/o) {
|
|
my $i = $1;
|
|
print FILE_TMP "timeline vol" . $vol_cnt . " $i\n";
|
|
$img2vol{$i} = "vol" . $vol_cnt;
|
|
$img2vol2{$i} = "vol" . $vol_cnt;
|
|
$vol_cnt++;
|
|
}
|
|
|
|
# timezone XYZ
|
|
elsif (/^timezone\s+($::REG_ZONE_ARGS)$/o) {
|
|
print FILE_TMP "$_\n";
|
|
}
|
|
|
|
# timeskew XYZ
|
|
elsif (/^timeskew\s+($::REG_SKEW)$/o) {
|
|
print FILE_TMP "$_\n";
|
|
}
|
|
|
|
# desc XYZ
|
|
elsif (/^desc\s+(.*)$/) {
|
|
print FILE_TMP "$_\n";
|
|
}
|
|
|
|
# hash databases
|
|
elsif (/^alert_db\s+'(.*)'$/) {
|
|
print FILE_TMP "$_\n";
|
|
}
|
|
elsif (/^exclude_db\s+'(.*)'$/) {
|
|
print FILE_TMP "$_\n";
|
|
}
|
|
else {
|
|
my $msg =
|
|
"Error: invalid entry in $cfile:$." . "\n"
|
|
. "image path fs_type mnt_point\n"
|
|
. "strings path orig_img\n"
|
|
. "blkls path [orig_img]\n"
|
|
. "body path\n"
|
|
. "timeline path\n"
|
|
. "timezone TZ\n"
|
|
. "desc DESCRIPTION\n";
|
|
Print::print_check_err($msg);
|
|
}
|
|
}
|
|
|
|
close(FILE);
|
|
close(FILE_TMP);
|
|
unless (rename $cfile, $cfile . ".bak") {
|
|
print STDERR "Error backing up original host config file\n";
|
|
}
|
|
unless (rename $tmpcfile, $cfile) {
|
|
print STDERR "Error renaming new host config file\n";
|
|
}
|
|
|
|
Notes::convert(\%img2vol);
|
|
Hash::convert(\%img2vol2);
|
|
}
|
|
|
|
# reads host config file and sets global hash values for images and other
|
|
sub read_host_config {
|
|
|
|
if ($::LIVE == 1) {
|
|
%Caseman::mod2vol = ();
|
|
%Caseman::vol2str = ();
|
|
%Caseman::vol2uni = ();
|
|
%Caseman::vol2blkls = ();
|
|
$Caseman::tz = "";
|
|
$Caseman::ts = 0;
|
|
$Caseman::host_desc = "";
|
|
$Caseman::exclude_db = "";
|
|
$Caseman::alert_db = "";
|
|
return;
|
|
}
|
|
|
|
my $host = Args::get_host();
|
|
|
|
my $cfile = host_config_fname();
|
|
restart:
|
|
unless (open(FILE, $cfile)) {
|
|
Print::print_check_err("Error opening $cfile");
|
|
}
|
|
|
|
%Caseman::vol2mnt = ();
|
|
%Caseman::vol2ftype = ();
|
|
%Caseman::vol2dtype = ();
|
|
%Caseman::vol2cat = ();
|
|
%Caseman::mod2vol = ();
|
|
%Caseman::vol2str = ();
|
|
%Caseman::vol2uni = ();
|
|
%Caseman::vol2blkls = ();
|
|
%Caseman::vol2par = ();
|
|
%Caseman::vol2start = ();
|
|
%Caseman::vol2end = ();
|
|
$Caseman::vol2path = ();
|
|
$Caseman::vol2sname = ();
|
|
|
|
$Caseman::tz = "";
|
|
$Caseman::ts = 0;
|
|
$Caseman::host_desc = "";
|
|
$Caseman::exclude_db = "";
|
|
$Caseman::alert_db = "";
|
|
|
|
while (<FILE>) {
|
|
next if ((/^\#/) || (/^\s+$/));
|
|
|
|
# remove whitespace
|
|
s/^\s+//;
|
|
s/\s+$//;
|
|
|
|
# old file system image entry
|
|
#
|
|
# 'image images/hda1.dd openbsd /usr
|
|
if (/^image\s+($::REG_IMG)\s+([\w\-]+)\s+([\w\-\_\.\/:\\]+)$/o) {
|
|
|
|
close(FILE);
|
|
convert_host_config();
|
|
goto restart;
|
|
}
|
|
elsif (
|
|
/^image\s+($::REG_INAME)\s+($::REG_IMGTYPE)\s+($::REG_IMG_CONFIG)$/o
|
|
)
|
|
{
|
|
my $me = $1;
|
|
my $t = $2;
|
|
my $i = $3;
|
|
|
|
unless ((-e "$::host_dir$i")
|
|
|| ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i")))
|
|
{
|
|
Print::print_check_err(
|
|
"Error: image $i in ${host}.host:$. not found: "
|
|
. "$::host_dir"
|
|
. "$i \nEdit the config file and refresh your browser\n"
|
|
. "(Or your version of Perl does not support large files)"
|
|
);
|
|
}
|
|
|
|
if (exists $Caseman::vol2path{$me}) {
|
|
$Caseman::vol2path{$me} .= " \'$::host_dir" . "$i\'";
|
|
}
|
|
else {
|
|
$Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'";
|
|
$Caseman::vol2sname{$me} = $i;
|
|
$Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/);
|
|
|
|
$Caseman::vol2par{$me} = "";
|
|
$Caseman::vol2cat{$me} = "image";
|
|
$Caseman::vol2itype{$me} = $t;
|
|
$Caseman::vol2ftype{$me} = "";
|
|
|
|
$Caseman::vol2start{$me} = 0;
|
|
$Caseman::vol2end{$me} = 0;
|
|
}
|
|
}
|
|
elsif (
|
|
/^part\s+($::REG_VNAME)\s+($::REG_INAME)\s+(\d+)\s+(\d+)\s+($::REG_FTYPE)\s*([\w\-\_\.\/:\\]+)?$/o
|
|
)
|
|
{
|
|
my $par = $2;
|
|
my $me = $1;
|
|
my $s = $3;
|
|
my $e = $4;
|
|
my $t = $5;
|
|
my $r = $6; # Not defined for swap and raw
|
|
|
|
unless (exists $Fs::addr_unit{$t}) {
|
|
Print::print_check_err(
|
|
"Error: unknown type: $t in host config: $."
|
|
. "\nEdit the file and refresh your browser");
|
|
}
|
|
|
|
if (exists $Caseman::vol2itype{$par}) {
|
|
$Caseman::vol2itype{$me} = $Caseman::vol2itype{$par};
|
|
}
|
|
else {
|
|
Print::print_check_err(
|
|
"Error: Image $par for partition $me was not found in config: $."
|
|
. "\nEdit the file and refresh your browser");
|
|
}
|
|
|
|
$Caseman::vol2ftype{$me} = $t;
|
|
$Caseman::vol2cat{$me} = "part";
|
|
$Caseman::vol2start{$me} = $s;
|
|
$Caseman::vol2end{$me} = $e;
|
|
|
|
# Add trailing / to original mount point if needed
|
|
if ((defined $r) && ($r !~ /.*?\/$/) && ($r !~ /.*?\\$/)) {
|
|
$r .= '/';
|
|
}
|
|
$Caseman::vol2mnt{$me} = $r;
|
|
$Caseman::vol2par{$me} = $par;
|
|
$Caseman::vol2path{$me} = $Caseman::vol2path{$par};
|
|
$Caseman::vol2sname{$me} =
|
|
$Caseman::vol2sname{$par} . "-" . $s . "-" . $e;
|
|
}
|
|
elsif (/^disk\s+($::REG_VNAME)\s+($::REG_INAME)\s+($::REG_FTYPE)?$/o) {
|
|
my $par = $2;
|
|
my $me = $1;
|
|
my $t = $3;
|
|
|
|
unless (exists $Vs::type{$t}) {
|
|
Print::print_check_err(
|
|
"Error: unknown volume system type: $t in host config: $."
|
|
. "\nEdit the file and refresh your browser");
|
|
}
|
|
|
|
if (exists $Caseman::vol2itype{$par}) {
|
|
$Caseman::vol2itype{$me} = $Caseman::vol2itype{$par};
|
|
}
|
|
else {
|
|
Print::print_check_err(
|
|
"Error: Image $par for disk $me was not found in config: $.\n"
|
|
. "Edit the file and refresh your browser");
|
|
}
|
|
|
|
$Caseman::vol2ftype{$me} = "raw";
|
|
$Caseman::vol2dtype{$me} = $t;
|
|
$Caseman::vol2cat{$me} = "disk";
|
|
$Caseman::vol2start{$me} = 0;
|
|
$Caseman::vol2end{$me} = 0;
|
|
$Caseman::vol2mnt{$me} = "";
|
|
$Caseman::vol2par{$me} = $par;
|
|
$Caseman::vol2path{$me} = $Caseman::vol2path{$par};
|
|
$Caseman::vol2sname{$me} = $Caseman::vol2sname{$par} . "-disk";
|
|
}
|
|
|
|
# entry for a strings or blkls file
|
|
#
|
|
# strings data/hda1.str volX
|
|
elsif (/^strings\s+($::REG_VNAME)\s+($::REG_VNAME)\s+($::REG_IMG)$/o) {
|
|
my $i = $3;
|
|
my $par = $2;
|
|
my $me = $1;
|
|
|
|
unless ((-e "$::host_dir$i")
|
|
|| ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i")))
|
|
{
|
|
Print::print_check_err("Error: strings file not found: "
|
|
. "$::host_dir$i\nEdit host config in $::host_dir and refresh your browser"
|
|
);
|
|
}
|
|
|
|
unless (exists $Caseman::vol2cat{$par}) {
|
|
Print::print_check_err(
|
|
"Error: Volume $par for strings $me was not found in config: $."
|
|
. "\nEdit the file and refresh your browser");
|
|
}
|
|
|
|
$Caseman::vol2ftype{$me} = "strings";
|
|
$Caseman::vol2cat{$me} = "mod";
|
|
$Caseman::vol2itype{$me} = "raw";
|
|
$Caseman::mod2vol{$me} = $par;
|
|
$Caseman::vol2str{$par} = $me;
|
|
$Caseman::vol2par{$me} = $par;
|
|
$Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'";
|
|
$Caseman::vol2start{$me} = 0;
|
|
$Caseman::vol2end{$me} = 0;
|
|
$Caseman::vol2sname{$me} = $i;
|
|
$Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/);
|
|
|
|
}
|
|
|
|
# entry for a strings or blkls file
|
|
#
|
|
# unistrings data/hda1.str volX
|
|
elsif (/^unistrings\s+($::REG_VNAME)\s+($::REG_VNAME)\s+($::REG_IMG)$/o)
|
|
{
|
|
my $i = $3;
|
|
my $par = $2;
|
|
my $me = $1;
|
|
|
|
unless ((-e "$::host_dir$i")
|
|
|| ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i")))
|
|
{
|
|
Print::print_check_err("Error: Unicode strings file not found: "
|
|
. "$::host_dir$i\nEdit host config in $::host_dir and refresh your browser"
|
|
);
|
|
}
|
|
|
|
unless (exists $Caseman::vol2cat{$par}) {
|
|
Print::print_check_err(
|
|
"Error: Volume $par for unistrings $me was not found in config: $."
|
|
. "\nEdit the file and refresh your browser");
|
|
}
|
|
|
|
$Caseman::vol2ftype{$me} = "strings";
|
|
$Caseman::vol2cat{$me} = "mod";
|
|
$Caseman::vol2itype{$me} = "raw";
|
|
$Caseman::mod2vol{$me} = $par;
|
|
$Caseman::vol2uni{$par} = $me;
|
|
$Caseman::vol2par{$me} = $par;
|
|
$Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'";
|
|
$Caseman::vol2start{$me} = 0;
|
|
$Caseman::vol2end{$me} = 0;
|
|
$Caseman::vol2sname{$me} = $i;
|
|
$Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/);
|
|
}
|
|
|
|
# blkls entry
|
|
# blkls themname myname
|
|
elsif (/^blkls\s+($::REG_VNAME)\s+($::REG_VNAME)\s+($::REG_IMG)$/o) {
|
|
my $i = $3;
|
|
my $par = $2;
|
|
my $me = $1;
|
|
|
|
unless (
|
|
(-e "$::host_dir$i")
|
|
|| ( (-l "$::host_dir$i")
|
|
&& (-e readlink "$::host_dir$i"))
|
|
)
|
|
{
|
|
Print::print_check_err("Error: blkls file not found: "
|
|
. "$::host_dir$i \nEdit host config in $::host_dir and refresh your browser"
|
|
);
|
|
}
|
|
|
|
unless (exists $Caseman::vol2cat{$par}) {
|
|
Print::print_check_err(
|
|
"Error: Volume $par for blkls $me was not found in config: $."
|
|
. "\nEdit the file and refresh your browser");
|
|
}
|
|
|
|
$Caseman::vol2ftype{$me} = "blkls";
|
|
$Caseman::vol2cat{$me} = "mod";
|
|
$Caseman::vol2itype{$me} = "raw";
|
|
$Caseman::vol2mnt{$me} = "";
|
|
$Caseman::vol2par{$me} = $par;
|
|
$Caseman::mod2vol{$me} = $par;
|
|
$Caseman::vol2blkls{$par} = $me;
|
|
$Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'";
|
|
$Caseman::vol2start{$me} = 0;
|
|
$Caseman::vol2end{$me} = 0;
|
|
$Caseman::vol2sname{$me} = $i;
|
|
$Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/);
|
|
|
|
}
|
|
|
|
# body data/body.txt
|
|
elsif (/^body\s+($::REG_VNAME)\s+($::REG_IMG)$/o) {
|
|
my $me = $1;
|
|
my $i = $2;
|
|
|
|
unless ((-e "$::host_dir$i")
|
|
|| ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i")))
|
|
{
|
|
Print::print_check_err("Error: body file not found: "
|
|
. "$::host_dir$i <br>Edit host config in $::host_dir and refresh your browser"
|
|
);
|
|
}
|
|
|
|
$Caseman::vol2cat{$me} = "timeline";
|
|
$Caseman::vol2ftype{$me} = "body";
|
|
$Caseman::vol2itype{$me} = "raw";
|
|
$Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'";
|
|
$Caseman::vol2start{$me} = 0;
|
|
$Caseman::vol2end{$me} = 0;
|
|
$Caseman::vol2sname{$me} = $i;
|
|
$Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/);
|
|
}
|
|
|
|
# timeline data/timeline.txt
|
|
elsif (/^timeline\s+($::REG_VNAME)\s+($::REG_IMG)$/o) {
|
|
my $me = $1;
|
|
my $i = $2;
|
|
|
|
unless ((-e "$::host_dir$i")
|
|
|| ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i")))
|
|
{
|
|
Print::print_check_err("Error: timeline file not found: "
|
|
. "$::host_dir$i \nEdit host config in $::host_dir and refresh your browser"
|
|
);
|
|
}
|
|
|
|
$Caseman::vol2cat{$me} = "timeline";
|
|
$Caseman::vol2ftype{$me} = "timeline";
|
|
$Caseman::vol2itype{$me} = "raw";
|
|
|
|
# We do not add the quotes to the path for timeline because it is opened only by the Perl code and it doesn't like the quotes
|
|
$Caseman::vol2path{$me} = "$::host_dir" . "$i";
|
|
$Caseman::vol2start{$me} = 0;
|
|
$Caseman::vol2end{$me} = 0;
|
|
$Caseman::vol2sname{$me} = $i;
|
|
$Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/);
|
|
|
|
}
|
|
|
|
# timezone XYZ
|
|
elsif (/^timezone\s+($::REG_ZONE_ARGS)$/o) {
|
|
$Caseman::tz = "\'$1\'";
|
|
}
|
|
|
|
# timeskew XYZ
|
|
elsif (/^timeskew\s+($::REG_SKEW)$/o) {
|
|
$Caseman::ts = "\'$1\'";
|
|
}
|
|
|
|
# desc XYZ
|
|
elsif (/^desc\s+(.*)$/) {
|
|
$Caseman::host_desc = "$1";
|
|
}
|
|
|
|
# hash databases
|
|
elsif (/^alert_db\s+'(.*)'$/) {
|
|
$Caseman::alert_db = "$1";
|
|
}
|
|
elsif (/^exclude_db\s+'(.*)'$/) {
|
|
$Caseman::exclude_db = "$1";
|
|
}
|
|
else {
|
|
my $msg = "Error: invalid entry in $cfile:$." . "\n" . "$_\n";
|
|
Print::print_check_err($msg);
|
|
}
|
|
}
|
|
close(FILE);
|
|
}
|
|
|
|
# Add a new image entry to the host config and return its id
|
|
sub add_img_host_config {
|
|
my $type = shift;
|
|
my $other = shift;
|
|
my $id = shift;
|
|
|
|
my $read = host_config_fname();
|
|
my $write = $read . "-" . rand();
|
|
|
|
unless (open(READ, "<$read")) {
|
|
Print::print_check_err("Error opening $read");
|
|
}
|
|
|
|
unless (open(WRITE, ">$write")) {
|
|
Print::print_check_err("Error opening $write");
|
|
}
|
|
|
|
my $maxcnt = 0;
|
|
|
|
while (<READ>) {
|
|
s/^\s+//;
|
|
s/\s+$//;
|
|
if (/^\w+\s+img(\d+)\s+.*$/) {
|
|
$maxcnt = $1 if ($1 > $maxcnt);
|
|
}
|
|
print WRITE "$_\n";
|
|
}
|
|
$maxcnt++;
|
|
if ($id eq "") {
|
|
$id = "img" . $maxcnt;
|
|
}
|
|
print WRITE "$type $id $other\n";
|
|
|
|
Print::log_host_info("Image added: $type $id $other");
|
|
|
|
close(READ);
|
|
close(WRITE);
|
|
unless (rename $write, $read) {
|
|
print STDERR "Error renaming temp host config file\n";
|
|
}
|
|
|
|
return $id;
|
|
}
|
|
|
|
# Add a new volume entry to the host config and return its id
|
|
sub add_vol_host_config {
|
|
my $type = shift;
|
|
my $other = shift;
|
|
|
|
my $read = host_config_fname();
|
|
my $write = $read . "-" . rand();
|
|
|
|
unless (open(READ, "<$read")) {
|
|
Print::print_check_err("Error opening $read");
|
|
}
|
|
|
|
unless (open(WRITE, ">$write")) {
|
|
Print::print_check_err("Error opening $write");
|
|
}
|
|
|
|
# We want to find the max count ... not just the unused
|
|
# ones because we could end up reusing one and that could
|
|
# mess up the notes
|
|
my $maxcnt = 0;
|
|
|
|
while (<READ>) {
|
|
s/^\s+//;
|
|
s/\s+$//;
|
|
if (/^\w+\s+vol(\d+)\s+.*$/) {
|
|
$maxcnt = $1 if ($1 > $maxcnt);
|
|
}
|
|
print WRITE "$_\n";
|
|
}
|
|
$maxcnt++;
|
|
print WRITE "$type vol" . $maxcnt . " $other\n";
|
|
Print::log_host_info("Volume added: $type vol" . $maxcnt . " $other");
|
|
|
|
close(READ);
|
|
close(WRITE);
|
|
unless (rename $write, $read) {
|
|
print STDERR "Error renaming temp host config file\n";
|
|
}
|
|
|
|
return "vol" . $maxcnt;
|
|
}
|
|
|
|
# Delete anentry from the host config
|
|
# DOES NOT WORK RIGHT NOW
|
|
sub del_host_config_BLAH {
|
|
return;
|
|
my $type = shift;
|
|
my $other = shift;
|
|
|
|
my $read = host_config_fname();
|
|
my $write = $read . "-" . rand();
|
|
|
|
unless (open(READ, "<$read")) {
|
|
Print::print_check_err("Error opening $read");
|
|
}
|
|
|
|
unless (open(WRITE, ">$write")) {
|
|
Print::print_check_err("Error opening $write");
|
|
}
|
|
|
|
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);
|
|
unless (rename $write, $read) {
|
|
print STDERR "Error renaming temp host config file\n";
|
|
}
|
|
|
|
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 $vol = shift;
|
|
my $md5 = shift;
|
|
$md5 =~ tr/[a-f]/[A-F]/;
|
|
|
|
my $read = "$::host_dir/md5.txt";
|
|
my $write = $read . "-" . rand();
|
|
|
|
unless (open(WRITE, ">$write")) {
|
|
Print::print_check_err("Error opening $write");
|
|
}
|
|
|
|
if (-e "$read") {
|
|
unless (open(READ, "<$read")) {
|
|
Print::print_check_err("Error opening $read");
|
|
}
|
|
|
|
while (<READ>) {
|
|
s/^\s+//;
|
|
s/\s+$//;
|
|
print WRITE "$_\n"
|
|
unless ((/^$::REG_MD5\s+($::REG_VNAME)/o) && ($1 eq $vol));
|
|
}
|
|
close(READ);
|
|
}
|
|
|
|
print WRITE "$md5 $vol\n" if ($md5 ne "");
|
|
|
|
close(WRITE);
|
|
|
|
unless (rename $write, $read) {
|
|
print STDERR "Error renaming temp MD5 hash file\n";
|
|
}
|
|
return;
|
|
}
|
|
|
|
sub host_add {
|
|
Print::print_html_header("Add A New Host To $Args::args{'case'}");
|
|
|
|
print "<b>Case: </b> $Args::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=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_ADD_DOIT\">\n"
|
|
. Args::make_hidden()
|
|
. "<tr><td colspan=\"2\"> </td></tr>"
|
|
.
|
|
|
|
# Host name
|
|
"<tr><td align=\"left\" colspan=2>1. <b>Host Name:</b> The name of the computer being investigated. It can contain only letters, numbers, and symbols.</td></tr>"
|
|
. "<tr><td align=\"left\"> </td>"
|
|
. "<td align=\"left\"><input type=\"text\" name=\"host\" size=32 maxlength=32 value=\"host1\"></td></tr>\n"
|
|
.
|
|
|
|
# Description
|
|
"<tr><td align=\"left\" colspan=2>2. <b>Description:</b> An optional one-line description or note about this computer.</td></tr>"
|
|
. "<tr><td align=\"left\"> </td>"
|
|
. "<td align=\"left\">"
|
|
. "<input type=\"text\" name=\"desc\" size=32 maxlength=32></td></tr>\n"
|
|
.
|
|
|
|
# Empty line
|
|
"<tr><td colspan=\"2\"> </td></tr>" .
|
|
|
|
# Timezone
|
|
"<tr><td align=\"left\" colspan=2>3. <b>Time zone:</b> An optional timezone value (i.e. EST5EDT). If not given, it defaults to the local setting. A list of time zones can be found in the help files.</td></tr>"
|
|
. "<tr><td align=\"left\"> </td>"
|
|
. "<td align=\"left\">"
|
|
. "<input type=\"text\" name=\"tz\" size=16 maxlength=64></td></tr>\n"
|
|
.
|
|
|
|
# Timeskew
|
|
"<tr><td align=\"left\" colspan=2>4. <b>Timeskew Adjustment:</b> An optional value to describe how many seconds this computer's clock was out of sync. For example, if the computer was 10 seconds fast, then enter -10 to compensate.</td></tr>"
|
|
. "<tr><td align=\"left\"> </td>"
|
|
. "<td align=\"left\">"
|
|
. "<input type=\"text\" name=\"ts\" size=8 maxlength=16 value=\"0\">"
|
|
. "</td></tr>\n"
|
|
.
|
|
|
|
# Spacer
|
|
"<tr><td colspan=\"2\"> </td></tr>" .
|
|
|
|
# Alert
|
|
"<tr><td align=\"left\" colspan=2>5. <b>Path of Alert Hash Database:</b> An optional hash database of known bad files.</td></tr>"
|
|
. "<tr><td align=\"left\"> </td>"
|
|
. "<td align=\"left\">"
|
|
. "<input type=\"text\" name=\"alert_db\" size=32 maxlength=512>"
|
|
. "</td></tr>\n"
|
|
.
|
|
|
|
# Ignore
|
|
"<tr><td align=\"left\" colspan=2>6. <b>Path of Ignore Hash Database:</b> An optional hash database of known good files.</td></tr>"
|
|
. "<tr><td align=\"left\"> </td>"
|
|
. "<td align=\"left\">"
|
|
. "<input type=\"text\" name=\"exclude_db\" size=32 maxlength=512>"
|
|
. "</td></tr>\n"
|
|
.
|
|
|
|
# Spacer
|
|
"<tr><td colspan=\"2\"> </td></tr>" . "</table>\n";
|
|
|
|
if (exists $Args::args{'inv'}) {
|
|
print
|
|
"<input type=\"hidden\" name=\"inv\" value=\"$Args::args{'inv'}\">\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=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN\">\n"
|
|
. "<input type=\"hidden\" name=\"case\" value=\"$Args::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>";
|
|
|
|
Print::print_html_footer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
# Make the directories and config files for a host
|
|
sub host_add_doit {
|
|
Args::check_tz()
|
|
if ((exists $Args::args{'tz'}) && ($Args::args{'tz'} ne ""));
|
|
Args::check_ts();
|
|
Print::print_html_header(
|
|
"Adding Host $Args::args{'host'} to $Args::args{'case'}");
|
|
|
|
print "<h3>Adding host: <tt>$Args::args{'host'}</tt> to "
|
|
. "case <tt>$Args::args{'case'}</tt></h3>\n";
|
|
|
|
# Do some sanity checks before we start making the directories and such
|
|
if ( (exists $Args::args{'alert_db'})
|
|
&& ($Args::args{'alert_db'} ne ""))
|
|
{
|
|
|
|
unless ($Args::args{'alert_db'} =~ /^$::REG_HASHDB$/o) {
|
|
print "Invalid Alert Database path\n"
|
|
. "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::HOST_ADD&case=$Args::args{'case'}\">"
|
|
. "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" "
|
|
. "width=\"43\" height=20 border=\"0\"></a>\n";
|
|
return 1;
|
|
}
|
|
|
|
unless (-e "$Args::args{'alert_db'}") {
|
|
print "Alert Database Not Found: $Args::args{'alert_db'}"
|
|
. "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::HOST_ADD&case=$Args::args{'case'}\">"
|
|
. "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" "
|
|
. "width=\"43\" height=20 border=\"0\"></a>\n";
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if ( (exists $Args::args{'exclude_db'})
|
|
&& ($Args::args{'exclude_db'} ne ""))
|
|
{
|
|
unless ($Args::args{'exclude_db'} =~ /^$::REG_HASHDB$/o) {
|
|
print "Invalid Exclude Database path\n"
|
|
. "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::HOST_ADD&case=$Args::args{'case'}\">"
|
|
. "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" "
|
|
. "width=\"43\" height=20 border=\"0\"></a>\n";
|
|
return 1;
|
|
}
|
|
|
|
unless (-e "$Args::args{'exclude_db'}") {
|
|
print "Exclude Database Not Found: $Args::args{'exclude_db'}"
|
|
. "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::HOST_ADD&case=$Args::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 "Error: $::host_dir already exists<br>"
|
|
. "Please remove the directory and its contents and try again"
|
|
. "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::HOST_OPEN&case=$Args::enc_args{'case'}\">"
|
|
. "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" "
|
|
. "width=\"43\" height=20 border=\"0\"></a>\n";
|
|
Print::print_err("\n");
|
|
}
|
|
unless (mkdir "$::host_dir", $::MKDIR_MASK) {
|
|
Print::print_err("Error making directory $::host_dir: $!");
|
|
}
|
|
|
|
print "Host Directory (<tt>$::host_dir</tt>) created<p>\n";
|
|
Print::log_case_info("Host $Args::args{'host'} added to case");
|
|
|
|
# Images directory
|
|
unless (mkdir "$::host_dir" . "$::IMGDIR", $::MKDIR_MASK) {
|
|
rmdir "$::host_dir";
|
|
Print::print_err("Error making $::host_dir" . "$::IMGDIR");
|
|
}
|
|
|
|
# Output Directory
|
|
unless (mkdir "$::host_dir" . "$::DATADIR", $::MKDIR_MASK) {
|
|
rmdir "$::host_dir" . "$::IMGDIR";
|
|
rmdir "$::host_dir";
|
|
Print::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::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::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::print_err("Error making $::host_dir" . "mnt");
|
|
}
|
|
|
|
Print::log_host_info(
|
|
"Host $Args::args{'host'} added to case $Args::args{'case'}");
|
|
|
|
# Create config file
|
|
my $fname = Caseman::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::args{'case'} Host: $Args::args{'host'}\n"
|
|
. "# Created: "
|
|
. localtime() . "\n\n";
|
|
|
|
if ((exists $Args::args{'desc'}) && ($Args::args{'desc'} ne "")) {
|
|
Print::print_err(
|
|
"Invalid Description\n" . "Use the browser's back button to fix")
|
|
if ($Args::args{'desc'} =~ /\n/);
|
|
|
|
print HOST_CONFIG "desc $Args::args{'desc'}\n";
|
|
}
|
|
|
|
print HOST_CONFIG "timezone " . Args::get_tz() . "\n"
|
|
if ((exists $Args::args{'tz'}) && ($Args::args{'tz'} ne ""));
|
|
print HOST_CONFIG "timeskew " . Args::get_ts() . "\n";
|
|
|
|
if ( (exists $Args::args{'alert_db'})
|
|
&& ($Args::args{'alert_db'} ne ""))
|
|
{
|
|
|
|
# Index it if it is not
|
|
unless (-e "$Args::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::args{'alert_db'});
|
|
print "<hr>\n";
|
|
}
|
|
|
|
# only print it if it was successful
|
|
print HOST_CONFIG "alert_db \'$Args::args{'alert_db'}\'\n"
|
|
if (-e "$Args::args{'alert_db'}-md5.idx");
|
|
}
|
|
|
|
if ( (exists $Args::args{'exclude_db'})
|
|
&& ($Args::args{'exclude_db'} ne ""))
|
|
{
|
|
|
|
# Index it if it is not
|
|
unless (-e "$Args::args{'exclude_db'}-md5.idx") {
|
|
print
|
|
"Exclude Database has not been indexed - it will be as an md5sum file<br>\n";
|
|
|
|
print "<hr>\n";
|
|
Hash::index_md5sum($Args::args{'exclude_db'});
|
|
print "<hr>\n";
|
|
}
|
|
|
|
# only print it if it was successful
|
|
print HOST_CONFIG "exclude_db \'$Args::args{'exclude_db'}\'\n"
|
|
if (-e "$Args::args{'exclude_db'}-md5.idx");
|
|
}
|
|
|
|
close HOST_CONFIG;
|
|
|
|
print "Configuration file (<tt>$fname</tt>) created<br><br>\n";
|
|
|
|
print "We must now import an image file for this host\n";
|
|
|
|
print "<br><br><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::HOST_OPEN_LOG&$Args::baseargs\">"
|
|
. "<img src=\"pict/menu_b_inew.jpg\" alt=\"Add Image\" "
|
|
. " height=20 border=\"0\"></a>\n";
|
|
|
|
Print::print_html_footer();
|
|
return 0;
|
|
}
|
|
|
|
# Open a host in the given case
|
|
sub host_open {
|
|
Print::print_html_header("Open Host In $Args::args{'case'}");
|
|
|
|
# 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 = Caseman::host_config_fname($h);
|
|
push @hosts, $h
|
|
if ((-d "$::case_dir" . "$h") && (-e "$hfile"));
|
|
}
|
|
closedir HOSTS;
|
|
|
|
print "<b>Case:</b> $Args::args{'case'}<br><br>\n";
|
|
|
|
print "<center>";
|
|
|
|
if (scalar @hosts == 0) {
|
|
print "No hosts have been added to the case yet"
|
|
. "<br><br>Select the Add Host button below to create one.<br>\n";
|
|
}
|
|
else {
|
|
|
|
print "Select the host to open or create a new one<br>\n";
|
|
|
|
print_menu_tabs();
|
|
|
|
print "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\" "
|
|
. "background=\"$::YEL_PIX\" border=0>\n";
|
|
|
|
print "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN_LOG\">\n"
|
|
. Args::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 = Caseman::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?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::HOST_DETAILS&$Args::baseargs&"
|
|
. "host=$h\">details</a></td></tr>\n";
|
|
}
|
|
print "</table>\n";
|
|
|
|
# Display pulldown of investigators
|
|
my @invs = read_invest();
|
|
if (scalar @invs == 0) {
|
|
print "<input type=\"hidden\" name=\"inv\" value=\"unknown\">\n";
|
|
}
|
|
else {
|
|
print "<br>Investigator (for reports only): ";
|
|
my $cur_inv = "";
|
|
$cur_inv = $Args::args{'inv'} if (exists $Args::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=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_ADD\">\n"
|
|
. "<input type=\"hidden\" name=\"case\" value=\"$Args::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=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::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";
|
|
|
|
Print::print_html_footer();
|
|
return 0;
|
|
}
|
|
|
|
# Log that a given host was opened and then proceed to open an image
|
|
sub host_open_log {
|
|
unless ((exists $Args::args{'inv'}) && ($Args::args{'inv'} ne "")) {
|
|
my @invs = read_invest();
|
|
if (scalar @invs == 0) {
|
|
$Args::args{'inv'} = $Args::enc_args{'inv'} = 'unknown';
|
|
}
|
|
else {
|
|
Print::print_html_header("Missing Investigator");
|
|
print "<br>An investigator must be selected<p>\n"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN_LOG\">\n"
|
|
. Args::make_hidden();
|
|
|
|
print "Select one of the following:";
|
|
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";
|
|
|
|
Print::print_html_footer();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Args::check_inv();
|
|
Print::log_case_info(
|
|
"Host $Args::args{'host'} opened by $Args::args{'inv'}");
|
|
Print::log_host_info(
|
|
"Host $Args::args{'host'} opened by $Args::args{'inv'}");
|
|
Print::log_host_inv("Host $Args::args{'host'} opened");
|
|
|
|
$Args::args{'view'} = $Args::enc_args{'view'} = $Caseman::VOL_OPEN;
|
|
vol_open();
|
|
}
|
|
|
|
# Provide details about the configuration of a host. This window is
|
|
# a link from the HOST_OPEN window
|
|
sub host_details {
|
|
Print::print_html_header(
|
|
"Details of $Args::args{'case'}:$Args::args{'host'}");
|
|
|
|
print "<b>Case: </b>$Args::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::args{'host'}</tt></td></tr>\n"
|
|
.
|
|
|
|
# Description
|
|
"<tr><td align=\"right\"><b>Description:</b></td>"
|
|
. "<td align=\"left\"><tt>"
|
|
. (($Caseman::host_desc ne "") ? $Caseman::host_desc : " ")
|
|
. "</tt></td></tr>\n"
|
|
.
|
|
|
|
# Timezone
|
|
"<tr><td align=\"right\"><b>Time zone: </b></td>"
|
|
. "<td align=\"left\"><tt>$Caseman::tz</tt></td></tr>\n"
|
|
.
|
|
|
|
# Timeskew
|
|
"<tr><td align=\"right\"><b>Timeskew:</b></td>"
|
|
. "<td align=\"left\"><tt>$Caseman::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>"
|
|
. (($Caseman::alert_db ne "") ? $Caseman::alert_db : " ")
|
|
. "</tt></td></tr>\n"
|
|
.
|
|
|
|
# Exclude Database
|
|
"<tr><td align=\"right\"><b>Exclude Hash Database:</b></td>"
|
|
. "<td align=\"left\"><tt>"
|
|
. (($Caseman::exclude_db ne "") ? $Caseman::exclude_db : " ")
|
|
. "</tt></td></tr>\n"
|
|
. "</table>\n";
|
|
|
|
# Final Button
|
|
print "<br><br><form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN\">\n"
|
|
. Args::make_hidden()
|
|
. "<input type=\"image\" src=\"pict/menu_b_ok.jpg\" "
|
|
. "alt=\"Ok\" width=\"167\" height=20 border=\"0\">\n</form>";
|
|
|
|
Print::print_html_footer();
|
|
|
|
return;
|
|
}
|
|
|
|
# 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, $1
|
|
if (/^($::REG_INVESTIG)$/o);
|
|
}
|
|
close(INVES);
|
|
sort { lc($a) cmp lc($b) } @investigs;
|
|
}
|
|
|
|
# File of investigators name in list
|
|
sub investig_fname {
|
|
return "$::case_dir" . "investigators.txt";
|
|
}
|
|
|
|
####################################################################
|
|
# Image Functions
|
|
|
|
# Types of modes for fname (i.e. can we overwrite it if it exists)
|
|
my $FNAME_MODE_INIT = 0;
|
|
my $FNAME_MODE_OVER = 1;
|
|
|
|
my $MD5_NOTHING = 1;
|
|
my $MD5_CALC = 2;
|
|
my $MD5_ADD = 3;
|
|
|
|
my $IMG_ADD_SYM = 1;
|
|
my $IMG_ADD_COPY = 2;
|
|
my $IMG_ADD_MOVE = 3;
|
|
|
|
# Open an image that has been configured
|
|
sub vol_open {
|
|
Print::print_html_header(
|
|
"Open Image In $Args::args{'case'}:$Args::args{'host'}");
|
|
|
|
print "<b>Case:</b> $Args::args{'case'}<br>\n";
|
|
print "<b>Host:</b> $Args::args{'host'}<br>\n";
|
|
print "<center>\n";
|
|
|
|
# the images have been loaded from reading the host config file in
|
|
# autopsy_main
|
|
if (scalar(keys %Caseman::vol2ftype) == 0) {
|
|
print "No images have been added to this host yet<br><br>\n"
|
|
. "Select the Add Image File button below to add one\n";
|
|
goto EGRESS;
|
|
}
|
|
|
|
if ($::LIVE == 1) {
|
|
print "Select a volume to analyze.<br>\n";
|
|
}
|
|
else {
|
|
print "Select a volume to analyze or add a new image file.<br>\n";
|
|
}
|
|
|
|
print_menu_tabs();
|
|
|
|
print "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\" "
|
|
. "background=\"$::YEL_PIX\" border=0>\n";
|
|
|
|
# We want to sort, so rearrange the hash
|
|
my %mnt2vol;
|
|
my %par2disk;
|
|
|
|
# Cycle through each image we read from the host config
|
|
foreach my $i (keys %Caseman::vol2cat) {
|
|
if ($Caseman::vol2cat{$i} eq "disk") {
|
|
$mnt2vol{"1disk--AUTOPSY--$i"} = $i;
|
|
}
|
|
elsif ($Caseman::vol2cat{$i} eq "part") {
|
|
if ( ($Caseman::vol2ftype{$i} eq "raw")
|
|
|| ($Caseman::vol2ftype{$i} eq "swap"))
|
|
{
|
|
$mnt2vol{"2$Caseman::vol2ftype{$i}--AUTOPSY--$i"} = $i;
|
|
}
|
|
else {
|
|
$mnt2vol{"2$Caseman::vol2mnt{$i}--AUTOPSY--$i"} = $i;
|
|
}
|
|
}
|
|
}
|
|
|
|
# sort via parent volume, then starting location,
|
|
# and then mount point (which includes the name)
|
|
my @mnt = sort {
|
|
($Caseman::vol2par{$mnt2vol{$a}} cmp $Caseman::vol2par{$mnt2vol{$b}})
|
|
or ($Caseman::vol2start{$mnt2vol{$a}} <=>
|
|
$Caseman::vol2start{$mnt2vol{$b}})
|
|
or (lc($a) cmp lc($b))
|
|
} keys %mnt2vol;
|
|
|
|
# It is possible to have only the blkls 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_blkls;
|
|
|
|
# cycle through each image and check its type and original
|
|
foreach my $k (keys %Caseman::vol2ftype) {
|
|
if ( ($Caseman::vol2ftype{$k} eq "blkls")
|
|
&& (!exists $Caseman::mod2vol{$k}))
|
|
{
|
|
push @orphan_blkls, $k;
|
|
}
|
|
}
|
|
|
|
print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_OPEN_LOG\">\n"
|
|
. Args::make_hidden()
|
|
|
|
. "<tr><th> </th>"
|
|
. "<th align=left>mount</th>"
|
|
. "<th align=left>name</th>"
|
|
. # vol name
|
|
"<th align=left>fs type</th></tr>\n";
|
|
|
|
my $prev_par = "";
|
|
|
|
for (my $i = 0; $i <= $#mnt; $i++) {
|
|
my $vol = $mnt2vol{$mnt[$i]};
|
|
|
|
if ($Caseman::vol2par{$vol} ne $prev_par) {
|
|
print "<tr><td colspan=5><hr></td></tr>\n" if ($i != 0);
|
|
$prev_par = $Caseman::vol2par{$vol};
|
|
}
|
|
|
|
# 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] =~ /^\d(.*?)--AUTOPSY--$::REG_VNAME$/o);
|
|
print "<tr>" . "<td><input type=\"radio\" name=\"vol\" value=$vol";
|
|
print " CHECKED" if ($i == 0);
|
|
print "></td>" . "<td><tt>$mnt[$i]</tt></td>";
|
|
|
|
# image name and ftype
|
|
print
|
|
"<td><tt>$Caseman::vol2sname{$vol}</tt></td><td>$Caseman::vol2ftype{$vol}</td>";
|
|
if ($::LIVE == 0) {
|
|
print "<td align=center><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::VOL_DETAILS&$Args::baseargs&"
|
|
. "vol=$vol\">details</a></td>"
|
|
. "</tr>\n";
|
|
}
|
|
else {
|
|
print "<td> </td></tr>\n";
|
|
}
|
|
}
|
|
|
|
# If we are done with the regular images and have some orphan
|
|
# blkls images, print them
|
|
my @sort = sort @orphan_blkls;
|
|
for (my $i = 0; $i <= $#sort; $i++) {
|
|
print
|
|
"<tr><td> </td><td> </td><td>(<input type=\"radio\" name=\"vol\" "
|
|
. "value=$sort[$i]";
|
|
print " CHECKED" if ($#mnt == 0);
|
|
print
|
|
"> unalloc)</td><td><tt>$Caseman::vol2sname{$sort[$i]}</tt></td><td>$Caseman::vol2ftype{$sort[$i]}</td></tr>\n";
|
|
}
|
|
|
|
# Begin Button
|
|
print "</table>\n";
|
|
|
|
EGRESS:
|
|
|
|
print "<br><br>"
|
|
. "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">\n";
|
|
|
|
# Ok Button
|
|
if (scalar(keys %Caseman::vol2ftype) == 0) {
|
|
print "<tr><td width=200> </td>\n";
|
|
}
|
|
else {
|
|
print "<tr><td align=center width=200>"
|
|
. "<input type=\"image\" src=\"pict/menu_b_analyze.jpg\" "
|
|
. "alt=\"Analyze\" width=\"167\" height=20 border=0>\n"
|
|
. "</form></td>\n";
|
|
}
|
|
|
|
# Image Add Button
|
|
if ($::LIVE == 0) {
|
|
print "<td align=center width=200>"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD\">\n"
|
|
. Args::make_hidden()
|
|
. "<input type=\"image\" src=\"pict/menu_b_ifnew.jpg\" "
|
|
. "alt=\"Add Image\" width=167 height=20 border=0></form></td>\n"
|
|
.
|
|
|
|
# Cancel Button
|
|
"<td align=center width=200>"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN\">\n"
|
|
. "<input type=\"hidden\" name=\"case\" value=\"$Args::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>";
|
|
}
|
|
else {
|
|
print "<td width=200> </td><td width=200> </td></tr>\n";
|
|
}
|
|
|
|
# Help Button
|
|
print
|
|
"<td width=200> </td><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 width=200> </td></tr>\n"
|
|
. "</table>\n";
|
|
|
|
# Other features that can be done on a host
|
|
|
|
if ($::LIVE == 0) {
|
|
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?${Args::baseargs_novol}&"
|
|
. "mod=$::MOD_TL&view=$Timeline::FRAME\">"
|
|
. "<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?${Args::baseargs_novol}&"
|
|
. "mod=$::MOD_HASH&view=$Hash::IMG_LIST_FR\">"
|
|
. "<img border=0 "
|
|
. "src=\"pict/menu_b_int.jpg\" "
|
|
. "width=\"167\" height=20 "
|
|
. "alt=\"Image Integrity\"></a></td>\n"
|
|
.
|
|
|
|
# Hashdatabases
|
|
"<td align=\"center\" width=200>"
|
|
. "<a href=\"$::PROGNAME?${Args::baseargs_novol}&"
|
|
. "mod=$::MOD_HASH&view=$Hash::DB_MANAGER\">"
|
|
. "<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?${Args::baseargs_novol}&mod=$::MOD_NOTES&view=$Notes::READ_NORM\">"
|
|
. "<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?${Args::baseargs_novol}&mod=$::MOD_NOTES&view=$Notes::READ_SEQ\">"
|
|
. "<img border=0 "
|
|
. "src=\"pict/menu_b_seq.jpg\" "
|
|
. "width=\"167\" height=20 "
|
|
. "alt=\"Event Sequencer\"></a></td>\n"
|
|
.
|
|
|
|
"</tr>\n" . "</table>\n";
|
|
}
|
|
|
|
# If LIVE
|
|
}
|
|
else {
|
|
print "<a href=\"./about\"><br>\n"
|
|
. "<img src=\"pict/logo.jpg\" border=0 alt=\"Logo\"></a><br>\n";
|
|
|
|
}
|
|
|
|
Print::print_html_footer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
# Log in the host log that a given image was opened by what user
|
|
# then open the main window
|
|
sub vol_open_log {
|
|
|
|
# These will be stopped in the func during LIVE
|
|
Print::log_host_info(
|
|
"Image $Args::args{'vol'} opened by $Args::args{'inv'}");
|
|
Print::log_host_inv("$Args::args{'vol'}: volume opened");
|
|
|
|
$Args::args{'mod'} = $Args::enc_args{'mod'} = $::MOD_FRAME;
|
|
$Args::args{'view'} = $Args::enc_args{'view'} = $Frame::IMG_FRAME;
|
|
Frame::main();
|
|
}
|
|
|
|
# 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
|
|
#
|
|
sub img_add {
|
|
Print::print_html_header(
|
|
"Add Image To $Args::args{'case'}:$Args::args{'host'}");
|
|
|
|
print "<b>Case:</b> $Args::args{'case'}<br>\n"
|
|
. "<b>Host:</b> $Args::args{'host'}<br>\n";
|
|
|
|
print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD_PREP\">\n"
|
|
. Args::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=4> </td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td align=left colspan=4>
|
|
1. <b>Location</b><br>Enter the full path (starting with <tt>/</tt>) to the image file.<br>
|
|
If the image is split (either raw or EnCase), then enter '*' for the extension.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=3>
|
|
<input type=\"text\" name=\"img_path\" size=36 maxlength=256>
|
|
</td>
|
|
</tr>
|
|
<tr><td colspan=4> </td><tr>
|
|
<tr>
|
|
<td align=left colspan=4>2. <b>Type</b><br>Please select if this image file is for a disk or a single partition.</td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left>
|
|
<input type=\"radio\" name=\"imgtype\" value="disk" CHECKED>
|
|
Disk
|
|
</td>
|
|
<td align=left>
|
|
<input type=\"radio\" name=\"imgtype\" value="volume">
|
|
Partition
|
|
</td>
|
|
<td align=left>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr><td colspan=4> </td><tr>
|
|
<tr>
|
|
<td align=left colspan=4>3. <b>Import Method</b><br>To analyze the image file, it must be located in the evidence locker. It can be imported from its current location using a symbolic link, by copying it, or by moving it. Note that if a system failure occurs during the move, then the image could become corrupt.</td>
|
|
</tr>
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left>
|
|
<input type=\"radio\" name=\"sort\" value=$IMG_ADD_SYM CHECKED>
|
|
Symlink
|
|
</td>
|
|
<td align=left>
|
|
<input type=\"radio\" name=\"sort\" value=$IMG_ADD_COPY>
|
|
Copy
|
|
</td>
|
|
<td align=left>
|
|
<input type=\"radio\" name=\"sort\" value=$IMG_ADD_MOVE>
|
|
Move
|
|
</td>
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
<td colspan=4> </td>
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
<br>
|
|
<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">
|
|
<tr>
|
|
<td align=center colspan=2>
|
|
<input type=\"image\" src=\"pict/menu_b_next.jpg\" alt=\"Next Step\" width=\"167\" height=20 border=0>
|
|
</td>
|
|
</tr>
|
|
|
|
</form>
|
|
|
|
EOF1
|
|
|
|
print "<tr><td colspan=2> </td></tr>\n"
|
|
. "<td align=center>\n"
|
|
. " <form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. " <input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. " <input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_OPEN\">\n"
|
|
.
|
|
|
|
Args::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";
|
|
|
|
Print::print_html_footer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
# List the images from the glob - called from img_add_prep if spl_conf is not set
|
|
sub img_add_split_conf {
|
|
my $img_path = Args::get_img_path_wild();
|
|
my $img_type = $Args::args{'imgtype'};
|
|
|
|
print "<center><br><br><b>Split Image Confirmation</b><br><br>\n";
|
|
|
|
my @spl_img = glob($img_path);
|
|
if (scalar(@spl_img) == 0) {
|
|
print "No images were found at this location ($img_path)<br>\n"
|
|
. "Use the back button and fix the path<br>\n";
|
|
return;
|
|
}
|
|
|
|
print <<EOF1;
|
|
The following images will be added to the case.<br>
|
|
If this is not the correct order, then you should change the naming convention.<br>
|
|
Press the Next button at the bottom of the page if this is correct.<br><br>
|
|
|
|
<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" background=\"$::YEL_PIX\" border=0>
|
|
<tr>
|
|
<td colspan=2> </td>
|
|
</tr>
|
|
EOF1
|
|
|
|
my $a = 0;
|
|
foreach $i (@spl_img) {
|
|
|
|
# We need to do this when we analyze the image, so do it here too to show
|
|
# what will be analyzed
|
|
$i = $1 if ($i =~ /^($::REG_IMG_PATH)$/);
|
|
print
|
|
"<tr><td align=\"center\">$a</td><td align=\"left\"><tt>$i</tt></td></tr>\n";
|
|
$a++;
|
|
}
|
|
|
|
my $vs = "";
|
|
$vs = "&vstype=$Args::args{'vstype'}"
|
|
if (exists $Args::args{'vstype'});
|
|
|
|
# Print the Ok Button
|
|
print "</table><br><br>\n"
|
|
. "<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" border=0>"
|
|
. "<tr><td width=\"300\" align=\"center\"><a href=\"$::PROGNAME?${Args::baseargs_novol}&"
|
|
. "mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD_PREP&spl_conf=1&sort=$Args::args{'sort'}&"
|
|
. "img_path=$img_path&imgtype=$Args::args{'imgtype'}$vs\">"
|
|
. "<img src=\"pict/menu_b_next.jpg\" alt=\"Next\" "
|
|
. "width=\"167\" height=20 border=0></a></td>\n"
|
|
. "<td width=\"300\" align=\"center\"><a href=\"$::PROGNAME?${Args::baseargs_novol}&"
|
|
. "mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD\">"
|
|
. "<img src=\"pict/menu_b_cancel.jpg\" alt=\"cancel\" width=\"167\" height=\"20\" border=\"0\">"
|
|
. "</a></td></tr></table>\n";
|
|
|
|
return 0;
|
|
}
|
|
|
|
# Run the autodetect stuff and get confirmation from the user
|
|
sub img_add_prep {
|
|
Args::check_img_path_wild();
|
|
Args::check_sort();
|
|
unless ((exists $Args::args{'imgtype'})
|
|
&& ($Args::args{'imgtype'} =~ /^\w+$/))
|
|
{
|
|
Print::print_check_err("Invalid image type");
|
|
}
|
|
|
|
Print::print_html_header("Collecting details on new image file");
|
|
|
|
my $img_path = Args::get_img_path_wild();
|
|
|
|
my $img_type = $Args::args{'imgtype'};
|
|
my $spl_conf = 0;
|
|
$spl_conf = 1
|
|
if ((exists $Args::args{'spl_conf'}) && ($Args::args{'spl_conf'} == 1));
|
|
|
|
# If we have a wildcard then it is a split image, so we verify it first and
|
|
# then make a string of the images so we can test it.
|
|
if ($img_path =~ /[\*\?]/) {
|
|
if ($spl_conf == 0) {
|
|
return img_add_split_conf();
|
|
}
|
|
else {
|
|
$img_tmp = "";
|
|
foreach my $i (glob($img_path)) {
|
|
if ($i =~ /^($::REG_IMG_PATH)$/) {
|
|
$img_tmp .= "\"$1\" ";
|
|
}
|
|
}
|
|
$img_path = $img_tmp;
|
|
}
|
|
}
|
|
else {
|
|
unless ((-f $img_path)
|
|
|| (-d $img_path)
|
|
|| (-l $img_path)
|
|
|| (-b $img_path)
|
|
|| (-c $img_path))
|
|
{
|
|
Print::print_err("Image file not found ($img_path)");
|
|
}
|
|
$img_path = "\"$img_path\"";
|
|
}
|
|
|
|
# Get the image type
|
|
local *OUT;
|
|
Exec::exec_pipe(*OUT, "'$::TSKDIR/img_stat' -t $img_path");
|
|
my $itype = Exec::read_pipe_line(*OUT);
|
|
if (defined $itype) {
|
|
chomp $itype;
|
|
$itype = $1 if ($itype =~ /^(\w+)$/);
|
|
}
|
|
else {
|
|
print
|
|
"The image format type could not be determined for this image file<br>\n";
|
|
return;
|
|
}
|
|
close(OUT);
|
|
|
|
# The plan here is to collect the needed info and then we print it
|
|
|
|
my $conflict = 0;
|
|
my $cnt = 0;
|
|
$start[0] = "";
|
|
$end[0] = "";
|
|
$type[0] = "";
|
|
$desc[0] = "";
|
|
$active[0] = "";
|
|
|
|
my $vstype = "";
|
|
|
|
my $vstype_flag = "";
|
|
my $mmls_out = ""; # Will contain output of mmls (if disk image)
|
|
if ($img_type eq "disk") {
|
|
my $out;
|
|
|
|
if ( (exists $Args::args{'vstype'})
|
|
&& ($Args::args{'vstype'} =~ /^(\w+)$/))
|
|
{
|
|
$vstype = $Args::args{'vstype'};
|
|
$vstype_flag = "-t $vstype";
|
|
}
|
|
|
|
# Get the type
|
|
else {
|
|
|
|
Exec::exec_pipe(*OUT, "'$::TSKDIR/mmstat' -i $itype $img_path");
|
|
|
|
$vstype = Exec::read_pipe_line(*OUT);
|
|
close(OUT);
|
|
|
|
chomp $vstype if (defined $vstype);
|
|
|
|
if ( (!defined $vstype)
|
|
|| ($vstype =~ /^Error determining/)
|
|
|| ($vstype eq "")
|
|
|| (!exists $Vs::type{$vstype})
|
|
|| ($vstype !~ /^\w+$/))
|
|
{
|
|
print
|
|
"<table><tr><td colspan=2><font color=\"$::DEL_COLOR[0]\">Warning:</font> Autopsy could not determine the volume system type for the disk image (i.e. the type of partition table).<br>\n"
|
|
. "Please select the type from the list below or reclassify the image as a volume image instead of as a disk image.</td></tr>\n"
|
|
. "<tr><td colspan=2> </td></tr>\n"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD_PREP\">\n"
|
|
. "<input type=\"hidden\" name=\"spl_conf\" value=\"1\">\n"
|
|
. "<input type=\"hidden\" name=\"img_path\" value=\"$Args::args{'img_path'}\">\n"
|
|
. "<input type=\"hidden\" name=\"sort\" value=\"$Args::enc_args{'sort'}\">\n"
|
|
. Args::make_hidden()
|
|
. "<tr><td>Disk Image <input type=\"radio\" name=\"imgtype\" value=\"disk\" CHECKED></td>\n"
|
|
. "<td>Volume Image<input type=\"radio\" name=\"imgtype\" value=\"volume\"></td></tr>\n"
|
|
. "<tr><td>Volume System Type (disk image only): <select name=\"vstype\">\n";
|
|
|
|
foreach my $vs (sort keys %Vs::type) {
|
|
print "<option value=\"$vs\"";
|
|
print " selected" if ($vs eq 'dos');
|
|
print ">${vs}</option>\n";
|
|
}
|
|
|
|
print "</select></td>"
|
|
. "<td> </td></tr>"
|
|
. "<tr><td colspan=2> </td></tr>"
|
|
. "</table><br><br>\n"
|
|
. "<input type=\"image\" src=\"pict/menu_b_ok.jpg\" alt=\"Ok\" width=\"176\" height=20 border=0>"
|
|
. "</form>\n";
|
|
return;
|
|
}
|
|
$vstype = $1 if ($vstype =~ /^(\w+)$/);
|
|
$vstype_flag = "-t $vstype";
|
|
}
|
|
|
|
# Run 'mmls' on the image
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/mmls' -a -i $itype -aM $vstype_flag -r $img_path");
|
|
|
|
# cycle through results and add each to table with file system type
|
|
my $part_type = "";
|
|
|
|
while ($_ = Exec::read_pipe_line(*OUT)) {
|
|
$mmls_out .= "$_"; # Save the line
|
|
last if (/^Error determining partition/);
|
|
|
|
if (/^\d+:\s+[\d:]+\s+(\d+)\s+(\d+)\s+\d+\s+(\S.*)$/) {
|
|
$start[$cnt] = $1;
|
|
$end[$cnt] = $2;
|
|
$desc[$cnt] = $3;
|
|
$active[$cnt] = 1;
|
|
}
|
|
elsif ((/^DOS Partition/)
|
|
|| (/^BSD Disk/)
|
|
|| (/^Sun VTOC/)
|
|
|| (/^MAC Partition/)
|
|
|| (/^GUID Partition/))
|
|
{
|
|
$part_type = $_;
|
|
|
|
#print "<tr><td colspan=7> </td></tr>\n";
|
|
#print "<tr><td colspan=7>$_</td></tr>\n";
|
|
next;
|
|
}
|
|
elsif (/^Sector:/) {
|
|
|
|
#print "<tr><td colspan=7>$_</td></tr>\n";
|
|
next;
|
|
}
|
|
else {
|
|
next;
|
|
}
|
|
|
|
# Skip the BSD partition for the full disk
|
|
next
|
|
if ( ($part_type =~ /^BSD Disk/)
|
|
&& ($start[$cnt] == 0)
|
|
&& ($desc[$cnt] =~ /^Unused/));
|
|
|
|
# Skip if this is an extended DOS partition
|
|
next
|
|
if ( ($part_type =~ /^DOS Partition/)
|
|
&& ($desc[$cnt] =~ /Extended \(/));
|
|
|
|
# Get rid of the leading 0s
|
|
$start[$cnt] = $1
|
|
if ($start[$cnt] =~ /^0+([1-9]\d*)$/);
|
|
$end[$cnt] = $1
|
|
if ($end[$cnt] =~ /^0+([1-9]\d*)$/);
|
|
|
|
# Do we already have this partition?
|
|
my $i;
|
|
for ($i = 0; $i < $cnt; $i++) {
|
|
next if ($active[$i] == 0);
|
|
|
|
if ($start[$i] == $start[$cnt]) {
|
|
$conflict = 1;
|
|
|
|
if ($end[$i] == $end[$cnt]) {
|
|
last;
|
|
}
|
|
|
|
#The previous was the BSD partition - skip it */
|
|
if ( ($desc[$i] =~ /^FreeBSD \(0xA5\)/)
|
|
|| ($desc[$i] =~ /^OpenBSD \(0xA6\)/)
|
|
|| ($desc[$i] =~ /^NetBSD \(0xA9\)/))
|
|
{
|
|
$active[$i] = 0;
|
|
|
|
# if the current one is the BSD partition for
|
|
# the full partition/disk then skip it
|
|
if ($desc[$cnt] =~ /^Unused /) {
|
|
$active[$cnt] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
# Do we start inside of another?
|
|
if (($start[$i] > $start[$cnt]) && ($end[$i] < $start[$cnt])) {
|
|
$conflict = 1;
|
|
}
|
|
|
|
# Do we end inside of another?
|
|
elsif (($start[$i] < $end[$cnt]) && ($end[$i] > $end[$cnt])) {
|
|
$conflict = 1;
|
|
}
|
|
}
|
|
if (($end[$i] == $end[$cnt]) && ($i != $cnt)) {
|
|
next;
|
|
}
|
|
|
|
local *OUT2;
|
|
my $out2;
|
|
|
|
# Run 'fstat -t' on the image
|
|
Exec::exec_pipe(*OUT2,
|
|
"'$::TSKDIR/fsstat' -o $start[$cnt] -i $itype -t $img_path");
|
|
|
|
$type[$cnt] = Exec::read_pipe_line(*OUT2);
|
|
close(OUT2);
|
|
|
|
if ( (!exists $type[$cnt])
|
|
|| (!defined $type[$cnt])
|
|
|| ($type[$cnt] =~ /^Cannot determine/)
|
|
|| ($type[$cnt] eq ""))
|
|
{
|
|
$type[$cnt] = "Unknown";
|
|
}
|
|
chomp $type[$cnt];
|
|
|
|
$cnt++;
|
|
}
|
|
close(OUT);
|
|
|
|
if ($conflict == 1) {
|
|
print
|
|
"<tr><td colspan=2><font color=\"$::DEL_COLOR[0]\">Warning:</font> Conflicts in the partitions were detected.<br>The full <tt>mmls</tt> output is given at the bottom of the page</td></tr>\n"
|
|
. "<tr><td colspan=2> </td></tr>\n";
|
|
}
|
|
}
|
|
|
|
# If a volume, then run fsstat on it
|
|
elsif ($img_type eq "volume") {
|
|
|
|
# Run 'fstat -t' on the image
|
|
Exec::exec_pipe(*OUT, "'$::TSKDIR/fsstat' -t -i $itype $img_path");
|
|
|
|
$type[0] = Exec::read_pipe_line(*OUT);
|
|
close(OUT);
|
|
|
|
if ( (!defined $type[0])
|
|
|| ($type[0] =~ /^Cannot determine/)
|
|
|| ($type[0] eq ""))
|
|
{
|
|
$type[0] = "Unknown";
|
|
print
|
|
"<font color=\"$::DEL_COLOR[0]\">Warning:</font> The file system type of the volume image file could not be determined.<br>\n"
|
|
. "If this is a disk image file, return to the previous page and change the type.<br><br>\n";
|
|
}
|
|
chomp $type[0];
|
|
$start[0] = 0;
|
|
$end[0] = 0;
|
|
$active[0] = 1;
|
|
$desc[0] = $type[0];
|
|
$cnt++;
|
|
close(OUT);
|
|
}
|
|
else {
|
|
Print::print_err("Unknown image type: $img_type");
|
|
}
|
|
|
|
my $sname = $img_path;
|
|
$sname = "$::IMGDIR/" . "$1" if ($sname =~ /\/($::REG_FILE)\"$/);
|
|
|
|
# Now that we have the information about the partitions and disks, print the fields
|
|
print <<EOF1;
|
|
|
|
<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">
|
|
<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">
|
|
<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD_DOIT\">
|
|
<input type=\"hidden\" name=\"img_path\" value=\"$Args::args{'img_path'}\">
|
|
<input type=\"hidden\" name=\"num_img\" value=\"$cnt\">
|
|
<input type=\"hidden\" name=\"sort\" value=\"$Args::enc_args{'sort'}\">
|
|
|
|
|
|
<center>
|
|
<h3>Image File Details</h3>
|
|
<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" background=\"$::YEL_PIX\" border=0>
|
|
<tr>
|
|
<td align=left colspan=4>
|
|
<b>Local Name: </b> $sname
|
|
</td>
|
|
</tr>
|
|
|
|
EOF1
|
|
|
|
# We do not currently offer integrity options for non-raw files
|
|
if (($itype eq "raw") || ($itype eq "split")) {
|
|
|
|
print <<EOF1b;
|
|
<tr>
|
|
<td align=left colspan=4>
|
|
<b>Data Integrity: </b> An MD5 hash can be used to verify the
|
|
integrity of the image. (With split images, this hash is for the full image file)
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=3>
|
|
<input type=\"radio\" name=\"do_md5\" value=\"$MD5_NOTHING\" CHECKED>
|
|
<u>Ignore</u> the hash value for this image.
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=3>
|
|
<input type=\"radio\" name=\"do_md5\" value=\"$MD5_CALC\">
|
|
<u>Calculate</u> the hash value for this image.
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=3>
|
|
<input type=\"radio\" name=\"do_md5\" value=\"$MD5_ADD\">
|
|
<u>Add</u> the following MD5 hash value for this image:
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=3>
|
|
<input type=\"text\" name=\"md5\" size=36 maxlength=32>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td> </td>
|
|
<td align=left colspan=3>
|
|
<input type=\"checkbox\" name=\"ver_md5\" value=\"1\">
|
|
Verify hash after importing?
|
|
</td>
|
|
</tr>
|
|
EOF1b
|
|
}
|
|
else {
|
|
print
|
|
"<input type=\"hidden\" name=\"do_md5\" value=\"$MD5_NOTHING\">\n";
|
|
}
|
|
|
|
print <<EOF1c;
|
|
</table>
|
|
|
|
<h3>File System Details</h3>
|
|
<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" background=\"$::YEL_PIX\" border=0>
|
|
|
|
<tr>
|
|
<td colspan=2 align=left>Analysis of the image file shows the following partitions:</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan=2> </td>
|
|
</tr>
|
|
|
|
EOF1c
|
|
|
|
print Args::make_hidden();
|
|
|
|
print "<input type=\"hidden\" name=\"vstype\" value=\"$vstype\">\n"
|
|
if ($vstype ne "");
|
|
|
|
my $idx = 1;
|
|
my $ms_cnt = 0;
|
|
my @ms_name = ("C:", "D:", "E:", "F:", "G:", "H:", "I:", "J:");
|
|
for (my $i = 0; $i < $cnt; $i++) {
|
|
next if ($active[$i] == 0);
|
|
print
|
|
"<tr><td colspan=2><u>Partition $idx</u> (Type: $desc[$i])</td><tr>\n";
|
|
|
|
if ($cnt > 1) {
|
|
print "<tr><td colspan=2> Add to case? "
|
|
. "<input type=\"checkbox\" name=\"yes-${idx}\" value=1 CHECKED></td></tr>\n";
|
|
}
|
|
else {
|
|
print "<input type=\"hidden\" name=\"yes-${idx}\" value=1>\n";
|
|
}
|
|
|
|
unless (($start[$i] == 0) && ($end[$i] == 0)) {
|
|
print "<tr><td colspan=2> Sector Range: "
|
|
. "$start[$i] to $end[$i]"
|
|
. "</td></tr>\n";
|
|
}
|
|
|
|
print
|
|
"<input type=\"hidden\" name=\"start-${idx}\" value=\"$start[$i]\">"
|
|
. "<input type=\"hidden\" name=\"end-${idx}\" value=\"$end[$i]\">\n"
|
|
. "<tr><td> Mount Point: <input type=\"text\" name=\"mnt-${idx}\" size=\"6\"";
|
|
if (($type[$i] =~ /^ntfs/) || ($type[$i] =~ /^fat/)) {
|
|
print " value=\"$ms_name[$ms_cnt]\""
|
|
if ($ms_cnt < 8);
|
|
$ms_cnt++;
|
|
}
|
|
elsif (($type[$i] =~ /^raw/)
|
|
|| ($type[$i] =~ /^swap/))
|
|
{
|
|
print " value=\"N/A\"";
|
|
}
|
|
else {
|
|
print " value=\"/$idx/\"";
|
|
}
|
|
print "></td>\n"
|
|
. "<td>File System Type: <select name=\"ftype-${idx}\">\n";
|
|
|
|
foreach my $fs (@Fs::types) {
|
|
print "<option value=\"$fs\"";
|
|
print " selected" if ($fs eq $type[$i]);
|
|
print ">${fs}</option>\n";
|
|
}
|
|
|
|
# The following do not have 'metas' but should be in the list
|
|
print "<option value=\"\">======</option>\n";
|
|
if ($type[$i] eq "Unknown") {
|
|
print "<option value=\"raw\" selected>raw</option>\n";
|
|
}
|
|
else {
|
|
print "<option value=\"raw\">raw</option>\n";
|
|
}
|
|
|
|
print "<option value=\"swap\">swap</option>\n"
|
|
. "</select></td></tr>\n"
|
|
. "<tr><td colspan=2> </td></tr>\n";
|
|
|
|
$idx++;
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
print <<EOF2;
|
|
<br><br>
|
|
<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">
|
|
<tr>
|
|
<td align=center>
|
|
<input type=\"image\" src=\"pict/menu_b_add.jpg\"
|
|
alt=\"Add\" width=\"176\" height=20 border=0>
|
|
</td>
|
|
</form>
|
|
<td align=center>
|
|
<form action=\"$::PROGNAME\" method=\"get\">
|
|
EOF2
|
|
print Args::make_hidden();
|
|
print <<EOF3;
|
|
<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">
|
|
<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_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>
|
|
EOF3
|
|
|
|
if ($img_type eq "disk") {
|
|
print
|
|
"</center><p>For your reference, the <tt>mmls</tt> output was the following:<br><pre>$mmls_out</pre>\n";
|
|
}
|
|
|
|
Print::print_html_footer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
# Add the image to the configuration by adding it to the host config file
|
|
# and the md5.txt file if that data was provided
|
|
sub img_add_doit {
|
|
|
|
Args::check_num_img();
|
|
Args::check_img_path_wild();
|
|
Args::check_sort();
|
|
Args::check_do_md5();
|
|
|
|
my $num_img = Args::get_num_img();
|
|
my $img_path = Args::get_img_path_wild();
|
|
my $import_type = Args::get_sort();
|
|
|
|
Print::print_html_header("Add a new image to an Autopsy Case");
|
|
|
|
my $err = 0;
|
|
my $add_num = 0;
|
|
$start[0] = 0;
|
|
$end[0] = 0;
|
|
$ftype[0] = "";
|
|
$mnt[0] = "";
|
|
|
|
# We need a string with all images in it for the hashes and file system testing
|
|
my $img_path_full;
|
|
if ($img_path =~ /[\*\?]/) {
|
|
$img_path_full = "";
|
|
foreach my $i (glob($img_path)) {
|
|
if ($i =~ /^($::REG_IMG_PATH)$/) {
|
|
$img_path_full .= "\"$1\" ";
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
$img_path_full = "\"$img_path\"";
|
|
}
|
|
|
|
# Get the image type
|
|
local *OUT;
|
|
Exec::exec_pipe(*OUT, "'$::TSKDIR/img_stat' -t $img_path_full");
|
|
my $itype = Exec::read_pipe_line(*OUT);
|
|
if (defined $itype) {
|
|
chomp $itype;
|
|
$itype = $1 if ($itype =~ /^(\w+)$/);
|
|
}
|
|
else {
|
|
print
|
|
"The image format type could not be determined for this image file<br>\n";
|
|
return;
|
|
}
|
|
close(OUT);
|
|
|
|
# Check the hash of the image if that is the plan
|
|
my $do_md5 = Args::get_do_md5();
|
|
my $act_md5 = "";
|
|
unless ($do_md5 == $MD5_NOTHING) {
|
|
|
|
# Do we need to calculate an MD5?
|
|
if (
|
|
($do_md5 == $MD5_CALC)
|
|
|| ( ($do_md5 == $MD5_ADD)
|
|
&& (exists $Args::args{'ver_md5'})
|
|
&& ($Args::args{'ver_md5'} == 1))
|
|
)
|
|
{
|
|
|
|
print "<p>Calculating MD5 (this could take a while)<br>\n";
|
|
$act_md5 = Hash::calc_md5_split($img_path_full);
|
|
unless ($act_md5 =~ /^$::REG_MD5$/o) {
|
|
print "Error calculating MD5: $act_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::args{'md5'})) {
|
|
|
|
my $md5 = $Args::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?"
|
|
. "mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD&"
|
|
. "$Args::baseargs\">"
|
|
. "<img src=\"pict/menu_b_back.jpg\" border=\"0\" "
|
|
. "width=\"167\" height=20 alt=\"Back\"></a>\n";
|
|
return 1;
|
|
}
|
|
$md5 =~ tr/[a-f]/[A-F]/;
|
|
|
|
# They also want us to validate the MD5
|
|
if ( (exists $Args::args{'ver_md5'})
|
|
&& ($Args::args{'ver_md5'} == 1))
|
|
{
|
|
|
|
if ($act_md5 eq $md5) {
|
|
print "Integrity Check Passed<br>\n";
|
|
Print::log_host_info("Integrity check passed on new image");
|
|
}
|
|
else {
|
|
print "<font color=\"$::DEL_COLOR[0]\">"
|
|
. "Integrity Check Failed<br></font><br>\n"
|
|
. "Provided: <tt>$md5</tt><br>\n"
|
|
. "Image not added to case<br>\n";
|
|
|
|
Print::log_host_info("Integrity check failed on new image");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
# set the act_md5 value to what was given and verified
|
|
$act_md5 = $md5;
|
|
}
|
|
|
|
# We will add the MD5 to the config file after we get its ID
|
|
}
|
|
|
|
# Proces the image arguments to make sure they are all there and test the
|
|
# file system type
|
|
print "Testing partitions<br>\n";
|
|
for (my $i = 0; $i <= $num_img; $i++) {
|
|
|
|
next
|
|
unless ((exists $Args::args{"yes-" . $i})
|
|
&& ($Args::args{"yes-" . $i} == 1));
|
|
|
|
if ( (exists $Args::args{"start-" . $i})
|
|
&& ($Args::args{"start-" . $i} =~ /^(\d+)$/))
|
|
{
|
|
$start[$add_num] = $1;
|
|
}
|
|
else {
|
|
print "Missing starting address for partition $i<br>\n";
|
|
$err = 1;
|
|
last;
|
|
}
|
|
|
|
if ( (exists $Args::args{"end-" . $i})
|
|
&& ($Args::args{"end-" . $i} =~ /^(\d+)$/))
|
|
{
|
|
$end[$add_num] = $1;
|
|
}
|
|
else {
|
|
print "Missing ending address for partition $i<br>\n";
|
|
$err = 1;
|
|
last;
|
|
}
|
|
|
|
if ( (exists $Args::args{"mnt-" . $i})
|
|
&& ($Args::args{"mnt-" . $i} =~ /^($::REG_MNT)$/))
|
|
{
|
|
$mnt[$add_num] = $1;
|
|
}
|
|
else {
|
|
print "Missing mount point for partition $i<br>\n";
|
|
$err = 1;
|
|
last;
|
|
}
|
|
|
|
if ( (exists $Args::args{"ftype-" . $i})
|
|
&& ($Args::args{"ftype-" . $i} =~ /^($::REG_FTYPE)$/))
|
|
{
|
|
$ftype[$add_num] = $1;
|
|
}
|
|
else {
|
|
print "Missing file system type for partition $i<br>\n";
|
|
$err = 1;
|
|
last;
|
|
}
|
|
|
|
# Test the File System
|
|
if (($ftype[$add_num] ne 'swap') && ($ftype[$add_num] 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::exec_pipe(*OUT,
|
|
"'$::TSKDIR/fsstat' -o $start[$add_num] -i $itype -f $ftype[$add_num] $img_path_full"
|
|
);
|
|
unless (read(OUT, $out, 1)) {
|
|
print
|
|
"<p>Partition $i is not a <tt>$ftype[$add_num]</tt> file system<br>\n";
|
|
$err = 1;
|
|
last;
|
|
}
|
|
close(OUT);
|
|
}
|
|
$add_num++;
|
|
}
|
|
|
|
# Go back if we got an error
|
|
if ($err == 1) {
|
|
print "Use the browser's back button to fix the data<br>\n";
|
|
return 1;
|
|
}
|
|
|
|
##################################################
|
|
# Copy the images and add them to the config file
|
|
|
|
if ($import_type == $IMG_ADD_SYM) {
|
|
Print::print_err("ERROR: /bin/ln missing")
|
|
unless (-x '/bin/ln');
|
|
|
|
print "Linking image(s) into evidence locker<br>\n";
|
|
}
|
|
elsif ($import_type == $IMG_ADD_COPY) {
|
|
Print::print_err("ERROR: /bin/cp missing")
|
|
unless (-x '/bin/cp');
|
|
|
|
print
|
|
"Copying image(s) into evidence locker (this could take a little while)<br>\n";
|
|
}
|
|
elsif ($import_type == $IMG_ADD_MOVE) {
|
|
Print::print_err("ERROR: /bin/mv missing")
|
|
unless (-x '/bin/mv');
|
|
|
|
print "Moving image(s) into evidence locker<br>\n";
|
|
}
|
|
else {
|
|
Print::print_err("Invalid Import Type: $import_type\n");
|
|
}
|
|
|
|
my $imgid = "";
|
|
foreach my $i (glob($img_path)) {
|
|
|
|
# remove the tainting
|
|
$i = $1 if ($i =~ /^($::REG_IMG_PATH)$/);
|
|
|
|
# Deterine the local (target) name
|
|
my $img = "";
|
|
if ($i =~ /\/($::REG_FILE)$/) {
|
|
$img = "$::IMGDIR/$1";
|
|
}
|
|
else {
|
|
Print::print_err("Error Parsing Image Path ($i)\n");
|
|
}
|
|
|
|
# Get the full path of the destination
|
|
my $img_dst = "$::host_dir" . "$img";
|
|
if ((-e "$img_dst") || (-l "$img_dst")) {
|
|
Print::print_err(
|
|
"An image by the same name already exists in the Host directory ($img)\n"
|
|
. "Use the browser's back button to fix the name or delete the existing file."
|
|
);
|
|
}
|
|
|
|
my $orig_size = (stat("$i"))[7];
|
|
|
|
# Copy, Move, or link it
|
|
if ($import_type == $IMG_ADD_SYM) {
|
|
|
|
Print::log_host_info(
|
|
"Sym Linking image $img_path into $Args::args{'case'}:$Args::args{'host'}"
|
|
);
|
|
|
|
Exec::exec_sys("/bin/ln -s '$i' '$img_dst'");
|
|
}
|
|
elsif ($import_type == $IMG_ADD_COPY) {
|
|
Print::log_host_info(
|
|
"Copying image $img_path into $Args::args{'case'}:$Args::args{'host'}"
|
|
);
|
|
|
|
Exec::exec_sys("/bin/cp '$i' '$img_dst'");
|
|
}
|
|
elsif ($import_type == $IMG_ADD_MOVE) {
|
|
Print::log_host_info(
|
|
"Moving image $img_path into $Args::args{'case'}:$Args::args{'host'}"
|
|
);
|
|
|
|
Exec::exec_sys("/bin/mv '$i' '$img_dst'");
|
|
}
|
|
|
|
my $new_size = (stat("$img_dst"))[7];
|
|
|
|
if ($new_size != $orig_size) {
|
|
Print::print_err(
|
|
"Original image size ($orig_size) is not the same as the destination size ($new_size)"
|
|
);
|
|
}
|
|
|
|
# Add the disk and partition images to the config file
|
|
$imgid = Caseman::add_img_host_config("image", "$itype $img", $imgid);
|
|
}
|
|
print "Image file added with ID <tt>$imgid</tt><br>\n";
|
|
|
|
# AFM files have raw files that we also need to copy
|
|
# This approach is not the best, since it may copy more than
|
|
# is needed
|
|
if ($itype eq "afm") {
|
|
my $afm_base_path = "";
|
|
|
|
if ($img_path =~ /^(.*?)\.afm/i) {
|
|
$afm_base_path = $1;
|
|
$afm_base_path .= ".[0-9][0-9][0-9]";
|
|
}
|
|
else {
|
|
Print::print_err(
|
|
"Error parsing out base name of AFM file $img_path");
|
|
}
|
|
|
|
print "BASE: $afm_base_path<br>\n";
|
|
|
|
my $copied = 0;
|
|
|
|
foreach my $i (glob($afm_base_path)) {
|
|
$copied++;
|
|
|
|
# remove the tainting
|
|
$i = $1 if ($i =~ /^($::REG_IMG_PATH)$/);
|
|
|
|
# Deterine the local (target) name
|
|
my $img = "";
|
|
if ($i =~ /\/($::REG_FILE)$/) {
|
|
$img = "$::IMGDIR/$1";
|
|
}
|
|
else {
|
|
Print::print_err("Error Parsing Image Path ($i)\n");
|
|
}
|
|
|
|
# Get the full path of the destination
|
|
my $img_dst = "$::host_dir" . "$img";
|
|
if ((-e "$img_dst") || (-l "$img_dst")) {
|
|
Print::print_err(
|
|
"An image by the same name already exists in the Host directory ($img) (AFM import)\n"
|
|
. "Use the browser's back button to fix the name or delete the existing file."
|
|
);
|
|
}
|
|
|
|
my $orig_size = (stat("$i"))[7];
|
|
|
|
# Copy, Move, or link it
|
|
if ($import_type == $IMG_ADD_SYM) {
|
|
|
|
Print::log_host_info(
|
|
"Sym Linking image $img_path into $Args::args{'case'}:$Args::args{'host'}"
|
|
);
|
|
|
|
Exec::exec_sys("/bin/ln -s '$i' '$img_dst'");
|
|
}
|
|
elsif ($import_type == $IMG_ADD_COPY) {
|
|
Print::log_host_info(
|
|
"Copying image $img_path into $Args::args{'case'}:$Args::args{'host'}"
|
|
);
|
|
|
|
Exec::exec_sys("/bin/cp '$i' '$img_dst'");
|
|
}
|
|
elsif ($import_type == $IMG_ADD_MOVE) {
|
|
Print::log_host_info(
|
|
"Moving image $img_path into $Args::args{'case'}:$Args::args{'host'}"
|
|
);
|
|
|
|
Exec::exec_sys("/bin/mv '$i' '$img_dst'");
|
|
}
|
|
|
|
my $new_size = (stat("$img_dst"))[7];
|
|
|
|
if ($new_size != $orig_size) {
|
|
Print::print_err(
|
|
"Original image size ($orig_size) is not the same as the destination size ($new_size) after AFM import"
|
|
);
|
|
}
|
|
}
|
|
if ($copied == 0) {
|
|
Print::print_err(
|
|
"No AFM raw files were found with the same base name and a numeric extension"
|
|
);
|
|
}
|
|
else {
|
|
print "$copied AFM raw files imported<br>\n";
|
|
}
|
|
}
|
|
|
|
Caseman::update_md5("$imgid", "$act_md5")
|
|
unless (($do_md5 == $MD5_NOTHING) || ($imgid eq ""));
|
|
|
|
# Add a disk entry if the image is of a disk
|
|
unless (($add_num == 1) && ($end[0] == 0) && ($start[0] == 0)) {
|
|
unless ((exists $Args::args{'vstype'})
|
|
&& ($Args::args{'vstype'} =~ /^(\w+)$/))
|
|
{
|
|
Print::print_err("Missing Volume System Type");
|
|
}
|
|
my $vstype = $Args::args{'vstype'};
|
|
|
|
my $diskid = Caseman::add_vol_host_config("disk", "$imgid $vstype");
|
|
print "<p>Disk image (type $vstype) added with ID <tt>$diskid</tt>\n";
|
|
}
|
|
|
|
# Add the file system / partition entries
|
|
for (my $i = 0; $i < $add_num; $i++) {
|
|
my $volid =
|
|
Caseman::add_vol_host_config("part",
|
|
"$imgid $start[$i] $end[$i] $ftype[$i] $mnt[$i]");
|
|
print
|
|
"<p>Volume image ($start[$i] to $end[$i] - $ftype[$i] - $mnt[$i]) added with ID <tt>$volid</tt>\n";
|
|
}
|
|
|
|
print <<EOF;
|
|
<p>
|
|
<center>
|
|
<table width=600>
|
|
<tr>
|
|
<td width=300 align=center>
|
|
<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&view=$Caseman::VOL_OPEN&${Args::baseargs_novol}\">
|
|
<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?mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD&${Args::baseargs_novol}\">
|
|
<img src=\"pict/menu_b_inew.jpg\" alt=\"Ok\" width=\"167\" height=20 border=\"0\">
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
EOF
|
|
Print::print_html_footer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
# Display details of image based on config values
|
|
# provides links to remove the config of the image and to get the file
|
|
# system details
|
|
|
|
sub vol_details {
|
|
Print::print_html_header("Details of $Args::args{'vol'}");
|
|
|
|
Args::get_unitsize();
|
|
|
|
my $vol = Args::get_vol('vol');
|
|
|
|
my $mnt = $Caseman::vol2mnt{$vol};
|
|
my $ftype = $Caseman::vol2ftype{$vol};
|
|
|
|
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>$Caseman::vol2sname{$vol}</tt></td></tr>\n"
|
|
. "<tr><td align=\"right\" width=\"300\"><b>Volume Id:</b></td>"
|
|
. "<td align=\"left\"><tt>$vol</tt></td></tr>\n"
|
|
. "<tr><td align=\"right\" width=\"300\"><b>Parent Volume Id:</b></td>"
|
|
. "<td align=\"left\"><tt>$Caseman::vol2par{$vol}</tt></td></tr>\n"
|
|
. "<tr><td align=\"right\" width=\"300\"><b>Image File Format:</b></td>"
|
|
. "<td align=\"left\"><tt>$Caseman::vol2itype{$vol}</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";
|
|
|
|
# Host Directory
|
|
print " <tr><td colspan=\"2\"> </td></tr>\n"
|
|
|
|
# Strings File
|
|
. " <tr><td colspan=2 align=\"center\"><b>External Files</b></td></tr>\n"
|
|
. " <tr><td align=\"right\"><b>ASCII Strings:</b></td>"
|
|
. "<td align=\"left\"><tt>"
|
|
. (
|
|
(exists $Caseman::vol2str{$vol})
|
|
? $Caseman::vol2sname{$Caseman::vol2str{$vol}}
|
|
: " "
|
|
)
|
|
. "</tt></td></tr>\n"
|
|
.
|
|
|
|
# Unicode Strings File
|
|
" <tr><td align=\"right\"><b>Unicode Strings:</b></td>"
|
|
. "<td align=\"left\"><tt>"
|
|
. (
|
|
(exists $Caseman::vol2uni{$vol})
|
|
? $Caseman::vol2sname{$Caseman::vol2uni{$vol}}
|
|
: " "
|
|
)
|
|
. "</tt></td></tr>\n";
|
|
|
|
if (($ftype ne "raw") && ($ftype ne "swap")) {
|
|
|
|
# blkls file
|
|
print
|
|
" <tr><td align=\"right\"><b>Unallocated $Fs::addr_unit{$ftype}s:</b></td>"
|
|
. "<td align=\"left\"><tt>"
|
|
. (
|
|
(exists $Caseman::vol2blkls{$vol})
|
|
? $Caseman::vol2sname{$Caseman::vol2blkls{$vol}}
|
|
: " "
|
|
)
|
|
. "</tt></td></tr>\n";
|
|
|
|
# Strings of blkls
|
|
print
|
|
" <tr><td align=\"right\"><b>ASCII Strings of Unallocated:</b></td>"
|
|
. "<td align=\"left\"><tt>"
|
|
. (
|
|
(
|
|
(exists $Caseman::vol2blkls{$vol})
|
|
&& (exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}})
|
|
)
|
|
? $Caseman::vol2sname{$Caseman::vol2str{$Caseman::vol2blkls{$vol}}}
|
|
: " "
|
|
)
|
|
. "</tt></td></tr>\n";
|
|
|
|
# Unicodde Strings of blkls
|
|
print
|
|
" <tr><td align=\"right\"><b>Unicode Strings of Unallocated:</b></td>"
|
|
. "<td align=\"left\"><tt>"
|
|
. (
|
|
(
|
|
(exists $Caseman::vol2blkls{$vol})
|
|
&& (exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}})
|
|
)
|
|
? $Caseman::vol2sname{$Caseman::vol2uni{$Caseman::vol2blkls{$vol}}}
|
|
: " "
|
|
)
|
|
. "</tt></td></tr>\n";
|
|
}
|
|
|
|
print " <tr><td colspan=\"2\"> </td></tr>\n"
|
|
. "</table>\n<a name=\"extract\"\n";
|
|
|
|
# Section for Strings file and 'blkls' file
|
|
|
|
if (
|
|
(!(exists $Caseman::vol2str{$vol}))
|
|
|| (!(exists $Caseman::vol2uni{$vol}))
|
|
|| (!(exists $Caseman::vol2blkls{$vol}))
|
|
|| (
|
|
(exists $Caseman::vol2blkls{$vol})
|
|
&& ( (!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}}))
|
|
|| (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}})))
|
|
)
|
|
)
|
|
{
|
|
print "<hr><table width=600>\n<tr>";
|
|
}
|
|
|
|
# Strings File
|
|
if ( (!(exists $Caseman::vol2str{$vol}))
|
|
|| (!(exists $Caseman::vol2uni{$vol})))
|
|
{
|
|
|
|
print
|
|
"<td align=\"center\" width=280><h3>Extract Strings of<br>Entire Volume</h3>"
|
|
. "Extracting the ASCII and Unicode strings from a file system will "
|
|
. "make keyword searching faster.<br><br>\n"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "Generate MD5? "
|
|
. "<input type=\"checkbox\" name=\"md5\" value=\"1\" CHECKED><br><br>"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_MAKESTR\">\n"
|
|
. "<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n"
|
|
. Args::make_hidden();
|
|
|
|
if (!(exists $Caseman::vol2str{$vol})) {
|
|
print
|
|
"ASCII: <input type=\"checkbox\" name=\"str\" value=\"1\" CHECKED> \n";
|
|
}
|
|
if (!(exists $Caseman::vol2uni{$vol})) {
|
|
print
|
|
" Unicode: <input type=\"checkbox\" name=\"uni\" value=\"1\" CHECKED>\n";
|
|
}
|
|
|
|
print "<br><br><input type=\"image\" src=\"pict/srch_b_str.jpg\" "
|
|
. "alt=\"Extract Strings\" border=\"0\">\n</form></td>\n"
|
|
. "<td width=40> </td>\n";
|
|
}
|
|
|
|
if (($ftype eq 'blkls') || ($ftype eq 'swap') || ($ftype eq 'raw')) {
|
|
|
|
# Place holder for types that have no notion of unallocated
|
|
}
|
|
|
|
# Unallocated Space File
|
|
elsif (!(exists $Caseman::vol2blkls{$vol})) {
|
|
|
|
print
|
|
"<td align=\"center\" width=280><h3>Extract Unallocated $Fs::addr_unit{$ftype}s</h3>"
|
|
. "Extracting the unallocated data in a file system allows "
|
|
. "more focused keyword searches and data recovery.<br><br>\n"
|
|
. "(Note: This Does Not Include Slack Space)<br>\n"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\">\n";
|
|
|
|
print "Generate MD5? "
|
|
. "<input type=\"checkbox\" name=\"md5\" value=\"1\" CHECKED><br><br>"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_MAKEBLKLS\">\n"
|
|
.
|
|
|
|
"<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n"
|
|
. Args::make_hidden()
|
|
. "<input type=\"image\" src=\"pict/srch_b_un.jpg\" "
|
|
. "alt=\"Extract Unallocated Data\" border=\"0\">\n<br></form>\n";
|
|
}
|
|
|
|
# strings of 'blkls'
|
|
elsif ((!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}}))
|
|
|| (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}})))
|
|
{
|
|
|
|
print
|
|
"<td align=\"center\" width=280><h3>Extract Strings of<br>Unallocated $Fs::addr_unit{$ftype}s</h3>"
|
|
. "Extracting the ASCII strings from the unallocated data will make "
|
|
. "keyword searching faster.<br><br>\n"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "Generate MD5? "
|
|
. "<input type=\"checkbox\" name=\"md5\" value=\"1\" CHECKED><br><br>"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_MAKESTR\">\n"
|
|
.
|
|
|
|
"<input type=\"hidden\" name=\"vol\" value=\"$Caseman::vol2blkls{$vol}\">\n"
|
|
. "<input type=\"hidden\" name=\"fname_mode\" value=\"$FNAME_MODE_INIT\">\n"
|
|
. Args::make_hidden();
|
|
|
|
if (!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}})) {
|
|
print
|
|
"ASCII: <input type=\"checkbox\" name=\"str\" value=\"1\" CHECKED> \n";
|
|
}
|
|
if (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}})) {
|
|
print
|
|
" Unicode: <input type=\"checkbox\" name=\"uni\" value=\"1\" CHECKED>\n";
|
|
}
|
|
print "<br><br><input type=\"image\" src=\"pict/srch_b_str.jpg\" "
|
|
. "alt=\"Extract Strings\" border=\"0\">\n</form></td>\n";
|
|
}
|
|
if (
|
|
(!(exists $Caseman::vol2str{$vol}))
|
|
|| (!(exists $Caseman::vol2uni{$vol}))
|
|
|| (!(exists $Caseman::vol2blkls{$vol}))
|
|
|| (
|
|
(exists $Caseman::vol2blkls{$vol})
|
|
&& ( (!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}}))
|
|
|| (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}})))
|
|
)
|
|
)
|
|
{
|
|
print "</tr></table><hr>\n";
|
|
}
|
|
|
|
print "<p>"
|
|
. "<table width=\"400\" cellspacing=\"0\" cellpadding=\"2\">\n"
|
|
.
|
|
|
|
# Ok
|
|
"<tr><td align=center width=200>"
|
|
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n"
|
|
. "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_OPEN\">\n"
|
|
. Args::make_hidden()
|
|
. "<input type=\"image\" src=\"pict/menu_b_close.jpg\" "
|
|
. "alt=\"Close\" 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"
|
|
. Args::make_hidden()
|
|
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FRAME\">\n"
|
|
. "<input type=\"hidden\" name=\"submod\" value=\"$::MOD_FS\">\n"
|
|
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\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
|
|
# THis was removed 12/03 because it causes problems because the image still
|
|
# exists and config entries and ... it becomes a mess
|
|
# print
|
|
# "<td align=center width=200>".
|
|
# "<form action=\"$::PROGNAME\" method=\"get\">\n".
|
|
# "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n".
|
|
# "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_DEL\">\n".
|
|
# Args::make_hidden().
|
|
# "<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n".
|
|
# "<input type=\"hidden\" name=\"mnt\" value=\"$Args::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";
|
|
|
|
Print::print_html_footer();
|
|
return 0;
|
|
}
|
|
|
|
# remove the config files
|
|
sub img_del {
|
|
Args::check_vol('vol');
|
|
|
|
# Args::check_ftype();
|
|
Print::print_html_header(
|
|
"Removing Configuration Settings for $Args::args{'vol'}");
|
|
|
|
Caseman::del_host_config("", $Args::args{'vol'}, "");
|
|
Caseman::update_md5($Args::args{'vol'}, "");
|
|
|
|
print "Settings for <tt>$Args::args{'vol'}</tt> removed from "
|
|
. "<tt>$Args::args{'case'}:$Args::args{'host'}</tt>.\n"
|
|
. "<p>NOTE: The actual file still exists in the host directory.\n";
|
|
|
|
print "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::VOL_OPEN&${Args::baseargs_novol}\">"
|
|
. "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" "
|
|
. "width=\"43\" height=20 border=\"0\"></a>\n";
|
|
|
|
Print::print_html_footer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
# Make a strings -t d file for the image to decrease the search time
|
|
# Can make both ASCII and Unicode strings files
|
|
sub vol_makestr {
|
|
Print::print_html_header("Extracting Strings");
|
|
|
|
my $ascii = 0;
|
|
my $uni = 0;
|
|
|
|
my $vol = Args::get_vol('vol');
|
|
my $ftype = $Caseman::vol2ftype{$vol};
|
|
my $img = $Caseman::vol2path{$vol};
|
|
my $offset = $Caseman::vol2start{$vol};
|
|
my $imgtype = $Caseman::vol2itype{$vol};
|
|
|
|
if ((exists $Args::args{'str'}) && ($Args::args{'str'} == 1)) {
|
|
if (exists $Caseman::vol2str{$vol}) {
|
|
Print::print_err(
|
|
"Image already has an ASCII strings file: $Caseman::vol2sname{$vol}"
|
|
);
|
|
}
|
|
$ascii = 1;
|
|
}
|
|
|
|
if ((exists $Args::args{'uni'}) && ($Args::args{'uni'} == 1)) {
|
|
if (exists $Caseman::vol2uni{$vol}) {
|
|
Print::print_err(
|
|
"Image already has a Unicode strings file: $Caseman::vol2sname{$vol}"
|
|
);
|
|
}
|
|
|
|
$uni = 1;
|
|
}
|
|
if (($uni == 0) && ($ascii == 0)) {
|
|
goto str_egress;
|
|
}
|
|
|
|
my $base_name = $Caseman::vol2sname{$vol};
|
|
|
|
if ($ascii == 1) {
|
|
my $fname_rel = "$::DATADIR/${base_name}-$ftype.asc";
|
|
my $fname = "$::host_dir" . "$fname_rel";
|
|
|
|
if (-e "$fname") {
|
|
my $i = 1;
|
|
$i++ while (-e "$::host_dir"
|
|
. "$::DATADIR/"
|
|
. "${base_name}-$ftype-$i.asc");
|
|
|
|
$fname_rel = "$::DATADIR/${base_name}-$ftype-$i.asc";
|
|
$fname = "$::host_dir" . "$fname_rel";
|
|
}
|
|
|
|
print
|
|
"Extracting ASCII strings from <tt>$Caseman::vol2sname{$vol}</tt><br>\n";
|
|
|
|
Print::log_host_inv(
|
|
"$Caseman::vol2sname{$vol}: Saving ASCII strings to $fname_rel");
|
|
|
|
local *OUT;
|
|
|
|
my $hit_cnt = 0;
|
|
$SIG{ALRM} = sub {
|
|
if (($hit_cnt++ % 5) == 0) {
|
|
print "+";
|
|
}
|
|
else {
|
|
print "-";
|
|
}
|
|
alarm(5);
|
|
};
|
|
|
|
alarm(5);
|
|
|
|
if ($ftype eq "blkls") {
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/srch_strings' -a -t d $img > '$fname'");
|
|
}
|
|
elsif ((($ftype eq "raw") || ($ftype eq "swap"))
|
|
&& ($Caseman::vol2end{$vol} != 0))
|
|
{
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/blkls' -e -f $ftype -i $imgtype $img "
|
|
. $Caseman::vol2start{$vol} . "-"
|
|
. $Caseman::vol2end{$vol}
|
|
. " | '$::TSKDIR/srch_strings' -a -t d > '$fname'");
|
|
}
|
|
else {
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d > '$fname'"
|
|
);
|
|
}
|
|
alarm(0);
|
|
$SIG{ALRM} = 'DEFAULT';
|
|
|
|
print $_ while ($_ = Exec::read_pipe_line(*OUT));
|
|
close(OUT);
|
|
|
|
print "<br>\n" if ($hit_cnt != 0);
|
|
|
|
# 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<br>");
|
|
goto str_uni;
|
|
}
|
|
|
|
# append to config
|
|
my $strvol =
|
|
Caseman::add_vol_host_config("strings", "$vol $fname_rel");
|
|
print "Host configuration file updated<br>";
|
|
|
|
$Caseman::vol2ftype{$strvol} = "strings";
|
|
$Caseman::mod2vol{$strvol} = $vol;
|
|
$Caseman::vol2str{$vol} = $strvol;
|
|
$Caseman::vol2cat{$strvol} = "mod";
|
|
$Caseman::vol2itype{$strvol} = "raw";
|
|
|
|
$Caseman::vol2par{$strvol} = $vol;
|
|
$Caseman::vol2path{$strvol} = "$::host_dir" . "$fname_rel";
|
|
$Caseman::vol2start{$strvol} = 0;
|
|
$Caseman::vol2end{$strvol} = 0;
|
|
$Caseman::vol2sname{$strvol} = $fname_rel;
|
|
|
|
# Calculate MD5
|
|
if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) {
|
|
print "Calculating MD5 Value<br><br>\n";
|
|
my $m = Hash::int_create_wrap($strvol);
|
|
print "MD5 Value: <tt>$m</tt><br><br>\n";
|
|
}
|
|
}
|
|
|
|
str_uni:
|
|
|
|
if ($uni == 1) {
|
|
|
|
my $fname_rel = "$::DATADIR/${base_name}-$ftype.uni";
|
|
my $fname = "$::host_dir" . "$fname_rel";
|
|
|
|
if (-e "$fname") {
|
|
my $i = 1;
|
|
$i++ while (-e "$::host_dir"
|
|
. "$::DATADIR/"
|
|
. "${base_name}-$ftype-$i.uni");
|
|
|
|
$fname_rel = "$::DATADIR/${base_name}-$ftype-$i.uni";
|
|
$fname = "$::host_dir" . "$fname_rel";
|
|
}
|
|
|
|
print "<hr>\n" if ($ascii == 1);
|
|
|
|
print
|
|
"Extracting Unicode strings from <tt>$Caseman::vol2sname{$vol}</tt><br>\n";
|
|
|
|
Print::log_host_inv(
|
|
"$Caseman::vol2sname{$vol}: Saving Unicode strings to $fname_rel");
|
|
|
|
local *OUT;
|
|
|
|
my $hit_cnt = 0;
|
|
$SIG{ALRM} = sub {
|
|
if (($hit_cnt++ % 5) == 0) {
|
|
print "+";
|
|
}
|
|
else {
|
|
print "-";
|
|
}
|
|
alarm(5);
|
|
};
|
|
|
|
alarm(5);
|
|
if ($ftype eq "blkls") {
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/srch_strings' -a -t d -e l $img > '$fname'");
|
|
}
|
|
elsif ((($ftype eq "raw") || ($ftype eq "swap"))
|
|
&& ($Caseman::vol2end{$vol} != 0))
|
|
{
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/blkls' -e -f $ftype -i $imgtype $img "
|
|
. $Caseman::vol2start{$vol} . "-"
|
|
. $Caseman::vol2end{$vol}
|
|
. " | '$::TSKDIR/srch_strings' -a -t d -e l > '$fname'");
|
|
}
|
|
|
|
else {
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d -e l > '$fname'"
|
|
);
|
|
}
|
|
|
|
alarm(0);
|
|
$SIG{ALRM} = 'DEFAULT';
|
|
|
|
print $_ while ($_ = Exec::read_pipe_line(*OUT));
|
|
close(OUT);
|
|
|
|
print "<br>\n" if ($hit_cnt != 0);
|
|
|
|
# Verify that it worked
|
|
unless (open(STR, "$fname")) {
|
|
print "Error opening $fname<br>\n"
|
|
. "Either an error occurred while generating the file or "
|
|
. "no Unicode strings exist";
|
|
goto str_egress;
|
|
}
|
|
|
|
# append to config
|
|
my $strvol =
|
|
Caseman::add_vol_host_config("unistrings", "$vol $fname_rel");
|
|
print "Host configuration file updated<br>";
|
|
|
|
$Caseman::vol2ftype{$strvol} = "strings";
|
|
$Caseman::mod2vol{$strvol} = $vol;
|
|
$Caseman::vol2uni{$vol} = $strvol;
|
|
$Caseman::vol2cat{$strvol} = "mod";
|
|
$Caseman::vol2itype{$strvol} = "raw";
|
|
|
|
$Caseman::vol2par{$strvol} = $vol;
|
|
$Caseman::vol2path{$strvol} = "$::host_dir" . "$fname_rel";
|
|
$Caseman::vol2start{$strvol} = 0;
|
|
$Caseman::vol2end{$strvol} = 0;
|
|
$Caseman::vol2sname{$strvol} = $fname_rel;
|
|
|
|
# Calculate MD5
|
|
if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) {
|
|
print "Calculating MD5 Value<br><br>\n";
|
|
$m = Hash::int_create_wrap($strvol);
|
|
print "MD5 Value: <tt>$m</tt><br><br>\n";
|
|
}
|
|
}
|
|
|
|
str_egress:
|
|
|
|
my $dest_vol = $vol;
|
|
|
|
# We need to return with a real image to VOL_DETAILS so check the mod
|
|
$dest_vol = $Caseman::mod2vol{$vol}
|
|
if (exists $Caseman::mod2vol{$vol});
|
|
|
|
print "<hr><a href=\"$::PROGNAME?$Args::baseargs_novol&mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::VOL_DETAILS&vol=$dest_vol\" target=_top>Image Details</a><p>\n";
|
|
|
|
print
|
|
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_KWSRCH&$Args::baseargs\""
|
|
. " target=\"_top\">Keyword Search</a>\n";
|
|
|
|
Print::print_html_footer();
|
|
|
|
return 0;
|
|
}
|
|
|
|
sub vol_makeblkls {
|
|
Print::print_html_header("Extracting Unallocated Space");
|
|
|
|
my $vol = Args::get_vol('vol');
|
|
my $ftype = $Caseman::vol2ftype{$vol};
|
|
my $img = $Caseman::vol2path{$vol};
|
|
my $offset = $Caseman::vol2start{$vol};
|
|
my $imgtype = $Caseman::vol2itype{$vol};
|
|
|
|
my $base_name = $Caseman::vol2sname{$vol};
|
|
$base_name = $1 if ($base_name =~ /^(.*?)\.dd$/);
|
|
my $fname_rel = "$::DATADIR/${base_name}-$ftype.unalloc";
|
|
my $fname = "$::host_dir" . "$fname_rel";
|
|
|
|
if (-e "$::host_dir" . "$fname_rel") {
|
|
my $i = 1;
|
|
$i++ while (-e "$::host_dir"
|
|
. "$::DATADIR/"
|
|
. "${base_name}-$ftype-$i.unalloc");
|
|
|
|
$fname_rel = "$::DATADIR/${base_name}-$ftype-$i.unalloc";
|
|
$fname = "$::host_dir" . "$fname_rel";
|
|
}
|
|
|
|
Print::log_host_inv(
|
|
"$Args::args{'vol'}: Saving unallocated data to $fname_rel");
|
|
|
|
print
|
|
"Extracting unallocated data from <tt>$Caseman::vol2sname{$vol}</tt><br>\n";
|
|
|
|
local *OUT;
|
|
|
|
my $hit_cnt = 0;
|
|
$SIG{ALRM} = sub {
|
|
if (($hit_cnt++ % 5) == 0) {
|
|
print "+";
|
|
}
|
|
else {
|
|
print "-";
|
|
}
|
|
alarm(5);
|
|
};
|
|
|
|
alarm(5);
|
|
|
|
Exec::exec_pipe(*OUT,
|
|
"'$::TSKDIR/blkls' -f $ftype -o $offset -i $imgtype $img > '$fname'");
|
|
|
|
alarm(0);
|
|
$SIG{ALRM} = 'DEFAULT';
|
|
|
|
print "$_" while ($_ = Exec::read_pipe_line(*OUT));
|
|
close(OUT);
|
|
|
|
print "<br>\n"
|
|
if ($hit_cnt != 0);
|
|
|
|
# append to config
|
|
my $blklsvol = Caseman::add_vol_host_config("blkls", "$vol $fname_rel");
|
|
print "Host configuration file updated<br>";
|
|
|
|
$Caseman::vol2ftype{$blklsvol} = "blkls";
|
|
$Caseman::mod2vol{$blklsvol} = $vol;
|
|
$Caseman::vol2blkls{$vol} = $blklsrvol;
|
|
$Caseman::vol2cat{$blklsvol} = "mod";
|
|
$Caseman::vol2itype{$blklsvol} = "raw";
|
|
|
|
$Caseman::vol2par{$blklsvol} = $vol;
|
|
$Caseman::vol2path{$blklsvol} = "$::host_dir" . "$fname_rel";
|
|
$Caseman::vol2start{$blklsvol} = 0;
|
|
$Caseman::vol2end{$blklsvol} = 0;
|
|
$Caseman::vol2sname{$blklsvol} = $fname_rel;
|
|
|
|
# Calculate MD5
|
|
if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) {
|
|
print "Calculating MD5 Value<br>\n";
|
|
my $m = Hash::int_create_wrap($blklsvol);
|
|
print "MD5 Value: <tt>$m</tt><br><br>\n";
|
|
}
|
|
|
|
print "<a href=\"$::PROGNAME?$Args::baseargs&mod=$::MOD_CASEMAN&"
|
|
. "view=$Caseman::VOL_DETAILS\" target=_top>Image Details</a><p>\n";
|
|
|
|
print
|
|
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_KWSRCH&$Args::baseargs_novol&"
|
|
. "vol=$fname_rel\" target=\"_top\">Keyword Search</a>\n";
|
|
|
|
Print::print_html_footer();
|
|
return 0;
|
|
}
|
|
|
|
1;
|