Initial import from CVS

This commit is contained in:
Brian Carrier 2008-09-29 02:42:46 +00:00
commit ecdcab0589
183 changed files with 21555 additions and 0 deletions

532
CHANGES.txt Normal file
View File

@ -0,0 +1,532 @@
7/1/08: Update: Updated FAT sizes based on new "special" files.
7/9/08: Update: Updated NTFS processing for orphan files / removed
ifind -p etc.
7/9/08: Update: Updated mactime and time formats to ISO formats.
9/13/08: Update: Changed usage to new TSK d* to blk* names.
9/26/08: Bug Fix: Input check on host was printing invalid host values
w/out encoding HTML entities. Reported by Russ McRee.
--------------------------- Version 2.10 --------------------------------
2/20/08: Bug Fix: Added 'tsk' to the path for sorter to find the 'images'
config file. Reported by Russell Reynolds.
3/2/08: Update: Modified the adding of disk image process to save a
call to mmls (reported by Pope).
3/2/08: Update: Added more basic control char filtering back into Print().
--------------------------- Version 2.09 --------------------------------
2/4/07: Update: Bind only to localhost network if remote addr is local.
Suggested by Markus Waldeck.
4/19/07: Bug Fix: Event sequencer notes for file did not have clock skew
in the times. Reported by Len CulBreath.
12/21/07: Update: updated configure and install process for TSK 2.50
1/28/08: Update: Added NSRL support back in.
--------------------------- Version 2.08 --------------------------------
8/23/06: Bug Fix: The configure script did not like TSK directory names
with a space in them.
8/23/06: Update: The PATH variable is not entirely cleared anymore.
Instead, it is replaced by the basic bin directories (this was causing
some problems with Cygwin).
8/31/06: Update: If Autopsy is running under Cygwin, then it will set
the PATH to contain the basic bin directories. Otherwise, it is clear
(original behavior).
--------------------------- Version 2.07 --------------------------------
3/15/06: Bug Fix: Caseman.pm had DATA_DIR instead of DATADIR and a
concatenation error message occurred. Reported by Jason DePriest.
5/3/06: Update: Added support for ISO9660 file systems.
5/3/06: Update: Added support for AFF and AFD image formats.
5/03/06: Update: Added image format type to image details screen.
5/3/06: Update: Added hexdump view for file analysis and reports (initial
patch by Patrick Knight).
5/3/06: Update: Changed number of dashes in reports to 70 instead of 62.
5/4/06: Update: Integrity checking disabled for non-raw image files
until a specialized tool exists in TSK to abstract the embedded hash
calculation.
5/8/06: Update: Added support for AFM files.
--------------------------- Version 2.06 --------------------------------
05/02/05: Fix: Typo in timeline creation window (reported by Surago Jones).
06/15/05: Update: Added css style sheet and changed some formatting.
08/13/05: Update: Added "utf-8" as HTML type so that TSK unicode
output will be properly dispayed.
10/13/05: Update: Removed print_output() function contents because
it broke the Unicode chars.
10/13/05: Update: Require 5.8 version of Perl now (in config and
in source) because it has best Unicode support.
--------------------------- Version 2.05 --------------------------------
03/16/05: Update: Image name is given in the Image Details window
when adding a new image file. (Suggested by Surago Jones).
03/17/05: Bug Fix: swap and raw host config entries could not be
read after the conversion because of a regular expression bug in
the read code. (Reported by Surago Jones) (BUG: 1165235)
03/21/05: Bug Fix: When a new host was added to a case with no
investigator names, then it would prompt you to select a name from
an empty list. (BUG: 1167970).
03/25/05: Update: Check return status of rename functions and print
error if failed.
04/04/05: Bug Fix: A missing volume type message was reported when
adding a disk image. The flow of add_img_prep was modified to
ensure that it was set. (Reported by Bradley Bitzkowski) (BUG:
1177042)
04/08/05: Update: A thumbnail of images is shown when selected in the File
mode. Suggested by and patch by Guy Voncken.
--------------------------- Version 2.04 --------------------------------
10/22/04: Update: Changed the way that NTFS lists directory contents. No
longer lists the deleted entries from 'fls', only from 'ifind'. Reduces
the inaccurate information.
02/XX/05: Update: Incorporated new TSK 2 features:
- Disk images (split and raw)
- new config file formats
- moved images and output md5.txt file into one
03/01/05: Update: Changed behavior of some links that created new
Autopsy Windows
03/05/05: Update: timeline output can be in comma delimited format
03/05/05: Update: Added SSN and credit card seach patterns from
Jerry Shenk.
03/05/05: Update: Added temporal data when a note is creaed.
03/11/05: Update: Changed to new TSK names for srch_strings and img_stat
03/15/05: Update: improved handling of white space around investigator
names and image names (suggested by Brian Baskin).
--------------------------- Version 2.03 --------------------------------
08/24/04: Update: Added SHA-1 hash to the metadata view.
09/01/04: Update: Added sstrings instead of local version of strings.
09/05/04: Update: Added more help text.
09/06/04: Update: Use the local version of file if TSK version is
not found.
09/06/04: Update: Added links to the notes and events page after a
note or event has been created.
09/06/04: Update: Added Unicode extract and search functionality using
the 'sstrings' tool from TSK.
--------------------------- Version 2.02 --------------------------------
07/19/04: Bug Fix: print_err message in Caseman.lib did not have correct
Print:: package, which caused an error (BUG: 994199).
07/29/04: Update: Added support for NTFS 'ifind -p' option to find deleted
files that do not have a name in the parent directory.
07/29/04: Update: Added a filter to remove duplicate entries from a file
listing. Duplicate names with the same name and meta address are
removed.
07/29/04: Update: OS X no longer needs the strings script, Autopsy
will adjust for the different flags.
07/29/04: Update: When a deleted file name is entered into the find
directory box, the recover bit is set so the full contents are shown.
--------------------------- Version 2.01 --------------------------------
03/29/04: Update: Changed text for the data integrity option when
adding a new image.
04/20/04: Bug Fix: Fixed error that occured when data browsing with
a raw or swap image. The TSK usage for these file system types was
inconsistent and it was fixed in version 1.69. (BUG: 925382).
(Reported by Harald Katzer)
05/03/04: Update: Changed regular expression in META so that the
new recovery listing in FAT istat will not show up as a hyperlink.
05/03/04: Update: Removed usage of '-H' with 'icat' in File.PM.
05/20/04: Bug Fix: Fixed the incorrect error message that was printed
when installing autopsy with a newer version of TSK than 1.68.
(BUG: 938909)
05/20/04: Update: Added new feature that allows perl regular
expressions to be used to find file names.
05/20/04: Update: Added file recovery features to File.pm, Meta.pm,
and Appview.pm.
05/27/04: Update: Added a space to $REG_ZONE2 so that CYGWIN would
work if no zone was given (Marcus Muller).
/05/27/04: Update: Added 'p' as an option for the type of a file in the
'fls' output and made the $::REG_MTYPE global for the pattern.
05/28/04: Update: Cleaned up code so that commands and directories
do not have double slashes (//) sometimes. This caused problems
with CYGWIN (reported by Marcus Muller).
05/28/04: Bug Fix: Keyword search of unallocated space would link to
incorrect data unit (although the address was correct). (Reported by
Jorge Ortiz, David Perez, Raul Siles). (BUG: 962410).
05/28/04: Update: Updated dcat usage and syntax to reflect changes to
TSK.
05/28/04: Update: Changed the messages printed when multiple data units
were displayed. Now the number of units or range are given instead of
number of bytes.
--------------------------- Version 2.00 --------------------------------
11/25/03: Update: made evidence locker directory names constant (define.pl)
11/25/03: Update: Started process of re-architecture
12/2/03: Update: Replaced logo.jpg with Hash the Hound
12/7/03: Update: Added favicon.ico with Hash
01/06/04: Update: Changed command line arguments
01/24/04: Update: made it only a warning if cookie file can't be opened
02/15/04: Update: Timezone is now optional. Defaults to local if not given.
02/15/04: Update: Timezone value optional in () in file listing (prevents
parsing errors if incorrect timezone is given
03/16/04: Bug Fix: Fixed zombie problem by ignoring child signal
(BUG: 860186) Reported by Angus Marshall.
03/18/04: Update: New layout for adding cases, hosts, and images.
03/18/04: Update: changed HTML to use lowercase values instead of all caps.
03/18/04: Update: New windows are no longer opened when changing modes.
03/19/04: Release: Big release with a new redesign and a few other
changes (live analysis)
--------------------------- Version 1.75 --------------------------------
09/22/03: Update: Changed the internal 'get_' functions that parse the
URL arguments to error instead of just return 0 when a problem occurs.
10/22/03: Bug Fix: Check for an investigator name before trying to log
to the exec log. This is a problem when indexing a hash database, an
error message is printed because of the null string. reported by
Brian Baskin.
11/10/03: Update: Improved error message when strings can't be parsed.
(Bug: 823081)
11/15/03: Update: Improved messages in installation script
11/15/03: Bug Fix: Added 'defined' checks to command output to prevent
string errors when command fails. (BUG 842824)
11/15/03: Update: Added 'HEIGHT' value to HTML images to make images
align better and load faster and with the right size
11/15/03: Update: Added a timer so that a char is printed every 5 seconds
during keyword searching, file type sorting, and MD5 for images.
--------------------------- Version 1.74 --------------------------------
08/03/03: Bug Fix: Notes could not be added for some files because
the HTML code was missing a closing bracket.
08/18/03: Bug Fix: added POSIX:settz() because some versions of Perl do
not use the most recent ENV{TZ} variable when running 'localtime'. This
cause some incorrect times for events in the sequencer.
08/19/03: Update: NSRL is no longer used with 'sorter' until it is
easier to identify which files in the NSRL are known good and which
are known bad.
08/20/03: Update: Added support for swap and raw images for searching
and data unit analysis.
08/20/03: Update: Added the unit size to the display of the Data Unit
mode.
08/20/03: Update: Search for perl5.6.0 first during install
08/21/03: Update: Changed use of backticks to pipes for executing commands
08/21/03: ?: Added a 'sleep(1)' to the pipe to prevent the loss of data
that can be seen with perl5.8.0 in the buffer. This should be fixed
in a better way though.
08/21/03: Update: The exact command executed is now saved to the log
directory.
08/21/03: Update: Changed 'date' regexp to make year optional.
08/22/03: Update: Added warning if Perl 5.8 is used because of the buffer
problem.
08/22/03: Bug Fix: Fixed some keyword escape values in the search mode.
08/22/03: Update: Added a new help page on the limitations of keyword
searching.
08/22/03: Update: Moved the unallocated space and strings file creation
to the Image Details view instead of the keyword search window
(suggested by: Paul Bakker)
08/25/03: Update: improved wording of the Add Image window to better
explain the mounting point.
08/26/03: Update: When adding sequencer notes in manually, the time
is set to the last note entered to make it easier to add notes from
logs and external sources.
08/26/03: Update: The keyword search display has a final clause that
prints the results even if they are not found in the 'index' method.
This prevents any hits from being lost during the analysis of the
output.
08/26/03: Bug Fix: strings less than 4 chars would not be found before
because 'strings' only shows strings that are 4 or more in length
08/28/03: Update: if more than 1000 keyword hits are found, then a message
is reported and the user must choose a new keyword. This prevents the
browser from hanging from a huge HTML table.
08/28/03: Update: A '.' is printed during the keyword search for each
100 hits as a status update.
--------------------------- Version 1.73 --------------------------------
06/10/03: Bug Fix: The '-i day' was not added to the mactime code and
caused an error (reported by Cathy Buckman)
--------------------------- Version 1.72 ---------------------------------
04/09/03: Bug Fix: The Java Script check on the main page broke in 1.71
because the document.write was on multiple lines
04/11/03: Bug Fix: Keyword Search False Hit code had a bug that it
would be printed in error and message was improved
04/22/03: Update: Added examples to case management help file
05/06/03: Bug Fix: calc_md5 did not need 'o' tag on end of regular
expression because it would not work if the method was called more
than once. (Paul Bakker)
06/01/03: Bug Fix: Some keyword searches with $ in it were failing
06/01/03: Update: Keyword searches are now saved to a file and can be
found in the keyword seach main menu
06/01/03: Update: Changed the format a little of the keyword search
menu
06/01/03: Update: Added grep cheat sheet
06/03/03: Update: Tables now have alternating colors for file listing
and timeline viewing
06/03/03: Update: Sequencer mode added
06/03/03: Update: Sequencer help file added
06/04/03: Bug Fix: Added 'LANG=C LC_ALL=C' to sorter & mactime to prevent
UTF-8 errors (Debugging help from Daniel Schwartzer)
06/04/03: Bug Fix: The regular expression for viewing timelines did not
allow multiple users to have the same UID (reported by Cathy Buckman)
06/05/03: Update: Added button for Event Sequencer and added tables to
the standard notes reading window
06/09/03: Update: Added '-i day' flag to mactime for new feature in
The Sleuth Kit
--------------------------- Version 1.71 ---------------------------------
02/27/03: Bug Fix: Regular expression searches w/out a strings file had
problems because the '-n' value was being incorrectly calculated.
03/17/03: Update: Added more logging to investigator log
03/17/03: Bug Fix: The case opening was not being logged in the case log
03/17/03: Update: The current 'mode' tab is also a hyperlink now
03/17/03: Bug Fix: Fixed bug that did not allow the path for a strings
file to have a space in it.
03/17/03: Update: When no port and remote address are given on the
command line, port 9999 and localhost are used. Documents also
updated to reflect new syntax.
03/18/03: Update: Use the 'x' repetition operator for ASCII reports
instead of a row of dashes.
03/18/03: Update: Added <NOFRAMES> tag to MAIN_FR and incorporated more
'<<EOF' HTML code.
03/19/03: Update: Added $FIL_NAME function that translates a name to
a meta data address using 'ifind -n'
03/19/03: Update: A directory name can be entered in the $FIL_DIR
frame now to jump to a directory or file
03/19/03: Update: The directory path in $FIL_LIST was changed to have
hyperlinks that allow one to jump to a previous directory (using
$FILE_NAME)
03/19/03: Update: Cleaned up HTML code in $FIL_LIST
03/20/03: Update: passwd and group files are now imported in timelines
by selecting the image - no more inode values
03/20/03: Update: Cleaned up HTML code in timeline section
03/21/03: Update: Added '-z' flag to usage of 'file' so that comressed
files are opened.
03/21/03: Bug Fix: Some special values needed to be escaped in the
grep keyword search (for non regular expressions) (\.]^$"-).
03/24/03: Update: Changed how images are added (symlinks, copies,
or moves).
03/24/03: Update: Added a file system sanity check when adding one
03/27/03: Update: Added a check to the 'File Type' mode that extracts
just graphic images and makes thumbnails.
03/27/03: Update: Added '-i' flag when 'mactime' is run to create the
summary file for timelines.
03/27/03: Update: Added link to summary page with hyper links to actual
month for timelines
03/27/03: Update: Added more HTML table columns for date in timeline view
03/27/03: Update: Made the 'ifind' process optional in Data Unit and key
word searching mode (makes browsing faster)
03/27/03: Update: Evidence Locker now contains entries for when a case
is created or opened.
03/30/03: Update: Improved the help file for time lines.
03/31/03: Update: Changed addresses to sleuthkit.org
--------------------------- Version 1.70 ---------------------------------
Interface Changes:
- Too many to note individually
- New windows are created when modes or images are changed
- Improved error messages
- Can load the unallocated image in the Data Unit Mode
- Case management
12/10/02: Update: Help is now a directory and contents can be viewed at
any time.
01/02/03: Update: Added support for sorter and hfind tools in TASK
01/02/03: Update: NSRL now requested at startup
01/02/03: Update: Alert and exclude hash databases are options when making
a new host now
01/09/03: Update: Carriage Returns are now sent if it is a Windows client
01/09/03: Update: Improved the pre-defined IP keyword search expression
01/10/03: Update: Changed use of "_new" as target to "_blank"
01/28/03: Update: Installation and other system directories can now
have spaces and other symbols in them (Dave Goldsmith)
--------------------------- Version 1.62 ---------------------------------
10/07/02: Update: Added File Type to block mode
10/07/02: Update: Can now add notes to 'dls' image blocks
10/07/02: Update: One can now view as many consecutive data units as they
want in data mode. Many other changes and updates were done with this
as well. (inspired by the Honeynet sotm)
10/07/02: Update: The File System details view for FAT now has hyperlinks
to view the run and follow to the next run.
10/09/02: Bug Fix: Removed use of 'use integer' so that large blocks do
no turn into '-1' when doing a keyword search (Michael Stone - Loyola)
--------------------------- Version 1.61 ---------------------------------
08/28/02: Update: White space is allowed at the begining of the morgue file
08/28/02: Bug Fix: No error is generated if md5.txt does not exist from
main menu
08/28/02: Update: Improved error messages
08/28/02: Update: Added code to Main Menu to check for Java Script turned on
09/19/02: Update: fsmorgue can be a symlink in the morgue directory
--------------------------- Version 1.60 ---------------------------------
- Changed NTFS c-time to Changed from Created (5/20/02)
- Fixed a couple little bugs with parsing NTFS output (5/20/02)
- Improved sorting (name is case insensitive and name is used as
secondary sorting index) (5/20/02)
- Improved error messages of invalid input to inode & block mode
- Added ability to import password and group files when making a time line
(5/28/02)
- Fixed bug that did not allow IP addresses to be used for the ACL when
DNS was not available (5/30/02)
- Fixed some issues to make Internet Explorer not complain so much (05/30/02)
- Improved the logging so that one can retrace their actions (05/31/02)
- Moved autopsy.log to logs directory (05/31/02)
- Added ability to write Notes about a given block, inode, or file (06/04/02)
(suggestion by Dave Dittrich)
- Set default investigators name (an error was generated if no name was given)
(06/04/02)
- Added links in the help page to the window help pages (06/05/02)
- Updated timeline to reflect new format in new TASK (06/19/02)
- Added '-C' flag to turn off cookies on command line (06/20/02)
- Added new main menu (06/20/02)
- Made MD5 generation 'opt-out' (06/22/02)
- New code to remove duplicate entries in md5.txt and fsmorgue
- fsmorgue can have whitespace at end of line (7/6/02)
- An error is generated if an image in fsmorgue does not exist (7/6/02)
- updated automatic date search (7/9/02)
- New feature allows one to save the MD5 values of all files in a directory,
which makes the Solaris Finger Print Database easier (7/12)
--------------------------- Version 1.50 ---------------------------------
- Modified to support TASK instead of TCT and TCTUTILs (8/25/01)
- Removed chmod 'bug' for the cookie file (8/25/01)
- Fixed number of hits bug in Search mode (off by one) (8/25/01)
- Added ftype support (8/28/01)
- Added ftype field to reports (8/28/01)
- Encoded dir arg in FIL_DEL
- Filter option holds for usage of next and rev in block mode
- If using fat, a separate option is given to run find_inode due to how
slow it runs
- removed use of zoneinfo in favor of the new timezone value in fsmorgue.
- strings now uses '-a' flag to show all strings
- When doing a search, the length of the string is given as the '-n'
flag to strings to speed up the search
- Allow user to "force" blocks when an inode size is 0 (the istat -b flag)
- use the md5 that comes with TCT/TASK
- multiple images with the same mounting point can now exist
- Added the morgue directory to the MENU to make it easier to manage
multiple hosts
- Files are sorted by name by default
- can import strings files and create them if needed
- Run files through 'file' to get data type
- case insensitive searches
- MAC headers correspond to file system type (create vs change)
- Deleted files are displayed in red
- Correct address name used (fragment, sector etc.)
- Support for NTFS attributes
- parse bad tags from HTML when viewing it (send sterile pict)
- cookie file has port number to aid in scripting
- cookie files are deleted upon closing
- log messages are printed for each request
- added integrity checker
- renamed aux directory to base to make Windows happy
- added time line support
- added fsstat support
- Added built-in search values in search.pl
May 29, 2001 1.01 released
- Fixed Hex link when in search mode (3/23/01)
- Corrected heading of ctime (Addam Schroll, Purdue University) (4/24/01)
- Parses output of new istat correctly (5/1/01)
- When viewing 'inode as a file', the image and inode are sent as the dir
name (5/1/01)
- Added wait() to collect zombies in Linux (5/22/01)
- Added auto-flush to prevent repeat log entries (5/22/01)
- Added a 'save as' option to file and inode browsing (Addam Schroll)
(5/22/01)
- Added option for unrm block numbers (due to blockcalc) (5/22/01)
- Improved side menu for inode, block, and search (5/22/01)
- Added "Content-Disposition" so that reports and "save as" have a
unique default filename. (5/23/01)
- Organization changes to Main Menu (5/24/01)
- Automated installation process (5/24/01)
March 19, 2001 1.0 released
- Added man page for autopsy (3/10/01)
- Directory entries in config files no longer require an / at the end
- Morgue file names can have a '.' in them (but still not '/') (3/10)
- autopsy first checks for /dev/urandom for random cookie (3/10/01)
- morgue directory is a command line option to autopsy (3/10/01)
- the lib variable in autopsy is no longer set to './' so that it
can be run outside of /usr/local/autopsy (3/10/01)
- changed all references of device to image (3/11/01)
- changed all reports to print full image path (3/11/01)
- Investigator is a command line option to autopsy (3/11/01)
- CGI support removed. Only autopsy is supported (3/16/01)
- renamed autopsyd to autopsy (3/16/01)
- Fixed UID and GID heading (3/16/01)
- Run image through strings before grep to prevent memory errors (3/16/01)
- output of find_file and find_inode is prepended with rdir (3/16/01)
Feb 27, 2001 0.2b released
- Added stand alone server, autopsyd (as suggested by Dan Farmer)
- Reorganized files due to new program
- Changed names of some executables that changed in TCTUTILs
Feb 19, 2001 0.1b released
------------------------------------------------------------------------

340
COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

36
INSTALL.txt Normal file
View File

@ -0,0 +1,36 @@
Autopsy Forensic Browser
http://www.sleuthkit.org/autopsy
Brian Carrier [carrier@sleuthkit.org]
Last Update: January 29, 2008
Installation
-----------------------------------------------------------------------------
1. Install The Sleuth Kit (see README for download locations). This
includes doing a 'make install' so that the executables and files
are installed in a single directory.
2. Untar the Autopsy file.
3. Run 'make'. It will try to locate the grep and strings utilities.
If any are not found, it will prompt you for the location. It will
also search for the TSK installation.
4. The install script will ask if you have the NIST National Software
Reference Library (NSRL). If you do, you will need to enter the
path of it. The NSRL is available from www.nsrl.nist.gov.
5. You will be prompted for the Evidence Locker location. This is the
base directory where all cases will be stored. You must create this
directory on your own.
Live Analysis
------------------------------------------------------------------------------
Type 'make live' or run the 'make-live-cd' script to build the 'live-cd'
directory. The 'live-cd' directory can be burned to a CD.
------------------------------------------------------------------------------
Brian Carrier [carrier@sleuthkit.org]

30
Makefile Normal file
View File

@ -0,0 +1,30 @@
all:
@sh ./configure
conf.pl:
@sh ./configure
live: conf.pl
./make-live-cd
indent:
cd lib; perltidy -b *.pm *.pl
cd base; perltidy -b autopsy.base
clean:
rm -f ./autopsy
rm -f ./make-live-cd
rm -f ./conf.pl
rm -f ./config.tmp
rm -f ./config2.tmp
rm -rf ./live-cd/
rm -f ./lib/*.bak
rm -f ./base/*.bak
find . -name ".DS_Store" | xargs rm -f
find . -type f -perm +g+x,o+x,u+x | xargs chmod -x
grep "curtskver=" ./configure
grep "VER" ./lib/define.pl
find . -name ".*" | grep -v perltidy
release:
find . -name "CVS" | xargs rm -rf

119
README-LIVE.txt Normal file
View File

@ -0,0 +1,119 @@
Autopsy Forensic Browser
http://www.sleuthkit.org/autopsy
Live Analysis Mode
Last Updated: January 2005
What is Live Analysis?
--------------------------------------------------------------------
Live analysis is, in my mind, an investigation that occurs using
the software resources of the suspect system. An example scenario
of this is when a suspect system is found running, a CD is placed
into it, and commands are run. If the suspect system is powered
down and booted from a bootable Linux CD (or similar), then the
investigation is a dead analysis.
This is most commonly done when investigating a server or other
computer that is suspected of being compromised, but verification
is needed before it can be powered down. Using The Sleuth Kit and
Autopsy will prevent the access times on individual files from being
updated (although the raw device's A-time will be) and can bypass
most rootkits that hide files and directories.
What are the Issues with Live Analysis?
--------------------------------------------------------------------
Live analysis is not ideal because you are relying on the suspect
system, which can lie, cheat, and steal. In addition to the potential
of getting false information from the operating system you will
also overwrite memory and maybe swap space during the investigation.
If you are interested in examining the memory of the system, you
should probably acquire that before you begin a live analysis.
An issue with doing live analysis with Autopsy is that it requires
Perl, which is a large program and will likely need to depend on
libraries and other files on the suspect system.
How do I make a CD with Autopsy on it?
--------------------------------------------------------------------
You will want to have a trusted CD for a live analysis, and autopsy
makes that fairly easy. Compile autopsy as you would for a normal
dead analysis installation. Then execute 'make live' in Autopsy.
This script will make a 'live-cd' sub-directory in the autopsy directory,
which contains a copy of autopsy and copies of TSK executables, grep,
strings, perl etc:
# make live
Making base directory (./live-cd/)
Copying executables
Copying autopsy files
Creating configuration file using existing settings
Try the 'make static' with TSK to see if you can make static
executables for your platform.
The 'live-cd' directory has a 'bin' directory where additional
executables can be copied to and then the whole directory can be
burned to a CD.
How Do I Use the CD?
--------------------------------------------------------------------
After the CD has been created and there is a system suspected of
being compromised, then it is time to take advantage of the new
features. There are two scenarios for live analysis. The first
scenario uses a network share from a trusted system that you can
write to. In this case, autopsy is run as normal and you specify
the evidence locker directory as the mounted disk. The evidence
locker is specified with '-d':
# ./autopsy -d /mnt/ev_lock 10.1.32.123
The above would start autopsy, use '/mnt/ev_lock/' as the evidence
locker and would allow connections from 10.1.32.123 (where the
investigator would connect from using an HTML browser). Remember that
we do not want to write to the suspect system, so we should only use
a network share and not a local directory in this scenario.
The second scenario does not use an evidence locker and does not
intentionally write any data to disk. This scenario does not need
the network share and each of the devices (or partitions) that will
be analyzed are specified on the command line using the '-i' flags.
The '-i' flag requires three arguments: the device, the file system
type, and the mounting point. For example, to examine the '/dev/hda5'
and '/dev/hda8' partitions on a Linux system, the following could
be used:
# ./autopsy -i /dev/hda5 linux-ext3 / -i /dev/hda8 linux-ext3 /usr/ \
10.1.32.123
The file system type must be one of the types that are supported
by TSK. The remote IP address must also be given, otherwise you
will have to use a browser on the suspect system and that will write
data to the disk.
When you use the '-i' flag, then autopsy will start in the 'Host
Manager' view where you can select the image that you want to
analyze. You will skip the case and host configuration. The default
case name will be 'live', the default host name is 'local', and the
default investigator name is 'unknown'.
Additional Information
--------------------------------------------------------------------
I wrote a more detailed explanation of the live analysis mode of
Autopsy version 2.00 in the 13th issue of The Sleuth Kit Informer.
Some of this document is taken from the Informer issue.
http://www.sleuthkit.org/informer/sleuthkit-informer-13.html
--------------------------------------------------------------------
Copyright (c) 2004 by Brian Carrier. All Rights Reserved
Brian Carrier [carrier <at> sleuthkit <dot> org]

393
README.txt Normal file
View File

@ -0,0 +1,393 @@
Autopsy Forensic Browser
http://www.sleuthkit.org/autopsy
Last Updated: January 2008
Quick Overview
-----------------------------------------------------------------------------
The Autopsy Forensic Browser is a graphical interface to utilities
found in The Sleuth Kit (TSK). TSK is a collection of command line
tools that allow you to investigate a Windows or Unix system by
examining the hard disk contents. TSK and Autopsy will show you
the files, data units, and metadata of NTFS, FAT, EXTxFS, and UFS
file system images in a read-only environment. Autopsy allows you
to search for specific types of evidence based on keywords, MAC
times, hash values, and file types.
Autopsy is HTML-based and uses a client-server model. The Autopsy
server runs on many UNIX systems and the client can be any platform
with an HTML browser. This enables one to create a flexible
environment with a central Autopsy server and several remote clients.
For incident response scenarios, a CD with The Sleuth Kit and Autopsy
can be created to allow the responder read-only remote access to a
live suspect system from an HTML-browser on a trusted system. Refer
to the README-live.txt file for more details.
Autopsy will not modify the original images and the integrity of
the images can be verified in Autopsy using MD5 values. There are
help pages for the main analysis modes and The Sleuth Kit Informer
is a newsletter that adds additional documentation. This document
provides an overview of how to use Autopsy and what it can do.
http://www.sleuthkit.org/informer/
Case Management
-----------------------------------------------------------------------------
Starting with Autopsy 1.70, you can have multiple cases. When
Autopsy is started, there is an Evidence Locker directory (specified
on the command line or at installation time). This directory is
the base where all cases will be stored.
A CASE is any investigation and can have one or more hosts in it.
A list of investigators is assigned to each case. Each case gets
a subdirectory of the evidence locker and there is a configuration
file for the case and the list of investigators.
A HOST is a subset of a CASE. A host contains one or more file
system images that are analyzed. Each host gets a subdirectory
in the case directory. Each host has its own configuration file
that describes the files that it uses. Each host also has five
directories in it:
- images: for all the disk and partition images - this should have strict
permissions to prevent modification
- output: for all output files from tools. This includes unallocated
disk space and data unit contents.
- logs: Audit logs and investigator notes are stored here
- reports: All ASCII and HTML reports can be stored here
- mnt: Can be used to mount the images in loopback mode
An IMAGE corresponds to a disk or partition image. Image files are
imported into an Autopsy host. The image file must be a raw copy
of a partition or disk. These can be created by the 'dd' tool.
Issue 11 of The Sleuth Kit informer discussed how to make images
using 'dd'.
When importing an image, you have the option of moving the image
to the evidence locker, copying the image to the evidence locker,
or making a symbolic link from its current location to the evidence
locker. You also have the option to calculate or add the MD5 hash
value of the image.
Main Functions
-------------------------------------------------------------------------
After you have setup your case and imported the file system images,
you can begin the investigation. The Host Gallery view provides a
list of the imported file system images and you can select one of
them to analyze. After you have selected it, you will enter the
anlaysis view. The top of the window will have a series of tabs
that represent different analysis modes.
Each mode performs a different type of analysis. Choose the mode
that will help you find the type of evidence you are looking for.
If you are looking for a specifiic file, choose the File mode. If
you have a specific keyword in mind, choose that mode. If you are
looking for a specific file type, then choose that mode. You will
now need to use your sleuthing skills to search for evidence. You
may want to refer to some books dedicated to this topic if you have
not done this before.
I will now give an overview of each of the modes:
FILE BROWSING: Allows browsing the image as a file system. This
gives a list of directories on the left, and files and file content
on the right hand side. The output of each file can be seen as
ASCII or can be run through strings.
Since this analyzes directory entries, deleted file names can
still be seen and depending on the OS, the deleted file contents
can also be easily recovered. If a file name has a check before it,
it has been deleted. The directory contents listings can be resorted
based on name, size, times etc. by selecting the proper column
header.
KEYWORD SEARCHING: Search an image using grep(1) for a given
string. The result will be a list of data units that have this
string. Selecting each unit brings the user into Data Unit mode
to view the contents. Case insensitive searches and 'grep' regular
expression searches can also be performed. To decrease the searching
time, a file can be generated with just the ASCII strings of the
image. Also, the unallocated data can be extracted and searched
to make deleted data recovery more efficient.
The search.pl file contains predefined search values. Autopsy
currently comes with a regular expression to identify date strings
and IP addresses. Additional values can be added by the user.
The format is given in the file.
TIMELINE ANALYSIS: A timeline of file activity can be created and
viewed. The timeline allows one to identify file and directory
locations to examine. The times associated with files can be easily
modified, so the time line should be used as reference only.
IMAGE DETAILS: Details about the file system are displayed. Examples
of this mode include the Volume name, last mount time, and the
physical layout of the data structures. For FAT file systems, the
FAT contents are given and UNIX-based systems show the group layouts.
FILE TYPE ANALYSIS: Data reduction is an important aspect of
digital forensics. One way of doing data reduction is to exclude
known files and identify unknown files or categories. The File
Type Analysis mode will examine all of the files in an image and
sort them based on their file type. For example, all JPEG and GIF
files would be identified as 'images'. This mode can also identify
files that have an extension that is different than its file type.
This uses the 'sorter' tool from The Sleuth Kit. The hash databases
are used in this mode to exclude files that are known to be good
and identify 'known bad' files. Refer to issues 3, 4, and 5 of
The Sleuth Kit Informer for more details.
METADATA BROWSING: Metadata is descriptive data about a file.
This includes information such as times, owner id, and a list of
data unit pointers. This mode allows one to view the contents of
the file system structures that hold these values. In UNIX-based
file system these are typically called inodes, for FAT they are
directory entries, and for NTFS they are MFT entries. In this
mode, one enters the address of the structure and the details are
shown. The file(s) that are using the file will also be displayed
(even if they have been deleted for some OSes).
Metadata browsing can also be entered from within File browsing.
When the file's metadata address is selected, the browser switches
to metadata mode and displays the associated details. The data
units that the file has allocated can be viewed using the data unit
browsing.
DATA UNIT BROWSING: All file systems need to store file data some
where. Typically, the file system space is organized into large
chunks of consecutive bytes. These chunks have different names
depending on the file system type, so we will just refer to them
as data units. For UNIX-based file system the chunks are fragments,
FAT are sectors or clusters, and NTFS are sectors.
This mode allows one to examine any data unit they want. Just
enter the address and it is displayed in a variety of formats.
This is most useful when used with searching or metadata browsing.
The contents of the data unit can be displayed in ASCII, hexdump,
or by running the raw output through strings(1). The metadata
structure that has allocated the unit will be displayed (if any)
along with the file name (if any).
There are two types of data unit addresses in Autopsy, regular and
unallocated. The regular address is the unit number in a regular
image created from dd. The unallocated address is the unit number
in an image created from the unallocated units in a regular image
(by using blkls). When unallocated addresses are entered, they are
converted to the regular address and the corresponding regular unit
is shown. This is useful when using Autopsy along with foremost
(http://foremost.sourceforge.net) or Lazarus (TCT).
INVESTIGATOR NOTES: An investigator can add notes about any file, data
unit, or metadata structure. The notes can be viewed through Autopsy
at the Main Menu or by any text editor. The notes file is saved in the
'logs' directory. When viewing through Autopsy, the location that the
note refers to can be easily viewed.
REPORT GENERATION: Each of the above browsing techniques allows
a report to be generated. This report lists the date, md5 value,
investigator, and other context information in a text format. This
can be used for record keeping when deleted data units of data have
been found.
THE CELL: In an ideal world, forensics should only be performed
on an air-gapped network. In some cases, such as incident response
of critical systems, this is not possible. For this reason and
because of a history of HTML-browser security issues, files in
Autopsy are not "interpreted" by your browser. For example, an
HTML document by default will be shown as the raw HTML text. If
an investigator wants to view the actual HTML output or an image,
they can do so in a sterilized environment that parses out embedded
scripts and off-site references. Refer to issue #1 of The Sleuth
Kit Informer for more details.
Requirements
-----------------------------------------------------------------------------
Supported Platforms:
Autopsy will run on any system that is supported by The Sleuth Kit.
Autopsy needs the following software:
The Sleuth Kit (version 3.0.0 or above)
http://www.sleuthkit.org/sleuthkit
PERL (5.8.0 or above)
If large files will be used (larger than 2GB), Perl must be compiled
to support Large Files. Most systems now ship with 5.8 with large
file support.
HTML Browser:
Any that supports frames and forms will do. Some issues exist with
some versions of Internet Explorer. Netscape and Mozilla always work
fine though. Explorer will sometimes error when referencing 'localhost',
but '127.0.0.1' will work.
Recommended UNIX Utilities (most platforms already have these). The
default version that comes with some systems are not supported by
Autopsy. For example, the grep in Solaris.
grep: http://www.gnu.org/software/grep/grep.html
You will need a local md5 or md5sum executable as well. Most systems
now come with this utility.
Regular Usage
------------------------------------------------------------------------------
To use Autopsy:
1. Ensure that the evidence locker directory has been created and start
Autopsy.
# ./autopsy
Copy and Paste the URL into an HTML browser on the local system. It
will look something like:
http://localhost:9999/290263284571318993/autopsy
2. Select the 'Create Case' button and enter a name and list of
valid investigator names. Note that both the case and investigator
names must be valid directory names.
3. Select the case from the Case Gallery and then select 'Add Host' in
the Host Gallery menu. Enter the host name, and time information
such as the timezone and clock skew (if known). The timeskew is
how many seconds fast or slow the original system was and the output
times will be adjusted using it. For example, if the host was 3
seconds slow, this field would get a '-3'.
4. Select the host from the Host Gallery and then select 'Add Image'
in the Host Manager menu. Copy the images to the directory shown on
the screen. It is a subdirectory of the Evidence Locker for the new
host and case that have been created. After the images are in the
directory, press 'Refresh'. The images must be partition images
in a raw format (i.e. dd).
5. Select the file system type and mounting information. By default,
the MD5 value will be calculated for the image and saved for future
integrity checks. If you already know it, select 'Add Known Value' and
paste it in.
6. Continue to add images and hosts to the case. When done, select one
of the images and using the different browsing modes.
Common Configurations
-------------------------------------------------------------------------
The basic usage is for a single user with the client and server on the
same system. Autopsy 1.70+ can now handle more than one case at a time.
The syntax is as follows for the server to run on port 9999 and only
allow access from localhost:
# ./autopsy
To specify a different port number, use this:
# ./autopsy -p 8888
To specify a different remote host, use this:
# ./autopsy 10.0.0.1
To specify both a port and remote address use:
# ./autopsy -p 8888 10.0.0.1
If more than one investigator is going to be using the same server, then
just choose different ports:
# ./autopsy -p 9000 10.0.0.1
and
# ./autopsy -p 9050 10.0.50
You can also specify a new evidence locker location by providing
the '-d' argument:
# ./autopsy -d /usr/local/forensics2
Security Considerations
-------------------------------------------------------------------------
The Autopsy server is a Perl program that only processes Autopsy
urls. It offers easy access control restrictions by limiting access
to the server to one host and uses a random numeric "cookie" to
further authenticate a remote user. The random cookie is generated
when the server starts and allows an investigator to use a multi-user
machine. The recommended usage is to have the browser and autopsy
running on the same single-user system, which is the default
behavior.
If a non-localhost system is specified, a cookie is automatically
generated. If localhost is used, then a cookie is not used by
default. The default behavior can be changed using the command
line arguments. SSH forwarding can be used if encryption is needed
over a network.
File names must be very simple (letters, digits, -, _, and .).
This allows fast and easy checking of file names passed in the URL
and does not allow people to move out of the morgue directory.
Symbolic links can be created between the simple names and more
complex ones.
Troubleshooting
------------------------------------------------------------------------------
Autopsy is complaining that it can't find X:
Verify the variable settings in conf.pl (see the INSTALL file)
Autopsy takes a very long time to display large directories:
This occurs because directory contents are displayed as an HTML
table, and many browsers are not very efficient at displaying
large tables. So, it is not Autopsy that is slow, it is the
browser.
Autopsy hangs when opening directories:
Same answer as previous question. Browsers don't like big tables.
Autopsy is getting slower and slower:
If you start an intensive operation, such as searching or making a
strings file, and you hit the back button you will not stop the
search or operation. There is no current way to stop these
types of processes besides issuing a 'kill' command from a
shell.
Errors are generated by the 'strings' and 'grep' utilities:
This occurs because you most likely do not have the GNU version and
the flags are not working. Install the GNU grep and bin-utils and
verify that Autopsy is pointing to them in conf.pl.
Internet Explorer gives protocol and host errors:
If you are accessing the localhost, then use the 127.0.0.1 IP
address instead of the localhost name.
A file system image doesn't show up on the menu:
Make sure your version of Perl supports large files.
Feedback
------------------------------------------------------------------------------
Please e-mail me with suggestions on what you would like to see done
differently and new features.
------------------------------------------------------------------------------
Brian Carrier
carrier [at] sleuthkit [dot] org

57
TODO.txt Normal file
View File

@ -0,0 +1,57 @@
Look into adding the unallocated partiion space when an image is added.
Look into integrating clamshell or other AV
There is an error when viewing the event sequencer notes about
initialized in "ne".
test date search
Add SHA-1 to more places (images, lookups etc.)
Get "Can't ignore signal CHLD, forcing to default." message with
file type sorting (BUG: 919829).
Figure out details around having Perl on the live analysis CD.
(BUG: 919831)
-------------------- FILE MODE ----------------------------
- Make a file system depend seperator for / or \
- check for tar during install
- List contents like HTML does now
--------------------- SEARCH -----------------------------
- new mode where searching is done on output of 'icat' of allocated
inodes
- Bug: if the string that matches a keyword starts with spaces, then
the 'index' function returns the idx to the start of the spaces and not
the substring. (BUG 842858)
--------------------- TIMELINE -----------------------------
--------------------- LOGGING -----------------------------
- New Report Creation:
- Add pulldown in notes for common things:
- New MD5 / SHA-1
- Part of rootkit
- Suspected child porn
- known child porn
--------------------- SORTER -----------------------------
- Should sorter be at the host level instead of image, with output
files appended to each other?
- Allow one to browse output files
--------------------- GENERAL -----------------------------
- Add foremost
- link in meta data to list just unallocated / used
- HTML encode output data (TASK outout)
- Make data bases updatable in the host details view
- Option to mount images in loopback when it is a Linux system
- read config files in autopsy itself and not everytime ...
- Make a way to kill intensive processes (searching, fls)

5
base/.perltidyrc Executable file
View File

@ -0,0 +1,5 @@
-i=4 # indent of 4
-pt=2 # paren tightness
-sbt=2 # square paren tightness
-bt=2 # curly paren tightness
-nsfs # no space after semi in for loop

834
base/autopsy.base Normal file
View File

@ -0,0 +1,834 @@
#
# autopsy gui server
# Autopsy Forensic Browser
#
#
# This file requires The Sleuth Kit
# www.sleuthkit.org
#
#
# 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.
#
#
# refer to Security Considerations in README for a description of the
# cookie authentication
#
require 5.008;
use strict;
use Socket;
use Main;
use Print;
require Fs;
require Caseman;
require 'conf.pl';
require 'lib/define.pl';
# Import variables from conf.pl
use vars '$LOCKDIR', '$INSTALLDIR', '$PICTDIR';
use vars '$SANITIZE_TAG', '$SANITIZE_PICT';
use vars '$USE_STIMEOUT', '$STIMEOUT', '$CTIMEOUT';
use vars '$SAVE_COOKIE', '$GREP_EXE', '$FILE_EXE';
use vars '$NSRLDB';
# Default port
my $port = 9999;
# Default 'remote' host
my $rema = 'localhost';
$| = 1;
$::LIVE = 0;
$::USE_NOTES = 1;
$::USE_LOG = 1;
sub usage {
print
"\n\nusage: $0 [-c] [-C] [-d evid_locker] [-i device filesystem mnt] [-p port] [remoteaddr]\n";
print " -c: force a cookie in the URL\n";
print " -C: force NO cookie in the URL\n";
print " -d dir: specify the evidence locker directory\n";
print " -i device filesystem mnt: Specify info for live analysis\n";
print " -p port: specify the server port (default: $port)\n";
print " remoteaddr: specify the host with the browser (default: $rema)\n";
exit 1;
}
my $cook_force = 0;
my $vol_cnt = 0;
# Were options given?
while ((scalar(@ARGV) > 0) && ($ARGV[0] =~ /^-/)) {
my $f = shift;
# Evidence Locker
if ($f eq '-d') {
if (scalar(@ARGV) == 0) {
print "Missing Directory\n";
usage();
}
my $d = shift;
# We need to do this for the tainting
# We don't need to check for special characters in this case because
# all commands will be run with the same permissions as the
# original user. We will check for the obvious ';' though
if ($d =~ /;/) {
print "Illegal argument\n";
exit(1);
}
# If the path is relative, autopsyfunc will get screwed up when
# this is run from a directory other than where autopsyfunc is
# so force full paths
elsif ($d !~ /^\//) {
print "The evidence locker must be full path (i.e. begin with /)\n";
exit(1);
}
elsif ($d =~ /(.*)/) {
$LOCKDIR = $1;
}
}
# Force no cookie
elsif ($f eq '-C') {
$::USE_COOKIE = 0;
$cook_force = 1;
}
# force a cookie
elsif ($f eq '-c') {
$::USE_COOKIE = 1;
$cook_force = 1;
}
elsif ($f eq '-i') {
$::LIVE = 1;
$::USE_LOG = 0;
$::USE_NOTES = 0;
$::SAVE_COOKIE = 0;
if (scalar(@ARGV) < 3) {
print "Missing device, file system, and mount point arguments\n";
usage();
}
my $vol = "vol" . $vol_cnt;
$vol_cnt++;
my $dev = shift;
if ($dev =~ /($::REG_IMG_PATH)/) {
$dev = $1;
}
else {
print "invalid device: $dev\n";
usage();
}
unless ((-e "$dev") || (-l "$dev")) {
print "Device ($dev) not found\n";
usage();
}
my $fs = shift;
if ($fs =~ /($::REG_FTYPE)/) {
$fs = $1;
}
else {
print "invalid file system: $fs\n";
usage();
}
unless ((exists $Fs::root_meta{$fs})
&& (defined $Fs::root_meta{$fs}))
{
print "File system not supported: $fs\n";
usage();
}
$Caseman::vol2ftype{$vol} = "$fs";
my $mnt = shift;
if ($mnt =~ /($::REG_MNT)/) {
$mnt = $1;
}
else {
print "invalid mount point: $mnt\n";
usage();
}
$Caseman::vol2mnt{$vol} = "$mnt";
$Caseman::vol2cat{$vol} = "part";
$Caseman::vol2itype{$vol} = "raw";
$Caseman::vol2start{$vol} = 0;
$Caseman::vol2end{$vol} = 0;
# This makes me nervous ...
$Caseman::vol2par{$vol} = $vol;
$Caseman::vol2path{$vol} = "$dev";
$Caseman::vol2sname{$vol} = "$dev";
}
# Specify a different port
elsif ($f eq '-p') {
if (scalar(@ARGV) == 0) {
print "Missing port argument\n";
usage();
}
my $p = shift;
if ($p =~ /(\d+)/) {
$p = $1;
}
else {
print "invalid port: $p\n";
usage();
}
if (($p < 1) || ($p > 65535)) {
print "invalid port: $port\n";
usage();
}
$port = $p;
}
else {
print "Invalid flag: $f\n";
usage();
}
}
# remote address
if (scalar(@ARGV) > 0) {
$rema = shift;
}
# Get remote address
my @acl_addr; # Array of host addresses
my $hn; # Host name
my $tmp;
if ($rema =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/) {
$acl_addr[0] = pack('C4', ($1, $2, $3, $4));
$hn = $rema;
}
else {
($hn, $tmp, $tmp, $tmp, @acl_addr) = gethostbyname($rema);
unless (defined $tmp) {
print "Host not found: $rema\n";
usage();
}
}
# Determine the address that will be used to access this server
my $lclhost;
my @ta = unpack('C4', $acl_addr[0]);
my $bindaddr;
# If we are being accessed by localhost, we need that and not the hostname
if ( ($ta[0] == 127)
&& ($ta[1] == 0)
&& ($ta[2] == 0)
&& ($ta[3] == 1))
{
$lclhost = "localhost";
$bindaddr = $acl_addr[0];
# Force no cookie to be used unless we already set this value
# with arguments
$::USE_COOKIE = 0 unless ($cook_force == 1);
}
else {
$lclhost = `/bin/hostname`;
chop $lclhost;
$bindaddr = INADDR_ANY;
# Force a cookie to be used unless we already set this value
# with arguments
$::USE_COOKIE = 1 unless ($cook_force == 1);
}
# Verify the variables defined in the configuration files
check_vars();
# Remove the final '/' from TSKDIR if it exists
$::TSKDIR = $1
if ($::TSKDIR =~ /(.*?)\/$/);
#
# Verify that all of the required executables exist
#
check_tools();
# remove environment stuff that we don't need and that could be insecure
# We allow basic bin directories for CYGWIN though, since they are
# required for the CYGWIN dlls
my $UNAME = "";
if (-e "/bin/uname") {
$UNAME = "/bin/uname";
}
elsif (-e "/usr/bin/uname") {
$UNAME = "/usr/bin/uname";
}
my $ispathclear = 1;
if (($UNAME ne "") && (`$UNAME` =~ /^CYGWIN/)) {
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ispathclear = 0;
}
else {
$ENV{PATH} = '';
}
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
my $date = localtime;
if ($::LIVE == 0) {
# Remove the final '/' if it exists
$LOCKDIR = $1
if ($LOCKDIR =~ /(.*?)\/$/);
}
# Setup socket
my $proto = getprotobyname('tcp');
socket(Server, PF_INET, SOCK_STREAM, $proto)
or die "Error creating network socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, 1)
or die "Error setting network socket options (reuse): $!";
setsockopt(Server, SOL_SOCKET, SO_KEEPALIVE, 1)
or die "Error setting network socket options (keep alive): $!";
bind(Server, sockaddr_in($port, $bindaddr))
or die "Error binding to port $port (is Autopsy already running?): $!";
listen(Server, SOMAXCONN)
or die "Error listening to socket for connections: $!";
my $magic; # magic authentication cookie
my $cook_file;
my $cookie_url = "";
if ($::USE_COOKIE == 1) {
# Try for a real random device, or use rand if all else fails
if (-e "/dev/urandom") {
my $r;
open RAND, "</dev/urandom" or die "can not open /dev/urandom";
read RAND, $r, 4;
$magic = unpack "I", $r;
read RAND, $r, 4;
$magic .= unpack "I", $r;
close RAND;
}
else {
$magic = int(rand 0xffffffff) . int(rand 0xffffffff);
}
$cookie_url = "$magic/";
# Save to file in case the stdout gets overwritten
if ($SAVE_COOKIE == 1) {
$cook_file = "$LOCKDIR/.$port.cookie";
if (open COOK, ">$cook_file") {
chmod 0600, "$cook_file";
print COOK "$magic\n";
close COOK;
}
else {
print "WARNING: Cannot open file to save cookie in ($cook_file)";
}
}
}
print <<EOF;
============================================================================
Autopsy Forensic Browser
http://www.sleuthkit.org/autopsy/
ver $::VER
============================================================================
EOF
if ($::LIVE == 0) {
print "Evidence Locker: $LOCKDIR\n";
}
else {
print "Live Analysis Mode\n";
}
if ($ispathclear == 0) {
print
"\nCYGWIN Mode (Internal path contains /bin, /usr/bin, and /usr/local/bin)\n\n";
}
print <<EOF2;
Start Time: $date
Remote Host: $rema
Local Port: $port
Open an HTML browser on the remote host and paste this URL in it:
http://$lclhost:${port}/${cookie_url}$::PROGNAME
Keep this process running and use <ctrl-c> to exit
EOF2
Print::log_session_info("Starting session on port $port and $hn\n");
# Set the server alarm
$SIG{ALRM} = \&SIG_ALARM_SERVER;
$SIG{INT} = \&SIG_CLOSE;
# setting this to ignore will automatically wait for children
$SIG{CHLD} = 'IGNORE';
# Wait for Connections
while (1) {
alarm($STIMEOUT) if ($USE_STIMEOUT == 1);
my $raddr = accept(CLIENT, Server);
next unless ($raddr);
my ($rport, $riaddr) = sockaddr_in($raddr);
die "Error creating child" unless (defined(my $pid = fork()));
if (0 == $pid) {
open(STDOUT, ">&CLIENT") or die "Can't dup client to stdout";
# open(STDERR, ">&CLIENT") or die "Can't dup client to stdout";
open(STDIN, "<&CLIENT") or die "Can't dup client to stdin";
$| = 1;
my @rip = unpack('C4', $riaddr);
# Check ACL
foreach $tmp (@acl_addr) {
if ($tmp eq $riaddr) {
spawn_cli($riaddr);
close CLIENT;
exit 0;
}
}
forbid("$rip[0].$rip[1].$rip[2].$rip[3]");
Print::log_session_info("ERROR: Unauthorized Connection from: "
. "$rip[0].$rip[1].$rip[2].$rip[3]\n");
close CLIENT;
exit 1;
}
else {
close CLIENT;
}
}
# Error messages
sub forbid {
my $ip = shift;
print "HTTP/1.0 403 Forbidden$::HTTP_NL"
. "Content-type: text/html$::HTTP_NL$::HTTP_NL"
. "<html><center>\n"
. "<h2>Access Denied</h2>\n"
. "<h3>Your connection from: $ip has been logged</h3>\n"
. "</center></html>$::HTTP_NL$::HTTP_NL$::HTTP_NL";
return;
}
sub bad_req {
print "HTTP/1.0 404 Bad Request$::HTTP_NL"
. "Content-type: text/html$::HTTP_NL$::HTTP_NL"
. "<html><body><center>\n"
. "<h2>Invalid URL<br><tt>"
. shift()
. "</tt></h2>\n"
. "</center></body></html>"
. "$::HTTP_NL$::HTTP_NL$::HTTP_NL";
return;
}
# Alarm Functions
sub SIG_ALARM_CLIENT {
Print::log_session_info("Connection timed out\n");
close CLIENT;
exit 1;
}
sub SIG_ALARM_SERVER {
print "Server Timeout ($STIMEOUT seconds), Exiting\n";
Print::log_session_info("Server Timeout ($STIMEOUT seconds), Exiting\n");
exit 0;
}
# Close the system down when Control-C is given
sub SIG_CLOSE {
# delete the cookie file
if (($::USE_COOKIE == 1) && ($SAVE_COOKIE == 1)) {
unlink "$cook_file";
}
print "End Time: " . localtime() . "\n";
Print::log_session_info("Ending session on port $port and $hn\n");
exit 0;
}
# Pass the remote IP address as the argument for logging
sub spawn_cli {
# Set timeout for 10 seconds if we dont get any input
alarm($CTIMEOUT);
$SIG{ALRM} = \&SIG_ALARM_CLIENT;
while (<STDIN>) {
if (/^GET \/+(\S*)\s?HTTP/) {
my $url = $1;
my $script;
my $args;
if (/\x0d\x0a$/) {
$::HTTP_NL = "\x0d\x0a";
}
else {
$::HTTP_NL = "\x0a";
}
# Magic Cookie
# If we are using cookies, then the url should be:
# cookie/autopsy?var=val ...
if ($::USE_COOKIE == 1) {
if ( ($url =~ /^(\d+)\/+([\w\.\/]+)(?:\?(.*))?$/)
&& ($1 == $magic))
{
$script = $2;
$args = $3;
}
else {
my @rip = unpack('C4', shift());
Print::log_session_info("ERROR: Incorrect Cookie from: "
. "$rip[0].$rip[1].$rip[2].$rip[3]\n");
forbid("$rip[0].$rip[1].$rip[2].$rip[3]");
return 1;
}
}
# if we aren't using cookies, then it should be:
# autopsy?var=val ...
else {
if ($url =~ /^\/?([\w\.\/]+)(?:\?(.*))?$/) {
$script = $1;
$args = $2;
}
else {
bad_req($url);
return 1;
}
}
if ($script eq $::PROGNAME) {
$args = "" unless (defined $args);
# Turn timer off
alarm(0);
# Print status
print "HTTP/1.0 200 OK$::HTTP_NL";
::main($args);
}
elsif ($script eq "global.css") {
show_file($script);
}
# Display the sanitized picture or reference error
elsif ($script eq $::SANITIZE_TAG) {
Appview::sanitize_pict($args);
return 1;
}
# Display a picture or help file
elsif (($script =~ /^(pict\/[\w\.\/]+)/)
|| ($script =~ /^(help\/[\w\.\/]+)/))
{
show_file($1);
}
elsif ($script eq 'about') {
about();
}
# I'm not sure why this is needed, but there are reqs for it
elsif ($script eq 'favicon.ico') {
show_file("pict/favicon.ico");
}
else {
bad_req($url);
Print::log_session_info("Unknown function: $script\n");
return 1;
}
return 0;
}
} # end of while (<>)
} # end of spawn_cli
# Print the contents of a local picture or help file
sub show_file {
my $file = "$INSTALLDIR/" . shift;
if (-e "$file") {
print "HTTP/1.0 200 OK$::HTTP_NL";
open FILE, "<$file"
or die "can not open $file";
if ($file =~ /\.css$/i) {
print "Content-type: text/css$::HTTP_NL$::HTTP_NL";
}
elsif ($file =~ /\.jpg$/i) {
print "Content-type: image/jpeg$::HTTP_NL$::HTTP_NL";
}
elsif ($file =~ /\.gif$/i) {
print "Content-type: image/gif$::HTTP_NL$::HTTP_NL";
}
elsif ($file =~ /\.ico$/i) {
print "Content-type: image/ico$::HTTP_NL$::HTTP_NL";
}
elsif ($file =~ /\.html$/i) {
print "Content-type: text/html$::HTTP_NL$::HTTP_NL";
}
else {
print "HTTP/1.0 404 Bad Request$::HTTP_NL"
. "Content-type: text/html$::HTTP_NL$::HTTP_NL"
. "<html>\n"
. "<head><title>Error</title></head>\n"
. "<h2><center>Unknown Extension</h2>\n"
. "</center></html>$::HTTP_NL$::HTTP_NL$::HTTP_NL";
exit(1);
}
while (<FILE>) {
print "$_";
}
close(FILE);
print "$::HTTP_NL$::HTTP_NL";
}
else {
print "HTTP/1.0 404 Bad Request$::HTTP_NL"
. "Content-type: text/html$::HTTP_NL$::HTTP_NL"
. "<html>\n"
. "<head><title>Error</title></head>\n"
. "<h2><center>File Not Found</h2>"
. "</center></html>$::HTTP_NL$::HTTP_NL$::HTTP_NL";
exit(1);
}
return;
}
sub about {
print "HTTP/1.0 200 OK$::HTTP_NL"
. "Content-type: text/html$::HTTP_NL$::HTTP_NL";
my $tskver = ::get_tskver();
print <<EOF;
<html>
<head><title>About Autopsy</title></head>
<body BGCOLOR=#CCCC99>
<center><h2>About Autopsy</h2>
<br>
<img src=\"pict/logo.jpg\" alt=\"Logo\">
<br><br>
<b>Version</b>: $::VER
<br>
<tt><a href="http://www.sleuthkit.org/autopsy/">http://www.sleuthkit.org/autopsy/</a></tt>
<br>
<tt><a href="http://www.sleuthkit.org/informer/">http://www.sleuthkit.org/informer/</a></tt>
</center>
<h3>Credits</h3>
<UL>
<LI>Code Development: Brian Carrier (carrier at sleuthkit dot org)
<LI>Interface Assistance: Samir Kapuria
<LI>Mascot: Hash the Hound
</UL>
<h3>Configuration</h3>
<b>The Sleuth Kit</b>:<br>
&nbsp;&nbsp;URL: <a href="http://www.sleuthkit.org/sleuthkit/">
<tt>http://www.sleuthkit.org/sleuthkit/</tt></a><br>
&nbsp;&nbsp;Installation Location: <tt>$::TSKDIR</tt><br>
&nbsp;&nbsp;Version: $tskver<br>
<b>Evidence Locker</b>: <tt>$LOCKDIR</tt><br>
<b>grep</b>: <tt>$GREP_EXE</tt><br>
<b>file</b>: <tt>$FILE_EXE</tt><br>
<b><a href="http://www.nsrl.nist.gov/">NIST NSRL</a></b>: <tt>$NSRLDB</tt><br>
</body></html>
EOF
return 0;
}
### Check that the required tools are there
sub check_tools {
# Sleuth Kit execs
unless (-x $::TSKDIR . "/icat") {
print "ERROR: Sleuth Kit icat executable missing: $::TSKDIR\n";
exit(1);
}
unless (-x $::TSKDIR . "/istat") {
print "ERROR: Sleuth Kit istat executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/ifind") {
print "ERROR: Sleuth Kit ifind executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/ils") {
print "ERROR: Sleuth Kit ils executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/fls") {
print "ERROR: Sleuth Kit fls executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/ffind") {
print "ERROR: Sleuth Kit ffind executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/blkcat") {
print "ERROR: Sleuth Kit blkcat executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/blkcalc") {
print "ERROR: Sleuth Kit blkcalc executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/blkls") {
print "ERROR: Sleuth Kit blkls executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/img_stat") {
print "ERROR: Sleuth Kit img_stat executable missing\n";
exit(1);
}
unless (-x "$::FILE_EXE") {
print "ERROR: Sleuth Kit (or local) file executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/fsstat") {
print "ERROR: Sleuth Kit fsstat executable missing\n";
exit(1);
}
unless (-x "$::MD5_EXE") {
print "ERROR: md5 executable missing\n";
exit(1);
}
if ($::SHA1_EXE ne "") {
unless (-x "$::SHA1_EXE") {
print "ERROR: sha1 executable missing\n";
exit(1);
}
}
unless (-x $::TSKDIR . "/srch_strings") {
print "ERROR: Sleuth Kit srch_strings executable missing\n";
exit(1);
}
if ($::LIVE == 0) {
unless (-x $::TSKDIR . "/sorter") {
print "ERROR: Sleuth Kit sorter executable missing\n";
exit(1);
}
unless (-x $::TSKDIR . "/hfind") {
print "ERROR: Sleuth Kit hfind executable missing\n";
print
" You likely have an old version of The Sleuth Kit or TASK\n";
exit(1);
}
}
unless (-x "$GREP_EXE") {
print "ERROR: grep executable missing\n";
exit(1);
}
}
# check values that should be defined in the configuration files
# This will show incomplete installations
sub check_vars {
unless ((defined $::TSKDIR) && ($::TSKDIR ne "")) {
print "ERROR: TSKDIR variable not set in configuration file\n";
print " This could been caused by an incomplete installation\n";
exit(1);
}
unless (-d "$::TSKDIR") {
print "Invalid Sleuth Kit binary directory: $::TSKDIR\n";
exit(1);
}
return if ($::LIVE == 1);
# Verify The evidence locker directory
unless ((defined $LOCKDIR) && ($LOCKDIR ne "")) {
print "ERROR: LOCKDIR variable not set in configuration file\n";
print " This could been caused by an incomplete installation\n";
exit(1);
}
unless (-d "$LOCKDIR") {
print "Invalid evidence locker directory: $LOCKDIR\n";
exit(1);
}
}

146
base/make-live-cd.base Normal file
View File

@ -0,0 +1,146 @@
#
# This makes a directory ($CD) with the needed files to burn to
# a CD for live analysis
#
# Current limitations are that Perl needs to be on the suspect system and
# that it uses the untrusted Perl files.
require 'conf.pl';
use vars '$USE_STIMEOUT', '$STIMEOUT', '$CTIMEOUT', '$SAVE_COOKIE';
use vars '$GREP_EXE', '$TSKDIR';
my $CD = "./live-cd/";
# Make the directories
if (-d "$CD") {
print "Live CD directory already exists ($CD)\n";
print "Plese delete and run this again\n";
exit (1);
}
print "Making base directory ($CD)\n";
die "Error making Live CD directory ($CD)"
unless (mkdir "$CD", 0775);
die "Error making Live CD binaries directory ($CD)"
unless (mkdir "$CD/bin/", 0775);
print "Copying executables\n";
# Copy the executables
die "Missing grep executable ($GREP_EXE)"
unless (-x "$GREP_EXE");
`cp '$GREP_EXE' '$CD/bin/grep'`;
die "Error copying grep executable"
unless (-x "$CD/bin/grep");
# Sleuth Kit Binaries
die "Missing Sleuth Kit Directory ($TSKDIR)"
unless (-d "$TSKDIR");
foreach my $exec ("blkcalc", "blkcat", "blkls", "blkstat", "ffind", "fls", "fsstat",
"icat", "ifind", "ils", "istat", "md5", "sha1", "srch_strings", "img_stat", "mmls") {
die "Missing Sleuth Kit executable ($exec)"
unless (-x "$TSKDIR/$exec");
`cp '$TSKDIR/$exec' '$CD/bin/$exec'`;
die "Error copying Sleuth Kit executable ($exec)"
unless (-x "$CD/bin/$exec");
}
# Make a fake file
open FILE, ">$CD/bin/file" or die ("Error creating Live CD file exec");
print FILE "#!./bin/perl\n";
print FILE "print STDOUT \"File Type Not Supported During Live Analysis\n\";\n";
close FILE;
`chmod +x "$CD/bin/file"`;
# Copy the autopsy directories
print "Copying autopsy files\n";
`cp -r help "$CD"`;
`cp -r lib "$CD"`;
`cp -r pict "$CD"`;
# Get the path for Perl from the current autopsy
open AUT, "<./autopsy" or die ("Error opening normal autopsy exec");
my $perl;
while (<AUT>) {
$perl = $_;
last;
}
close AUT;
if ($perl =~ /^#!(\S+)/) {
$perl = $1;
} else {
die "Error parsing Perl location from autopsy"
}
# Copy the perl exec
# @@@ I'm not sure if just copying the bin is enough ...
die "Missing Perl executable ($perl)"
unless (-x "$perl");
`cp '$perl' '$CD/bin/perl'`;
die "Error copying perl executable"
unless (-x "$CD/bin/perl");
# Make a new autopsy
open AUT, ">$CD/autopsy" or die ("Error opening Live CD autopsy exec");
print AUT "#!./bin/perl -wT\n";
print AUT "use lib '.';\n";
print AUT "use lib './lib/';\n";
open BASE, "<./base/autopsy.base" or die ("Error opening base autopsy");
print AUT $_
while (<BASE>);
close (AUT);
close (BASE);
`chmod +x "$CD/autopsy"`;
print "Creating configuration file using existing settings\n";
# Make the configuration file
open CONF, ">$CD/conf.pl" or die ("Error opening Live CD Config file");
print CONF "# Configuration file for Live CD version of Autopsy\n";
print CONF "# http://www.sleuthkit.org/autopsy\n";
print CONF "# Created on ".localtime()."\n\n";
# Variables
print CONF "\$USE_STIMEOUT = $USE_STIMEOUT;\n";
print CONF "\$STIMEOUT = $STIMEOUT;\n";
print CONF "\$CTIMEOUT = $CTIMEOUT;\n";
print CONF "\$SAVE_COOKIE = $SAVE_COOKIE;\n";
print CONF "\n";
print CONF "\$INSTALLDIR = './';\n";
print CONF "\$NSRLDB = '';\n";
print CONF "\$LOCKDIR = './read-only-live-version/';\n";
print CONF "\n";
print CONF "# System Utilities\n";
print CONF "\$GREP_EXE = './bin/grep';\n";
print CONF "\$FILE_EXE = './bin/file';\n";
print CONF "\$TSKDIR = './bin/';\n";
close CONF;
print "\n";

490
configure vendored Executable file
View File

@ -0,0 +1,490 @@
#!/bin/sh
# Minimum version of TSK that is required
minver="3.0.0";
# The last released version of TSK
curtskver="3.0.0";
# Configuration script for the Autopsy Forensic Browser
#
# Brian Carrier [carrier@sleuthkit.org]
#
# Copyright (c) 2003-2008 by Brian Carrier. All rights reserved
#
# Copyright (c) 2001-2003 by Brian Carrier, @stake. All rights reserved
#
# Copyright (c) 2001 by Brian Carrier. All rights reserved
#
# This file is part of the Autopsy Forensic Browser (Autopsy)
#
# Autopsy is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Autopsy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Autopsy; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
# THIS SOFTWARE IS 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.
# Directories to search in
dirs='/usr/local/bin/ /usr/bin/ /usr/ccs/bin/ /bin/ /usr/ucb/bin/ /sbin/ /usr/sbin/ /usr/local/sbin/'
echo ""
echo " Autopsy Forensic Browser Installation"
echo ""
#############################################################################
# Setup Perl locations
#############################################################################
found=0;
for d in $dirs
do if (test -x ${d}perl) then
if (test -n "`${d}perl -v 2> /dev/null | awk '/This is perl/ {print $0}'`") then
ver=`${d}perl -v 2> /dev/null | awk '/This is perl,/ {print $4}'`;
echo "perl found: ${d}perl (version $ver)";
echo "#!${d}perl -wT" > ./config.tmp;
echo "#!${d}perl" > ./config2.tmp;
found=1;
break;
fi;
fi;
done
# If it wasn't found, then prompt for it.
if (test $found -eq 0) then
echo 'ERROR: perl not found or the incorrect version found';
while (test 1 -eq 1)
do echo 'Enter location of perl executable:';
read perlexe;
if (test -x "$perlexe") then
if (test -n "`$perlexe -v 2> /dev/null | awk '/This is perl/ {print $0}'`") then
ver=`$perlexe -v 2> /dev/null | awk '/This is perl,/ {print $4}'`;
if (test "$ver" '<' "v5.8.0") then
echo "This version of Perl is too old, 5.8.0 or older needed";
else
echo "Correct version found";
echo "#!${d}perl -wT" > ./config.tmp;
echo "#!${d}perl" > ./config2.tmp;
found=1;
break;
fi;
else
echo "Perl found, but is not working. Try another";
fi;
else
echo "file not found";
fi
done
fi
# Check if this version of Perl supports large files
if (test -z "`${d}perl -V 2> /dev/null | awk '/USE_LARGE_FILES/ {print $0}'`") then
echo ''
echo ' NOTE: It appears that your Perl does not support large files.';
echo ' You therefore will not be able to analyze images larger than 2GB.';
echo ' Download the source version from www.cpan.org and compile a new version.';
echo " [Press Enter to Continue]";
read foo;
echo ''
fi;
# Get current working directory for lib
echo "use lib '$PWD/';" >> ./config.tmp
echo "use lib '$PWD/lib/';" >> ./config.tmp
# Write autopsy
if (test -f ./autopsy) then
echo "autopsy already exists, overwrite? (y/n):";
read rep;
if (test "$rep" = "y") then
cat ./config.tmp base/autopsy.base > ./autopsy
cat ./config2.tmp base/make-live-cd.base > ./make-live-cd
else
echo ' original version was kept';
fi
else
cat ./config.tmp base/autopsy.base > ./autopsy
cat ./config2.tmp base/make-live-cd.base > ./make-live-cd
fi
chmod 0755 ./autopsy
chmod 0755 ./make-live-cd
# cleanup
rm -f ./config.tmp
rm -f ./config2.tmp
#############################################################################
# create conf.pl
#############################################################################
conf='conf.pl'
if (test -f $conf) then
echo "A configuration file already exists, overwrite? (y/n):";
read rep;
if (test "$rep" = "n") then
exit 0;
fi
fi
# echo ''
# echo '---------------------------------------------------------------'
# echo ''
# echo 'Autopsy can use the configuration file from a previous installation'
# echo ''
# echo 'Would you like to use a previous configuration file (y/n) [n]'
# read rep;
# if (test "$rep" = "y") then
# echo 'Enter the directory of the previous installation (or cancel):'
# while (test 1 -eq 1)
# do read prevdir;
# if (test "$prevdir" = "cancel") then
# break;
# fi;
# if (test -f "${prevdir}/conf.pl") then
# /bin/cp "${prevdir}/conf.pl" .
# echo ' Configuration file copied from $prevdir';
# # Check the config status
# exit 0;
# fi;
# echo 'Configuration file not found, try again (or 'cancel' to stop):'
# done;
#fi;
# First add the variables that are static
#
# DEFAULT USER SETTINGS
#
echo '# Autopsy configuration settings' > $conf
echo '' >> $conf
echo '# when set to 1, the server will stop after it receives no' >> $conf
echo '# connections for STIMEOUT seconds. ' >> $conf
echo '$USE_STIMEOUT = 0;' >> $conf
echo '$STIMEOUT = 3600;'>> $conf
echo '' >> $conf
echo '# number of seconds that child waits for input from client' >> $conf
echo '$CTIMEOUT = 15;' >> $conf
echo '' >> $conf
echo '# set to 1 to save the cookie value in a file (for scripting)' >> $conf
echo '$SAVE_COOKIE = 1;' >> $conf
#############################################################################
# INSTALLATION DIRECTORY
#############################################################################
echo '' >> $conf;
echo \$INSTALLDIR = \'$PWD/\'\; >> $conf;
# Now add the variables that need user interaction
#
# FIND THE UTILITIES
#
echo '' >> $conf
echo '' >> $conf
echo '# System Utilities' >> $conf
#
# GREP
#
echo ''
echo '---------------------------------------------------------------'
echo ''
found=0
for d in $dirs
do if (test -x ${d}grep) then
echo \$GREP_EXE = \'${d}grep\'\; >> $conf;
echo "grep found: ${d}grep";
grepexe="${d}grep";
found=1;
break;
fi;
done
# Prompt if not found
if (test $found -eq 0) then
echo 'ERROR: grep utility not found';
echo 'Enter location of executable:';
while (test 1 -eq 1)
do read grepexe;
if (test -x "$grepexe") then
echo \$GREP_EXE = \'$grepexe\'\; >> $conf;
break;
else
echo 'grep was not found (try again):';
fi;
done
fi
#
# FILE
#
found=0
for d in $dirs
do if (test -x ${d}file) then
echo \$FILE_EXE = \'${d}file\'\; >> $conf;
echo "file found: ${d}file";
found=1;
break;
fi;
done
# Prompt if not found
if (test $found -eq 0) then
echo 'ERROR: file utility not found';
echo 'Enter location of executable:';
while (test 1 -eq 1)
do read fileexe;
if (test -x "$fileexe") then
echo \$FILE_EXE = \'$filexe\'\; >> $conf;
break;
else
echo 'file was not found (try again):';
fi;
done
fi
#
# MD5
#
found=0
for d in $dirs
do if (test -x ${d}md5) then
echo \$MD5_EXE = \'${d}md5\'\; >> $conf;
echo "md5 found: ${d}md5";
found=1;
break;
elif (test -x ${d}md5sum) then
echo \$MD5_EXE = \'${d}md5sum\'\; >> $conf;
echo "md5 found: ${d}md5sum";
found=1;
break;
fi;
done
# Prompt if not found
if (test $found -eq 0) then
echo 'ERROR: md5/md5sum utility not found';
echo 'Enter location of executable:';
while (test 1 -eq 1)
do read md5exe;
if (test -x "$md5exe") then
echo \$MD5_EXE = \'$md5exe\'\; >> $conf;
break;
else
echo 'md5 was not found (try again):';
fi;
done
fi
#
# SHA-1
#
found=0
for d in $dirs
do if (test -x ${d}sha15) then
echo \$SHA1_EXE = \'${d}sha\'\; >> $conf;
echo "sha1 found: ${d}sha1";
found=1;
break;
elif (test -x ${d}sha1sum) then
echo \$SHA1_EXE = \'${d}sha1sum\'\; >> $conf;
echo "sha1 found: ${d}sha1sum";
found=1;
break;
fi;
done
if (test $found -eq 0) then
echo 'WARNING: sha1/sha1sum utility not found';
echo \$SHA1_EXE = \'\'\; >> $conf;
fi;
#############################################################################
# The Sleuth Kit
#############################################################################
echo '' >> $conf
echo '' >> $conf
echo '# Directories' >> $conf
echo ''
echo '---------------------------------------------------------------'
echo ''
echo 'Searching for Sleuth Kit Installation.'
found=0
for d in $dirs
do if ((test -x ${d}fls) && (test -x ${d}ffind) && (test -x ${d}blkstat) && \
(test -x ${d}blkls) && (test -x ${d}blkcat) && \
(test -x ${d}mmls) && (test -x ${d}mmstat) && \
(test -x ${d}fsstat) && (test -x ${d}img_stat) && \
(test -x ${d}istat) && (test -x ${d}ifind) && \
(test -x ${d}icat) && (test -x ${d}ils) && \
(test -x ${d}srch_strings) && \
(test -x ${d}mactime) && (test -x ${d}sorter)) then
echo \$TSKDIR = \'${d}\'\; >> $conf;
tskdir=${d};
echo "Found in: ${d}";
found=1;
break;
fi;
done
if (test $found -eq 0) then
echo 'Sleuth Kit tools were not found in the standard install locations.'
echo 'If you have not installed them, do so now and configure autopsy again.'
echo 'If you have installed them in a non-standard location, then'
echo ' enter the "bin" directory now:'
while (test 1 -eq 1)
do read tskdir;
if ((test -x ${tskdir}/fls) && (test -x ${tskdir}/ffind) && (test -x ${tskdir}/blkstat) && \
(test -x ${tskdir}/blkls) && (test -x ${tskdir}/blkcat) && \
(test -x ${tskdir}/mmls) && (test -x ${tskdir}/mmstat) && \
(test -x ${tskdir}/fsstat) && (test -x ${tskdir}/img_stat) && \
(test -x ${tskdir}/istat) && (test -x ${tskdir}/ifind) && \
(test -x ${tskdir}/icat) && (test -x ${tskdir}/ils) && \
(test -x ${tskdir}/srch_strings) && \
(test -x ${tskdir}/mactime) && (test -x ${tskdir}/sorter)) then
echo \$TSKDIR = \'${tskdir}\'\; >> $conf;
break;
else
echo 'TSK tools were not found or incomplete (try again):';
fi;
done
fi;
# Test for latest version
ver=`"${tskdir}/fls" -V | awk '/The Sleuth Kit ver / {print $5}'`;
echo " Version $ver found";
if (test "$ver" '<' "$minver") then
echo "Your version of The Sleuth Kit is not current enough - $minver is needed";
exit 1;
elif (test "$ver" '<' "$curtskver") then
echo '';
echo "*** NOTE: A more recent version ($curtskver) of The Sleuth Kit Exists ***"
echo " [Press Enter to Continue]";
read foo;
else
echo ' Required version found';
fi
# NSRL
echo ''
echo '---------------------------------------------------------------'
echo ''
echo 'The NIST National Software Reference Library (NSRL) contains'
echo 'hash values of known good and bad files.'
echo ' http://www.nsrl.nist.gov'
echo ''
echo 'Have you purchased or downloaded a copy of the NSRL (y/n) [n]'
read rep;
if (test "$rep" = "y") then
echo 'Enter the directory where you installed it:'
while (test 1 -eq 1)
do read nsrldir;
if (test "$nsrldir" = "cancel") then
echo \$NSRLDB = \'\'\; >> $conf;
break;
fi;
if (test -f "${nsrldir}/NSRLFile.txt") then
echo ' NSRL database was found (NSRLFile.txt)';
echo \$NSRLDB = \'${nsrldir}/NSRLFile.txt\'\; >> $conf;
if (test -f "${nsrldir}/NSRLFile.txt-md5.idx") then
echo ' NSRL Index file found (NSRLFile.txt-md5.idx)';
else
echo ' NSRL Index file not found, do you want it created? (y/n) [n]:'
read rep;
if (test "$rep" = "y") then
echo ''
echo '-------------- begin hfind output --------------'
"${tskdir}/hfind" -i nsrl-md5 "${nsrldir}/NSRLFile.txt";
echo '--------------- end hfind output ---------------'
echo ''
fi;
fi;
break;
else
echo 'The NSRL was not found (the directory should have NSRLFile.txt in it)';
echo 'Enter a new directory (or cancel to stop):';
fi;
done
else
echo \$NSRLDB = \'\'\; >> $conf;
fi;
#############################################################################
# EVIDENCE LOCKER
#############################################################################
mdone=0
echo ''
echo '---------------------------------------------------------------'
echo ''
echo 'Autopsy saves configuration files, audit logs, and output to the'
echo 'Evidence Locker directory.'
echo ''
echo 'Enter the directory that you want to use for the Evidence Locker:';
read locker;
if (test -d "${locker}") then
echo " $locker already exists"
else
echo '';
echo "WARNING: $locker does not exist"
mdone=1
fi
echo \$LOCKDIR = \'${locker}\'\; >> $conf;
#############################################################################
# CLEANUP
#############################################################################
echo ''
echo '---------------------------------------------------------------'
echo ''
echo "Settings saved to $conf."
echo "Execute the './autopsy' command to start with default settings."
echo ''

View File

@ -0,0 +1,410 @@
The Sleuth Kit Informer
http://www.sleuthkit.org/informer
http://sleuthkit.sourceforge.net/informer
Brian Carrier
carrier at sleuthkit dot org
Issue #13
March 15, 2004
CONTENTS
--------------------------------------------------------------------
- Introduction
- What's New?
- Call For Papers
- Did You Know?
- UNIX Incident Verification With Autopsy
INTRODUCTION
--------------------------------------------------------------------
I'm almost done! Releasing version 2.00 of Autopsy that is. I'm
polishing up the final changes and documentation and it will be
released later this week. March 19 is the birthday of Autopsy and
The Sleuth Kit's predecessor, TCTutils, also the goal release date
for version 2.00.
This issue of the Informer will focus on the new live analysis
feature of (the unreleased) Autopsy. This issue also has a lot
entries in the "What's New?" category because we are on a bimonthly
schedule. If you missed getting the February issue of The Informer
and have lessons to share with people then make sure you read the
Call For Papers section so that you can learn how to submit articles
of your own.
WHAT'S NEW?
--------------------------------------------------------------------
A new version (1.68) of The Sleuth Kit was released. It contains
a couple of bug fixes. There have been discussions on the
sleuthkit-developers list about what new functions should be added
to the next big version 2.00 release. Michael Cohen has been looking
into support for disk images, split images, RAID images, and other
non-raw formats. David Collett has been looking into output formats
for TSK tools so that they can be imported into databases.
Version 2.00 of Autopsy will be released later this week. I'm
adding the final touches and documentation and the goal is to release
it on March 19, which is the 3 year anniversary of the first release
of Autopsy and TCTutils. Version 2.00 has a new internal design
and has live analysis features (see below article). If you can't
wait for a few days and want one of the beta copies, let me know.
Guido Metzner has been translating The Sleuth Kit Informer into
German. If anyone else is translating this, let me know and I'll
add a link.
http://www.guframe.de/sleuthkit.html
I started to provide a GPG signature of the source code as it is
released. I have meant to do this for ages. This can help to
ensure that the code being downloaded has not been modified by an
attacker.
CALL FOR PAPERS
--------------------------------------------------------------------
I posted a call for papers on the website in late January for
people that are interested in writing articles for the Informer.
Here is the relevant section:
The Sleuth Kit Informer is looking for articles on open source tools
and techniques for digital investigations (computer / digital
forensics) and incident response. Articles that discuss The Sleuth
Kit and Autopsy are appreciated, but not required. Example topics
include (but are not limited to):
- Tutorials on open source tools
- User experiences and reviews of open source tools
- New investigation techniques using open source tools
- Open source tool testing results
http://www.sleuthkit.org/informer/cfp.html
Writing these articles takes away from my development time of new
tool features, so any help is appreciated. To keep with the incident
verification theme, any articles on the basics of using 'netstat',
'lsof', etc. to look for signs of an intrusion are also welcome for
the next few issues. If we get enough interest, I'll consider going
back to a monthly schedule.
DID YOU KNOW?
--------------------------------------------------------------------
Have you ever noticed that the number of occurrences and locations
of keywords for regular expressions in Autopsy are not always
accurate? This came up on one of the mailing lists this past month
and I'll explain it again here.
Previous issues of The Informer have covered keyword searching, but
the general idea in Autopsy is that it runs the 'strings' command
on the image file and then uses 'grep' to find the keyword. The
'strings' command returns a long ASCII string that grep examines.
If the keyword is found in the string, then grep fill flag the
string and autopsy will search the string to find the exact location
of the keyword.
This is easy if a non-regular expression is used, but much more
difficult with regular expressions because 'grep' regular expressions
are different from Perl regular expressions. I do not have a way
to convert the grep regular expression to Perl and therefore I only
return the number of big strings that have the keyword and the
location of the start of the big string. There could be more than
one keyword in the string, in which case the total occurrences value
is too small. The location will also be off because it points to
the start of the large string and not the specific keyword.
If anyone knows of, or wants to write, a grep to perl regular
expression converter, let me know so that we can update this.
UNIX INCIDENT VERIFICATION WITH AUTOPSY
--------------------------------------------------------------------
INTRODUCTION
For a couple of years, I have been saying that Autopsy can be used
to analyze a live system, but it has taken me a while to make it
EASY to use to analyze a live system. When version 2.0 of Autopsy
is released later this week, you will find that it is much easier
to configure so that it runs on a CD-ROM so that you can examine a
system that is suspected of being compromised. This will allow you
to view files that are hidden by rootkits and will not change the
access times on files that are viewed.
This article will give an overview of how to use the new features
and what features are available for dead analysis are not for live
analysis. I will also show the future work for Autopsy. This
article uses many of the same concepts as the "UNIX Incident
Verification with The Sleuth Kit" article in issue #10 of the
Informer.
MOTIVATION
Some may be asking "why would I want a live analysis feature?".
The primary motivation is for a more automated Incident Verification
procedure. We saw in issue #10 of the Informer, that The Sleuth
Kit can be used to verify an incident because it can show files
that are hidden by rootkits and will not update the access times
on files when they are read. Executing a bunch of command line
tools is tedious though and Autopsy can provide a more automated
investigation procedure.
The basic scenario is that Autopsy and The Sleuth Kit will be burned
to a CD and inserted into a suspect computer. An investigator will
connect to Autopsy on the suspect UNIX computer with her HTML browser
on a trusted laptop and remotely examine the hard disk contents.
If the computer is found to have been compromised, then it can be
taken offline and acquired using normal procedures.
Recall from issue #10 that I used two guidelines for incident
verification:
1. Minimize the amount of trust that you place in the system so
that more accurate information is collected.
2. Minimize the amount of data that you change on the system so
that evidence is preserved.
CREATING THE CD
To satisfy guideline #1 from above, we want to minimize the amount
of trust that we place in the system, so we use our own executables.
At a minimum, we need The Sleuth Kit and Autopsy on the CD and you
will probably have additional tools to examine open network ports
and running processes. This has been the most difficult part of
using Autopsy for live analysis because Autopsy relies on a given
directory structure and locations that it can write to.
It is now very easy with v2. With v2, you compile TSK and Autopsy
on a similar system to the one that will be investigated just like
you do for a dead analysis. Try the 'make static' with TSK to see
if you can make static executables for your platform. After both
Autopsy and TSK have been compiled, you execute the 'make-live-cd'
command in Autopsy. This script will make a 'live-cd' sub-directory
in the autopsy directory, which contains a copy of autopsy and
copies of TSK executables, grep, strings, perl etc:
# ./make-live-cd
Making base directory (./live-cd/)
Copying executables
Copying autopsy files
Creating configuration file using existing settings
The 'live-cd' directory has a 'bin' directory where additional
executables can be copied to and then the whole directory can be
burned to a CD.
BASIC USAGE
After the CD has been created and there is a system suspected of
being compromised, then it is time to take advantage of the new
features. There are two scenarios for live analysis. The first
scenario uses a network share from a trusted system that you can
write to. In this case, autopsy is run as normal and you specify
the evidence locker directory as the mounted disk. The evidence
locker is specified with '-d':
# ./autopsy -d /mnt/ev_lock 10.1.32.123
The above would start autopsy, use '/mnt/ev_lock/' as the evidence
locker and would allow connections from 10.1.32.123 (where the
investigator would connect from using an HTML browser). Remember that
we do not want to write to the suspect system, so we should only use
a network share and not a local directory in this scenario.
The second scenario does not use an evidence locker and does not
intentionally write any data to disk. This scenario does not need
the network share and each of the devices (or partitions) that will
be analyzed are specified on the command line using the '-i' flags.
The '-i' flag requires three arguments: the device, the file system
type, and the mounting point. For example, to examine the '/dev/hda5'
and '/dev/hda8' partitions on a Linux system, the following could
be used:
# ./autopsy -i /dev/hda5 linux-ext3 / -i /dev/hda8 linux-ext3 /usr/ \
10.1.32.123
The file system type must be one of the types that are supported
by TSK. The remote IP address must also be given, otherwise you
will have to use a browser on the suspect system and that will write
data to the disk.
When you use the '-i' flag, then autopsy will start in the 'Host
Manager' view where you can select the image that you want to
analyze. You will skip the case and host configuration. The default
case name will be 'live', the default host name is 'local', and the
default investigator name is 'unknown'.
DIFFERENCES WITH DEAD ANALYSIS
There are some features that are not available for live analysis
because they write files to the disk. In this section, I am using
the term live analysis for the scenario where there is not a mounted
network share and there is not evidence locker.
No auditing is performed during a live analysis because there is
no where to write the logs. In the future, if this is needed, then
a method of writing logs to a floppy disk could be configured.
Timelines of file activity cannot be created because they need to
create files. Hash databases are also not currently used, although
they could in the future. It may be difficult to maintain the
latest hash database on the same CD as the latest autopsy and TSK
version though. Notes and event sequencer notes cannot be created.
Keyword searches can be performed, but the strings file and unallocated
only search cannot be performed because they both require a file
to be created. The search results are also not cached. You can
also not sort files by their type (all executables, all pictures
etc.). In many cases, you would not want to do many of these
operations because they are time intensive and you are generally
looking for obvious and quick evidence during the incident verification.
If you need theses features, then you can use the network share
scenario.
SIMILARITIES WITH DEAD ANALYSIS
Now that we know what is different, I'll cover what is the same.
All of the file mode analysis is the same, except that you cannot
get the file type. The method that is used to compile 'file' in
TSK does not allow autopsy to easily move it around. This behavior
may change in the future. Meta data, data unit, and file system
mode all work as usual.
You can still export file contents to your trusted laptop because
it uses the HTTP to save the file. So, you can select the export
button on a log file to save a copy. You can also generate ASCII
reports and save them to your local analysis station.
GUIDELINE COMPLIANCE
All of these features may sound great, but lets examine how well
the new Autopsy satisfies the two guidelines. I think it is always
important to compare a new tool or technique against generic
guidelines.
The first guideline was about not trusting the local system. No
software-based live analysis tool can be 100% independent from the
local system because it always needs to request service from the
operating system. With Autopsy, we use our own copies of the Autopsy
perl code, TSK executables, grep, and strings.
There is one large problem with the current Autopsy model and it
is because of Perl. Perl is a beast and contains many modules and
libraries. When the 'make-live-cd' script is run, a copy of the
'perl' executable is copied to the 'live-cd' directory, but that
is it. The executable will still need the modules and libraries
on the local system. Solving this may require building a special
version of Perl that is more static. I need to investigate this
more.
Another method of getting around this limitation is to use the
'perl2exe' program that converts a Perl script to a dynamic executable.
The resulting executable will still rely on dynamic libraries on
the suspect system, but it seems a little cleaner. The perl2exe
program is a commercial tool.
One of the benefits of the Autopsy design, is that Autopsy did not
exist on the system when it was suspected of being compromised.
Therefore, the attacker will not know that Autopsy will be used to
investigate the system and therefore will be less likely to tamper
with its dependencies. If the investigation tools are running on
the system during the attack, then I would guess that the attacker
will be more likely to tamper with them.
The second guideline was about modifying data on the system. I
described the features that were removed in the previous section.
This was easy to do because there were functions that write the
logs or notes. Each of those starts with a check to see if logging
is enabled. Timelines and file type sorting were also disabled
because it required writing to disk.
I can never guarantee that no data will be written from a live
analysis. Memory will be overwritten when the software is loaded
and the access times on dynamic libraries will updated. Running
the tools may require the operating system to write memory to the
page file, which may overwrite data from the attacker.
This is a shameless plug, but for those that are interested in live
analysis, then you may want to check out a paper that a colleague,
Joe Grand (author of pdd), and I wrote about a hardware device to
acquire memory from a live system. It does not overwrite memory
because there is no process to load and it access the physical
memory directly so it does not rely on the local operating system.
It was recently published in the new Journal of Digital Investigation
(reference is below and that issue of the journal is currently free
to view).
FUTURE WORK
There is always more to do, and I'll cover that here.
I would like to also include other system utilities, such as 'ps' or
'netstat' on the CD and allow the Autopsy user to run the commands
from within autopsy. This should be fairly easy, but the difficult
part is that many of the operating systems use different flags for
different tools.
I would like to start incorporating scripts into the tool (for both dead
and live analysis). This will allow you to more easily detect rootkits
or other signatures.
The biggest thing that needs future work is using Perl. Autopsy
still relies on the version of Perl on the suspect system and that
could run into problems if an attacker modifies it. Using the
perl2exe tool can reduce the risk, but it is a commercial tool.
CONCLUSION
The live analysis mode of Autopsy allows you to more easily analyze
a system that is suspected of being compromised. It can also be
used to examine a honeypot. Live analysis is not ideal because you
are stilly relying on the suspect operating system for data, but
it is required in some situations. More work needs to be done with
Autopsy so that it depends less on the local system.
REFERENCES
Autopsy
http://www.sleuthkit.org/autopsy/
perl2exe
http://www.indigostar.com/perl2exe.htm
Sleuth Kit
http://www.sleuthkit.org/sleuthkit
Sleuth Kit Informer #10
http://www.sleuthkit.org/informer/sleuthkit-informer-10.html
A hardware-based memory acquisition procedure for digital investigations
Brian D. Carrier and Joe Grand
Volume 1, Issue 1 - Journal of Digital Investigations
http://www.sciencedirect.com/science/journal/17422876
--------------------------------------------------------------------
Copyright (c) 2004 by Brian Carrier. All Rights Reserved

19
global.css Normal file
View File

@ -0,0 +1,19 @@
h3 {
font-size: 18px;
color: #000000;
}
h2 {
font-size: 20px;
color: #000000;
}
h1 {
font-size: 24px;
color: #000000;
}
body {
font-family: Helvetica, Geneva, Arial, sans-serif;
font-size: 14px;
color: #000000;
#background-color: #dedede;
}

25
help/blank.html Normal file
View File

@ -0,0 +1,25 @@
<HTML>
<HEAD><TITLE>Blank Page</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
&nbsp;
<p>
&nbsp;
<p>
&nbsp;
<p>
<center>
<h3>HELP!</h3>
Here are the help files for using Autopsy.
<p>In addition to these files, the <tt>Sleuth Kit Informer</tt>
newsletter could be useful.<br>
The Informer typically goes into more technical details than what
is provided here.</p>
<p><a href="http://www.sleuthkit.org/informer/" target=\"_blank\">
http://www.sleuthkit.org/informer/</a></p>
<p>Send documentation updates to &lt;doc-updates at sleuthkit dot org&gt;</p>
</BODY>
</HTML>

161
help/caseman.html Normal file
View File

@ -0,0 +1,161 @@
<HTML>
<HEAD><TITLE>Autopsy Case Management Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Case Management</H2></CENTER>
<P>
<H3>Overview</H3>
Autopsy organizes images based on the case and host that they came
from. A case contains one or more hosts (a new case should be
created for each investigation). Each host can contain one or more
images, which correspond to disks or partitions on the host.
<P>
<H3>Creating a New Case</H3>
From the Main Menu (at startup) select <U>New Case</U>. You will
have to enter the case name and an optional short description.
The case name must be a valid directory name (no spaces - no
symbols). A list of investigators will also be requested. These
will be used for the audit logs, not for authentication. A directory
with the same name as the case will be created in the Evidence
Locker. To later rename the case, simply rename the directory.
<P>
For example:
<TABLE CELLSPACING=8>
<TR>
<TD>Case Name:</TD><TD><TT>bankofmars</TT></TD>
</TR>
<TR>
<TD>Case Description:</TD><TD><TT>Theft of $1,000,000,000.01 from The Bank of Mars</TT></TD>
</TR>
<TR>
<TD>Investigators:</TD><TD><TT>gadget</TT></TD>
</TR>
</TABLE>
<P>
<H3>Adding a New Host</H3>
A Host must then be created in the Case. Select the Case that was
just created from the Case Gallery and enter the Host Gallery.
Select <U>Add Host</U> and enter the host name, a short description,
and time information such as time zone and clock skew. The clock
skew is how many seconds the system was off from a synchronized
clock. Adding a host will create a directory in the case directory
and subdirectories in the host for the images, output data, logs,
and reports. If you do not add a time zone, then it will default to
the time zone of your analysis system. A list of time zones can be
found <a href="timezones.html">here</a>.
<P>
You can optionally add the path to <A HREF="hash_db.html">hash databases</A>.
<P>
For example, the 'Bank of Mars' incident could have two hosts
involved:
<TABLE CELLSPACING=8>
<TR>
<TD>Host Name:</TD><TD><TT>db_server</TT></TD>
</TR>
<TR>
<TD>Host Description:</TD><TD><TT>Main Database Server - Solaris</TT></TD>
</TR>
<TR>
<TD>Timezone:</TD><TD><TT>EST5EDT</TT></TD>
</TR>
<TR>
<TD>Timeskew:</TD><TD><TT>-100</TT></TD>
</TR>
<TR>
<TD>Known Good Database:</TD><TD><TT>none</TT></TD>
</TR>
<TR>
<TD>Known Bad Database:</TD><TD><TT>none</TT></TD>
</TR>
</TABLE>
<P>
<TABLE CELLSPACING=8>
<TR>
<TD>Host Name:</TD><TD><TT>file_server</TT></TD>
</TR>
<TR>
<TD>Host Description:</TD><TD><TT>Windows File Server - Win 2k</TT></TD>
</TR>
<TR>
<TD>Timezone:</TD><TD><TT>CST6CDT</TT></TD>
</TR>
<TR>
<TD>Timeskew:</TD><TD><TT>0</TT></TD>
</TR>
<TR>
<TD>Known Good Database:</TD><TD><TT>/usr/local/forensics/hash/win2k.txt</TT></TD>
</TR>
<TR>
<TD>Known Bad Database:</TD><TD><TT>/usr/local/forensics/hash/win_hack.txt</TT></TD>
</TR>
</TABLE>
<P>
<H3>Adding a New Image</H3>
Next, images must be added to the host. Select the host that was
just added from the Host Gallery and enter the Host Manager. Select
<U>Add Image File</U> and a new form is shown. The first text box in
the form is for the path of the image file. If you are importing a
split image, then the extension must be ordered based on the file order.
Supply a '*' in the file name extension where the numbers or letters are.
(i.e. .../image.*). The image file can be
of a full disk or of an individual partition. You must select which
it is though. Before they can analyzed, the images will have to
be located in the evidence locker. You are given a choice to either
create a symbolic link from the current location, to copy the file,
or to move the file from its current location to the host directory.
Select the desired import method. For example:
<TABLE CELLSPACING=8>
<tr><td>Image Path:</TD><TD><TT>/mnt/sys1/disk2.*</TT></TD></TR>
<tr><td>Type:</td><td><tt>Disk</tt></td></tr>
<tr><td>Import Action:</TD><TD><TT>symlink</TT></TD></TR>
</table>
<p>
If you are importing a split image, then the next window will confirm the
order of the images. After that, the next window will allow you to specify
or calculate the MD5 for the file. This should be of the full file and if you
are importing a split image then it should be for all files combined.
If you are importing a volume image, then Autopsy will try to determine the
file system type. You will also need to specify the mounting point. This is used for cosmetic purposes only when printing the full path of files.
<p>
If the image file is a disk image then Autopsy will list all of the partitions and try to determine the file system in each one. You have the option to not import a partition and to change the file system type.
<P>
<H3>MD5 Values</H3>
Each host has an <TT>md5.txt</TT> file that contains
the MD5 value for files in that directory. Autopsy uses that file
to validate the integrity of files. By default, when a file is
imported into Autopsy, its MD5 will be calculated. If it is already
known, then it can be entered in the 'Add Images' window.
<P>
<H3>Host Subdirectories</H3>
Each host has an <TT>images</TT> directory and an <TT>output</TT>
directory. All data generated by Autopsy is saved to the <TT>output</TT>
directory. The theory behind this design, was to allow the <TT>images</TT>
directory to have strict permissions to prevent accidently modifying
the images. Therefore, the <TT>images</TT> directory can have its write
bits removed to prevent modifications.
<p>
<h3>References</h3>
Issue 2 of <a href="http://www.sleuthkit.org/informer/" target=\"_blank\">The Sleuth Kit Informer</a> discusses case management and how to break a disk image into file system images.
<P><HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

97
help/data_mode.html Normal file
View File

@ -0,0 +1,97 @@
<HTML>
<HEAD><TITLE>Autopsy Data Unit Analysis Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Data Unit Analysis</H2></CENTER>
<H3>Overview</H3>
<P>
The Data Analysis Mode allows an investigator to view the contents
of an individual data unit. Data units is a generic term used to
describe the areas on the disk that are used to store data. Each
file system calls the data unit a different thing (i.e. Fragments
or Clusters). This mode is most useful when recovering and analyzing
deleted data.
<H3>Input</H3>
<P>
To view the contents of a specific address, enter it into the text
box on the left-hand side. By default, only one data unit will be
displayed. To view more than one consecutive unit, enter the
number in the text box below.
<P>
It is common to extract the unallocated space from a file system
image and analyze it for deleted material. The 'blkls' tool in The
Sleuth Kit allows one to extract the data. If interesting data is
found in the 'blkls' file, the next step could be to find its location
in the original image and examine the surrounding data. To do
this, simply calculate which data unit the data was found in (by
dividing the byte offset of the interesting data by the data unit
size (which can be found in <U>Image Details</U>)). Enter that
address into the original text box and select the <U>Unallocated</U>
type. This will find the original location and display it for you.
<P>
If Autopsy knows about the 'blkls' image, then it can be loaded at any
time by selecting the <U>Load Unallocated</U> button. Then, any
data unit in that file can be examined.
<P>
The <B>Lazarus</B> tool was part of <TT>TCT</TT>. It analyzes a chunk
of data and identifies what file type it is and tries to group
consecutive types together. Lazarus numbers its output though starting
with 1. Therefore, instead of subtracting 1 every time you want to view
a data unit identified by Lazarus, simply select the check box.
<P>
Press the <U>Ok</U> button to display the contents of the address on
the right-hand side of the window.
<P>
The <U>Allocation List</U> link displays the allocation status of
addresses in intervals of 500.
<H3>Viewing</H3>
<P>
After the unit address has been entered, the contents are displayed
in the right-hand side. Filters can be used to view the data in the
desired format (strings, hexdump, ASCII).
<P>
A report can be generated so that the contents and meta-data about
it will be saved on record. To save the contents locally, press the
<U>Export Contents</U> button. The <U>Add Note</U> button will allow
one to add a comment about the given data unit so that it can be
easily recalled later.
<P>
The file type is also displayed. This is identified by running
the output through the 'file' command in The Sleuth Kit.
<P>
Autopsy will try to find the meta-data structure that allocated
the unit and display both its address and a file name. This process
is very slow for FAT file systems, so this process is not done by
default during analysis.
<H3>FAT Notes</H3>
<P>
The Sleuth Kit and Autopsy do not use clusters when dealing with a FAT image.
Only sectors are used. The reason is because FAT does not start
addressing clusters until many sectors into the file system. If
clusters were used to address data units, then there would be no
way to address the sectors in the FAT and secondary FAT. Therefore,
sectors are used for all addresses. NTFS changed the way clusters
were addressed and do not have this problem. See the documentation
in The Sleuth Kit for more details.
<P>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

99
help/file_category.html Normal file
View File

@ -0,0 +1,99 @@
<HTML>
<HEAD><TITLE>Autopsy File Category Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>File Category Type Analysis Help</H2></CENTER>
<H3>Overview</H3>
Analyzing large file system images can be very daunting. One way
of identifying files that should be examined is to sort the files based
on file type. This mode of Autopsy will allow one to sort the files
in an image based on type and to exclude known files (i.e. data
reduction). It also allows one to flag files that are known to be bad.
<H3>Procedure</H3>
The <TT>sorter</TT> document in the <TT>docs</TT> directory of The
Sleuth Kit has more details on the details, but this will provide
an overview of the interface given by Autopsy.
<P>
The first step is to <U>Sort</U> the image. There are several
options to choose when doing this. The <TT>sorter</TT> tool from
The Sleuth Kit will perform the sorting. There are two major
actions that <TT>sorter</TT> can do: sort files by type and validate
extensions.
<P>
By default, Autopsy will perform both actions. If you do not want
it to do a given action, deselect it.
<P>Within sorting, there are two options:
<UL>
<LI> The first is to save the output. By default,
details about each file will be added to a category file. For
example, a JPEG image will have the meta data address and image
name saved to the <TT>images</TT> file. By selecting the <U>Save</U>
option, a directory will be created for each category and a copy
of the files will be saved. This could require lots of disk space
(as much as the original image size).
<LI> The second option is to save unknown file types. There are
configuration files that contain rules about common data types. If
a file is encountered that does not have a rule, it is added to an
<TT>unknown</TT> file. If this is not desired, select the <U>Do Not
Save Unknown</U> option.
</UL>
<P>
During the sorting process, the <TT>sorter</TT> tool will also examine
the extension of the file. If the file type is known, it has known
extensions, and the file does not have one of those extensions, it will
be added to a <TT>mismatch</TT> file. This can be deselected if it is
not wanted.
<H3>Hash Databases</H3>
One easy way of data reduction is to use hash databases. The <TT>sorter</TT>
tool can use three different hash databases. Each can be configured
within Autopsy and used in other screens.
<UL>
<LI><B>NIST NSRL</B>: The NIST NSRL contains hashes of trusted operating
systems and programs. This is used to ignore known files. Files found
in the NSRL will not be included in the file categories (to save time
when reviewing the files). If the file is in the NSRL and has an
extension mismatch, it will be noted in a special file.
<LI><B>Ignore Database</B>: This database must be created by the user
and added to the host. It is similar to the NSRL in that it contains
hashes of known good files. They will be ignored in the same way that
those from NSRL are.
<LI><B>Alert Database</B>: This database must also be created by the
user and added to the host. It contains hashes of files that are
known to be bad and should identified if found in the image. This would
include known rootkits or photographs. Hits from this databases are
found in the <TT>alert</TT> file.
</UL>
<P>
More details can be found in the <A HREF="hash_db.html">Hash
Database</A> Help.
<H3>Output</H3>
Currently, there is no way to view the output from within Autopsy.
All data can be found in the <TT>output</TT> directory of the host.
A directory is created for the <TT>sorter</TT> output. View the
<TT>index.html</TT> file and it contains links to the other files.
<p>
<h3>References</h3>
Issues 3, 4, and 5 of <a href="http://www.sleuthkit.org/informer/" target=\"_blank\">The
Sleuth Kit Informer</a> discussed using the 'sorter' tool.
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

221
help/file_mode.html Normal file
View File

@ -0,0 +1,221 @@
<HTML>
<HEAD><TITLE>Autopsy File Analysis Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>File Analysis</H2></CENTER>
<H3>Overview</H3>
The File Analysis mode allows one to analyze an image from the file
and directory perspective. This provides the same interface that users
typically use with a normal computer. This mode will also display
information about deleted files though.
<P>
This mode will allow one to examine the contents of files and directories
for evidence. It even allows one to perform basic binary analysis by
extracting the ASCII strings from a binary file. The files can also
be sorted by any field.
<H3>Directory List</H3>
<P>
The left-hand side window has four main options:
<UL>
<li>Directory Seek
<li>File Name Search
<LI>Hide / Expand Directories
<LI>Show All Deleted Files
</UL>
<P>
By default, the directory listing is not shown when this mode is
first entered. By select the <U>Expand Directories</U> button,
the full list of directories will be shown. The number of '+'
symbols represent the depth of the directory. As this is an HTML
interface and there is no state management occurring (no cookies
or session id), it would be difficult to have an interface where
one or more directories are expanded yet the rest are collapsed.
<P>
Selecting the <U>All Deleted Files</U> link will display all of the deleted
files in the image on the right-hand side.
<P>
There is a text box where a directory (or file) name can be
entered and it will be displayed on the right-hand side. This
makes it easy to jump to a directory without going through the
directory listings. For example, to seek to the 'windows\system32'
folder, you can enter that string into the box instead of scrolling
through the directories.
<p>
There is also a text box where a pattern of a file name can be
entered and all files that match that pattern will be displayed on
the right-hand side. The search pattern is a Perl regular expression,
so some values, such as '.' or '*' will need to be escaped. The
search is done case insensitive. To find all files that have a JPG
extension, the following could be used "\.jpg". Or to find all files
that begin with a dot, then we could use "^\.".
<H3>Directory Contents</H3>
<P>
The window in the upper right-hand side contains the directory
contents. In a file system, a directory allocates data units on
the disk and fills the data units with structures that contain the
name of the file and the address of the meta data structure. This
view parses the file name structures in the directory. It is filled
by either selecting a directory from the left-hand side directory
list or a directory from within the same window. The entries can
be resorted by clicking on any of the header values.
<P>
The column headers have the following definitions:
<UL>
<LI><B>del</B>: A check in this column represents a deleted file.
See below for a discussion on the different color types of deleted files.
<LI><B>Type</B>: This column contains the "type" that the file or
directory is. There are two values. The first (<TT>dir</TT>) is the
type according to the directory entry structure. The directory entry
is where the file name is located. The second value (<TT>in</TT>) is
the type according to the meta data structure.
These should be the same except
for deleted files. They are both given to help the investigator
identify if a deleted file has been reallocated or not. For example,
if the meta data structure type is different than the file name
type, then it is likely that one of the structures was reallocated for
a new file.
<LI><B>Name</B>: The name of the file or directory. Clicking on the
name displays file contents in the bottom window or directory contents
in the same window. For deleted files, no link will exist if the meta
data structure address
has been cleared (which many OS do). To identify the destination of
a UNIX symbolic link,
click on the address at the end of the row. Note that the name
will not be a link if the size of the file is 0 or if the meta data
structure is unknown.
<LI><B>Modified Time</B>: This column exists for UNIX and NTFS file
systems. It shows the last time that the file data was last modified.
In other words, when was data last written to the data units allocated
by the file. In UNIX, the <TT>utimes()</TT> function can modify this
value vary easily.
<LI><B>Written Time</B>: This column exists for FAT file systems and
is the time when the file was last written to. Of the three times,
this is the only value that is required by the FAT specification.
<LI><B>Accessed Time</B>: This column contains the last accessed time of
the file data. On a FAT image, this value is optional and is only
accurate to the day (not hours or seconds). This value can be
modified by the utimes() function in UNIX.
<LI><B>Changed Time</B>: This column exists for UNIX and NTFS file
systems. It is the last time that the file status (or meta data) was
changed. This is different than the Modified time because modified
deals with the file data and this deals with the descriptive data
in the inode or MFT entry. This value cannot be changed by the
<TT>utimes()</TT> function in UNIX.
<LI><B>Created Time</B>: This column exists for NTFS and FAT file systems. It
is the time when the file was created. According to the FAT spec,
it is an optional time.
<LI><B>Size</B>: The size of the file. Note that if the size of the
file is 0, no link will be shown with the name.
<LI><B>UID</B>: The User ID of the file owner.
<LI><B>GID</B>: The Group ID of the file owner.
<LI><B>Meta Data</B>: The file name structures contain a pointer to
the meta data structure that describes the file. This column contains
the address of the structure. Selecting this value
will display the details in the bottom window.
If the value is invalid, then a link will not exist. If it is for
a deleted file name that has a meta data structure with an allocated
status, a "realloc" string will
exist to identify this.
</UL>
The <U>Add Note</U> link allows you to make a comment about this directory and
have it saved in your personal notes file.
<P>
The <U>Generate MD5 List</U>
link will generate the MD5 value for every file in the directory and
allow you to save it as a text file. Using fingerprint data bases,
This makes it easy to check for files that were modified by an attacker.
<P>
The path on top of the window has hyperlinks in it that allow the
user to easily change to a previous directory.
<P>
There are two different colors used for deleted files. The difference
is based on the status of the data structures in the file. A <FONT
COLOR="red">bright red</FONT> entry means that the file
name data structure is not allocated and the meta data structure
that it points to is also not allocated. This is what we would
expect of a recently deleted file. This means that we can trust
the data we are seeing as long as the meta data structure was not
allocated and unallocated since the deletion. If it is <FONT
COLOR="#800000">darker red</FONT>, then the meta data
structure has been reallocated and the data is most likely not
accurate.
<P>
The file size reported by the meta data structure is very important
with The Sleuth Kit. The Sleuth Kit uses this value to identify
how many data units to display. If this size is 0, but the meta
data structure points to data blocks still, they will not be shown.
You can force Autopsy to display the values by selecting the meta
data address and using the 'force' option.
<P>
To look a file up in one of the <A HREF="./hash_db.html">Hash
Databases</A>, then select the meta data address. That view will
provide an interface to the databases.
<H3>File Contents</H3>
<P>
The lower right-hand side window displays the contents of a specified
file. The contents can be viewed in either the raw format (which your
browser will not likely display much of if the file is non-ASCII) or
through 'strings'. The strings option is helpful for a quick analysis
of a binary file.
<P>
Also shown is the file type. This is determined by running the 'file'
command on the output. It uses the magic header and footer values to
guess the file type. If the file type is an image or HTML, an option
will exist to <U>View</U> the data in its interpreted form (i.e. as
a picture or as a web page instead of the raw data). Note that
any HTML that is viewed will be processed in a sanitized environment
that does not load pictures and will not allow one to connect to a
remote site. To view the native picture, select 'Export' and open
the HTML document in another browser. Refer to issue #1 of The Sleuth
Kit Informer for more details on the sanitizing.
<P>
The <U>Report</U> options create ASCII reports that contain the file
contents as well as data such as MD5 values and dates.
<P>
The <U>Export</U> button extracts the file out of the image so you can save it
locally and use other tools on it.
<P>
The <U>Add Note</U> button adds a personal note to the investigator log for
future reference.
<p>
<h3>References</h3>
Issue 1 of <a href="http://www.sleuthkit.org/informer/" target=\"_blank\">The Sleuth
Kit Informer</a>.
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

46
help/fs_mode.html Normal file
View File

@ -0,0 +1,46 @@
<HTML>
<HEAD><TITLE>Autopsy Image Details Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Image Details</H2></CENTER>
<P>
<H3>Overview</H3>
Sometimes there are details about an image that do not correspond to
any file in particular. Those details can likely be found in this
mode. This mode gives the general details of the image and therefore
the contents will vary depending on the file system type.
<P>
<H3>FFS & EXT2FS</H3>
For the UNIX file systems, this mode will contain the details from
the super block. This generally includes times that the file system
was last mounted and any special flags. It also has the range of
inode addresses and fragment addresses. For advanced file recovery,
you can also identify the group layout and on-disk structure details.
These could be useful for restricting where you search for data.
Files will allocate blocks and fragments in the same Cylinder or
Block group as their inode is in, so your attention can be restricted
to that area.
<P>
<H3>FAT</H3>
For FAT file systems, this mode will contain the File Allocation
Table. It will have the cluster runs, which can be selected to
view their contents in <A HREF="data_mode.html">data unit</A>
analysis mode. Or, if the file is fragmented, the pointer can
be selected and the screen will link to the next cluster chain.
<P>
<H3>NTFS</H3>
The unique information for an NTFS image is the numerical type
associated with attributes. These values can be dynamic and this
area will identify what they are for that file system.
<P>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

103
help/general.html Normal file
View File

@ -0,0 +1,103 @@
<HTML>
<HEAD><TITLE>General Autopsy Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>General Autopsy Help</H2></CENTER>
<P>
The Autopsy Forensic Browser is a graphical interface to command
line forensics tools and standard UNIX utilities. It allows
you to perform volume and file system analysis on UNIX and Windows systems.
<P>
All data are saved in a directory in the Evidence Locker, which
was specified at install time or at run time. See
<A HREF="caseman.html">Case Management</A>
for more information. In the normal mode, Autopsy imports an
image file from a disk or partition. In the live mode, Autopsy
can analyze a running system and does not save any data to the
local disk.
<P>
The browser has the following modes:
<UL>
<LI>
<B><A HREF="file_mode.html">Files</A></B>:
Allows you to browse the image file as a file system and view the
contents of files and directories. This mode even shows deleted
file names and Alternate Data Streams in NTFS images. You can sort
the files and directories on meta data.
<LI><B><A HREF="meta_mode.html">
Meta Data</A></B>:
Allows you to analyze the image file by examining the meta data structures.
The address of a structure is entered and the details are shown.
This mode is useful for examining unallocated structures and getting
all details about allocated files (including all data units and
other information such as MD5 value).
<LI><B><A HREF="data_mode.html">
Data Unit</A></B>:
Allows browsing by block number. This is most useful when used
with searching or meta data browsing. The contents of the block
can be displayed in ASCII, hex dump, or through <I>strings(1)</I>.
The meta data structure that has allocated the block will be
displayed (if any) along with the file name (if any).
<LI><B><A HREF="srch_mode.html">
Keyword Search </A></B>:
Search an image file using <I>grep(1)</I> for a given string or regular
expression. The result will be a list of data units that have the
string. Each data unit can be selected to view the contents.
<LI><B><A HREF="fs_mode.html">
Image Details</A></B>:
List the details about the file or volume system. The output of
this mode depends on the file system. Examples of the file system
data include the last mount time, the last mount location, and a
detailed break down of block group information or File Allocation
Table contents.
<LI><B><A HREF="int_mode.html">
Image Integrity</A></B>:
The integrity of the data can be validated at any
point by selecting this mode. It uses the values in <TT>md5.txt</TT> to
identify if any data have been modified in the analysis process.
<LI><B><A HREF="tl.html">
File Activity Timelines</A></B>:
Autopsy can create timelines of file activity based on the Modified,
Access, and Change (Create in FAT/NTFS) times (MAC). The timeline
will contain details about deleted and allocated content. The
resulting timeline can be either viewed within Autopsy or using
other text viewing tools (WARNING: many HTML browsers do not handle
large tables like a timeline very well so using a text editor is
recommended).
<LI><B><A HREF="file_category.html">
File Type Categories</A></B>:
Autopsy can sort the files in an image file based on their file type.
For example, all JPEG and GIF files would be identified as images
and all executable files would be identified. This mode will also
ignore files that are found in hash databases of known good files,
identify files that are found in a hash database of known bad files,
and identify files that have an extension that is not consistent
with their file type.
<LI><B>Report Generation</B>:
Each of the above browsing techniques allows a report to be generated.
This report lists the date, md5 value, investigator, and other
context information in a text format. This can be used for record
keeping when deleted blocks of data have been found.
</UL>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

70
help/grep.html Normal file
View File

@ -0,0 +1,70 @@
<HTML>
<HEAD><TITLE>Autopsy grep Cheat Sheet</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>grep Cheat Sheet</H2></CENTER>
<H3>Escaped Values</H3>
Autopsy uses the <TT>grep</TT> utility to search an image. grep requires
that some values be "escaped" if they are searched for. Autopsy
will automatically escape those values if the serach is being done for
a <U>non-regular expression</U>. The escaped values include:
<UL>
<LI>\
<LI>.
<LI>[
<LI>^
<LI>$
<LI>'
<LI>*
<LI>initial -
</UL>
<H3>Regular Expressions</H3>
Refer to the man page for 'grep' for more details of creating regular
expressions. Autopsy uses the '-E' flag with 'grep' to specify
extended regular expressions. The following have special meaning
with grep:
<UL>
<LI><B>[A-Za-z]</B>: Any lower and upper case letter
<LI><B>[:alpha:]</B>: same as above
<LI><B>[0-9]</B>: Any number
<LI><B>[:digit:]</B>: same as above
<LI><B>[0-9A-Za-z]</B>: Any lower and upper case letter or digit
<LI><B>[:alnum:]</B>: same as above
<LI><B>[:space:]</B>: Any white space
</UL>
<P>
To specify how many times something can occur, the following are used:
<UL>
<LI><B>?</B>: Optional and can only occur once
<LI><B>*</B>: Optional and can occur more than once
<LI><B>+</B>: Required and can occur more than once
</UL>
<P>
To specify more than one string to match, use the <B>|</B> operator.
<H3>Examples</H3>
<P>
To search for 'Jane Smith' or 'Jack Smith': (Jane)|(Jack) Smith
<P>
To ensure it matches if a tab is between the first and last name:
(Jane)|(Jack)[:space:]Smith
<P>
To search for 'Jane Smith' or 'Jane Anne Smith':
Jane( Anne)? Smith
<P>
or: Jane([:space:]Anne)?[:space:]Smith
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

75
help/grep_lim.html Normal file
View File

@ -0,0 +1,75 @@
<HTML>
<HEAD><TITLE>Autopsy grep Search Limitations</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2><TT>grep</TT> Search Limitations</H2></CENTER>
<H3>Overview</H3>
<P>
Keyword searches are very basic in Autopsy. Autopsy uses the
<TT>strings</TT> and <TT>grep</TT> tools on the image and when a
hit is found, it uses <TT>ifind</TT> and <TT>ffind</TT> to identify
the file that has allocated the string. This is a very simple and
basic method of searching and is not ideal. This will cause false
positives and will miss data that crosses a fragmented part of a file.
The limitations are outlined in this file.
<H3>What Will Be Found</H3>
<TT>strings</TT> is first run on the image and the data is passed
to <TT>grep</TT> to do the actual search. This process will find
ASCII and UNICODE strings that are consecutive anywhere in the file. This is
frequently referred to as the physical layout. For example, it
will find strings in the middle of an allocated sector, in an
unallocated sector, in slack space, and in meta data strutures.
This will find a string that crosses sectors, which is good if the
two sectors are for the same file.
<P>
This technique leads to several types of false positives. For example,
a string that crosses from the allocated space of a file into the slack
space would be found by <TT>grep</TT>. A string that starts in the slack space
and ends in the allocated space of a file will also be found. A string
that crosses sectors of two different allocated files will also be found. The
user must identify if the hit is an actual hit or a false positive.
<h3>What Will Be Found, but May Be Confusing</h3>
<p>
If you are searching with regular expressions, then the exact
location and number of hits may not be correctly reported. If the
count is incorrect, then it will be too small. If the location
is incorrect, then it will be too early (and could even be in the
next data unit). The reason that this is in accurate is because
the <tt>grep</tt> tool will return a long string to Autopsy that
will contain one or more occurances of the keyword. Autopsy can
not search the long string to find the exact number and location
of the regular expression keywords like it can for non-regular
expression keywords, so it returns only the starting location of
the long string.
<H3>What Will NOT Be Found</H3>
The biggest category of 'hits' that will not occur using this technique
is strings in a file that cross fragmented data units. For example, consider
a file that has two clusters allocated, cluster 100 and cluster 150. A
string "mississippi" could have "missi" in the final 5 bytes of cluster 100
and "ssippi" in the initial 6 bytes of cluster 150. The string exists from
the logial level, but not at the physical level. Therefore, the <TT>grep</TT>
search would not find the string.
<P>
Although not because of <TT>grep</TT>, Autopsy will also not find
data in the slack space during an unallocated-only search. The
extraction tool for The Sleuth Kit (<TT>blkls</TT>) differentiates
between unallocated sectors in FAT and NTFS and slack space. There
is currently no way in Autopsy to extract the slack space and search
it. Autopsy currently only extracts the unallocated sectors and not
the allocated sectors that may have deleted data in them.
<H3>Conclusion</H3>
Autopsy has basic keyword search functionality. Future versions may provide
more features and better search results. In the mean time, it is important
that users understand the abilities and limitations of the tool so that they
can be taken into account during the investigation.
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

141
help/hash_db.html Normal file
View File

@ -0,0 +1,141 @@
<HTML>
<HEAD><TITLE>Autopsy Hash Database Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Hash Database Help</H2></CENTER>
<H3>Overview</H3>
Hash databases are used to quickly identify known good and known
bad files using the MD5 or SHA-1 checksum value. Autopsy uses
three types of hash databases to help the investigator reduce the
number of files that they have to look at.
<P>
The <B>NIST National Software Reference Library (NSRL)</B> contains
hashes of files that are found in operating systems and software
distributions. These files are <I>known to be good</I> in that they came
from trusted sources and are typically on authorized systems. When
processing files in the image, this database can be used to ignore
files because they are assumed to be known and therefore uninteresting.
The location of this database is configured when Autopsy is installed.
The NSRL must be obtained from NIST at <TT>www.nsrl.nist.gov</TT>.
<P>
The <B>Ignore Database</B> is a database that the investigator must
create. It is similar to the NIST NSRL in that it contains files
that are <I>known to be good</I> and can be ignored if the user
chooses to do so (only applicable when in <A HREF="file_category.html">File
Type Category Analysis</A>). Examples of files in this category include
system binaries for standard builds. See <A HREF="#db_create">Database
Creation</A> for information on creating this database. Its location
is configured when the host is created and can be edited in the
host configuration file.
<P>
The <B>Alert Database</B> is a database that the investigator must
create. It contains hashes of <I>known bad</I> files. These are
the files that an investigator wants to know about if they exist
on the system. Examples of this include rootkits or unauthorized
photographs.
When using the <A HREF="file_category.html">File Type Category
Analysis</A>, these files will be saved in a special file. See <A
HREF="#db_create">Database Creation</A> for information on creating
this database. Its location is configured when the host is created
and can be edited in the host configuration file.
<H3>Database Uses</H3>
Autopsy uses the hash databases in three ways.
<UL>
<LI><B><A HREF="file_category.html">File Type Category Analysis</A></B>: The
hash databases are used to identify the <I>known bad</I> files and
ignore the <I>known good</I> files.
<LI><B><A HREF="meta_mode.html">Meta Data Analysis</A></B>: The hash
databases can be used to identify a file from the meta data view. If
the databases are configured, the hash from a given file can be looked
up by pressing the 'lookup' button.
All three databases can be used in this view. This view can be found
from the File Analysis mode by selecting the meta data address in
the directory listing window.
<LI><B>Hash Database Manager</B>: From the Host Gallery view,
the Hash Database Manager can be entered. This is where one can
re-index the databases and perform single lookups in any of the
databases.
</UL>
<A NAME="db_create">
<H3>Database Creation</H3>
Currently, Autopsy will only allows one to look entries up in a
hash database. It does not allow one to easily create a database,
but this will describe the process (it is quite simple).
<P>
Autopsy uses the <TT>hfind</TT> tool from The Sleuth Kit to do the
lookups. This tool requires the database to be indexed so that it
can perform a fast lookup using a binary search algorithm (instead
of a slower sequential search that a tool like grep would do).
When ever a hash database is updated (or created), it must be
indexed. This can be done in Autopsy in the Hash Database Manager
(Note that the database must already be configured though).
<P>
The NIST NSRL obviously does not have to be created, but it does have
to be indexed before it is used.
<P>
To make a hash database, we will create a file with the same format
as the <TT>md5sum</TT> command uses. This is just the MD5 hash,
some white space, and the file name. For example:<BR>
&nbsp;&nbsp;&nbsp;&nbsp;<TT>c4a6761b486de3c6abf7cf2c554289e5
&nbsp;&nbsp;&nbsp;&nbsp;/bin/ps</TT><P>
Make a file with this format for every line (it does not have to
be sorted). For example, if you have a trusted system then you can make
a hash database of its system binaries using the following:<BR>
&nbsp;&nbsp;&nbsp;&nbsp;<TT># md5sum /bin/* /sbin/* > bin-md5.db</TT><P>
After creation, hash databases must be indexed and sorted (this
includes the NSRL). Databases will be indexed by using the
<TT>hfind</TT> tool. The NSRL database would be indexed with:<BR>
&nbsp;&nbsp;&nbsp;&nbsp;<TT># hfind -i nsrl-md5 PATH_TO_NSRL/NSRLFile.txt</TT><P>
A database made by <TT>md5sum</TT> would be indexed with:<BR>
&nbsp;&nbsp;&nbsp;&nbsp;<TT># hfind -i md5sum bin-md5.db</TT><P>
Or, if Autopsy has this file configured from when the host was added,
then it can be re-indexed from the Hash Database Manager.
<H3>Autopsy Configuration</H3>
The alert and ignore databases are stored in the host configuration file
with the headers of 'exclude_db' and 'alert_db'. For example:<BR>
&nbsp;&nbsp;&nbsp;&nbsp;<TT>alert_db&nbsp;&nbsp;&nbsp;&nbsp;'/usr/local/hash/bad.db'</TT><P>
These entries can be edited at any time.
<P>
The NSRL database is configured in the <TT>conf.pl</TT> file in the
directory where Autopsy was installed. It has the $NSRLDB variable.
For example:<BR>
&nbsp;&nbsp;&nbsp;&nbsp;<TT>$NSRLDB = '/usr/local/hash/nsrl/NSRLFile.txt';</TT><P>
It can be edited, added, and removed at any time (but you must restart
Autopsy).
<p>
<h3>References</h3>
Issues 6 and 7 of <a href="http://www.sleuthkit.org/informer/" target=\"_blank\">The
Sleuth Kit Informer</a> discussed hash databases.
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

11
help/index.html Normal file
View File

@ -0,0 +1,11 @@
<HTML>
<HEAD><TITLE>Autopsy Help</TITLE></HEAD>
<LINK REL="SHORTCUT ICON" HREF="../pict/favicon.ico">
<FRAMESET COLS="20%,*">
<FRAME SRC="menu.html">
<FRAME SRC="blank.html" NAME="cont">
</FRAMESET>
</HTML>

29
help/int_mode.html Normal file
View File

@ -0,0 +1,29 @@
<HTML>
<HEAD><TITLE>Autopsy Integrity Check Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Integrity Check</H2></CENTER>
<H3>Overview</H3>
It is always important to validate the integrity of images during
an analysis. Autopsy uses the MD5 algorithm to validate images
and other files that are created by Autopsy.
<P>
The <TT>md5.txt</TT> files contain the MD5 values for files in that
directory. Values are added to it when file system images are
imported into the system or when Autopsy creates the file. This mode
allows one to calculate the MD5 value if it was not created before
and to validate the integrity.
<P>
When the <U>Image Integrity</U> button is selected from the <U>Host
Manager</U> window, all files will be shown with their MD5 value
if known. Here any image can have its value verified or a new one
created.
<P>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

37
help/menu.html Normal file
View File

@ -0,0 +1,37 @@
<HTML>
<HEAD><TITLE>Autopsy Help Topics</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<P><A HREF="general.html" TARGET="cont">General Information</A>
<P><A HREF="caseman.html" TARGET="cont">Case Management</A>
<HR>
<P><A HREF="file_mode.html" TARGET="cont">File Analysis</A>
<P><A HREF="meta_mode.html" TARGET="cont">Meta Data Analysis</A>
<P><A HREF="data_mode.html" TARGET="cont">Data Unit Analysis</A>
<P><A HREF="fs_mode.html" TARGET="cont">Image Details</A>
<P><A HREF="srch_mode.html" TARGET="cont">Keyword Searching</A>
<P><A HREF="grep.html" TARGET="cont">grep Cheat Sheet</A>
<P><A HREF="grep_lim.html" TARGET="cont">grep Search Limitations</A>
<P><A HREF="tl.html" TARGET="cont">Timelines</A>
<P><A HREF="sequencer.html" TARGET="cont">Event Sequencer</A>
<P><A HREF="file_category.html" TARGET="cont">File Type Categories</A>
<P><A HREF="hash_db.html" TARGET="cont">Hash Databases</A>
<P><A HREF="int_mode.html" TARGET="cont">Image Integrity</A>
<P><A HREF="timezones.html" TARGET="cont">Time Zones</A>
</BODY></HTML>

93
help/meta_mode.html Normal file
View File

@ -0,0 +1,93 @@
<HTML>
<HEAD><TITLE>Autopsy Metadata Analysis Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Metadata Analysis</H2></CENTER>
<H3>Overview</H3>
The Metadata Analysis mode allows the investigator to view the
details of metadata structures. The metadata structures on the
on-disk structures that contain the details of a file, such as
times and pointers to the allocated data units. FFS and EXT2FS
file systems call them inode structures, NTFS file systems call
them Master File Table (MFT) entries (or File Entries), and the
FAT file system calls them directory entries. This mode is useful
for recovering data and getting a detailed look at a file.
<H3>Input</H3>
To view the contents of a structure, enter the address in the text
box on the left and select <U>Display</U>.
<P>
The <U>Allocation List</U> button can also be used to view the
allocation status of metadata structures in groups of 500.
<H3>Viewing</H3>
The structure details are displayed on the right-hand side.
Typically, the metadata structure does not have the name of the
file that uses that structure, so Autopsy will try to locate the
file name. This process is slow with a FAT file system, so it is
not done by default.
<P>
The <U>File Type</U> is given, which is the output of the 'file'
tool. This tool uses any header information in the file to
guess what its type is. The MD5 value of the file is also given.
<P>
If Autopsy has been configured to use hash databases, then one can
select which databases to look for the file in. See
<A HREF="hash_db.html">Hash Databases</A> for more details.
<P>
The rest of the information will vary depending on the file
system type. In general, the allocation status will be given as
well as the size and each data unit that it has allocated. A
link will exist for each data unit that will show its contents.
<P>
The <U>Report</U> option generates an ASCII report with the structure
details, MD5 values, and dates in it. The <U>View Contents</U> option
displays the allocated data contents as one large file. The <U>Export</U>
option allows one to save the data contents to a file. The
<U>Add Note</U> button allows one to add a comment about this structure so
that it can be later recalled.
<H3>NTFS Notes</H3>
<P>
NTFS is a much different design than UNIX file systems and the meta
data structures are addressed differently. They typically have
the form of <TT>A-B-C</TT>, <TT>88-128-3</TT> for example. The
<TT>A</TT> value is the address of the file in the Master File
Table, 88 for example. This is similar to the inode value in UNIX.
Each file has several attributes, including at least one in files
for the data. The <TT>B</TT> value is the type of attribute. In
most cases, the data attribute has a type of 128 so this is commonly
seen. But, if you want to see the file name attribute, you could
specify that type and see the contents if you like (it is fairly
boring). The final value, <TT>C</TT>, is the id. Every attribute
has a unique id value. So, if there are multiple attributes with
the same type, you can specify the type.
<H3>FAT Notes</H3>
<P>
FAT does not give addresses to the directory entry structures. in
FAT, directory entries can be stored anywhere on the disk. They
are stored in the clusters allocated to the parent directory. This
is unlike NTFS or UNIX where the structures are in a large table
that does not move. get around that,
<P>
The addressing issue was solved by providing an address to every
32-byte area in the Data Area. Whether that data was currently a
directory entry or not. This makes it easy to find a given address
and scale when new files are created. The downside is that not
every address is possible, so it is likely that you will see jumps
in the address values. See the documentation in The Sleuth Kit
for more details.
<P>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

49
help/sequencer.html Normal file
View File

@ -0,0 +1,49 @@
<HTML>
<HEAD><TITLE>Autopsy Event Sequencer Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Event Sequencer</H2></CENTER>
<H3>Overview</H3>
<P>
In many investigations, evidence is not found in the order that it was
created during the incident. The notes feature in Autopsy allows one to
make notes about certain files, but it does not help one to put a
series of events in order.
<P>
The Event Sequencer allows the investigator to make notes and comments
about pieces of evidence. Each note must have a time associated with
it. For files and meta data, the times can be one or more of the
MAC times. Other notes can have times entered manually. The sequencer
will sort the events after each is entered so that the investigator can
quickly identify where there are gaps in the findings.
<H3>Adding an Event</H3>
<P>
To add an event for a file, directory, or meta data structure, select
the <U>Add Note</U> button. At the bottom will be check boxes that allow
an event to be generated for each of the file's times. The "standard"
note does not have to be generated if it is not needed.
<P>
To add an event from a different source, go to the Event Sequencer from
the Host Gallery (where the images are listed). At the bottom of
the window will be an area where the new event can be added. The
<B>Source</B> of the event will be shown where the file name of
a file event is normally shown. Examples of this type include
entries from firewall logs or reports from the help desk.
<H3>Viewing the Sequence Events</H3>
<P>
The <U>Event Sequencer</U> button can be found in the Host Gallery.
This window shows the events that are sorted by the time. Events that
correspond to a file, directory, or meta data structure will have either
[M-Time], [A-Time], or [C-Time] in the note that shows what time this
event was generated from. Clicking on the name will show the contents of
the file or directory.
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

68
help/srch_mode.html Normal file
View File

@ -0,0 +1,68 @@
<HTML>
<HEAD><TITLE>Autopsy Keyword Search Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Keyword Search</H2></CENTER>
<H3>Overview</H3>
<P>
This mode searches an image for a given string. This is most useful
when searching for deleted content. To decrease the time required
for a search, a "strings" file can serve as an index. This file
will contain only the ASCII strings in the image.
<P>
Autopsy will also prompt you to create a file of unallocated data if one
does not exist. This obviously is useful for recovering deleted data.
If a string is found in this file, Autopsy will also report the location
in the original image.
<H3>Entering the String</H3>
Enter the string or regular expression into the text box. Autopsy
allows you to search for a either a specific string or using 'grep'
style regular expressions. A case insensitive search will occur
if the appropriate box is checked, otherwise it is case sensitive.
You will also have the option of searching for the string as an
ASCII or a Unicode string. Unicode is much more common in Windows
systems than Unix systems. If both types are selected, then two
searches will be done.
<P>
If you have not generated a strings file or unallocated data file yet,
that option will exist.
<P>
The <U>Load Unallocated Image</U> or <U>Load Allocated Image</U> button
exists to switch between the two file types if they have both been
generated.
<P>
Autopsy also has the ability to perform pre-configured searches. They
are shown in the "Predefined Searches" section.
<H3>Viewing the Results</H3>
After the image has been searched, a list of "hits" will appear on the
left-hand side. Each data unit that contains the string is listed with
the offset of each occurrence. If a regular expression is used, then the
exact location is not given.
<P>
If the search was done on an unallocated data file, then an option will
exist next to each address to also view the original. Doing so could
reveal the inode that allocated it.
<H3>Previous Searches</H3>
The search results are saved to a file so it is easy to recall the
results with out having to perform the search again.
<H3>Regular Expressions</H3>
You can use grep regular expressions in the search
(refer to the 'grep' <A HREF="grep.html">
help page</A> and man page for more details). To search for
a couple of different words you would use: <TT>(foo) | (bar)</TT>.
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

10
help/temp.html Normal file
View File

@ -0,0 +1,10 @@
<HTML>
<HEAD><TITLE>Autopsy File Analysis Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

508
help/timezones.html Normal file
View File

@ -0,0 +1,508 @@
<HTML>
<HEAD><TITLE>Autopsy File Analysis Help - Time zone</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<p>
When creating a host, you can specify a time zone. If you do not, it will default to the time zone to which your system is set. If the system being investigated came from a different time zone, then you need to figure out what it was called. Below are a list of time zones that are known by most computers.
<p><br>
This list was copied from this site:
<tt>http://showtunepink.com/ical/TIMEZONES</tt>
<pre>
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmera
Africa/Bangui
Africa/Blantyre
Africa/Brazzaville
Africa/Bujumbura
Africa/Cairo
Africa/Ceuta
Africa/Dar_es_Salaam
Africa/Djibouti
Africa/Douala
Africa/Gaborone
Africa/Harare
Africa/Johannesburg
Africa/Kampala
Africa/Khartoum
Africa/Kigali
Africa/Kinshasa
Africa/Lagos
Africa/Libreville
Africa/Luanda
Africa/Lubumbashi
Africa/Lusaka
Africa/Malabo
Africa/Maputo
Africa/Maseru
Africa/Mbabane
Africa/Mogadishu
Africa/Nairobi
Africa/Ndjamena
Africa/Niamey
Africa/Porto-Novo
Africa/Tripoli
Africa/Tunis
Africa/Windhoek
America/Adak
America/Anchorage
America/Anguilla
America/Antigua
America/Araguaina
America/Aruba
America/Asuncion
America/Atka
America/Barbados
America/Belem
America/Belize
America/Boa_Vista
America/Bogota
America/Boise
America/Buenos_Aires
America/Cambridge_Bay
America/Cancun
America/Caracas
America/Catamarca
America/Cayenne
America/Cayman
America/Chicago
America/Chihuahua
America/Cordoba
America/Costa_Rica
America/Cuiaba
America/Curacao
America/Dawson
America/Dawson_Creek
America/Denver
America/Detroit
America/Dominica
America/Edmonton
America/Eirunepe
America/El_Salvador
America/Ensenada
America/Fort_Wayne
America/Fortaleza
America/Glace_Bay
America/Godthab
America/Goose_Bay
America/Grand_Turk
America/Grenada
America/Guadeloupe
America/Guatemala
America/Guayaquil
America/Guyana
America/Halifax
America/Havana
America/Hermosillo
America/Indiana/Indianapolis
America/Indiana/Knox
America/Indiana/Marengo
America/Indiana/Vevay
America/Indianapolis
America/Inuvik
America/Iqaluit
America/Jamaica
America/Jujuy
America/Juneau
America/Kentucky/Louisville
America/Kentucky/Monticello
America/Knox_IN
America/La_Paz
America/Lima
America/Los_Angeles
America/Louisville
America/Maceio
America/Managua
America/Manaus
America/Martinique
America/Mazatlan
America/Mendoza
America/Menominee
America/Merida
America/Mexico_City
America/Miquelon
America/Monterrey
America/Montevideo
America/Montreal
America/Montserrat
America/Nassau
America/New_York
America/Nipigon
America/Nome
America/Noronha
America/Panama
America/Pangnirtung
America/Paramaribo
America/Phoenix
America/Port-au-Prince
America/Port_of_Spain
America/Porto_Acre
America/Porto_Velho
America/Puerto_Rico
America/Rainy_River
America/Rankin_Inlet
America/Recife
America/Regina
America/Rio_Branco
America/Rosario
America/Santiago
America/Santo_Domingo
America/Sao_Paulo
America/Scoresbysund
America/Shiprock
America/St_Johns
America/St_Kitts
America/St_Lucia
America/St_Thomas
America/St_Vincent
America/Swift_Current
America/Tegucigalpa
America/Thule
America/Thunder_Bay
America/Tijuana
America/Tortola
America/Vancouver
America/Virgin
America/Whitehorse
America/Winnipeg
America/Yakutat
America/Yellowknife
Antarctica/Casey
Antarctica/Davis
Antarctica/DumontDUrville
Antarctica/Mawson
Antarctica/McMurdo
Antarctica/Palmer
Antarctica/South_Pole
Antarctica/Syowa
Antarctica/Vostok
Arctic/Longyearbyen
Asia/Aden
Asia/Almaty
Asia/Amman
Asia/Anadyr
Asia/Aqtau
Asia/Aqtobe
Asia/Ashgabat
Asia/Ashkhabad
Asia/Baghdad
Asia/Bahrain
Asia/Baku
Asia/Bangkok
Asia/Beirut
Asia/Bishkek
Asia/Brunei
Asia/Calcutta
Asia/Chungking
Asia/Colombo
Asia/Dacca
Asia/Damascus
Asia/Dhaka
Asia/Dili
Asia/Dubai
Asia/Dushanbe
Asia/Gaza
Asia/Harbin
Asia/Hong_Kong
Asia/Hovd
Asia/Irkutsk
Asia/Istanbul
Asia/Jakarta
Asia/Jayapura
Asia/Jerusalem
Asia/Kabul
Asia/Kamchatka
Asia/Karachi
Asia/Kashgar
Asia/Katmandu
Asia/Krasnoyarsk
Asia/Kuala_Lumpur
Asia/Kuching
Asia/Kuwait
Asia/Macao
Asia/Magadan
Asia/Manila
Asia/Muscat
Asia/Nicosia
Asia/Novosibirsk
Asia/Omsk
Asia/Phnom_Penh
Asia/Pyongyang
Asia/Qatar
Asia/Rangoon
Asia/Riyadh
Asia/Riyadh87
Asia/Riyadh88
Asia/Riyadh89
Asia/Saigon
Asia/Samarkand
Asia/Seoul
Asia/Shanghai
Asia/Singapore
Asia/Taipei
Asia/Tashkent
Asia/Tbilisi
Asia/Tehran
Asia/Tel_Aviv
Asia/Thimbu
Asia/Thimphu
Asia/Tokyo
Asia/Ujung_Pandang
Asia/Ulaanbaatar
Asia/Ulan_Bator
Asia/Urumqi
Asia/Vientiane
Asia/Vladivostok
Asia/Yakutsk
Asia/Yekaterinburg
Asia/Yerevan
Atlantic/Azores
Atlantic/Bermuda
Atlantic/Canary
Atlantic/Cape_Verde
Atlantic/Faeroe
Atlantic/Jan_Mayen
Atlantic/Madeira
Atlantic/South_Georgia
Atlantic/Stanley
Australia/ACT
Australia/Adelaide
Australia/Brisbane
Australia/Broken_Hill
Australia/Canberra
Australia/Darwin
Australia/Hobart
Australia/LHI
Australia/Lindeman
Australia/Lord_Howe
Australia/Melbourne
Australia/NSW
Australia/North
Australia/Perth
Australia/Queensland
Australia/South
Australia/Sydney
Australia/Tasmania
Australia/Victoria
Australia/West
Australia/Yancowinna
Brazil/Acre
Brazil/DeNoronha
Brazil/East
Brazil/West
CET
CST6CDT
Canada/Atlantic
Canada/Central
Canada/East-Saskatchewan
Canada/Eastern
Canada/Mountain
Canada/Newfoundland
Canada/Pacific
Canada/Saskatchewan
Canada/Yukon
Chile/Continental
Chile/EasterIsland
Cuba
EET
EST
EST5EDT
Egypt
Eire
Etc/GMT+1
Etc/GMT+10
Etc/GMT+11
Etc/GMT+12
Etc/GMT+2
Etc/GMT+3
Etc/GMT+4
Etc/GMT+5
Etc/GMT+6
Etc/GMT+7
Etc/GMT+8
Etc/GMT+9
Etc/GMT-1
Etc/GMT-10
Etc/GMT-11
Etc/GMT-12
Etc/GMT-13
Etc/GMT-14
Etc/GMT-2
Etc/GMT-3
Etc/GMT-4
Etc/GMT-5
Etc/GMT-6
Etc/GMT-7
Etc/GMT-8
Etc/GMT-9
Europe/Amsterdam
Europe/Andorra
Europe/Athens
Europe/Belfast
Europe/Belgrade
Europe/Berlin
Europe/Bratislava
Europe/Brussels
Europe/Bucharest
Europe/Budapest
Europe/Chisinau
Europe/Copenhagen
Europe/Dublin
Europe/Gibraltar
Europe/Helsinki
Europe/Istanbul
Europe/Kaliningrad
Europe/Kiev
Europe/Lisbon
Europe/Ljubljana
Europe/London
Europe/Luxembourg
Europe/Madrid
Europe/Malta
Europe/Minsk
Europe/Monaco
Europe/Moscow
Europe/Nicosia
Europe/Oslo
Europe/Paris
Europe/Prague
Europe/Riga
Europe/Rome
Europe/Samara
Europe/San_Marino
Europe/Sarajevo
Europe/Simferopol
Europe/Skopje
Europe/Sofia
Europe/Stockholm
Europe/Tallinn
Europe/Tirane
Europe/Tiraspol
Europe/Uzhgorod
Europe/Vaduz
Europe/Vatican
Europe/Vienna
Europe/Vilnius
Europe/Warsaw
Europe/Zagreb
Europe/Zaporozhye
Europe/Zurich
GB
GB-Eire
GMT
HST
Hongkong
Indian/Antananarivo
Indian/Chagos
Indian/Christmas
Indian/Cocos
Indian/Comoro
Indian/Kerguelen
Indian/Mahe
Indian/Maldives
Indian/Mauritius
Indian/Mayotte
Indian/Reunion
Iran
Israel
Jamaica
Japan
Kwajalein
Libya
MET
MST
MST7MDT
Mexico/BajaNorte
Mexico/BajaSur
Mexico/General
Mideast/Riyadh87
Mideast/Riyadh88
Mideast/Riyadh89
NZ
NZ-CHAT
Navajo
PRC
PST8PDT
Pacific/Apia
Pacific/Auckland
Pacific/Chatham
Pacific/Easter
Pacific/Efate
Pacific/Enderbury
Pacific/Fakaofo
Pacific/Fiji
Pacific/Funafuti
Pacific/Galapagos
Pacific/Gambier
Pacific/Guadalcanal
Pacific/Guam
Pacific/Honolulu
Pacific/Johnston
Pacific/Kiritimati
Pacific/Kosrae
Pacific/Kwajalein
Pacific/Majuro
Pacific/Marquesas
Pacific/Midway
Pacific/Nauru
Pacific/Niue
Pacific/Norfolk
Pacific/Noumea
Pacific/Pago_Pago
Pacific/Palau
Pacific/Pitcairn
Pacific/Ponape
Pacific/Port_Moresby
Pacific/Rarotonga
Pacific/Saipan
Pacific/Samoa
Pacific/Tahiti
Pacific/Tarawa
Pacific/Tongatapu
Pacific/Truk
Pacific/Wake
Pacific/Wallis
Pacific/Yap
Poland
Portugal
ROC
ROK
Singapore
SystemV/AST4
SystemV/AST4ADT
SystemV/CST6
SystemV/CST6CDT
SystemV/EST5
SystemV/EST5EDT
SystemV/HST10
SystemV/MST7
SystemV/MST7MDT
SystemV/PST8
SystemV/PST8PDT
SystemV/YST9
SystemV/YST9YDT
Turkey
US/Alaska
US/Aleutian
US/Arizona
US/Central
US/East-Indiana
US/Eastern
US/Hawaii
US/Indiana-Starke
US/Michigan
US/Mountain
US/Pacific
US/Samoa
W-SU
WET
</pre>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

183
help/tl.html Normal file
View File

@ -0,0 +1,183 @@
<HTML>
<HEAD><TITLE>Autopsy Timeline Analysis Help</TITLE></HEAD>
<BODY BGCOLOR=#CCCC99>
<CENTER><H2>Timeline Mode</H2></CENTER>
<H3>Overview</H3>
<P>
For some investigations, creating a timeline of activity can be
useful to identify places where the analysis should begin. Of
course file times can be easily modified by an attacker, so they
can not be 100% trusted. But, Autopsy can create timelines of
file activity.
<P>
Files have at least three times associated with them. The details of
each time varies with the file system type.
<P>
The following times exist for UNIX file systems (EXT2FS & FFS):
<UL>
<LI><B>Modified</B>: When the file data was last
modified. This time can be modified using the utimes()
function. This time is preserved in a 'tar' archive, so it is
possible to have M-times of files prior to when they were introduced
to the system.
<LI><B>Accessed</B>: When the file data was last
accessed. This time can be modified using the utimes() function.
<LI><B>Changed</B>: When the file status (inode data)
was last changed. This time can not be set using the utimes()
function in UNIX (but it will be set when utimes() is used to modify
other values).
</UL>
The EXT2FS file system also has a Deleted time, but it is not displayed
in the timeline.
<P>
A FAT File system has the following times:
<UL>
<LI><B>Written</B>: When the file was last written to.
It is the ONLY required time in the FAT file system.
<LI><B>Accessed</B>: When the file was last accessed. In
FAT, it is only accurate to the day (not minute). It is an optional
value, so some Operating Systems may not update it.
<LI><B>Created</B>: When the file was created. It is
also optional, so some Operating Systems may not update it. In fact,
many Windows installations have a C-Time of 0 for directories such as
<TT>C:\\Windows</TT> and <TT>C:\\Program Files</TT>.
</UL>
<P>
The NTFS File system has several times, four of which are
used in the timeline. These times are gathered from the
<TT>\$STANDARD_INFORMATION</TT> attribute.
<UL>
<LI><B>Written</B>: When the file was last written to.
<LI><B>Accessed</B>: When the file was last accessed.
<LI><B>Changed</B>: When the MFT entry was last modified.
<LI><B>Created</B>: When the file was created.
</UL>
<H3>How to Create a Timeline</H3>
Creating a timeline takes two steps. The first step extracts and
saves the needed data from each file system images. This step
stores the data from each specific file system in a generic format.
Historically (from TCT), this file was called the <TT>body</TT>
file. The second step takes the <TT>body</TT> file as input and
generates an ASCII timeline of file activity between two specified
dates. The resulting timeline can be viewed in Autopsy or using
a text editor.
<H3>Creating the Body File</H3>
The file meta-data must be extracted from the file system images and saved
to the <TT>body</TT> file. There are three major types of files that data
can be extracted for:
<UL>
<LI><B>Allocated Files</B>:
Files that are seen when doing an 'ls' or 'dir' in a directory. In
other words, these are the files that have an allocated file name
structure.
<LI><B>Unallocated Files</B>:
Files that have been deleted, but that TSK can still access.
Files in this category include orphan files, which are files that
no longer have a name, but whose metadata still exists.
If a deleted file name points to an allocated metadata structure,
then the name will say (realloc) next to it.
</UL>
<P>
To create the <TT>body</TT> file, select the images to analyze from
the list on top. Next, select which types of data that you want to
extract. By default all types are extracted. Lastly, identify the
name of the body file to create. The file will be created in the
<TT>output</TT> directory and an entry will be added to the host config
file. You will be given the option to calculate the MD5 value of
the new file.
<H3>Creating the Timeline</H3>
The next window allows one to create a timeline based on the newly
created <TT>body</TT> file. Or, one can select the option from
the left-hand side menu. The range of dates must be selected as
well as the name of the timeline file. The resulting timeline will
use the time zone for the host.
<P>
If the images are from a
UNIX file system, then the password and group files can be used to
change the UID and GID to actual names. If the partition from the
root directory exists in the host, select it from the pull down
list and Autopsy will find the <TT>/etc/passwd</TT> and
<TT>/etc/group</TT> file contents.
<P>
The timeline will be created in the <TT>output</TT> directory.
You will be given the option to calculate the MD5 hash value of
the new file.
<H3>Viewing the Timeline</H3>
The timeline can be viewed in Autopsy. Timelines tend to be very
large though and have thousands of lines. HTML browsers can not
handle tables of this size very well and typically have trouble
processing it. Therefore, Autopsy only allows you to view the
timeline one month at a time. It will likely be easier to open a
shell and examine the timeline in a text editor or pager such as
'less' or 'more'.
<P>
The 'summary' link will show a page that contains a monthly summary
of activity. It shows how many many events occured in that month
and links to the details. This allows one to get a high level
view of when a lot of activity last occured.
<P>
The following columns are in the timeline (in order):
<UL>
<LI><B>Date and time</B>of the activity. If no date is given,
then the activity occured at the same time as the previous entry
with a time.
<LI><B>Size</B>. The size of the file.
<LI><B>Entry Type</B>. The 'm', 'a', 'c', and 'b' letters will exist to
identify which of the activity types this entry corresponds to. 'm' is
for modified times, 'a' is for access times, 'c' is for change times, and
'b' is for created (or born) times.
<LI><B>Mode</B. The UNIX mode is shown.
<LI><B>UID</B>. The User Id or User name is shown. If a password
file was provided when the timeline was created, then the colunn should
only have names.
<LI><B>GID</B>. The Group Id or Group name is shown. If a group
file was provided when the timeline was created, then the colunn should
only have names.
<LI><B>Meta Data Address</B>. The inode or MFT entry address for the
associated file.
<LI><B>File Name</B>. The name of the file and the destination of a
symbolic link. Deleted entries will have '(deleted)' at the end and
deleted entries that point to an allocated meta data structure will
have '(realloc)'.
</UL>
<HR>
<FONT SIZE=0>Brian Carrier</FONT>
</BODY></HTML>

5
lib/.perltidyrc Executable file
View File

@ -0,0 +1,5 @@
-i=4 # indent of 4
-pt=2 # paren tightness
-sbt=2 # square paren tightness
-bt=2 # curly paren tightness
-nsfs # no space after semi in for loop

399
lib/Appsort.pm Normal file
View File

@ -0,0 +1,399 @@
#
# Sort files based on their application type (content)
#
# Brian Carrier [carrier@sleuthkit.org]
# Copyright (c) 2001-2008 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 Appsort;
$Appsort::FRAME = 1;
$Appsort::MENU = 2;
$Appsort::ENTER = 3;
$Appsort::RUN = 4;
$Appsort::VIEW = 5;
$Appsort::BLANK = 6;
sub main {
if ($::LIVE == 1) {
Print::print_html_header("Unsupported for Live Analysis");
print
"<center><h2>This feature is not available during a live analysis</h2></center>";
Print::print_html_footer();
return 0;
}
# By default, show the main frame
$Args::args{'view'} = $Args::enc_args{'view'} = $Appsort::FRAME
unless (exists $Args::args{'view'});
Args::check_view();
my $view = Args::get_view();
if ($view == $Appsort::BLANK) {
return blank();
}
# Check Basic Args
Args::check_vol('vol');
# These windows don't need the meta data address
if ($view == $Appsort::FRAME) {
return frame();
}
elsif ($view == $Appsort::ENTER) {
return enter();
}
elsif ($view == $Appsort::MENU) {
return menu();
}
elsif ($view == $Appsort::RUN) {
return run();
}
elsif ($view == $Appsort::VIEW) {
return view();
}
else {
Print::print_check_err("Invalid Application Sorting View");
}
}
sub get_sorter_dir {
if ($Args::args{'vol'} =~ /^($::REG_VNAME)$/) {
return "$::host_dir" . "$::DATADIR/sorter-$1/";
}
Print::print_err("Invalid Sorter Directory");
}
sub get_sorter_graphics_dir {
if ($Args::args{'vol'} =~ /^($::REG_VNAME)$/) {
return "$::host_dir" . "$::DATADIR/sorter-graphics-$1/";
}
Print::print_err("Invalid Sorter Graphics Directory");
}
# sorter frameset
sub frame {
Print::print_html_header_frameset("Sorter on $Args::args{'vol'}");
print "<frameset cols=\"20%,80%\">\n";
# Block List
print "<frame src=\"$::PROGNAME?mod=$::MOD_APPSORT&view=$Appsort::MENU&"
. "$Args::baseargs\">\n";
# Blank
print "<frame src=\"$::PROGNAME?mod=$::MOD_APPSORT&view=$Appsort::BLANK&"
. "$Args::baseargs\" name=\"content\">\n"
. "</frameset>\n";
Print::print_html_footer_frameset();
return 0;
}
# The left-hand frame for running sorter
sub menu {
Print::print_html_header("sorter menu");
print "<p><a href=\"$::PROGNAME?mod=$::MOD_APPSORT&view=$Appsort::ENTER&"
. "$Args::baseargs\" "
. "target=\"content\">Sort Files by Type</a>";
print "<p><a href=\"$::PROGNAME?mod=$::MOD_APPSORT&view=$Appsort::VIEW&"
. "$Args::baseargs\" "
. "target=\"content\">View Sorted Files</a>";
Print::print_html_footer();
return 0;
}
# Get the data and print the form so that sorter can be run
sub enter {
Print::print_html_header("sorter - enter data to create");
print "<center>"
. "<h3>File Type Sortings</h3></center><br>"
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_APPSORT\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Appsort::RUN\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n"
. Args::make_hidden();
print <<EOF1;
<p>The <b>sorter</b> tool will process an image and organize the
files based on their file type. The files are organized into categories
that are defined in configuration files. The categories will be saved
in the <tt>$::DATADIR</tt> directory.
<hr>
EOF1
my $sort_dir = get_sorter_dir();
if (-d "$sort_dir") {
print "WARNING: This will overwrite any existing data in:<br>"
. "&nbsp;&nbsp;&nbsp;&nbsp;<tt>$sort_dir</tt><br>\n";
}
my $tab = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
print <<EOF2;
<p>
<input type=\"checkbox\" name=\"sorter_cat\" value=\"1\" CHECKED>
Sort files into categories by type
<p>$tab
<input type=\"checkbox\" name=\"sorter_unk\" value=\"1\">
Do not save data about <tt>unknown</tt> file types
<p>$tab
<input type=\"checkbox\" name=\"sorter_save\" value=\"1\">
Save a copy of files in category directory (may require lots of disk space)
<p>$tab
<input type=\"checkbox\" name=\"sorter_img\" value=\"1\">
Save ONLY graphic images and make thumbnails <br>
$tab (may require lots of disk space and will save to a different directory than sorting all file types)
<p>
<input type=\"checkbox\" name=\"sorter_ext\" value=\"1\" CHECKED>
Extension and File Type Validation
EOF2
if (($::NSRLDB ne "") && (-e "$::NSRLDB")) {
# NSRL
print
"<p><input type=\"checkbox\" name=\"sorter_nsrl\" value=\"1\" CHECKED>"
. "Exclude files in the <b>NIST NSRL</b>\n";
}
if (($Caseman::alert_db ne "") && (-e "$Caseman::alert_db")) {
print
"<p><input type=\"checkbox\" name=\"sorter_alert\" value=\"1\" CHECKED>"
. "Alert files that are found in the <b>Alert Hash Database</b>\n";
}
if (($Caseman::exclude_db ne "") && (-e "$Caseman::exclude_db")) {
print
"<p><input type=\"checkbox\" name=\"sorter_exclude\" value=\"1\" CHECKED>"
. "Ignore files that are found in the <b>Exclude Hash Database</b>\n";
}
print "<p><input type=\"image\" src=\"pict/but_ok.jpg\" "
. "width=43 height=20 alt=\"Ok\" border=\"0\">\n</form>\n";
Print::print_html_footer();
return;
}
# Run sorter on the image
sub run {
Print::print_html_header("sorter - create");
my $sort_args = "";
my $ext = 0;
my $cat = 0;
my $vol = Args::get_vol('vol');
my $mnt = $Caseman::vol2mnt{$vol};
my $ftype = $Caseman::vol2ftype{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
Print::log_host_inv("Running 'sorter' on ($Caseman::vol2sname{$vol}");
$ext = 1
if ( (exists $Args::args{'sorter_ext'})
&& ($Args::args{'sorter_ext'} == 1));
$cat = 1
if ( (exists $Args::args{'sorter_cat'})
&& ($Args::args{'sorter_cat'} == 1));
if (($cat == 0) && ($ext == 0)) {
print "At least one action must be selected\n"
. "<p><a href=\"$::PROGNAME?mod=$::MOD_APPSORT&"
. "view=$Appsort::ENTER&$Args::baseargs\">"
. "<img border=0 src=\"pict/but_ok.jpg\" alt=\"Ok\" "
. "width=43 height=20></a>\n";
return;
}
# If both actions are wanted then no flags are needed
$sort_args .= "-e " if (($ext == 1) && ($cat == 0));
$sort_args .= "-i " if (($ext == 0) && ($cat == 1));
my $sort_dir = get_sorter_dir();
if ($cat == 1) {
if ( (exists $Args::args{'sorter_img'})
&& ($Args::args{'sorter_img'} == 1))
{
my $config = "$::TSKDIR/../share/tsk/sorter/images.sort";
Print::print_err("images configuration file not found ($config)")
unless (-e "$config");
$sort_args .= "-C \'$config\' -s -U ";
$sort_dir = get_sorter_graphics_dir();
}
else {
$sort_args .= "-s "
if ( (exists $Args::args{'sorter_save'})
&& ($Args::args{'sorter_save'} == 1));
$sort_args .= "-U "
if ( (exists $Args::args{'sorter_unk'})
&& ($Args::args{'sorter_unk'} == 1));
}
}
if ($::NSRLDB ne "") {
$sort_args .= "-n \'$::NSRLDB\' "
if ( (exists $Args::args{'sorter_nsrl'})
&& ($Args::args{'sorter_nsrl'} == 1));
}
if ($Caseman::alert_db ne "") {
$sort_args .= "-a \'$Caseman::alert_db\' "
if ( (exists $Args::args{'sorter_alert'})
&& ($Args::args{'sorter_alert'} == 1));
}
if ($Caseman::exclude_db ne "") {
$sort_args .= "-x \'$Caseman::exclude_db\' "
if ( (exists $Args::args{'sorter_exclude'})
&& ($Args::args{'sorter_exclude'} == 1));
}
unless (-d "$sort_dir") {
unless (mkdir "$sort_dir", $::MKDIR_MASK) {
Print::print_err("Error making $sort_dir");
}
}
if (-e "$sort_dir/index.html") {
unlink("$sort_dir/index.html");
}
my $exec =
"-h -m '$mnt' -d '$sort_dir' -o $offset -i $imgtype -f $ftype $sort_args $img";
# print "Executing: <tt>sorter $exec</tt><p>\n";
# Execute Sorter
my $hit_cnt = 0;
$SIG{ALRM} = sub {
if (($hit_cnt++ % 5) == 0) {
print "+";
}
else {
print "-";
}
alarm(5);
};
alarm(5);
local *OUT;
Exec::exec_pipe(*OUT, "LANG=C LC_ALL=C '$::TSKDIR/sorter' $exec");
alarm(0);
$SIG{ALRM} = 'DEFAULT';
while ($_ = Exec::read_pipe_line(*OUT)) {
print "$_<br>\n";
$hit_cnt = 0;
}
close(OUT);
if (-e "$sort_dir/index.html") {
print "<p>Output can be found by viewing:<br>"
. "&nbsp;&nbsp;<tt>$sort_dir/index.html</tt><p>\n";
# Print the index.html file from the output
print "<hr><center><h3>Results Summary</h3></center>\n";
open INDEX, "<$sort_dir/index.html"
or die "Can't open sorter index file ($sort_dir/index.html)";
while (<INDEX>) {
next if ((/^<HTML><HEAD><TITLE>/i)
|| (/^<BODY><center><H2>/i));
# Extract out the symlinks to the categories
if (/^\s*<li><a href="\.\/[\w\.]+">([\w\s]+)<\/a> \((\d+)\)\s*$/i) {
print "<LI>$1 ($2)\n";
}
# Skip the link on the thumbnails link
elsif (/^\s*\(<a href=[\"\.\/\w]+>thumbnails<\/A>\)\s*$/) {
print "(thumbnails)\n";
}
else {
print "$_";
}
}
close(INDEX);
}
Print::print_html_footer();
return;
}
# View Page
sub view {
Print::print_html_header("");
print "<center><h3>File Type Sorting</h3>\n"
. "Autopsy does not currently support viewing the sorted files.<br>\n"
. "After sorting, you can view the results by opening the following file:<p>\n";
print "<tt>" . get_sorter_dir() . "index.html</tt>";
Print::print_html_footer();
return 0;
}
# Blank Page
sub blank {
Print::print_html_header("");
print "<center><h3>File Type Sorting</h3>\n"
. "In this mode, Autopsy will examine allocated and unallocated files<br> and "
. "sort them into categories and verify the extension.<p>This allows you to find a file based on"
. "its type and find \"hidden\" files.<p>\n"
.
"WARNING: This can be a time intensive process.<br>\n";
Print::print_html_footer();
return 0;
}

291
lib/Appview.pm Normal file
View File

@ -0,0 +1,291 @@
#
# View the application layer (HTML, picutures etc.)
#
# Brian Carrier [carrier@sleuthkit.org]
# Copyright (c) 2001-2005 by Brian Carrier. All rights reserved
#
# This file is part of the Autopsy Forensic Browser (Autopsy)
#
# Autopsy is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Autopsy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Autopsy; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
# IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Updated 1/15
package Appview;
$Appview::CELL_FRAME = 1;
$Appview::CELL_MENU = 2;
$Appview::CELL_CONT = 3;
sub main {
# By default, show the main frame
$Args::args{'view'} = $Args::enc_args{'view'} = $Appview::CELL_FRAME
unless (exists $Args::args{'view'});
Args::check_view();
my $view = Args::get_view();
# Check Basic Args
Args::check_vol('vol');
Args::check_meta('meta');
Args::check_dir();
Args::check_recmode();
if ($view == $Appview::CELL_FRAME) {
return cell_frame();
}
elsif ($view == $Appview::CELL_CONT) {
return cell_content();
}
elsif ($view == $Appview::CELL_MENU) {
return cell_menu();
}
else {
Print::print_check_err("Invalid Application Viewing View");
}
}
#########################################################################
#
# CELL - Sanitized Environment
#
my $CELL_MODE_SANIT = 1;
my $CELL_MODE_NORM = 2;
sub cell_frame {
Print::print_html_header_frameset("Autopsy Cell");
my $vol = Args::get_vol('vol');
my $mnt = $Caseman::vol2mnt{$vol};
my $fname = "$mnt$Args::args{'dir'}";
print "<frameset rows=\"15%,85%\">\n";
# if a mode was not given, then choose the Sanitized by default
$Args::args{'cell_mode'} = $CELL_MODE_SANIT
unless ((exists $Args::args{'cell_mode'})
&& ($Args::args{'cell_mode'} =~ /^\d$/));
my $url =
"&$Args::baseargs&meta=$Args::enc_args{'meta'}"
. "&dir=$Args::enc_args{'dir'}&"
. "cell_mode=$Args::args{'cell_mode'}&recmode=$Args::args{'recmode'}";
print
"<frame src=\"$::PROGNAME?mod=$::MOD_APPVIEW&view=$Appview::CELL_MENU${url}\">\n"
. "<frame src=\"$::PROGNAME?mod=$::MOD_APPVIEW&view=$Appview::CELL_CONT${url}\">\n"
. "</frameset>\n";
Print::print_html_footer_frameset();
return 0;
}
# Print the menu on top. This allows one to export the file and change modes
sub cell_menu {
Args::check_cell_mode();
Print::print_html_header("Cell Header");
my $cell_mode = $Args::args{'cell_mode'};
my $url =
"&$Args::baseargs&meta=$Args::enc_args{'meta'}&"
. "dir=$Args::enc_args{'dir'}&recmode=$Args::enc_args{'recmode'}";
if ($cell_mode == $CELL_MODE_SANIT) {
print <<EOF1;
<center>
This file is currently being viewed in a <b>sanitized environment</b><br>
HTML files have been edited to disable scripts and links.
The script contents will be shown as text.<br>
Pictures have been replaced by place holders<br>
<table width=300 cellspacing=\"0\" cellpadding=\"2\">
<tr>
<td align=center>
<a href=\"$::PROGNAME?mod=$::MOD_APPVIEW&view=$Appview::CELL_FRAME$url&cell_mode=$CELL_MODE_NORM\"
target=\"_top\">
<img src=\"pict/sanit_b_norm.jpg\" alt=\"Normal\" border=\"0\">
</a>
</td>
EOF1
}
elsif ($cell_mode == $CELL_MODE_NORM) {
print <<EOF2;
<center>
This file is currently being viewed in a <b>normal environment</b><br>
HTML files are being viewed without modification.<br>
<table width=300 cellspacing=\"0\" cellpadding=\"2\">
<tr>
<td align=center>
<a href=\"$::PROGNAME?mod=$::MOD_APPVIEW&view=$Appview::CELL_FRAME&$url&cell_mode=$CELL_MODE_SANIT\"
target=\"_top\">
<img src=\"pict/sanit_b_san.jpg\" alt=\"Sanitized\" border=\"0\">
</a>
</td>
EOF2
}
# Export the file
print "<td align=center>\n"
. "<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::EXPORT&$url\">"
. "<img src=\"pict/but_export.jpg\" alt=\"export\" border=\"0\" "
. "width=123 height=20>"
. "</a></td></tr>\n";
print "<tr><td colspan=\"2\" align=\"center\">"
. "Deleted File Recovery Mode</td></tr>\n"
if ($Args::enc_args{'recmode'} == $File::REC_YES);
print "</table>";
Print::print_html_footer();
return;
}
# Display safe and common things in the browser (pictures, basic html)
sub cell_content {
Args::check_meta('meta');
Args::check_dir();
Args::check_cell_mode();
my $meta = Args::get_meta('meta');
my $vol = Args::get_vol('vol');
my $mnt = $Caseman::vol2mnt{$vol};
my $ftype = $Caseman::vol2ftype{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
my $fname = "$mnt$Args::args{'dir'}";
my $recflag = "";
$recflag = " -r "
if (Args::get_recmode() == $File::REC_YES);
# identify what type it is
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -"
);
my $file_type = Exec::read_pipe_line(*OUT);
close(OUT);
$file_type = "Error getting file type"
if ((!defined $file_type) || ($file_type eq ""));
if ($file_type =~ /JPEG image data/) {
Print::log_host_inv("$vol: Viewing $fname ($meta) as JPEG");
print "Content-type: image/jpeg$::HTTP_NL$::HTTP_NL";
}
elsif ($file_type =~ /GIF image data/) {
Print::log_host_inv("$vol: Viewing $fname ($meta) as GIF");
print "Content-type: image/gif$::HTTP_NL$::HTTP_NL";
}
elsif ($file_type =~ /PNG image data/) {
Print::log_host_inv("$vol: Viewing $fname ($meta) as PNG");
print "Content-type: image/png$::HTTP_NL$::HTTP_NL";
}
elsif ($file_type =~ /PC bitmap data/) {
Print::log_host_inv("$vol: Viewing $fname ($meta) as BMP");
print "Content-type: image/bmp$::HTTP_NL$::HTTP_NL";
}
elsif ($file_type =~ /HTML document text/) {
Print::log_host_inv("$vol: Viewing $fname ($meta) as HTML");
print "Content-type: text/html$::HTTP_NL$::HTTP_NL";
}
else {
Print::log_host_inv("$vol: Unknown format of meta $meta ");
Print::print_check_err("Unknown File Type for Viewing: $file_type");
}
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta"
);
while ($_ = Exec::read_pipe_line(*OUT)) {
# Parse out bad "stuff"
if ( ($file_type =~ /HTML document text/)
&& ($Args::args{'cell_mode'} == $CELL_MODE_SANIT))
{
$_ =~ s/\bsrc=/src=$::SANITIZE_TAG\?/ig;
$_ =~ s/\bhref=/href=$::SANITIZE_TAG\?/ig;
$_ =~ s/<script/<$::SANITIZE_TAG-script/ig;
$_ =~ s/\bbackground=/background=$::SANITIZE_TAG\?/ig;
}
print "$_";
}
print "$::HTTP_NL$::HTTP_NL";
close(OUT);
return 0;
}
sub sanitize_pict {
my $url = shift();
my $lurl = $url;
$lurl =~ tr/[A-Z]/[a-z]/;
print "HTTP/1.0 200 OK$::HTTP_NL";
if ( ($lurl =~ /.jpg/i)
|| ($lurl =~ /.jpeg/i)
|| ($lurl =~ /.gif/i)
|| ($lurl =~ /.png/i)
|| ($lurl =~ /.bmp/i))
{
open PICT, "<$::PICTDIR/$::SANITIZE_PICT"
or die "can not open $::PICTDIR/$::SANITIZE_PICT";
print "Content-type: image/jpeg$::HTTP_NL$::HTTP_NL";
while (<PICT>) {
print "$_";
}
close(PICT);
print "$::HTTP_NL$::HTTP_NL";
}
else {
$url =~ tr/\+/ /;
$url =~ s/%([a-f0-9][a-f0-9])/chr( hex( $1 ) )/eig;
Print::print_html_header("Denied");
print "<h1><center>Unable to Complete Request</h1><br>\n"
. "<tt>Autopsy</tt> will not follow links from "
. "untrusted HTML pages:<br><tt>$url</tt><br>\n";
Print::print_html_footer();
}
exit(0);
}

927
lib/Args.pm Normal file
View File

@ -0,0 +1,927 @@
#
# Functions to check and get the arguments from URL
#
# ver 2.00+
# Brian Carrier [carrier@sleuthkit.org]
# Copyright (c) 2003-2004 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 Args;
# Parse the argument string into the args hash
sub parse_args {
my $lcl_args = shift;
foreach my $nam_val (split(/&/, $lcl_args)) {
my ($name, $value) = split(/=/, $nam_val);
if (defined $value) {
my $dec_name = url_decode($name);
$Args::enc_args{$dec_name} = $value;
$Args::args{$dec_name} = url_decode($value);
}
}
}
sub url_encode {
my $text = shift;
$text =~ s/([^a-z0-9_.!~*'() -])/sprintf "%%%02X", ord($1)/eig;
$text =~ tr/ /+/;
return $text;
}
sub url_decode {
my $text = shift;
$text =~ tr/\+/ /;
$text =~ s/%([a-f0-9][a-f0-9])/chr( hex( $1 ) )/eig;
return $text;
}
# This assumes that the checking of the types has been done and this just
# makes a string of the key values if they exist
#
# case
# host
# img
# Must add & after
sub make_baseargs {
$Args::baseargs = "";
# The standard case, host, and investigator
$Args::baseargs .= "case=$Args::enc_args{'case'}&"
if ((exists $Args::enc_args{'case'}) && ($Args::enc_args{'case'} ne ""));
$Args::baseargs .= "host=$Args::enc_args{'host'}&"
if ((exists $Args::enc_args{'host'}) && ($Args::enc_args{'host'} ne ""));
$Args::baseargs .= "inv=$Args::enc_args{'inv'}&"
if ((exists $Args::enc_args{'inv'}) && ($Args::enc_args{'inv'} ne ""));
$Args::baseargs_novol = $Args::baseargs;
# Add the image, file system type, and mount point
$Args::baseargs .= "vol=$Args::enc_args{'vol'}&"
if ((exists $Args::enc_args{'vol'}) && ($Args::enc_args{'vol'} ne ""));
# remove the final '&'
$Args::baseargs_novol = $1 if ($Args::baseargs_novol =~ /^(.*?)&$/);
$Args::baseargs = $1 if ($Args::baseargs =~ /^(.*?)&$/);
return;
}
# Does not do mnt or img
sub make_hidden {
my $str = "";
$str .=
"<input type=\"hidden\" name=\"host\" value=\"$Args::args{'host'}\">\n"
if ((exists $Args::args{'host'}) && ($Args::args{'host'} ne ""));
$str .=
"<input type=\"hidden\" name=\"case\" value=\"$Args::args{'case'}\">\n"
if ((exists $Args::args{'case'}) && ($Args::args{'case'} ne ""));
$str .=
"<input type=\"hidden\" name=\"inv\" value=\"$Args::args{'inv'}\">\n"
if ((exists $Args::args{'inv'}) && ($Args::args{'inv'} ne ""));
return $str;
}
###############################
# block
###############################
sub check_block {
if ((!exists $Args::args{'block'}) || ($Args::args{'block'} !~ /^\d+$/)) {
Print::print_check_err(
"Invalid block argument (positive numbers only)");
}
return 0;
}
sub get_block {
if ($Args::args{'block'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid Block");
}
###############################
# body
###############################
sub check_body {
unless (exists $Args::args{'body'}) {
Print::print_check_err("Missing body argument");
}
unless ($Args::args{'body'} =~ /^$::REG_VNAME$/o) {
Print::print_check_err(
"Invalid body value (only letters, " . "numbers,-,., and _)");
}
return 0;
}
sub get_body {
if ($Args::args{'body'} =~ /^($::REG_VNAME)$/o) {
return $1;
}
Print::print_err("Invalid Body");
}
################################
# Case name
################################
sub check_case {
unless (exists $Args::args{'case'}) {
Print::print_check_err("Missing case argument");
}
unless ($Args::args{'case'} =~ /^$::REG_CASE$/o) {
Print::print_check_err(
"Invalid case value (letters, num, and symbols only");
}
return 0;
}
sub get_case {
if ($Args::args{'case'} =~ /^($::REG_CASE)$/o) {
return $1;
}
Print::print_err("Invalid Case Name");
}
###############################
# cell_mode
###############################
sub check_cell_mode {
if ( (!exists $Args::args{'cell_mode'})
|| ($Args::args{'cell_mode'} !~ /^\d$/o))
{
Print::print_check_err(
"Invalid cell_mode argument (numbers >= 0 only)");
}
return 0;
}
################################
# dir
################################
sub check_dir {
if ( (!exists $Args::args{'dir'})
|| ($Args::args{'dir'} =~ /\/\.\.\//)
|| ($Args::args{'dir'} =~ /\;/))
{
Print::print_check_err("Invalid dir argument (valid file path only)");
}
return 0;
}
sub get_dir {
if ($Args::args{'dir'} =~ /([^;]*)/o) {
my $d = $1;
# Remove double slashes
$d =~ s/\/\//\//g;
return $d;
}
Print::print_err("Invalid Directory");
}
###############################
# dirmode
###############################
sub check_dirmode {
if ((!exists $Args::args{'dirmode'}) || ($Args::args{'dirmode'} !~ /^\d+$/))
{
Print::print_check_err(
"Invalid dirmode argument (positive numbers only)");
}
return 0;
}
sub get_dirmode {
if ($Args::args{'dirmode'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid dirmode");
}
################################
# do_md5
################################
sub check_do_md5 {
if ((!exists $Args::args{'do_md5'}) || ($Args::args{'do_md5'} !~ /^\d+$/)) {
Print::print_check_err("Missing do_md5 argument");
}
return 0;
}
sub get_do_md5 {
if ($Args::args{'do_md5'} =~ /^\s*(\d+)$/) {
return $1;
}
Print::print_err("Invalid MD5 Flag");
}
################################
# fname
################################
sub check_fname {
unless (exists $Args::args{'fname'}) {
Print::print_check_err("Missing fname argument");
}
unless ($Args::args{'fname'} =~ /^$::REG_FNAME$/o) {
Print::print_check_err(
"Invalid fname value (only letters, " . "numbers,-,., and _)");
}
return 0;
}
sub get_fname {
if ($Args::args{'fname'} =~ /^($::REG_FNAME)$/o) {
return "$::host_dir" . "$::DATADIR/$1";
}
Print::print_err("Invalid File Name");
}
################################
# fname_mode
################################
sub check_fname_mode {
if (!exists $Args::args{'fname_mode'}) {
Print::print_check_err("Missing fname_mode argument");
}
unless ($Args::args{'fname_mode'} =~ /^\d+$/) {
Print::print_check_err("invalid mode: numbers only");
}
return 0;
}
################################
# fname_rel
# Return the relative fname
################################
sub get_fname_rel {
if ($Args::args{'fname'} =~ /^($::REG_FNAME)$/o) {
return "$::DATADIR/$1";
}
Print::print_err("Invalid Relative File Name");
}
###############################
# force
###############################
sub get_force {
if ($Args::args{'force'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid Force Flag");
}
################################
# ftype
################################
sub get_ftype_blah {
if (exists $Args::args{'ftype'}) {
if ($Args::args{'ftype'} =~ /^($::REG_FTYPE)$/o) {
return $1;
}
}
if ( (exists $Args::args{'img'})
&& (exists $Caseman::vol2ftype{$Args::args{'img'}}))
{
return $Caseman::vol2ftype{$Args::args{'img'}};
}
Print::print_err("Missing ftype value");
}
sub check_ftype_blah {
unless (
(
(exists $Args::args{'img'})
&& (exists $Caseman::vol2ftype{$Args::args{'img'}})
&& ($Caseman::vol2ftype{$Args::args{'img'}} =~ /^$::REG_FTYPE$/o)
)
|| ( (exists $Args::args{'ftype'})
&& ($Args::args{'ftype'} =~ /^$::REG_FTYPE$/o))
)
{
Print::print_check_err("Missing or invalid ftype value");
}
return 0;
}
################################
# host
# Host for the case
################################
sub check_host {
unless (exists $Args::args{'host'}) {
Print::print_check_err("Missing host argument");
}
unless ($Args::args{'host'} =~ /^$::REG_HOST$/o) {
Print::print_check_err("Invalid host value");
}
return 0;
}
sub get_host {
if ($Args::args{'host'} =~ /^($::REG_HOST)$/o) {
return $1;
}
Print::print_err("Invalid Host");
}
################################
# htype
################################
sub check_htype {
if ((!exists $Args::args{'htype'}) || ($Args::args{'htype'} !~ /^\d+$/)) {
Print::print_check_err(
"Invalid htype argument (positive numbers only)");
}
return 0;
}
sub get_htype {
if ($Args::args{'htype'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid htype");
}
###############################
# ifind
# ifind is optional and by default is 0 if not given
###############################
sub get_ifind {
if (!exists $Args::args{'ifind'}) {
return 0;
}
elsif ($Args::args{'ifind'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid ifind flag");
}
###############################
# img_path is used when adding images - it is the full path to the
# non-evidence locker copy of the image
###############################
sub check_img_path {
if (!exists $Args::args{'img_path'}) {
Print::print_check_err("Missing image (img_path) argument");
}
elsif ($Args::args{'img_path'} =~ /^$::REG_IMG_PATH$/o) {
# Check for its actual existence
Print::print_check_err("Image not found at $Args::args{'img_path'}")
unless (
(-e "$Args::args{'img_path'}")
|| ( (-l "$Args::args{'img_path'}")
&& (-e readlink "$::host_dir" . "$Args::args{$img}"))
);
}
else {
Print::print_check_err("Invalid image path (only letters, "
. "numbers,-,.,_/ and start with /) [$Args::args{'img_path'}]");
}
return 0;
}
sub get_img_path {
if ($Args::args{'img_path'} =~ /^($::REG_IMG_PATH)$/o) {
return "$1";
}
Print::print_err("Invalid Image Path");
}
sub check_img_path_wild {
if (!exists $Args::args{'img_path'}) {
Print::print_check_err("Missing wild image (img_path) argument");
}
elsif ($Args::args{'img_path'} !~ /^$::REG_IMG_PATH_WILD$/o) {
# IF there is extra white space then remove it and move on
if ($Args::args{'img_path'} =~ /^\s*($::REG_IMG_PATH_WILD)\s*$/o) {
$Args::args{'img_path'} = $1;
return 0;
}
else {
Print::print_check_err("Invalid wild image (img_path) argument");
}
}
return 0;
}
sub get_img_path_wild {
if ($Args::args{'img_path'} =~ /^($::REG_IMG_PATH_WILD)$/o) {
return "$1";
}
Print::print_err("Invalid Image Path");
}
###############################
# meta
###############################
sub check_meta {
my $meta = shift;
if ( (!exists $Args::args{$meta})
|| ($Args::args{$meta} !~ /^$::REG_META$/o))
{
Print::print_check_err(
"Invalid meta address ($meta) argument (numbers >= 0 only)");
}
return 0;
}
sub get_meta {
my $meta = shift;
if ($Args::args{$meta} =~ /^($::REG_META)$/o) {
return $1;
}
Print::print_err("Invalid Meta Address");
}
################################
# inv
# Investigator
################################
sub check_inv {
unless (exists $Args::args{'inv'}) {
Print::print_check_err("Missing inv argument");
}
unless ($Args::args{'inv'} =~ /^$::REG_INVESTIG$/o) {
Print::print_check_err(
"Invalid inv value (letters, num, and symbols only");
}
return 0;
}
sub get_inv {
if ($Args::args{'inv'} =~ /^($::REG_INVESTIG)$/o) {
return $1;
}
Print::print_err("Invalid Investigator");
}
###############################
# len
###############################
sub check_len {
if ( (!exists $Args::args{'len'})
|| ($Args::args{'len'} !~ /^\d+$/)
|| ($Args::args{'len'} == 0))
{
Print::print_check_err("Invalid len argument (positive numbers only)");
}
return 0;
}
sub get_len {
if ((exists $Args::args{'len'}) && ($Args::args{'len'} =~ /^(\d+)$/)) {
return $1;
}
# return the default len of 1 if it is not defined
return 1;
}
###############################
# min
###############################
sub get_min {
if ($Args::args{'min'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid Minute");
}
################################
# module
################################
sub check_mod {
if ((!exists $Args::args{'mod'}) || ($Args::args{'mod'} !~ /^\d+$/)) {
Print::print_check_err(
"Invalid Module argument (positive numbers only)");
}
return 0;
}
sub get_mod {
if ($Args::args{'mod'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid Module");
}
################################
# mnt
###############################
sub check_mnt {
my $ftype = Args::get_ftype();
if (($ftype eq "blkls") || ($ftype eq "swap") || ($ftype eq "raw")) {
$Args::args{'mnt'} = $ftype;
$Args::enc_args{'mnt'} = $ftype;
}
elsif (!exists $Args::args{'mnt'}) {
# Look it up if it is not found
if (exists $Args::args{'img'}) {
unless (exists $Caseman::vol2mnt{$Args::args{'img'}}) {
Print::print_check_err(
"Mounting point not found: $Args::args{'img'}");
}
my $mnt = $Caseman::vol2mnt{$Args::args{'img'}};
$Args::args{'mnt'} = $mnt;
$Args::enc_args{'mnt'} = Args::url_encode($mnt);
}
else {
Print::print_check_err("Mounting point not found");
}
}
if ($Args::args{'mnt'} =~ /\/\.\.\//) {
Print::print_check_err(
"Invalid mount point argument (valid file path only)");
}
unless ($Args::args{'mnt'} =~ /^$::REG_MNT$/o) {
Print::print_check_err(
"Invalid mount point argument (valid file path only)");
}
return 0;
}
sub get_mnt {
if ((exists $Args::args{'mnt'}) && ($Args::args{'mnt'} =~ /($::REG_MNT)/o))
{
return $1;
}
Print::print_err("Invalid Mounting Point");
}
################################
# note
################################
sub check_note {
if (!exists $Args::args{'note'}) {
Print::print_check_err("Missing note argument");
}
return 0;
}
#################
# num_img - adding disk images
sub check_num_img {
if ((!exists $Args::args{'num_img'}) || ($Args::args{'num_img'} !~ /^\d+$/))
{
Print::print_check_err(
"Invalid num_img argument (positive numbers only)");
}
return 0;
}
sub get_num_img {
if ($Args::args{'num_img'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid num_img");
}
###############################
# recmode
###############################
sub check_recmode {
if ((!exists $Args::args{'recmode'}) || ($Args::args{'recmode'} !~ /^\d+$/))
{
Print::print_check_err(
"Invalid recmode argument (positive numbers only)");
}
return 0;
}
sub get_recmode {
if ($Args::args{'recmode'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid recmode");
}
################################
# srchidx
#
# Index for previous keyword search
###############################
sub check_srchidx {
if ((!exists $Args::args{'srchidx'}) || ($Args::args{'srchidx'} !~ /^\d+$/))
{
Print::print_check_err(
"Invalid srchidx argument (positive numbers only)");
}
return 0;
}
###############################
# sort
###############################
sub check_sort {
if ((!exists $Args::args{'sort'}) || ($Args::args{'sort'} !~ /^\d+$/)) {
Print::print_check_err("Invalid sort argument (positive numbers only)");
}
return 0;
}
sub get_sort {
if ($Args::args{'sort'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid sort flag");
}
################################
# st_mon
################################
sub check_st_mon {
if ( (exists $Args::args{'st_mon'})
&& ($Args::args{'st_mon'} =~ /^(\d\d?)$/))
{
if (($1 < 1) || ($1 > 12)) {
print("Invalid start month\n");
return 1;
}
}
else {
print("Invalid start month\n");
return 1;
}
}
sub get_st_mon {
if ($Args::args{'st_mon'} =~ /^(\d\d?)$/) {
return $1;
}
Print::print_err("Invalid Month");
}
################################
# st_year
################################
sub check_st_year {
if ( (exists $Args::args{'st_year'})
&& ($Args::args{'st_year'} =~ /^(\d\d\d\d?)$/))
{
if (($1 < 1970) || ($1 > 2020)) {
print("Invalid start year\n");
return 1;
}
}
else {
print("Invalid start year\n");
return 1;
}
}
sub get_st_year {
if ($Args::args{'st_year'} =~ /^(\d\d\d\d)$/) {
return $1;
}
Print::print_err("Invalid Year");
}
################################
# str
# search string
################################
# This should be made more flexible
sub check_str {
if (!exists $Args::args{'str'}) {
Print::print_check_err("Missing string argument");
}
return 0;
}
sub get_str {
if ($Args::args{'str'} =~ /^\s*(.*)$/) {
return $1;
}
Print::print_err("Invalid String");
}
###############################
# submod
# Used by the tab module to identify the actual module
###############################
sub check_submod {
if ((!exists $Args::args{'submod'}) || ($Args::args{'submod'} !~ /^\d+$/)) {
Print::print_check_err(
"Invalid sub-mode argument (positive numbers only)");
}
return 0;
}
sub get_submod {
if ($Args::args{'submod'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid sub-mode");
}
################################
# tl
###############################
sub check_tl {
if ((!exists $Args::args{'tl'}) || ($Args::args{'tl'} !~ /^$::REG_VNAME$/))
{
Print::print_check_err(
"Invalid timeline argument (positive numbers only)");
}
return 0;
}
sub get_tl {
if ($Args::args{'tl'} =~ /^($::REG_VNAME)$/o) {
return $1;
}
Print::print_err("Invalid Timeline");
}
################################
# ts
# time skew
################################
sub check_ts {
if ((!exists $Args::args{'ts'}) || ($Args::args{'ts'} !~ /^$::REG_SKEW$/o))
{
Print::print_check_err("Missing time skew argument");
}
return 0;
}
sub get_ts {
if ($Args::args{'ts'} =~ /^\s*($::REG_SKEW)$/o) {
return $1;
}
Print::print_err("Invalid Time Skew");
}
################################
# tz
# timezone
################################
sub check_tz {
if ( (!exists $Args::args{'tz'})
|| ($Args::args{'tz'} !~ /^$::REG_ZONE_ARGS$/o))
{
Print::print_check_err("Missing time zone argument");
}
return 0;
}
sub get_tz {
if ($Args::args{'tz'} =~ /^($::REG_ZONE_ARGS)$/o) {
return $1;
}
Print::print_err("Invalid Timezone");
}
################################
# unitsize
################################
sub get_unitsize {
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
my $blkcat_out;
if ($ftype eq 'blkls') {
if (exists $Caseman::mod2vol{$vol}) {
my $orig = $Caseman::mod2vol{$vol};
my $img = $Caseman::vol2path{$orig};
my $offset = $Caseman::vol2start{$orig};
my $imgtype = $Caseman::vol2itype{$orig};
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/blkcat' -f $Caseman::vol2ftype{$orig} -s -o $offset -i $imgtype $img"
);
$blkcat_out = <OUT>;
close(OUT);
}
# We don't have the original image, so just set the size to 512
else {
return 512;
}
}
elsif ($ftype eq 'swap') {
return 4096;
}
elsif ($ftype eq 'raw') {
return 512;
}
elsif ($Caseman::vol2cat{$vol} eq 'disk') {
return 512;
}
else {
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/blkcat' -f $ftype -s -o $offset -i $imgtype $img");
$blkcat_out = <OUT>;
close(OUT);
}
$blkcat_out = "Error getting unit size"
if ((!defined $blkcat_out) || ($blkcat_out eq ""));
if ($blkcat_out =~ /(\d+): Size of Addressable Unit/) {
return $1;
}
else {
Print::print_err("Error identifying block size (blkcat -s output)\n"
. "$blkcat_out\n");
}
}
################################
# View - subset of module
################################
sub check_view {
if ((!exists $Args::args{'view'}) || ($Args::args{'view'} !~ /^\d+$/)) {
Print::print_check_err("Invalid View argument (positive numbers only)");
}
return 0;
}
sub get_view {
if ($Args::args{'view'} =~ /^(\d+)$/) {
return $1;
}
Print::print_err("Invalid View");
}
###############################
# We don't allow much for the volume because this is an argument to
# the TSK programs. We keep these files only in one
# directory and for easy/simple security only allow basic names
# Symbolic links are allowed if these simple names are not desired
#
# Allowed values are A-Za-z0-9_-.
#
# The argument is the name of the image
###############################
sub check_vol {
my $vol = shift;
if ((!exists $Args::args{$vol}) || ($Args::args{$vol} !~ /^$::REG_VNAME$/))
{
Print::print_check_err(
"Invalid volume argument (name and number only)");
}
return 0;
}
sub get_vol {
my $vol = shift;
if ($Args::args{$vol} =~ /^($::REG_VNAME)$/) {
return $1;
}
Print::print_err("Invalid volume ($vol)");
}
1;

4151
lib/Caseman.pm Normal file

File diff suppressed because it is too large Load Diff

927
lib/Data.pm Normal file
View File

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

91
lib/Exec.pm Normal file
View File

@ -0,0 +1,91 @@
#
# Functions that wrap the execution of tools so that they are logged
#
# 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 Exec;
# exec_pipe(HANDLE, CMD);
sub exec_pipe {
my $handle = shift(@_);
my $cmd = shift(@_);
die "Can't open pipe for exec_pipe"
unless defined(my $pid = open($handle, '-|'));
if ($pid) {
return $handle;
}
else {
$| = 1;
Print::log_host_inv_exec("$cmd");
exec("$cmd") or die "Can't exec program: $!";
}
}
sub read_pipe_line {
my $handle = shift(@_);
my $out;
# for (my $i = 0; ($len = read ($handle, $$buf, $size)) && (!defined $len); $i++) {
for (my $i = 0; $i < 100; $i++) {
$out = <$handle>;
return $out if (defined $out);
}
return $out;
}
sub read_pipe_data {
my $handle = shift(@_);
my $size = shift(@_);
my $out;
my $len;
for (
my $i = 0;
($len = read($handle, $out, $size)) && (!defined $len) && ($i < 100);
$i++
)
{
}
return $out;
}
sub exec_sys {
my $cmd = shift(@_);
Print::log_host_inv_exec("$cmd");
system($cmd);
return;
}
1;

2293
lib/File.pm Normal file

File diff suppressed because it is too large Load Diff

170
lib/Filesystem.pm Normal file
View File

@ -0,0 +1,170 @@
#
# File system layer functions
#
# Brian Carrier [carrier@sleuthkit.org]
# Copyright (c) 2001-2005 by Brian Carrier. All rights reserved
#
# This file is part of the Autopsy Forensic Browser (Autopsy)
#
# Autopsy is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Autopsy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Autopsy; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
# IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Updated 1/13
package Filesystem;
$Filesystem::STATS = 0;
sub main {
# By default, show the main window
$Args::args{'view'} = $Args::enc_args{'view'} = $Filesystem::STATS
unless (exists $Args::args{'view'});
Args::check_view();
my $view = Args::get_view();
# Check Basic Args
Args::check_vol('vol');
# These windows don't need the meta data address
if ($view == $Filesystem::STATS) {
return stats();
}
else {
Print::print_check_err("Invalid File System View");
}
}
sub stats_disk {
Print::print_html_header("Disk Status");
my $vol = Args::get_vol('vol');
my $img = $Caseman::vol2path{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
my $offset = $Caseman::vol2start{$vol};
my $dtype = $Caseman::vol2dtype{$vol};
# Run 'mmls' on the image
Exec::exec_pipe(*OUT,
"'$::TSKDIR/mmls' -o $offset -i $imgtype -t $dtype -r $img");
# cycle through results and add each to table with file system type
print "<center><h3>Disk Image Details</h3></center>\n";
print "<b>PARTITION INFORMATION</b><p>\n";
while ($_ = Exec::read_pipe_line(*OUT)) {
print "<tt>$_</tt><br>\n";
}
return 0;
}
############ FILE SYSTEM ##################
sub stats {
my $vol = Args::get_vol('vol');
return stats_disk() if ($Caseman::vol2cat{$vol} eq "disk");
Print::print_html_header("File System Status");
my $ftype = $Caseman::vol2ftype{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: Displaying file system details");
print "<center><h3>General File System Details</h3></center><p>\n";
my $fat = 0;
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/fsstat' -f $ftype -o $offset -i $imgtype $img");
while ($_ = Exec::read_pipe_line(*OUT)) {
if (/\-\-\-\-\-\-\-\-\-\-/) {
# Ignore these and print them ahead of the headers
}
# need the space to prevent NTFS STD_INFORMATION from triggering it
elsif (/ INFORMATION/) {
print "<hr><b>$_</b><p>\n";
}
elsif (($ftype =~ /fat/) && ($_ =~ /FAT CONTENTS/)) {
print "<hr><b>$_</b><p>\n";
# Set the flag if we reach the FAT
$fat = 1;
}
# Special case for FAT
# We will be giving hyperlinks in the FAT table dump
elsif ($fat == 1) {
# Ignore the divider
if (/\-\-\-\-\-\-\-\-\-\-/) {
print "$_<br>";
next;
}
if (/^((\d+)\-\d+\s+\((\d+)\)) \-\> ([\w]+)$/) {
my $full = $1;
my $blk = $2;
my $len = $3;
my $next = $4;
# Print the tag so that other FAT entries can link to it
print "<a name=\"$blk\">\n";
print
"<a href=\"$::PROGNAME?$Args::baseargs&mod=$::MOD_FRAME&submod=$::MOD_DATA&"
. "block=$blk&len=$len\" target=\"_top\">$full</a> -> ";
if ($next eq 'EOF') {
print "EOF<br>\n";
}
else {
print "<a href=\"#$next\">$next</a><br>\n";
}
}
else {
$fat = 0;
print "$_<br>";
}
}
else {
print "$_<br>";
}
}
close(OUT);
Print::print_html_footer();
return 0;
}
1;

336
lib/Frame.pm Normal file
View File

@ -0,0 +1,336 @@
#
# Functions to create the tabs and frame of the main browsing mode
#
# 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 Frame;
$Frame::IMG_FRAME = 0;
$Frame::IMG_TABS = 1;
$Frame::IMG_BLANK = 2;
sub main {
Args::check_vol('vol');
# By default, show the main frame
$Args::args{'view'} = $Args::enc_args{'view'} = $Frame::IMG_FRAME
unless (exists $Args::args{'view'});
Args::check_view();
my $view = Args::get_view();
if ($view == $Frame::IMG_FRAME) {
vol_browse_frame();
}
elsif ($view == $Frame::IMG_TABS) {
vol_browse_tabs();
}
elsif ($view == $Frame::IMG_BLANK) {
vol_browse_blank();
}
else {
Print::print_check_err("Invalid Frame View");
}
return 0;
}
# create the frame for the tabs on top and the generic message on the bottom
sub vol_browse_frame {
Print::print_html_header_frameset(
"$Args::args{'case'}:$Args::args{'host'}:$Args::args{'vol'}");
my $submod = $::MOD_FRAME;
$submod = Args::get_submod() if (exists $Args::args{'submod'});
# Print the rest of the frames
my $str = "";
my $view = "";
if ($submod == $::MOD_FILE) {
$str .= "&meta=$Args::args{'meta'}" if (exists $Args::args{'meta'});
$str .= "&dir=$Args::args{'dir'}" if (exists $Args::args{'dir'});
$str .= "&sort=$Args::args{'sort'}" if (exists $Args::args{'sort'});
$str .= "&dmode=$Args::args{'dmode'}" if (exists $Args::args{'dmode'});
}
elsif ($submod == $::MOD_DATA) {
$str .= "&block=$Args::args{'block'}" if (exists $Args::args{'block'});
$str .= "&len=$Args::args{'len'}" if (exists $Args::args{'len'});
}
elsif ($submod == $::MOD_META) {
$str .= "&meta=$Args::args{'meta'}" if (exists $Args::args{'meta'});
}
elsif ($submod == $::MOD_FRAME) {
$view = "&view=$Frame::IMG_BLANK";
}
print <<EOF;
<frameset rows=\"40,*\">
<frame src=\"$::PROGNAME?mod=$::MOD_FRAME&view=$Frame::IMG_TABS&$Args::baseargs&submod=$submod\">
<frame src=\"$::PROGNAME?mod=$submod$view&$Args::baseargs$str\">
</frameset>
<NOFRAMES>
<center>
Autopsy requires a browser that supports frames.
</center>
</NOFRAMES>
EOF
Print::print_html_footer_frameset();
return 0;
}
# Display a message when the image is opened (below the tabs)
sub vol_browse_blank {
Print::print_html_header("Main Message");
print <<EOF;
<center>
<br><br><br><br><br><br><br>
To start analyzing this volume, choose an analysis mode from the tabs above.
</center>
EOF
Print::print_html_footer();
return 0;
}
sub vol_browse_tabs {
Args::check_submod();
Print::print_html_header_tabs("Mode Tabs");
my $submod = Args::get_submod();
my $vol = Args::get_vol('vol');
my $special = 0;
$special = 1
unless (($Caseman::vol2cat{$vol} eq "part")
&& ($Fs::is_fs{$Caseman::vol2ftype{$vol}} == 1));
# if ( ($Caseman::vol2ftype{$vol} eq "strings")
# || ($Caseman::vol2ftype{$vol} eq "blkls")
# || ($Caseman::vol2ftype{$vol} eq "swap")
# || ($Caseman::vol2ftype{$vol} eq "raw"));
print "<center><table width=\"800\" border=\"0\" cellspacing=\"0\" "
. "cellpadding=\"0\"><tr>\n";
# Files
print "<td align=\"center\" width=116>";
if ($special == 0) {
print
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_FILE&$Args::baseargs\""
. "target=\"_top\">";
# Current
if ($submod == $::MOD_FILE) {
print "<img border=0 "
. "src=\"pict/main_t_fil_cur.jpg\" "
. "width=116 height=38 "
. "alt=\"File Analysis (Current Mode)\"></a>";
}
# Link
else {
print "<img border=0 "
. "src=\"pict/main_t_fil_link.jpg\" "
. "width=116 height=38 "
. "alt=\"File Analysis\"></a>";
}
}
# non-link
else {
print "<img border=0 "
. "src=\"pict/main_t_fil_org.jpg\" "
. "width=116 height=38 "
. "alt=\"File Analysis (not available)\">";
}
# Search
print "</td>\n" . "<td align=\"center\" width=116>";
print
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_KWSRCH&$Args::baseargs\""
. " target=\"_top\">";
if ($submod == $::MOD_KWSRCH) {
print "<img border=0 "
. "src=\"pict/main_t_srch_cur.jpg\" "
. "width=116 height=38 "
. "alt=\"Keyword Search Mode (Current Mode)\"></a>";
}
else {
print "<img border=0 "
. "src=\"pict/main_t_srch_link.jpg\" "
. "width=116 height=38 "
. "alt=\"Keyword Search Mode\"></a>";
}
# File Type
print "</td>\n" . "<td align=\"center\" width=116>";
if (($special == 0) && ($::LIVE == 0)) {
print
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_APPSORT&$Args::baseargs\""
. " target=\"_top\">";
# Current
if ($submod == $::MOD_APPSORT) {
print "<img border=0 "
. "src=\"pict/main_t_ftype_cur.jpg\" "
. "width=116 height=38 "
. "alt=\"File Type (Current Mode)\"></a>";
}
else {
print "<img border=0 "
. "src=\"pict/main_t_ftype_link.jpg\" "
. "width=116 height=38 "
. "alt=\"File Type\"></a>";
}
}
else {
print "<img border=0 "
. "src=\"pict/main_t_ftype_org.jpg\" "
. "width=116 height=38 "
. "alt=\"File Type (not available)\">";
}
# Image Details
print "</td>\n" . "<td align=\"center\" width=116>";
if (($special == 0) || ($Caseman::vol2cat{$vol} eq "disk")) {
print
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_FS&$Args::baseargs\""
. " target=\"_top\">";
if ($submod == $::MOD_FS) {
print "<img border=0 "
. "src=\"pict/main_t_img_cur.jpg\" "
. "width=116 height=38 "
. "alt=\"Image Details Mode (Current Mode)\"></a>";
}
else {
print "<img border=0 "
. "src=\"pict/main_t_img_link.jpg\" "
. "width=116 height=38 "
. "alt=\"Image Details Mode\"></a>";
}
}
else {
print "<img border=0 "
. "src=\"pict/main_t_img_org.jpg\" "
. "width=116 height=38 "
. "alt=\"Image Details Mode (not available)\">";
}
# Meta Data
print "</td>\n" . "<td align=\"center\" width=116>";
if ($special == 0) {
print
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs\""
. " target=\"_top\">";
if ($submod == $::MOD_META) {
print "<img border=0 "
. "src=\"pict/main_t_met_cur.jpg\" "
. "width=116 height=38 "
. "alt=\"Meta Data Mode (Current Mode)\"></a>";
}
else {
print "<img border=0 "
. "src=\"pict/main_t_met_link.jpg\" "
. "width=116 height=38 "
. "alt=\"Meta Data Mode\"></a>";
}
}
else {
print "<img border=0 "
. "src=\"pict/main_t_met_org.jpg\" "
. "width=116 height=38 "
. "alt=\"Meta Data Mode (not available)\">";
}
# Data Units
print "</td>\n" . "<td align=\"center\" width=116>";
print
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_DATA&$Args::baseargs\""
. " target=\"_top\">";
# Current
if ($submod == $::MOD_DATA) {
print "<img border=0 "
. "src=\"pict/main_t_dat_cur.jpg\" "
. "width=116 height=38 "
. "alt=\"Data Units Mode (Current Mode)\"></a>";
}
# Link
else {
print "<img border=0 "
. "src=\"pict/main_t_dat_link.jpg\" "
. "width=116 height=38 "
. "alt=\"Data Units Mode\"></a>";
}
# Help - set to current mode
print "</td>\n"
. "<td align=\"center\" width=52>"
. "<a href=\"$::HELP_URL\""
. " target=\"_blank\">"
. "<img border=0 "
. "src=\"pict/tab_help.jpg\" "
. "width=52 "
. "alt=\"Help\">"
. "</a></td>\n";
# Close
print "<td align=\"center\" width=52>"
. "<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&"
. "view=$Caseman::VOL_OPEN&$Args::baseargs_novol\" target=\"_top\">"
. "<img border=0 src=\"pict/tab_close.jpg\" width=52 "
. "alt=\"Close Image\"></a></td>\n";
print "</tr></table>\n";
Print::print_html_footer_tabs();
return 0;
}

160
lib/Fs.pm Normal file
View File

@ -0,0 +1,160 @@
#
package Fs;
$Fs::types[0] = "ext";
$Fs::types[1] = "fat";
$Fs::types[2] = "ntfs";
$Fs::types[3] = "ufs";
$Fs::types[4] = "iso9660";
$Fs::types[5] = "-----";
$Fs::types[6] = "fat12";
$Fs::types[7] = "fat16";
$Fs::types[8] = "fat32";
$Fs::types[9] = "bsdi";
$Fs::types[10] = "freebsd";
$Fs::types[11] = "openbsd";
$Fs::types[12] = "solaris";
# These need to be updated as The Sleuth Kit supports more file systems
#
# addr_unit contains the addressable unit per filesystem type
# first_meta contains the first usable meta address on a system
# root_meta is the meta address for the root directory (diff than
# first on ntfs)
$Fs::addr_unit{'disk'} = 'Sector';
$Fs::first_addr{'disk'} = 0;
$Fs::is_fs{'disk'} = 0;
$Fs::addr_unit{'blkls'} = 'Unit';
$Fs::first_addr{'blkls'} = 0;
$Fs::is_fs{'blkls'} = 0;
# raw
$Fs::addr_unit{'raw'} = 'Unit';
$Fs::first_addr{'raw'} = 0;
$Fs::is_fs{'raw'} = 0;
# Swap
$Fs::addr_unit{'swap'} = 'Unit';
$Fs::first_addr{'swap'} = 0;
$Fs::is_fs{'swap'} = 0;
# BSDI
$Fs::first_meta{'bsdi'} = $Fs::root_meta{'bsdi'} = 2;
$Fs::first_addr{'bsdi'} = 0;
$Fs::addr_unit{'bsdi'} = 'Fragment';
$Fs::has_ctime{'bsdi'} = 1;
$Fs::has_crtime{'bsdi'} = 0;
$Fs::has_mtime{'bsdi'} = 1;
$Fs::meta_str{'bsdi'} = "Inode";
$Fs::is_fs{'bsdi'} = 1;
# FreeBSD
$Fs::first_meta{'freebsd'} = $Fs::root_meta{'freebsd'} = 2;
$Fs::first_addr{'freebsd'} = 0;
$Fs::addr_unit{'freebsd'} = 'Fragment';
$Fs::has_ctime{'freebsd'} = 1;
$Fs::has_crtime{'freebsd'} = 0;
$Fs::has_mtime{'freebsd'} = 1;
$Fs::meta_str{'freebsd'} = "Inode";
$Fs::is_fs{'freebsd'} = 1;
# OpenBSD
$Fs::first_meta{'openbsd'} = $Fs::root_meta{'openbsd'} = 2;
$Fs::first_addr{'openbsd'} = 0;
$Fs::addr_unit{'openbsd'} = 'Fragment';
$Fs::has_ctime{'openbsd'} = 1;
$Fs::has_crtime{'openbsd'} = 0;
$Fs::has_mtime{'openbsd'} = 1;
$Fs::meta_str{'openbsd'} = "Inode";
$Fs::is_fs{'openbsd'} = 1;
# Solaris
$Fs::first_meta{'solaris'} = $Fs::root_meta{'solaris'} = 2;
$Fs::first_addr{'solaris'} = 0;
$Fs::addr_unit{'solaris'} = 'Fragment';
$Fs::has_ctime{'solaris'} = 1;
$Fs::has_crtime{'solaris'} = 0;
$Fs::has_mtime{'solaris'} = 1;
$Fs::meta_str{'solaris'} = "Inode";
$Fs::is_fs{'solaris'} = 1;
# UFS
$Fs::first_meta{'ufs'} = $Fs::root_meta{'ufs'} = 2;
$Fs::first_addr{'ufs'} = 0;
$Fs::addr_unit{'ufs'} = 'Fragment';
$Fs::has_ctime{'ufs'} = 1;
$Fs::has_crtime{'ufs'} = 0;
$Fs::has_mtime{'ufs'} = 1;
$Fs::meta_str{'ufs'} = "Inode";
$Fs::is_fs{'ufs'} = 1;
# Linux
$Fs::first_meta{'linux-ext2'} = $Fs::root_meta{'linux-ext2'} = 2;
$Fs::first_addr{'linux-ext2'} = 0;
$Fs::addr_unit{'linux-ext2'} = 'Fragment';
$Fs::has_ctime{'linux-ext2'} = 1;
$Fs::has_crtime{'linux-ext2'} = 0;
$Fs::has_mtime{'linux-ext2'} = 1;
$Fs::meta_str{'linux-ext2'} = "Inode";
$Fs::is_fs{'linux-ext2'} = 1;
$Fs::first_meta{'linux-ext3'} = $Fs::root_meta{'linux-ext3'} = 2;
$Fs::first_addr{'linux-ext3'} = 0;
$Fs::addr_unit{'linux-ext3'} = 'Fragment';
$Fs::has_ctime{'linux-ext3'} = 1;
$Fs::has_crtime{'linux-ext3'} = 0;
$Fs::has_mtime{'linux-ext3'} = 1;
$Fs::meta_str{'linux-ext3'} = "Inode";
$Fs::is_fs{'linux-ext3'} = 1;
$Fs::first_meta{'ext'} = $Fs::root_meta{'ext'} = 2;
$Fs::first_addr{'ext'} = 0;
$Fs::addr_unit{'ext'} = 'Fragment';
$Fs::has_ctime{'ext'} = 1;
$Fs::has_crtime{'ext'} = 0;
$Fs::has_mtime{'ext'} = 1;
$Fs::meta_str{'ext'} = "Inode";
$Fs::is_fs{'ext'} = 1;
# FAT
$Fs::first_meta{'fat'} = $Fs::first_meta{'fat12'} = $Fs::first_meta{'fat16'} =
$Fs::first_meta{'fat32'} = 1;
$Fs::root_meta{'fat'} = $Fs::root_meta{'fat12'} = $Fs::root_meta{'fat16'} =
$Fs::root_meta{'fat32'} = 2;
$Fs::first_addr{'fat'} = $Fs::first_addr{'fat12'} = $Fs::first_addr{'fat16'} =
$Fs::first_addr{'fat32'} = 0;
$Fs::addr_unit{'fat'} = $Fs::addr_unit{'fat12'} = $Fs::addr_unit{'fat16'} =
$Fs::addr_unit{'fat32'} = 'Sector';
$Fs::has_ctime{'fat'} = $Fs::has_ctime{'fat12'} = $Fs::has_ctime{'fat16'} =
$Fs::has_ctime{'fat32'} = 0;
$Fs::has_crtime{'fat'} = $Fs::has_crtime{'fat12'} = $Fs::has_crtime{'fat16'} =
$Fs::has_crtime{'fat32'} = 1;
$Fs::has_mtime{'fat'} = $Fs::has_mtime{'fat12'} = $Fs::has_mtime{'fat16'} =
$Fs::has_mtime{'fat32'} = 1;
$Fs::meta_str{'fat'} = $Fs::meta_str{'fat12'} = $Fs::meta_str{'fat16'} =
$Fs::meta_str{'fat32'} = "Dir Entry";
$Fs::is_fs{'fat'} = $Fs::is_fs{'fat12'} = $Fs::is_fs{'fat16'} =
$Fs::is_fs{'fat32'} = 1;
# NTFS
$Fs::first_meta{'ntfs'} = 0;
$Fs::root_meta{'ntfs'} = 5;
$Fs::first_addr{'ntfs'} = 0;
$Fs::addr_unit{'ntfs'} = 'Cluster';
$Fs::has_ctime{'ntfs'} = 1;
$Fs::has_crtime{'ntfs'} = 1;
$Fs::has_mtime{'ntfs'} = 1;
$Fs::meta_str{'ntfs'} = "MFT Entry";
$Fs::is_fs{'ntfs'} = 1;
# ISO9660
$Fs::first_meta{'iso9660'} = $Fs::root_meta{'iso9660'} = 0;
$Fs::first_addr{'iso9660'} = 0;
$Fs::addr_unit{'iso9660'} = 'Block';
$Fs::has_ctime{'iso9660'} = 0;
$Fs::has_crtime{'iso9660'} = 1;
$Fs::has_mtime{'iso9660'} = 0;
$Fs::meta_str{'iso9660'} = "Directory Entry";
$Fs::is_fs{'iso9660'} = 1;

947
lib/Hash.pm Normal file
View File

@ -0,0 +1,947 @@
#
# Hash database and calculation functions
#
# Brian Carrier [carrier@sleuthkit.org]
# Copyright (c) 2001-2008 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 Hash;
$Hash::DB_MANAGER = 1;
$Hash::DB_LOOKUP = 2;
$Hash::DB_INDEX = 3;
$Hash::IMG_VERIFY = 4;
$Hash::IMG_CALC = 5;
$Hash::IMG_LIST_FR = 6;
$Hash::IMG_LIST = 7;
$Hash::BLANK = 8;
sub main {
return if ($::LIVE == 1);
Args::check_view();
my $view = Args::get_view();
if ($view == $Hash::BLANK) {
blank();
return 0;
}
elsif ($view == $Hash::DB_MANAGER) {
return db_manager();
}
elsif ($view == $Hash::DB_LOOKUP) {
return db_lookup();
}
elsif ($view == $Hash::DB_INDEX) {
return db_index();
}
elsif ($view == $Hash::IMG_LIST_FR) {
return img_list_fr();
}
elsif ($view == $Hash::IMG_LIST) {
return img_list();
}
Args::check_vol('vol');
if ($view == $Hash::IMG_CALC) {
return img_calc();
}
elsif ($view == $Hash::IMG_VERIFY) {
return img_verify();
}
else {
Print::print_check_err("Invalid Hash View");
}
}
sub index_md5sum {
my $db = shift;
local *OUT;
Exec::exec_pipe(*OUT, "'$::TSKDIR/hfind' -i md5sum '$db'");
while ($_ = Exec::read_pipe_line(*OUT)) {
print "$_<br>\n";
}
close(OUT);
}
sub index_nsrl {
local *OUT;
Exec::exec_pipe(*OUT, "'$::TSKDIR/hfind' -i nsrl-md5 '$::NSRLDB'");
while ($_ = Exec::read_pipe_line(*OUT)) {
print "$_<br>\n";
}
close(OUT);
}
# Manager/status Window from HOST Manager
sub db_manager {
Print::print_html_header("Hash Database Manager");
print <<EOF;
Hash databases allow Autopsy to quickly identify known files. This includes
files that are known to be good and those that are known to be bad. The
'hfind' tool is used to lookup entries in the databases and it needs an
index file for each database. This window allows one to re-index the
database after it has been updated.
<p>
To edit the location of the databases, you must manually edit the
<tt>host.aut</tt> file in the host directory.
<hr>
<center>
<img src=\"pict/hashdb_h_alert.jpg\" alt=\"Alert Database\" border=\"0\">
</center>
<p><b>Overview</b><br>
These files are known to be <U>bad</U> and are the ones that you want to
know about if they are in the image you are analyzing. For example,
this database would include hashes of known attacker tools, rootkits,
or photographs.
EOF
print "<p><b>Details</b><br>\n";
if ($Caseman::alert_db eq "") {
print "Location: <tt>Not Configured</tt><br>\n";
}
elsif (-e "$Caseman::alert_db") {
print "Location: <tt>$Caseman::alert_db</tt><br>\n";
if (-e "$Caseman::alert_db" . "-md5.idx") {
print "Status: MD5 Index File Exists<br>\n";
}
else {
print "Status: Database has not been MD5 indexed<br>\n";
}
# Index Button
print "<p><a href=\"$::PROGNAME?mod=$::MOD_HASH&"
. "view=$Hash::DB_INDEX&hash_alert=1&$Args::baseargs\">"
. "<img src=\"pict/but_indexdb.jpg\" alt=\"Index DB\" "
. "width=116 height=20 border=\"0\">"
. "</a>\n";
# Lookup Button
if (-e "$Caseman::alert_db" . "-md5.idx") {
print "<p><b>Lookup</b><br>"
. "<form action=\"$::PROGNAME\" method=\"get\">"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_HASH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Hash::DB_LOOKUP\">\n"
. "<input type=\"hidden\" name=\"hash_alert\" value=\"1\">\n"
. Args::make_hidden()
. "<table cellspacing=\"10\" cellpadding=\"2\">\n<tr>\n"
. "<td align=\"left\">Enter MD5 Value: "
. "<input type=\"text\" name=\"md5\" size=40 maxlength=32></td>\n"
. "<td align=\"left\">"
. "<input type=\"image\" src=\"pict/but_lookup.jpg\" alt=\"Ok\" "
. "width=116 height=20 border=\"0\">\n"
. "</td></tr>\n</table>\n"
. "</form>";
}
}
else {
print "Location: <tt>$Caseman::alert_db</tt><br>\n"
. "ERROR: Database not found<br>\n";
}
print <<EOF2;
<hr>
<center>
<img src=\"pict/hashdb_h_ig.jpg\" alt=\"Ignore Database\" border=\"0\">
</center>
<p><b>Overview</b><br>
These files are known to be <U>good</U> and are the ones that you
can ignore if they are found in the image you are analyzing. For
example, this database would include hashes of known system binaries
and other documents that you do not want to waste time on when running
'sorter' or files that you want to confirm were not modified by an
attacker.
EOF2
print "<p><b>Details</b><br>\n";
if ($Caseman::exclude_db eq "") {
print "Location: <tt>Not Configured</tt><br>\n";
}
elsif (-e "$Caseman::exclude_db") {
print "Location: <tt>$Caseman::exclude_db</tt><br>\n";
if (-e "$Caseman::exclude_db" . "-md5.idx") {
print "Status: MD5 Index File Exists<br>\n";
}
else {
print "Status: Database has not been MD5 indexed<br>\n";
}
# Index Button
print "<p><a href=\"$::PROGNAME?mod=$::MOD_HASH&view=$Hash::DB_INDEX&"
. "hash_exclude=1&$Args::baseargs\">"
. "<img src=\"pict/but_indexdb.jpg\" alt=\"Index DB\" "
. "width=116 height=20 border=\"0\">"
. "</a>\n";
# Lookup Button
if (-e "$Caseman::exclude_db" . "-md5.idx") {
print "<p><b>Lookup</b><br>"
. "<form action=\"$::PROGNAME\" method=\"get\">"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_HASH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Hash::DB_LOOKUP\">\n"
. "<input type=\"hidden\" name=\"hash_exclude\" value=\"1\">\n"
. Args::make_hidden()
. "<table cellspacing=\"10\" cellpadding=\"2\">\n<tr>\n"
. "<td align=\"left\">Enter MD5 Value: "
. "<input type=\"text\" name=\"md5\" size=40 maxlength=32></td>\n"
. "<td align=\"left\">"
. "<input type=\"image\" src=\"pict/but_lookup.jpg\" alt=\"Ok\" "
. "width=116 height=20 border=\"0\">\n"
. "</td></tr>\n</table>\n"
. "</form>";
}
}
else {
print "Location: <tt>$Caseman::exclude_db</tt><br>\n"
. "ERROR: Database not found<br>\n";
}
print <<EOF3;
<hr>
<center>
<img src=\"pict/hashdb_h_nsrl.jpg\" alt=\"NSRL Database\" border=\"0\">
</center>
<p><b>Overview</b><br>
These files are known to be <U>good</U> and <U>bad</U>. It is currently
difficult to distinguish between known good and known bad, but the NSRL
is used in Autopsy to ignore all known files.
EOF3
print "<p><b>Details</b><br>\n";
if ($::NSRLDB eq "") {
print "Location: <tt>Not Configured</tt><br>\n";
}
elsif (-e "$::NSRLDB") {
print "Location: <tt>$::NSRLDB</tt><br>\n";
if (-e "$::NSRLDB" . "-md5.idx") {
print "Status: MD5 Index File Exists<br>\n";
}
else {
print "Status: Database has not been MD5 indexed<br>\n";
}
# Index Button
print "<p><a href=\"$::PROGNAME?mod=$::MOD_HASH&view=$Hash::DB_INDEX&"
. "hash_nsrl=1&$Args::baseargs\">"
. "<img src=\"pict/but_indexdb.jpg\" alt=\"Index DB\" "
. "width=116 height=20 border=\"0\">"
. "</a>\n";
# Lookup Button
if (-e "$::NSRLDB" . "-md5.idx") {
print "<p><b>Lookup</b><br>"
. "<form action=\"$::PROGNAME\" method=\"get\">"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_HASH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Hash::DB_LOOKUP\">\n"
. "<input type=\"hidden\" name=\"hash_nsrl\" value=\"1\">\n"
. Args::make_hidden()
. "<table cellspacing=\"10\" cellpadding=\"2\">\n<tr>\n"
. "<td align=\"left\">Enter MD5 Value: "
. "<input type=\"text\" name=\"md5\" size=40 maxlength=32></td>\n"
. "<td align=\"left\">"
. "<input type=\"image\" src=\"pict/but_lookup.jpg\" "
. "alt=\"Lookup\" width=116 height=20 border=0>\n"
. "</td></tr>\n</table>\n"
. "</form>";
}
}
else {
print "Location: <tt>$::NSRLDB</tt><br>\n"
. "ERROR: Database not found<br>\n";
}
print <<EOF4;
<hr><center>
<table width=600 cellspacing=\"0\" cellpadding=\"2\">
<tr>
<td align=center>
<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&view=$Caseman::VOL_OPEN&$Args::baseargs\">
<img src=\"pict/menu_b_close.jpg\" alt=\"Close\" width=\"167\" height=20 border=\"0\">
</a>
</td>
<td align=center>
<a href=\"$::HELP_URL\" target=\"_blank\">
<img src=\"pict/menu_b_help.jpg\" alt=\"Help\"
width=\"167\" height=20 border=0>
</a>
</td>
</tr>
</table>
EOF4
Print::print_html_footer();
return 0;
}
sub db_index {
Print::print_html_header("Hash Database Indexing");
if ( (exists $Args::args{'hash_exclude'})
&& ($Args::args{'hash_exclude'} == 1)
&& ($Caseman::exclude_db ne ""))
{
Print::log_host_info("Exclude Database Re-Indexed");
print "<hr><b>Exclude Database Indexing</b><p>\n";
index_md5sum($Caseman::exclude_db);
}
if ( (exists $Args::args{'hash_alert'})
&& ($Args::args{'hash_alert'} == 1)
&& ($Caseman::alert_db ne ""))
{
Print::log_host_info("Alert Database Re-Indexed");
print "<hr><b>Alert Database Indexing</b><p>\n";
index_md5sum($Caseman::alert_db);
}
if ( (exists $Args::args{'hash_nsrl'})
&& ($Args::args{'hash_nsrl'} == 1)
&& ($::NSRLDB ne ""))
{
Print::log_host_info("NSRL Database Re-Indexed");
print "<hr><b>NSRL Database Indexing</b><p>\n";
index_nsrl();
}
print "<p>Indexing Complete<br>\n"
. "<hr><p>\n<a href=\"$::PROGNAME?mod=$::MOD_HASH&view=$Hash::DB_MANAGER&"
. "$Args::baseargs\">\n"
. "<img src=\"pict/menu_b_hashdb.jpg\" width=\"167\" "
. "height=20 alt=\"Hash Databases\" border=\"0\"></a>\n";
Print::print_html_footer();
return 0;
}
# Lookup hashes in database
sub db_lookup {
Print::print_html_header("Hash Database Lookup");
unless ((exists $Args::args{'md5'})
&& ($Args::args{'md5'} =~ /^$::REG_MD5$/o))
{
Print::print_err("Invalid MD5 Argument");
}
if ( (exists $Args::args{'hash_nsrl'})
&& ($Args::args{'hash_nsrl'} == 1)
&& ($::NSRLDB ne ""))
{
print "<hr><b>NSRL Lookup</b><p>\n";
if (-e "$::NSRLDB") {
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/hfind' '$::NSRLDB' $Args::args{'md5'}");
print "$_<br>\n" while ($_ = Exec::read_pipe_line(*OUT));
close(OUT);
Print::log_host_inv("NSRL Lookup ($Args::args{'md5'})");
}
else {
print "NSRL Database Missing<br>\n";
Print::log_host_inv(
"NSRL Lookup ($Args::args{'md5'}) - Database Missing");
}
}
if ( (exists $Args::args{'hash_exclude'})
&& ($Args::args{'hash_exclude'} == 1)
&& ($Caseman::exclude_db ne ""))
{
print "<hr><b>Exclude Database Lookup</b><p>\n";
if (-e "$Caseman::exclude_db") {
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/hfind' '$Caseman::exclude_db' $Args::args{'md5'}");
print "$_<br>\n" while ($_ = Exec::read_pipe_line(*OUT));
close(OUT);
Print::log_host_inv("Exclude Database Lookup ($Args::args{'md5'})");
}
else {
print "Exclude Database Missing<br>\n";
Print::log_host_inv(
"Exclude Database Lookup ($Args::args{'md5'}) - Database Missing"
);
}
}
if ( (exists $Args::args{'hash_alert'})
&& ($Args::args{'hash_alert'} == 1)
&& ($Caseman::alert_db ne ""))
{
print "<hr><b>Alert Database Lookup</b><p>\n";
if (-e "$Caseman::alert_db") {
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/hfind' '$Caseman::alert_db' $Args::args{'md5'}");
print "$_<br>\n" while ($_ = Exec::read_pipe_line(*OUT));
close(OUT);
Print::log_host_inv("Alert Database Lookup ($Args::args{'md5'})");
}
else {
print "Alert Database Missing<br>\n";
Print::log_host_inv(
"Alert Database Lookup ($Args::args{'md5'}) - Database Missing"
);
}
}
print "<hr><p>\n"
. "If any of the hash databases need to be re-indexed, use the "
. "<U>Hash Database Manager</U><p>"
. "<a href=\"$::PROGNAME?mod=$::MOD_HASH&view=$Hash::DB_MANAGER&"
. "$Args::baseargs\" target=\"_top\">\n"
. "<img src=\"pict/menu_b_hashdb.jpg\" width=\"167\" "
. "height=20 alt=\"Hash Databases\" border=\"0\"></a>\n";
Print::print_html_footer();
return 0;
}
############ INTEGRITY CHECKS ##################
# Special view for printing integrity check menu
# We show any file that we have a reference for
# pass the md5 hash (from md5.txt) and then the sorted array
sub int_menu_print {
my %md5s = %{$_[0]};
my @sort = @{$_[1]};
for (my $i = 0; $i <= $#sort; $i++) {
print
"<tr><td align=\"right\"><tt><b>$Caseman::vol2sname{$sort[$i]}</b></tt></td>\n";
# It already exists, so make verify button
if (exists $md5s{$sort[$i]}) {
print "<td><tt>$md5s{$sort[$i]}</tt></td><td>"
. "<form action=\"$::PROGNAME\" method=\"get\" target=\"cont\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$sort[$i]\">\n"
. Args::make_hidden()
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_HASH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Hash::IMG_VERIFY\">\n"
. "<input type=\"image\" src=\"pict/int_b_valid.jpg\" "
. "alt=\"Validate\" border=\"0\">\n"
. "</form></td></tr>\n";
}
# we currenly only support integrity for raw and split image formats
elsif (($Caseman::vol2itype{$sort[$i]} ne "raw")
&& ($Caseman::vol2itype{$sort[$i]} ne "split"))
{
print
"<td colspan=2>Integrity checks for image type $Caseman::vol2itype{$sort[$i]} not yet supported</td></tr>\n";
}
# Generate New button
else {
print "<td>&nbsp;</td><td>"
. "<form action=\"$::PROGNAME\" method=\"get\" target=\"cont\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$sort[$i]\">\n"
. Args::make_hidden()
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_HASH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Hash::IMG_CALC\">\n"
. "<input type=\"image\" src=\"pict/int_b_calc.jpg\" "
. "alt=\"Calculate\" border=\"0\">\n"
. "</form></td></tr>\n";
}
}
return;
}
# Create a frame with two rows, one with the list of images to check
# and then the bottom actually does it.
sub img_list_fr {
Print::print_html_header_frameset(
"$Args::args{'case'}:$Args::args{'host'} Integrity Check");
print "<frameset rows=\"80%,20%\">\n";
# Block List
print "<frame src=\"$::PROGNAME?mod=$::MOD_HASH&view=$Hash::IMG_LIST&"
. "$Args::baseargs\">\n"
. "<frame src=\"$::PROGNAME?mod=$::MOD_HASH&view=$Hash::BLANK&"
. "$Args::baseargs\" name=\"cont\">\n"
. "</frameset>\n";
Print::print_html_footer_frameset();
return 0;
}
# Reads the MD5 file to fill in the MENU list for the integrity
# check mode
sub img_list {
Print::print_html_header("Image Integrity Menu");
my %md5s;
my @blkls;
my @str;
my @img;
my @body;
my @tl;
# Read the known values if the file exists
if (open(FILE, "$::host_dir" . "/md5.txt")) {
# Read the md5 values into a hash
while (<FILE>) {
s/^\s+//;
s/\s+$//;
if (/($::REG_MD5)\s+(.*)/o) {
$md5s{"$2"} = $1;
$md5s{"$2"} =~ tr/[a-f]/[A-F]/;
}
else {
print "Error reading line $. of md5.txt: $_<br>\n";
return 1;
}
}
close(FILE);
}
# sort the images into the different types
foreach my $k (keys %Caseman::vol2cat) {
if ($Caseman::vol2cat{$k} eq "image") {
push @img, $k;
}
elsif ($Caseman::vol2ftype{$k} eq "blkls") {
push @blkls, $k;
}
elsif ($Caseman::vol2ftype{$k} eq "strings") {
push @str, $k;
}
elsif ($Caseman::vol2ftype{$k} eq "body") {
push @body, $k;
}
elsif ($Caseman::vol2ftype{$k} eq "timeline") {
push @tl, $k;
}
}
print "<center><table cellspacing=\"10\" cellpadding=\"2\">";
# image files
if (scalar @img > 0) {
print "<tr><th colspan=3>"
. "<img src=\"pict/int_h_img.jpg\" alt=\"Image Files\">"
. "</th></tr>\n";
my @sort = sort { $a cmp $b } @img;
int_menu_print(\%md5s, \@sort);
}
# Unallocated (blkls) images
if (scalar @blkls > 0) {
print "<tr><th colspan=3>&nbsp;</th></tr>\n"
. "<tr><th colspan=3>"
. "<img src=\"pict/int_h_unalloc.jpg\" alt=\"Unallocated Data Files\">"
. "</th></tr>\n";
my @sort = sort { $a cmp $b } @blkls;
int_menu_print(\%md5s, \@sort);
}
# Strings files (of blkls or fs images)
if (scalar @str > 0) {
print "<tr><th colspan=3>&nbsp;</th></tr>\n"
. "<tr><th colspan=3>"
. "<img src=\"pict/int_h_str.jpg\" alt=\"Strings of Images\">"
. "</th></tr>\n";
my @sort = sort { $a cmp $b } @str;
int_menu_print(\%md5s, \@sort);
}
# timeline body files
if (scalar @body > 0) {
print "<tr><th colspan=3>&nbsp;</th></tr>\n"
. "<tr><th colspan=3>"
. "<img src=\"pict/int_h_data.jpg\" alt=\"Timeline Data Files\">"
. "</th></tr>\n";
my @sort = sort { $a cmp $b } @body;
int_menu_print(\%md5s, \@sort);
}
# timeline files
if (scalar @tl > 0) {
print "<tr><th colspan=3>&nbsp;</th></tr>\n"
. "<tr><th colspan=3>"
. "<img src=\"pict/int_h_tl.jpg\" alt=\"Timelines\">"
. "</th></tr>\n";
my @sort = sort { $a cmp $b } @tl;
int_menu_print(\%md5s, \@sort);
}
print <<EOF;
</table>
<p>
<table cellspacing=20 width=600 cellpadding=2>
<tr>
<td><a href=\"$::PROGNAME?$Args::baseargs&mod=$::MOD_CASEMAN&view=$Caseman::VOL_OPEN\" target=\"_top\">
<img src=\"pict/menu_b_close.jpg\" alt=\"close\"
width=\"167\" height=20 border=\"0\">
</a>
</td>
<td><a href=\"$::PROGNAME?$Args::baseargs&mod=$::MOD_HASH&view=$Hash::IMG_LIST_FR\" target=\"_top\">
<img src=\"pict/menu_b_ref.jpg\" alt=\"Refresh\"
width=\"167\" height=20 border=\"0\">
</a>
</td>
<td align=center>
<a href=\"$::HELP_URL\" target=\"_blank\">
<img src=\"pict/menu_b_help.jpg\" alt=\"Help\"
width=\"167\" height=20 border=0>
</a>
</td>
</tr>
</table>
EOF
Print::print_html_footer();
return 0;
}
# Pass the relative path (images/xyz) of the file. The MD5 is
# returned (or NULL) (in all caps)
sub lookup_md5 {
my $vol = shift;
my $md5 = "";
my $md5_file = "$::host_dir/md5.txt";
if (-e "$md5_file") {
unless (open(FILE, $md5_file)) {
print "Error opening $md5_file<br>\n";
return "";
}
while (<FILE>) {
s/^\s+//;
s/\s+$//;
if (/($::REG_MD5)\s+(.*)/o) {
my $m = $1;
if ($2 =~ /$vol$/) {
$md5 = $m;
$md5 =~ tr/[a-f]/[A-F]/;
last;
}
}
else {
print "Error reading line $. of $md5_file: $_<br>\n";
return "";
}
}
close(FILE);
}
return $md5;
}
sub img_verify {
Print::print_html_header("Image Integrity Check");
my $vol = Args::get_vol('vol');
my $md5 = lookup_md5($vol);
if ($md5 eq "") {
print
"The MD5 value of <tt>$Caseman::vol2sname{$vol}</tt> was not found<br>"
. "It can be calculated by pressing the button below."
. "<br><br>\n<form action=\"$::PROGNAME\" method=\"get\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_HASH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Hash::IMG_CALC\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n"
. Args::make_hidden()
. "<input type=\"image\" src=\"pict/int_b_calc.jpg\" "
. "alt=\"Calculate\" border=\"0\">\n</form>";
return 1;
}
Print::log_host_inv("$Caseman::vol2sname{$vol}: Checking image integrity");
print "Original MD5: <tt>$md5</tt><br>\n";
# We have the original value, now get the new one
my $img = $Caseman::vol2path{$vol};
my $cur;
if ($Caseman::vol2itype{$vol} eq "split") {
$cur = calc_md5_split($img);
}
else {
$cur = calc_md5($img);
}
if ($cur =~ /^$::REG_MD5$/o) {
print "Current MD5: <tt>$cur</tt><br><br>\n";
if ($cur eq $md5) {
print "Pass<br>\n";
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: Image integrity check PASSED");
}
else {
print "<font color=\"$::DEL_COLOR[0]\">Fail: Restore from backup"
. "<br>\n";
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: Image integrity check FAILED");
}
Print::print_html_footer();
return 0;
}
else {
print "$cur<br>\n";
Print::print_html_footer();
return 1;
}
}
# Calculate the MD5 value of a file (given the full path)
# return the value in upper case
# This one supports only single files - not split volumes
sub calc_md5 {
my $img = shift;
my $hit_cnt = 0;
$SIG{ALRM} = sub {
if (($hit_cnt++ % 5) == 0) {
print "+";
}
else {
print "-";
}
alarm(5);
};
alarm(5);
local *OUT;
Exec::exec_pipe(*OUT, "'$::MD5_EXE' $img");
alarm(0);
$SIG{ALRM} = 'DEFAULT';
print "<br>\n"
if ($hit_cnt > 0);
my $out = Exec::read_pipe_line(*OUT);
close(OUT);
$out = "Error calculating MD5"
if ((!defined $out) || ($out eq ""));
if ($out =~ /^($::REG_MD5)\s+/) {
my $m = $1;
$m =~ tr/[a-f]/[A-F]/;
return $m;
}
else {
return $out;
}
}
# Same as the version above, but this one can do split images
# it fails though if the file is not a multiple of 512
sub calc_md5_split {
my $img = shift;
my $hit_cnt = 0;
$SIG{ALRM} = sub {
if (($hit_cnt++ % 5) == 0) {
print "+";
}
else {
print "-";
}
alarm(5);
};
alarm(5);
local *OUT;
# We use the blkls method so that we can handle split images
Exec::exec_pipe(*OUT, "'$::TSKDIR/blkls' -f raw -e $img | '$::MD5_EXE'");
alarm(0);
$SIG{ALRM} = 'DEFAULT';
print "<br>\n"
if ($hit_cnt > 0);
my $out = Exec::read_pipe_line(*OUT);
close(OUT);
$out = "Error calculating MD5"
if ((!defined $out) || ($out eq ""));
if ($out =~ /^($::REG_MD5)\s+/) {
my $m = $1;
$m =~ tr/[a-f]/[A-F]/;
return $m;
}
else {
return $out;
}
}
# Pass it the full path and the short name
# and it adds it to md5.txt and returns the MD5
sub int_create_wrap {
my $vol = shift;
my $img = $Caseman::vol2path{$vol};
my $m;
if ( (exists $Caseman::vol2itype{$vol})
&& ($Caseman::vol2itype{$vol} eq "split"))
{
$m = calc_md5_split($img);
}
else {
$m = calc_md5($img);
}
Caseman::update_md5($vol, $m) if ($m =~ /^$::REG_MD5$/o);
return $m;
}
sub img_calc {
Print::print_html_header("Image Integrity Creation");
my $vol = Args::get_vol('vol');
print "Calculating MD5 value for <tt>$Caseman::vol2sname{$vol}</tt><br>\n";
Print::log_host_inv("$Caseman::vol2sname{$vol}: Calculating MD5 value");
my $m = int_create_wrap($vol);
print "MD5: <tt>$m</tt><br>\n";
print "<br>Value saved to host file<br><br>\n";
Print::print_html_footer();
return 0;
}
# Conver the 'image' format to the 'volume' format
# Make one central file
sub convert {
my %img2vol = %{shift()};
Print::log_host_info("Converting format of MD5 hash files");
# Get out of here if there are no hash files
return 0
unless ((-e "$::host_dir" . "$::IMGDIR" . "/md5.txt")
|| (-e "$::host_dir" . "$::DATADIR" . "/md5.txt"));
# We are going ot make a single file
my $md5_file_new = "$::host_dir" . "/md5.txt";
open MD5_NEW, ">$md5_file_new"
or die "Can't open writing file: $md5_file_new";
# Read the md5s for the image directory
my $md5_file = "$::host_dir" . "$::IMGDIR" . "/md5.txt";
if (open(FILE, $md5_file)) {
# Read the md5 values into a hash
while (<FILE>) {
s/^\s+//;
s/\s+$//;
if (/($::REG_MD5)\s+(.*)/o) {
my $md5 = $1;
my $img = $2;
unless (exists $img2vol{$img}) {
print STDERR
"Error finding image during hash file conversion: $img. Skipping\n";
next;
}
my $vol = $img2vol{$img};
print MD5_NEW "$md5 $vol\n";
}
else {
print MD5_NEW "$_";
}
}
close(FILE);
rename $md5_file, $md5_file . ".bak";
}
# Now do the data directory
$md5_file = "$::host_dir" . "$::DATADIR" . "/md5.txt";
if (open(FILE, $md5_file)) {
# Read the md5 values into a hash
while (<FILE>) {
s/^\s+//;
s/\s+$//;
if (/($::REG_MD5)\s+(.*)/o) {
my $md5 = $1;
my $img = $2;
unless (exists $img2vol{$img}) {
print STDERR
"Error finding image during hash file conversion: $img. Skipping\n";
next;
}
my $vol = $img2vol{$img};
print MD5_NEW "$md5 $vol\n";
}
else {
print MD5_NEW "$_";
}
}
close(FILE);
rename $md5_file, $md5_file . ".bak";
}
close(MD5_NEW);
return 0;
}
# Blank Page
sub blank {
Print::print_html_header("");
print "<!-- This Page Intentionally Left Blank -->\n";
Print::print_html_footer();
return 0;
}

954
lib/Kwsrch.pm Normal file
View File

@ -0,0 +1,954 @@
#
# Keyword search mode
#
# 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 Kwsrch;
require 'search.pl';
$Kwsrch::ENTER = 1;
$Kwsrch::RESULTS_FR = 2;
$Kwsrch::RUN = 3;
$Kwsrch::LOAD = 4;
$Kwsrch::BLANK = 5;
my $IMG_DETAILS = 0x80;
sub main {
# By default, show the main frame
$Args::args{'view'} = $Args::enc_args{'view'} = $Kwsrch::ENTER
unless (exists $Args::args{'view'});
Args::check_view();
my $view = Args::get_view();
if ($view == $Kwsrch::BLANK) {
blank();
return 0;
}
# Check Basic Args
Args::check_vol('vol');
# These windows don't need the meta data address
if ($view == $Kwsrch::ENTER) {
return enter();
}
elsif ($view == $Kwsrch::RESULTS_FR) {
return results_fr();
}
elsif ($view == $Kwsrch::RUN) {
return run();
}
elsif ($view == $Kwsrch::LOAD) {
return load();
}
else {
Print::print_check_err("Invalid Keyword Search View");
}
}
my $CASE_INSENS = 1;
my $CASE_SENS = 0;
my $REG_EXP = 1;
my $STRING = 0;
# Form to enter search data
sub enter {
my $vol = Args::get_vol('vol');
Print::print_html_header("Search on $Caseman::vol2sname{$vol}");
my $ftype = $Caseman::vol2ftype{$vol};
if ($ftype eq 'blkls') {
print "<center><h3>Keyword Search of Unallocated Space</h3>\n";
}
elsif ($ftype eq 'swap') {
print "<center><h3>Keyword Search of swap partition</h3>\n";
}
elsif ($ftype eq 'raw') {
print "<center><h3>Keyword Search of raw data</h3>\n";
}
elsif ($Caseman::vol2cat{$vol} eq "disk") {
print "<center><h3>Keyword Search of disk</h3>\n";
}
else {
print
"<center><h3>Keyword Search of Allocated and Unallocated Space</h3>\n";
}
# @@@ Fix this - caused by writing all results to a file
if ($::LIVE == 1) {
Print::print_err(
"Keyword searching is temporarily not available during live analysis mode"
);
}
print "<form action=\"$::PROGNAME\" method=\"get\">\n"
. "Enter the keyword string or expression to search for:<br> <input type=\"text\" name=\"str\"><br><br>\n"
. Args::make_hidden()
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_KWSRCH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Kwsrch::RESULTS_FR\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n";
print "<table width=400><tr>\n"
. "<td width=200 align=center><input type=\"checkbox\" name=\"ascii\" value=\"1\" CHECKED>"
. "ASCII \n</td>"
. "<td width=200 align=center><input type=\"checkbox\" name=\"unicode\" value=\"1\" CHECKED>"
. "Unicode</td></tr>\n"
. "<tr><td align=center><input type=\"checkbox\" name=\"srch_case\" value=\"$CASE_INSENS\">"
. "Case Insensitive</td>\n"
. "<td align=center><input type=\"checkbox\" name=\"regexp\" value=\"$REG_EXP\">\n"
. "<tt>grep</tt> Regular Expression</td></tr></table>\n"
. "<input type=\"image\" src=\"pict/but_search.jpg\" "
. "alt=\"Search\" border=\"0\">\n</form>\n";
if ($::LIVE == 0) {
print "<table width=600><tr>\n";
# If we are a non-blkls image and one exists - make a button to load it
if (($ftype ne 'blkls') && (exists $Caseman::vol2blkls{$vol})) {
print "<td align=center width=200>"
. "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FRAME\">\n"
. "<input type=\"hidden\" name=\"submod\" value=\"$::MOD_KWSRCH\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$Caseman::vol2blkls{$vol}\">\n"
. Args::make_hidden()
. "<input type=\"image\" src=\"pict/srch_b_lun.jpg\" "
. "alt=\"Load Unallocated Image\" border=\"0\">\n<br></form></td>\n";
}
# If we are a blkls and the original exists - make a button to load it
elsif (($ftype eq 'blkls')
&& (exists $Caseman::mod2vol{$vol}))
{
print "<td align=center width=200>"
. "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FRAME\">\n"
. "<input type=\"hidden\" name=\"submod\" value=\"$::MOD_KWSRCH\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$Caseman::mod2vol{$vol}\">\n"
. Args::make_hidden()
. "<input type=\"image\" src=\"pict/srch_b_lorig.jpg\" "
. "alt=\"Load Original Image\" border=\"0\">\n<br></form></td>\n";
}
# Strings Button
if ( (!(exists $Caseman::vol2str{$vol}))
|| (!(exists $Caseman::vol2uni{$vol})))
{
my $dest_vol = $vol;
$dest_vol = $Caseman::mod2vol{$vol}
if exists($Caseman::mod2vol{$vol});
print "<td align=center width=200>"
. "<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_DETAILS\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$dest_vol\">\n"
. Args::make_hidden()
. "<input type=\"image\" src=\"pict/srch_b_str.jpg\" "
. "alt=\"Extract Strings\" border=\"0\">\n<br></form></td>\n";
}
# Unallocated Space Button
if ( ($Fs::is_fs{$ftype})
&& (!(exists $Caseman::vol2blkls{$vol})))
{
print "<td align=center width=200>"
. "<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_DETAILS\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n"
. Args::make_hidden()
. "<input type=\"image\" src=\"pict/srch_b_un.jpg\" "
. "alt=\"Extract Unallocated Space\" border=\"0\">\n<br></form></td>\n";
}
print "</tr></table>\n";
}
print "<a href=\"help/grep.html\" target=\"_blank\">"
. "Regular Expression Cheat Sheet</a>\n<br><br>\n";
print "<p><font color=\"red\">NOTE:</font> The keyword search runs "
. "<tt>grep</tt> on the image.<br>\n"
. "A list of what will and "
. "what will not be found is available "
. "<a href=\"help/grep_lim.html\" target=\"_blank\">here</a>.<br>\n";
# Section for previous searches
if ($::LIVE == 0) {
my $srch_name = get_srch_fname(0);
if (-e $srch_name) {
print "<hr><h3>Previous Searches</h3>\n" . "<table width=600>\n";
my $row_idx = 0;
# Cycle through the files
for (my $srch_idx = 0;; $srch_idx++) {
$srch_name = get_srch_fname($srch_idx);
last unless (-e $srch_name);
# Open the file to get the string and count
unless (open(SRCH, "$srch_name")) {
print "Error opening search file: $srch_name\n";
return 1;
}
my $prev_str = "";
my $prev_cnt = 0;
while (<SRCH>) {
unless (/^(\d+)\|(.*?)?\|(.*)$/) {
print
"Error pasing header of search file: $srch_name\n";
return 1;
}
$prev_cnt = $1;
$prev_str = $3;
if (length($prev_str) > 32) {
$prev_str = substr($prev_str, 0, 32);
$prev_str .= "...";
}
last;
}
close(SRCH);
print "<tr>\n" if ($row_idx == 0);
print " <td align=center width=150>\n"
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_KWSRCH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Kwsrch::RESULTS_FR\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n"
. "<input type=\"hidden\" name=\"srchidx\" value=\"$srch_idx\">\n"
. Args::make_hidden();
print "<input type=\"SUBMIT\" value=\"$prev_str ($prev_cnt)\">"
. "<br></form>\n";
if ($row_idx == 3) {
print "</tr>\n";
$row_idx = 0;
}
else {
$row_idx++;
}
}
print "</table>\n";
}
}
# Predefined expressions from search.pl
print "<hr><h3>Predefined Searches</h3>\n";
print "<table width=600>\n";
my $row_idx = 0;
my $r;
foreach $r (keys %Kwsrch::auto_srch) {
$Kwsrch::auto_srch_reg{$r} = 0
unless (defined $Kwsrch::auto_srch_reg{$r});
$Kwsrch::auto_srch_csense{$r} = 1
unless (defined $Kwsrch::auto_srch_csense{$r});
print "<tr>\n" if ($row_idx == 0);
# @@@ Make a unicode option in predefined
print " <td align=center width=150>\n"
. "<form action=\"$::PROGNAME\" method=\"get\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_KWSRCH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Kwsrch::RESULTS_FR\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n"
. "<input type=\"hidden\" name=\"str\" value=\"$Kwsrch::auto_srch{$r}\">\n"
. "<input type=\"hidden\" name=\"ascii\" value=\"1\">\n"
. Args::make_hidden();
if ($Kwsrch::auto_srch_reg{$r} == 1) {
print
"<input type=\"hidden\" name=\"regexp\" value=\"$REG_EXP\">\n";
}
if ($Kwsrch::auto_srch_csense{$r} == 0) {
print
"<input type=\"hidden\" name=\"srch_case\" value=\"$CASE_INSENS\">\n";
}
print "<input type=\"SUBMIT\" value=\"$r\"><br></form>\n" . " </td>\n";
if ($row_idx == 3) {
print "</tr>\n";
$row_idx = 0;
}
else {
$row_idx++;
}
}
print "</table>\n";
Print::print_html_footer();
return 0;
}
# MAIN WITH RESULTS
# Page that makes frame with the results on left and data units on right
sub results_fr {
my $vol = Args::get_vol('vol');
# A string was given for a new search
if (exists $Args::args{'str'}) {
Args::check_str();
Print::print_html_header_frameset(
"Search on $Caseman::vol2sname{$vol} for $Args::args{'str'}");
print "<frameset cols=\"35%,65%\">\n";
my $srch_case = "";
$srch_case = "&srch_case=$Args::args{'srch_case'}"
if (exists $Args::args{'srch_case'});
my $regexp = "";
$regexp = "&regexp=$Args::args{'regexp'}"
if (exists $Args::args{'regexp'});
my $ascii = "";
$ascii = "&ascii=$Args::args{'ascii'}"
if (exists $Args::args{'ascii'});
my $unicode = "";
$unicode = "&unicode=$Args::args{'unicode'}"
if (exists $Args::args{'unicode'});
# Block List
print "<frame src=\"$::PROGNAME?"
. "mod=$::MOD_KWSRCH&view=$Kwsrch::RUN&"
. "$Args::baseargs$srch_case$regexp&str=$Args::enc_args{'str'}$ascii$unicode\">\n";
}
elsif (exists $Args::args{'srchidx'}) {
Args::check_srchidx();
Print::print_html_header_frameset(
"Search on $Caseman::vol2sname{$vol} for Index $Args::args{'srchidx'}"
);
print "<frameset cols=\"35%,65%\">\n";
# Block List
print "<frame src=\"$::PROGNAME?"
. "mod=$::MOD_KWSRCH&view=$Kwsrch::LOAD&"
. "$Args::baseargs&srchidx=$Args::enc_args{'srchidx'}\">\n";
}
# Block Contents
print "<frame src=\"$::PROGNAME?mod=$::MOD_KWSRCH&view=$Kwsrch::BLANK&"
. "$Args::baseargs\" name=\"content\">\n"
. "</frameset>\n";
Print::print_html_footer_frameset();
return 0;
}
# Find an empty file to save the keyword searches to
sub find_srch_file {
my $vol = Args::get_vol('vol');
my $out_name = "$::host_dir" . "$::DATADIR/$Caseman::vol2sname{$vol}";
my $i;
for ($i = 0; -e "${out_name}-${i}.srch"; $i++) { }
return "${out_name}-${i}.srch";
}
# Pass the index
# return the full path of the file returned
sub get_srch_fname {
my $idx = shift;
my $vol = Args::get_vol('vol');
return "$::host_dir"
. "$::DATADIR"
. "/$Caseman::vol2sname{$vol}-${idx}.srch";
}
sub load {
Args::check_srchidx();
Print::print_html_header("");
if ($::LIVE == 1) {
print "Searches cannot be loaded during live analysis<br>\n";
return 1;
}
my $srch_name = get_srch_fname($Args::args{'srchidx'});
print "<b><a href=\"$::PROGNAME?mod=$::MOD_KWSRCH&view=$Kwsrch::ENTER&"
. "$Args::baseargs\" "
. "target=\"_parent\">New Search</a></b>\n<p>";
print_srch_results($srch_name);
Print::print_html_footer();
return 0;
}
# performs actual search, saves hits to file, and calls method to print
sub run {
Args::check_str();
Print::print_html_header("");
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 $orig_str = Args::get_str();
my $grep_str = $orig_str; # we will escape some values in the grep ver
# Check for a search string
if ($orig_str eq "") {
print "You must enter a string value to search<br>\n";
print "<b><a href=\"$::PROGNAME?mod=$::MOD_KWSRCH&view=$Kwsrch::ENTER&"
. "$Args::baseargs\" target=\"_parent\">New Search</a></b>\n<p>";
return 1;
}
my $log = ""; # Log entry string
my $ascii = 0;
my $unicode = 0;
if ((exists $Args::args{'ascii'}) && ($Args::args{'ascii'} == 1)) {
$ascii = 1;
$log .= "ASCII, ";
}
if ((exists $Args::args{'unicode'}) && ($Args::args{'unicode'} == 1)) {
$unicode = 1;
$log .= "Unicode, ";
}
if (($ascii == 0) && ($unicode == 0)) {
print "You must choose either ASCII or Unicode to search<br>\n";
print "<b><a href=\"$::PROGNAME?mod=$::MOD_KWSRCH&view=$Kwsrch::ENTER&"
. "$Args::baseargs\" target=\"_parent\">New Search</a></b>\n<p>";
return 1;
}
my $grep_flag = ""; # Flags to pass to grep
# Check if search is case insensitive
my $case = 0;
if ( (exists $Args::args{'srch_case'})
&& ($Args::args{'srch_case'} == $CASE_INSENS))
{
$grep_flag = "-i";
$case = 1;
$log .= "Case Insensitive ";
}
# Check if search is a regular expression
my $regexp = 0;
if ((exists $Args::args{'regexp'}) && ($Args::args{'regexp'} == $REG_EXP)) {
$grep_flag .= " -E";
$regexp = 1;
$log .= "Regular Expression ";
}
# if not a reg-exp, we need to escape some special values that
# 'grep' will misinterpret
else {
$grep_str =~ s/\\/\\\\/g; # \
$grep_str =~ s/\./\\\./g; # .
$grep_str =~ s/\[/\\\[/g; # [
$grep_str =~ s/\^/\\\^/g; # ^
$grep_str =~ s/\$/\\\$/g; # $
$grep_str =~ s/\*/\\\*/g; # *
# We need to add ' to end begin and end of the search as well
if ($grep_str =~ /\'/) {
$grep_str =~ s/\'/\\\'/g; # '
$grep_str = "'$grep_str'";
}
$grep_str =~ s/^\-/\\\-/; # starting with - (mistakes for an arg)
}
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: ${log}search for $grep_str");
# Get the addressable unit of image
my $bs = Args::get_unitsize();
# $norm_str is normalized to find the "hit" in the output
my $norm_str = $orig_str;
# make this lowercase if we are doing case insens
$norm_str =~ tr/[A-Z]/[a-z]/ if ($case == 1);
my $norm_str_len = length($norm_str);
# array to pass to printing method
my @results;
my $name_uni = "";
my $name_asc = "";
# round 0 is for ASCII and 1 is for Unicode
for (my $i = 0; $i < 2; $i++) {
next if (($i == 0) && ($ascii == 0));
next if (($i == 1) && ($unicode == 0));
@results = ();
local *OUT;
my $hit_cnt = 0;
$SIG{ALRM} = sub {
if (($hit_cnt++ % 5) == 0) {
print "+";
}
else {
print "-";
}
alarm(5);
};
alarm(5);
if ($i == 0) {
print "<b>Searching for ASCII</b>: ";
}
else {
print "<b>Searching for Unicode</b>: ";
}
# if the string is less than 4 chars, then it will not be in the
# strings file so it will be searched for the slow way
if (length($orig_str) < 4) {
my $ltmp = length($orig_str);
if ($i == 0) {
if ( (($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 -$ltmp | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d -$ltmp | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
}
else {
if ( (($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 -$ltmp | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d -e l -$ltmp | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
}
}
# Use the strings file if it exists
elsif (($i == 0) && (defined $Caseman::vol2str{$vol})) {
my $str_vol = $Caseman::vol2path{$Caseman::vol2str{$vol}};
Exec::exec_pipe(*OUT,
"'$::GREP_EXE' $grep_flag '$grep_str' $str_vol");
}
elsif (($i == 1) && (defined $Caseman::vol2uni{$vol})) {
my $str_vol = $Caseman::vol2path{$Caseman::vol2uni{$vol}};
Exec::exec_pipe(*OUT,
"'$::GREP_EXE' $grep_flag '$grep_str' $str_vol");
}
# Run strings on the image first and then grep that
else {
if ($i == 0) {
if ( (($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 | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
}
else {
if ( (($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 | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d -e l | '$::GREP_EXE' $grep_flag '$grep_str'"
);
}
}
}
alarm(0);
$SIG{ALRM} = 'DEFAULT';
# Cycle through the results and put them in an array
while ($_ = Exec::read_pipe_line(*OUT)) {
# Parse out the byte offset and hit string
if (/^\s*(\d+)\s+(.+)$/) {
my $off = $1;
my $hit_str_orig = $2;
my $idx = 0;
# Make a copy that we can modify & play with
my $hit_str = $hit_str_orig;
$hit_str =~ tr/[A-Z]/[a-z]/ if ($case == 1);
# How long was the string that we hit?
my $hit_str_len = length($hit_str);
# I'm not sure how to find a grep re in the hit yet, so
# for now we do not get the exact offset
if ($regexp) {
my $b = int($off / $bs);
my $o = int($off % $bs);
# $hit =~ s/\n//g;
push @results, "${b}|${o}|";
next;
}
# There could be more than one keyword in the string
# so cycle through all of them
my $psize = scalar(@results);
while (($idx = index($hit_str, $norm_str, $idx)) > -1) {
# The summary of the hit starts 5 chars before it
my $sum_min = $idx - 5;
$sum_min = 0 if ($sum_min < 0);
# Goto 5 after, if there is still space
my $sum_max = $idx + $norm_str_len + 5;
$sum_max = $hit_str_len if ($sum_max > $hit_str_len);
my $sum_hit =
substr($hit_str_orig, $sum_min, $sum_max - $sum_min);
# remove new lines
$sum_hit =~ s/\n/ /g;
# The actual offset for Unicode is 2 bytes per char
my $tmpidx = $idx;
$tmpidx *= 2
if ($i == 1);
my $b = int(($off + $tmpidx) / $bs);
my $o = int(($off + $tmpidx) % $bs);
push @results, "${b}|${o}|$sum_hit";
# advance index to find next hit
$idx++;
}
# If we did not find a term, then just print what
# was found-this occurs bc index does not find it
# sometimes.
if ($psize == scalar(@results)) {
my $b = int($off / $bs);
my $o = int($off % $bs);
# $hit =~ s/\n//g;
push @results, "${b}|${o}|";
next;
}
}
# A negative offset is common on FreeBSD with large images
elsif (/^\s*(\-\d+):?\s*(.+)$/) {
print "ERROR: Negative byte offset ($1) Your version of "
. "strings likely does not support large files: $2<br>\n";
}
else {
print "Error parsing grep result: $_<br>\n";
}
}
close(OUT);
print " <b>Done</b><br>";
my $cnt = scalar(@results);
my $srch_name = "";
if ($::LIVE == 0) {
print "<b>Saving</b>: ";
# Find a file to save the results to
$srch_name = find_srch_file();
unless (open(IDX, ">$srch_name")) {
print "Error opening $srch_name\n";
return (1);
}
# Print the header
if ($i == 0) {
print IDX "$cnt|${grep_flag}|${orig_str}|ascii\n";
$name_asc = $srch_name;
}
else {
print IDX "$cnt|${grep_flag}|${orig_str}|unicode\n";
$name_uni = $srch_name;
}
for (my $a = 0; $a < $cnt; $a++) {
print IDX "$results[$a]\n";
}
close(IDX);
print " <b>Done</b><br>\n";
}
if ($i == 0) {
print "$cnt hits";
print "- <a href=\"#ascii\">link to results</a>" if ($cnt > 0);
print "<br>\n";
}
else {
print "$cnt hits";
print "- <a href=\"#unicode\">link to results</a>" if ($cnt > 0);
print "<br>\n";
}
print "<hr>\n";
}
print "<b><a href=\"$::PROGNAME?mod=$::MOD_KWSRCH&view=$Kwsrch::ENTER&"
. "$Args::baseargs\" "
. "target=\"_parent\">New Search</a></b>\n<p>";
if ($::LIVE == 0) {
if ($ascii == 1) {
print_srch_results($name_asc);
}
if ($unicode == 1) {
print_srch_results($name_uni);
}
}
Print::print_html_footer();
return 0;
}
# Args are search string, grep flags, and array of hits
sub print_srch_results {
if (scalar(@_) != 1) {
print "Missing Args for print_srch_results()\n";
return 1;
}
my $srch_name = shift;
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
my $addr_str = $Fs::addr_unit{$ftype};
unless (open(SRCH, "$srch_name")) {
print "Error opening search file: $srch_name\n";
return 1;
}
my @results;
my $grep_str = "";
my $grep_flag = "";
my $cnt = 0;
my $type = 0; # ASCII iis 0 and Unicode is 1
my $prev = -1;
while (<SRCH>) {
# The first line is a header
if ($. == 1) {
if (/^(\d+)\|(.*?)?\|(.*)$/) {
$cnt = $1;
$grep_flag = $2;
$grep_str = $3;
$type = 0;
}
else {
print "Error pasing header of search file: $srch_name\n";
close(SRCH);
return 1;
}
if ($grep_str =~ /^(.*?)\|unicode$/) {
$grep_str = $1;
$type = 1;
}
elsif ($grep_str =~ /^(.*?)\|ascii$/) {
$grep_str = $1;
}
my $grep_str_html = Print::html_encode($grep_str);
print "<hr>\n";
if ($type == 0) {
print "<a name=\"ascii\">\n";
}
else {
print "<a name=\"unicode\">\n";
}
if ($cnt == 0) {
print "<b><tt>$grep_str_html</tt> was not found</b><br>\n";
}
elsif ($cnt == 1) {
print
"<b>1 occurrence of <tt>$grep_str_html</tt> was found</b><br>\n";
}
else {
print
"<b>$cnt occurrences of <tt>$grep_str_html</tt> were found</b><br>\n";
}
print "Search Options:<br>\n";
if ($type == 0) {
print "&nbsp;&nbsp;ASCII<br>\n";
}
else {
print "&nbsp;&nbsp;Unicode<br>\n";
}
if ($grep_flag =~ /\-i/) {
print "&nbsp;&nbsp;Case Insensitive<br>\n";
}
else {
print "&nbsp;&nbsp;Case Sensitive<br>\n";
}
if ($grep_flag =~ /\-E/) {
print "&nbsp;&nbsp;Regular Expression<br>\n";
}
print "<hr>\n";
if ($cnt > 1000) {
print "There were more than <U>1000</U> hits.<br>\n";
print "Please revise the search to a managable amount.\n";
print
"<p>The $cnt hits can be found in: <tt>$srch_name</tt><br>\n";
close(SRCH);
return 0;
}
next;
}
unless (/^(\d+)\|(\d+)\|(.*)?$/) {
print "Error parsing results: $_\n";
close(SRCH);
return 1;
}
my $blk = $1;
my $off = $2;
my $str = $3;
if ($blk != $prev) {
my $url =
"$::PROGNAME?mod=$::MOD_DATA&view=$Data::CONT_MENU_FR&$Args::baseargs&block=$blk";
print "<br>\n$addr_str $blk (<a href=\"$url&sort=$Data::SORT_HEX\" "
. "target=content>Hex</a> - "
. "<a href=\"$url&sort=$Data::SORT_ASC\" target=content>"
. "Ascii</a>";
print
" - <a href=\"$::PROGNAME?$Args::baseargs&mod=$::MOD_DATA&view=$Data::CONT_MENU_FR&"
. "mnt=$Args::enc_args{'mnt'}&vol=$Caseman::mod2vol{$vol}&"
. "btype=$Data::ADDR_BLKLS&block=$blk\" target=content>Original</a>"
if ( ($ftype eq 'blkls')
&& (exists $Caseman::mod2vol{$vol}));
print ")<br>";
$prev = $blk;
}
my $occ = $. - 1;
if ($str ne "") {
$str = Print::html_encode($str);
print "$occ: $off (<tt>$str</tt>)<br>\n";
}
else {
print "$occ: $off<br>\n";
}
}
close(SRCH);
return 0;
}
# Blank Page
sub blank {
Print::print_html_header("");
print "<!-- This Page Intentionally Left Blank -->\n";
Print::print_html_footer();
return 0;
}
1;

357
lib/Main.pm Normal file
View File

@ -0,0 +1,357 @@
#
# Main.pm
# Autopsy Forensic Browser
#
# This file requires The Sleuth Kit
# www.sleuthkit.org
#
# 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.
#
use lib './';
use strict;
use Appsort;
use Appview;
use Args;
use Caseman;
use Data;
use Exec;
use File;
use Filesystem;
use Frame;
use Fs;
use Hash;
use Kwsrch;
use Meta;
use Notes;
use Print;
use Timeline;
use Vs;
require 'conf.pl';
require 'define.pl';
# Get rid of insecure settings
$ENV{PATH} = "";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
# Formats for regular expressions
# Year.Mon.Day Hr:Min:Sec (TZ)
$::REG_DAY = '\d\d\d\d\-\d\d\-\d\d';
$::REG_TIME = '\d\d:\d\d:\d\d';
$::REG_ZONE_ARGS = '[\w\+\-\/\_]+';
$::REG_ZONE2 = '\([\w\+\- ]*\)';
$::REG_DATE = "$::REG_DAY" . '\s+' . "$::REG_TIME" . '\s+' . "$::REG_ZONE2";
$::REG_FTYPE = '[\w\-]+';
$::REG_SKEW = '[\+\-]?\d+';
$::REG_MTYPE = '[\?bcdflprsvw-]'; # Type according to meta data
$::REG_FILE = '[\w\-\_\.]+';
$::REG_CASE = $::REG_FILE;
$::REG_HOST = '[\w\-\_\.]+';
$::REG_INVESTIG = '[\w]+';
$::REG_IMG = "$::REG_FILE" . '/' . "$::REG_FILE";
$::REG_IMG_PATH = '/[\w\-\_\.\/]+';
$::REG_IMG_PATH_WILD = '/[\w\-\_\.\/]+\*?';
$::REG_IMG_CONFIG = '[\w\-\_\.\/ ]+';
$::REG_FNAME = $::REG_FILE;
$::REG_MNT = '[\w\-\_\.\/\:\\\\]+';
$::REG_SEQ_FILE = '[\w\s\-\_\.\/\:\\\\]+';
$::REG_HASHDB = '[\w\-\_\.\,\/]+';
$::REG_IMGTYPE = '[\w\,]+';
$::REG_INAME = '[\w]+';
$::REG_VNAME = '[\w]+';
$::REG_META = '[\d-]+';
$::REG_MD5 = '[0-9a-fA-F]{32,32}';
$::HELP_URL = "help/index.html";
# host_dir and case_dir will end with a '/'
$::host_dir = "";
$::case_dir = "";
################## NEW STUFF ##########################
# MODULES
# If the values of these are changed, or if new modules are added,
# Then the below pseudo-binary sort algorithm must be changed as well
$::MOD_CASEMAN = 0;
$::MOD_FRAME = 1;
$::MOD_FILE = 2;
$::MOD_META = 3;
$::MOD_KWSRCH = 4;
$::MOD_DATA = 5;
$::MOD_TL = 6;
$::MOD_FS = 7;
$::MOD_APPSORT = 8;
$::MOD_NOTES = 9;
$::MOD_HASH = 10;
$::MOD_APPVIEW = 11;
# Main Menu
#
# Display the title page
sub welcome {
Print::print_html_header_javascript("Autopsy Forensic Browser");
print "<center>\n";
# This problem has not been seen with the 1 second delay
if ((0) && ($] >= 5.008)) {
print
"<p><font color=\"red\">Warning: You are using Perl v5.8.</font><br>\n"
. " Some buffer problems have been reported with Autopsy and Perl 5.8 "
. "where output is not shown.<br>\n"
. "Perl 5.6 should be used if available.\n"
. "If data is missing, reload the page<br><hr>\n";
}
print <<EOF;
<table cellspacing=0 cellpadding=2 width=600 height=350 border=0>
<tr>
<td colspan=\"3\" align=\"center\" valign=\"MIDDLE\">
<b>Autopsy Forensic Browser $::VER</b>
</td>
</tr>
<tr>
<td colspan=\"3\">&nbsp;</td>
</tr>
<tr>
<td colspan=\"3\" align=\"center\" valign=\"MIDDLE\">
<a href=\"./about\">
<img src=\"pict/logo.jpg\" border=0 alt="Logo">
</a>
</td>
</tr>
<tr>
<td colspan=\"3\">&nbsp;</td>
</tr>
<tr>
<td colspan=\"3\" align=\"center\" valign=\"MIDDLE\">
<a href="http://www.sleuthkit.org/autopsy/">
<tt>http://www.sleuthkit.org/autopsy/</tt>
</a>
</td>
</tr>
<tr><td colspan=3>&nbsp;</td></tr>
<tr>
<td align=center width=200 valign=\"MIDDLE\">
<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&view=$Caseman::CASE_OPEN\">
<img src=\"pict/menu_b_copen.jpg\" alt=\"Open Case\" width=176 height=20 border=0>
</a>
</td>
<td align=center width=200 valign=\"MIDDLE\">
<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&view=$Caseman::CASE_NEW\">
<img src=\"pict/menu_b_cnew.jpg\" alt=\"New Case\" width=176 height=20 border=0>
</a>
</td>
<td align=center width=200 valign=\"MIDDLE\">
<a href=\"$::HELP_URL\" target=\"_blank\">
<img src=\"pict/menu_b_help.jpg\" alt=\"Help\" width=167 height=20 border=0>
</a>
</td>
</tr>
</table>
EOF
Print::print_html_footer_javascript();
return 0;
}
sub get_tskver {
local *OUT;
Exec::exec_pipe(*OUT, "'$::TSKDIR/fls' -V");
my $ver = Exec::read_pipe_line(*OUT);
$ver = $1 if ($ver =~ /^The Sleuth Kit ver (.*)$/);
close(OUT);
return $ver;
}
# This function is called by the code in the 'autopy' file.
# This will check for the basic module arguments and then host
# and case accordingly. The main function of each of the modules
# is called from here. Each of the modules will have to take care
# of the detailed argument checking.
sub main {
# Parse arguments
my $lcl_args = shift;
Args::parse_args($lcl_args);
# When autopsy is first run, no mod or arguments are given.
unless (exists $Args::args{'mod'}) {
# if we are not in live analysis mode, display the usual screen
if ($::LIVE == 0) {
return welcome();
}
else {
# If we are in live analysis mode, open up the window to select
# and image and supply basic host and case values.
$Args::args{'mod'} = $Args::enc_args{'mod'} = $::MOD_CASEMAN;
$Args::args{'view'} = $Args::enc_args{'view'} = $Caseman::VOL_OPEN;
$Args::args{'case'} = $Args::enc_args{'case'} = "live";
$Args::args{'host'} = $Args::enc_args{'host'} = "local";
$Args::args{'inv'} = $Args::enc_args{'inv'} = "unknown";
}
}
Args::check_mod();
my $module = Args::get_mod();
Args::make_baseargs();
# For live analysis, we need to change the regular expression
# for images because it can be a full path (to /dev/xxxxxxx)
$::REG_IMG = '/[\w\-\_\.\/]+'
if ($::LIVE == 1);
# The Case Management module is handled seperately because
# it may not have the host and case values
if ($module == $::MOD_CASEMAN) {
return Caseman::main();
}
# Check the minimum arguments
Args::check_case();
Args::check_host();
# Set the case and host variables
if ($::LIVE == 0) {
$::case_dir = "$::LOCKDIR/" . Args::get_case() . "/";
$::case_dir =~ s/\/\//\//g;
$::host_dir = "$::case_dir" . Args::get_host() . "/";
$::host_dir =~ s/\/\//\//g;
}
else {
$::host_dir = "";
$::case_dir = "";
}
Caseman::read_host_config();
# This is a partial binary sort method to reduce the number of checks
# 0 < mod < 6
if ($module < $::MOD_TL) {
# 0 < mod < 4
if ($module < $::MOD_KWSRCH) {
# mod == 1
if ($module == $::MOD_FRAME) {
return Frame::main();
}
# mod == 2
elsif ($module == $::MOD_FILE) {
return File::main();
}
# mod == 3
elsif ($module == $::MOD_META) {
return Meta::main();
}
}
# 4 <= mod < 6
else {
# mod == 4
if ($module == $::MOD_KWSRCH) {
return Kwsrch::main();
}
# mod == 5
elsif ($module == $::MOD_DATA) {
return Data::main();
}
}
}
# 6 <= mod
else {
# 6 <= mod < 9
if ($module < $::MOD_NOTES) {
# mod == 6
if ($module == $::MOD_TL) {
return Timeline::main();
}
# mod == 7
elsif ($module == $::MOD_FS) {
return Filesystem::main();
}
# mod == 8
elsif ($module == $::MOD_APPSORT) {
return Appsort::main();
}
}
# 9 <= mod
else {
# mod == 9
if ($module == $::MOD_NOTES) {
return Notes::main();
}
# mod == 10
elsif ($module == $::MOD_HASH) {
return Hash::main();
}
# mod == 11
elsif ($module == $::MOD_APPVIEW) {
return Appview::main();
}
# New modules can be added here
}
}
Print::print_check_err("Invalid Module");
}
1;

788
lib/Meta.pm Normal file
View File

@ -0,0 +1,788 @@
#
# Metadata mode
#
# Brian Carrier [carrier@sleuthkit.org]
# Copyright (c) 2001-2005 by Brian Carrier. All rights reserved
#
# This file is part of the Autopsy Forensic Browser (Autopsy)
#
# Autopsy is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Autopsy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Autopsy; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
# IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Updated 1/13
package Meta;
$Meta::FRAME = 0;
$Meta::ENTER = 1;
$Meta::STATS = 2;
$Meta::EXPORT = 3;
$Meta::FFIND = 4;
$Meta::LIST = 5;
$Meta::REPORT = 6;
$Meta::BLANK = 7;
sub main {
# By default, show the main frame
$Args::args{'view'} = $Args::enc_args{'view'} = $Meta::FRAME
unless (exists $Args::args{'view'});
Args::check_view();
my $view = Args::get_view();
# Check Basic Args
Args::check_vol('vol');
# These windows don't need the meta data address
if ($view == $Meta::FRAME) {
return frame();
}
elsif ($view == $Meta::ENTER) {
return enter();
}
elsif ($view == $Meta::LIST) {
return list();
}
elsif ($view == $Meta::BLANK) {
return blank();
}
# These windows do need the meta data address
Args::check_meta('meta');
if ($view == $Meta::STATS) {
return stats();
}
elsif ($view == $Meta::FFIND) {
return findfile();
}
Args::check_recmode();
if ($view == $Meta::EXPORT) {
return export();
}
elsif ($view == $Meta::REPORT) {
return report();
}
else {
Print::print_check_err("Invalid Meta View");
}
}
# Print the two frames
sub frame {
my $vol = Args::get_vol('vol');
Print::print_html_header_frameset(
"Meta Data Browse on $Caseman::vol2sname{$vol}");
print "<frameset cols=\"20%,80%\">\n";
# Print the frame where an addres can be entered and a frame for the
# contents
if (exists $Args::enc_args{'meta'}) {
print
"<frame src=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::ENTER&$Args::baseargs"
. "&meta=$Args::enc_args{'meta'}\">\n"
. "<frame src=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::STATS&"
. "meta=$Args::enc_args{'meta'}&$Args::baseargs\" "
. "name=\"content\">\n</frameset>\n";
}
else {
print
"<frame src=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::ENTER&$Args::baseargs\">\n"
. "<frame src=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::BLANK&$Args::baseargs\" "
. "name=\"content\">\n</frameset>\n";
}
Print::print_html_footer_frameset();
return 0;
}
# Generate the frame to enter the data into
sub enter {
Print::print_html_header("");
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
# Address
print "<form action=\"$::PROGNAME\" method=\"get\" target=\"content\">\n"
. "<b>$Fs::meta_str{$ftype} Number:</b><br>&nbsp;&nbsp&nbsp;&nbsp;"
. "<input type=\"text\" name=\"meta\" size=12 maxlength=12";
print " value=\"$Args::enc_args{'meta'}\"" if exists($Args::args{'meta'});
print ">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_META\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Meta::STATS\">\n"
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n"
. Args::make_hidden()
.
# View Button
"<p><input type=\"image\" src=\"pict/but_view.jpg\" "
. "width=45 height=22 alt=\"View\" border=\"0\"></form>\n";
# Allocation List
print "<hr><p>"
. "<a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::LIST&$Args::baseargs\" target=\"content\">"
. "<img src=\"pict/but_alloc_list.jpg\" border=\"0\" "
. "width=113 height=20 alt=\"Allocation List\">"
. "</a>\n";
Print::print_html_footer();
return 0;
}
# Display the contents of meta
sub stats {
Print::print_html_header("");
my $meta = Args::get_meta('meta');
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
my $tz = "";
$tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq "");
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: Displaying details of $Fs::meta_str{$ftype} $meta"
);
my $meta_int = $meta;
$meta_int = $1 if ($meta =~ /^(\d+)-\d+(-\d)?/);
my $prev = $meta_int - 1;
my $next = $meta_int + 1;
# We need to get the allocation status of this structure
my $recmode = $File::REC_NO;
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/ils' -f $ftype -e -o $offset -i $imgtype $img $meta_int");
while ($_ = Exec::read_pipe_line(*OUT)) {
chop;
next unless ($_ =~ /^$meta_int/);
if ($_ =~ /^$meta_int\|f/) {
$recmode = $File::REC_YES;
}
elsif ($_ =~ /^$meta_int\|a/) {
$recmode = $File::REC_NO;
}
else {
Print::print_err("Error parsing ils output: $_");
}
}
close(OUT);
print "<center>\n";
print
"<a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::STATS&$Args::baseargs&meta=$prev\">"
. "<img src=\"pict/but_prev.jpg\" alt=\"previous\" "
. "width=\"89\" height=20 border=\"0\"></a>\n"
unless ($prev < $Fs::first_meta{$ftype});
print
"<a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::STATS&$Args::baseargs&meta=$next\">"
. "<img src=\"pict/but_next.jpg\" alt=\"next\" "
. "width=\"89\" height=20 border=\"0\"></a>\n<br>";
# Report
print "<table cellspacing=\"0\" cellpadding=\"2\">\n<tr>"
. "<td><a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::REPORT"
. "&$Args::baseargs&meta=$meta&recmode=$recmode\""
. " target=\"_blank\">"
. "<img src=\"pict/but_report.jpg\" alt=\"report\" "
. "width=88 height=20 border=\"0\">"
. "</a></td>\n";
# View (File Mode)
print "<td><a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR"
. "&$Args::baseargs&meta=$meta&recmode=$recmode"
. "&dir=$vol-meta-$meta\" target=\"_blank\">"
. "<img src=\"pict/but_viewcont.jpg\" alt=\"view contents\" "
. "width=123 height=20 border=\"0\">"
. "</a></td>\n";
# Export
print "<td><a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::EXPORT"
. "&$Args::baseargs&meta=$meta&recmode=$recmode\">"
. "<img src=\"pict/but_export.jpg\" alt=\"export\" "
. "width=123 height=20 border=\"0\">"
. "</a></td>";
# Notes
print "<td><a href=\"$::PROGNAME?mod=$::MOD_NOTES&view=$Notes::ENTER_FILE"
. "&$Args::baseargs&meta=$meta&\" "
. "target=\"_blank\">"
. "<img src=\"pict/but_addnote.jpg\" alt=\"Add Note\" "
. "width=\"89\" height=20 border=\"0\">"
. "</a></td>"
if ($::USE_NOTES == 1);
print "</tr></table>\n</center>\n";
my $tmpr = $Caseman::vol2mnt{$vol};
if ($ftype =~ /fat/) {
print
"<a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::FFIND&$Args::baseargs&"
. "meta=$meta\" target=\"_blank\">Search for File Name</a><br><br>";
}
else {
print "<b>Pointed to by file:</b><br>\n";
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/ffind' -f $ftype -a -o $offset -i $imgtype $img $meta");
my $cnt = 0;
while ($_ = Exec::read_pipe_line(*OUT)) {
chop;
if (/^(\*)\s+\/*(.*)$/) {
Print::print_output("<tt><font color=\"$::DEL_COLOR[0]\">"
. Print::html_encode($tmpr . $2)
. "</font></tt> (deleted)<br><br>\n");
}
elsif (/^\/(.*)$/) {
Print::print_output("<tt>"
. Print::html_encode($tmpr . $1)
. "</tt><br><br>\n");
}
else {
Print::print_output(Print::html_encode($_) . "<br><br>\n");
}
$cnt++;
}
close(OUT);
if ($cnt == 0) {
print "<br>Invalid $Fs::meta_str{$ftype} value<br><br>\n";
return;
}
}
if ($recmode == $File::REC_YES) {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -"
);
}
my $file_type = Exec::read_pipe_line(*OUT);
close(OUT);
$file_type = "Error getting file type"
if ((!defined $file_type) || ($file_type eq ""));
if ($recmode == $File::REC_YES) {
print "<b>File Type (Recovered):</b><br>$file_type<br>\n";
}
else {
print "<b>File Type:</b><br>$file_type<br><br>\n";
}
# MD5 Value
if ($recmode == $File::REC_YES) {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::MD5_EXE'"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::MD5_EXE'"
);
}
my $md5out = Exec::read_pipe_line(*OUT);
close(OUT);
$md5out = "Error getting MD5"
if ((!defined $md5out) || ($md5out eq ""));
chomp $md5out;
if ($recmode == $File::REC_YES) {
print "<b>MD5 of recovered content:</b><br><tt>$md5out</tt><br><br>\n";
}
else {
print "<b>MD5 of content:</b><br><tt>$md5out</tt><br><br>\n";
}
# Hash Database Lookups
if (
(
($::NSRLDB ne "")
|| ($Caseman::alert_db ne "")
|| ($Caseman::exclude_db ne "")
)
&& ($md5out =~ /^$::REG_MD5$/o)
)
{
print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_blank\">\n"
. Args::make_hidden()
. "<input type=\"hidden\" name=\"md5\" value=\"$md5out\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_HASH\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Hash::DB_LOOKUP\">\n"
. "<table cellpadding=\"2\" cellspacing=\"8\"><tr>\n";
if ($::NSRLDB ne "") {
print "<td align=\"left\">"
. "<input type=\"checkbox\" name=\"hash_nsrl\" value=\"1\" CHECKED>"
. "NSRL</td>\n";
}
if ($Caseman::alert_db ne "") {
print "<td align=\"left\">"
. "<input type=\"checkbox\" name=\"hash_alert\" value=\"1\" CHECKED>"
. "Alert Database</td>\n";
}
if ($Caseman::exclude_db ne "") {
print "<td align=\"left\">"
. "<input type=\"checkbox\" name=\"hash_exclude\" value=\"1\" CHECKED>"
. "Exclude Database</td>\n";
}
print "<td align=\"left\">"
. "<input type=\"image\" src=\"pict/but_lookup.jpg\" "
. "width=116 height=20 alt=\"Ok\" border=\"0\">"
. "</td></tr></table>\n</form>\n";
}
# SHA-1 Value
if ($::SHA1_EXE ne "") {
if ($recmode == $File::REC_YES) {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::SHA1_EXE'"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::SHA1_EXE'"
);
}
my $sha1out = Exec::read_pipe_line(*OUT);
close(OUT);
$sha1out = "Error getting SHA-1"
if ((!defined $sha1out) || ($sha1out eq ""));
chomp $sha1out;
if ($recmode == $File::REC_YES) {
print
"<b>SHA-1 of recovered content:</b><br><tt>$sha1out</tt><br><br>\n";
}
else {
print "<b>SHA-1 of content:</b><br><tt>$sha1out</tt><br><br>\n";
}
}
# istat output
print "<b>Details:</b><br><br>\n";
my $mode = 0; # set to 1 when showing blocks
my $force = 0; # set to 1 if size of meta is 0
my @output;
if (exists($Args::args{'force'})) {
my $f = Args::get_force();
Exec::exec_pipe(*OUT,
"'$::TSKDIR/istat' -f $ftype $tz -s $Caseman::ts -b $f -o $offset -i $imgtype $img $meta"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/istat' -f $ftype $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta"
);
}
while ($_ = Exec::read_pipe_line(*OUT)) {
if ($mode == 1) {
if (/^Indirect Blocks/) {
print "$_<br>\n";
next;
}
elsif (/^Recover/) {
print "$_<br>\n";
next;
}
elsif (/^Type: (\S+) \((\d+\-\d+)\) (.*)$/) {
print "$1 ("
. "<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&$Args::baseargs"
. "&meta=$meta_int-$2&dir=$vol-meta-$meta_int-$2\" "
. "target=\"_blank\">$2</a>) $3<br>\n";
next;
}
my $blk;
foreach $blk (split(/ /, $_)) {
if ($blk =~ /^\d+$/) {
print
"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_DATA&"
. "$Args::baseargs&block=$blk\" target=\"_top\">$blk</a> ";
}
else {
print "$blk ";
}
}
print "<br>\n";
}
else {
if (/^Not Allocated$/) {
print "<font color=\"$::DEL_COLOR[0]\">$_</font><br>\n";
}
else {
print "$_<br>\n";
}
$mode = 1 if (/^Direct Blocks|^Sectors/);
$mode = 1 if (/^Attributes/);
if ((/^size: (\d+)/) && ($1 == 0)) {
$force = 1;
}
}
}
close(OUT);
# display a text box to force X number of blocks to be displayed
if ($force == 1) {
print "<form action=\"$::PROGNAME\" method=\"get\">\n"
. Args::make_hidden()
. "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n"
. "<input type=\"hidden\" name=\"meta\" value=\"$meta\">\n"
. "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_META\">\n"
. "<input type=\"hidden\" name=\"view\" value=\"$Meta::STATS\">\n";
print
"Enter number of $Fs::addr_unit{$ftype}s to display: <input type=\"text\" "
. "value=5 name=\"force\" size=\"3\">\n";
print "<input type=\"image\" src=\"pict/but_force.jpg\" "
. "width=53 height=20 alt=\"Force\" border=\"0\"> (because the size is 0)\n</form>\n";
}
Print::print_html_footer();
return 0;
}
sub findfile {
Print::print_html_header("Find File");
my $meta = Args::get_meta('meta');
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
my $tmpr = $Caseman::vol2mnt{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
print "<b>Pointed to by file:</b><br>\n";
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/ffind' -f $ftype -a -o $offset -i $imgtype $img $meta");
while ($_ = Exec::read_pipe_line(*OUT)) {
chop;
if (/(\*)\s+\/*(.*)/) {
Print::print_output("<tt><font color=\"$::DEL_COLOR[0]\">"
. Print::html_encode($tmpr . $2)
. "</font></tt> (deleted)<br>\n");
}
elsif (/^\/(.*)$/) {
Print::print_output(
"<tt>" . Print::html_encode($tmpr . $1) . "</tt><br>\n");
}
else {
Print::print_output(Print::html_encode($_) . "<br>\n");
}
}
close(OUT);
Print::print_html_footer();
return 0;
}
sub export {
my $meta = Args::get_meta('meta');
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
my $recmode = Args::get_recmode();
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: Saving contents of $Fs::meta_str{$ftype} $meta"
);
Print::print_oct_header("$vol" . "-meta" . "$meta" . ".raw");
local *OUT;
if ($recmode == $File::REC_YES) {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta");
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta");
}
print "$_" while ($_ = Exec::read_pipe_data(*OUT, 512));
close(OUT);
Print::print_oct_footer();
}
sub report {
my $meta = Args::get_meta('meta');
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
my $recmode = Args::get_recmode();
my $tz = "";
$tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq "");
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: Generating report for $Fs::meta_str{$ftype} $meta"
);
Print::print_text_header("filename=$vol-meta$meta.txt");
print " Autopsy $Fs::meta_str{$ftype} Report\n\n"
. "-" x 70 . "\n"
. " GENERAL INFORMATION\n\n"
. "$Fs::meta_str{$ftype}: $Args::args{'meta'}\n";
print "Pointed to by file(s):\n";
my $tmpr = $Caseman::vol2mnt{$vol};
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/ffind' -f $ftype -a -o $offset -i $imgtype $img $meta");
while ($_ = Exec::read_pipe_line(*OUT)) {
chop;
if (/^(\*)\s+\/*(.*)$/) {
Print::print_output(
" ${tmpr}${2} (deleted)\n");
}
elsif (/^\/(.*)$/) {
Print::print_output(" ${tmpr}${1}\n");
}
else {
Print::print_output(" $_\n");
}
}
close(OUT);
Exec::exec_pipe(*OUT,
"'$::TSKDIR/istat' -f $ftype $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta | '$::MD5_EXE'"
);
my $md5 = Exec::read_pipe_line(*OUT);
close(OUT);
$md5 = "Error getting MD5 Value"
if ((!defined $md5) || ($md5 eq ""));
chop $md5;
print "MD5 of istat output: $md5\n";
if ($::SHA1_EXE ne "") {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/istat' -f $ftype $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta | '$::SHA1_EXE'"
);
my $sha1 = Exec::read_pipe_line(*OUT);
close(OUT);
$sha1 = "Error getting SHA-1 Value"
if ((!defined $sha1) || ($sha1 eq ""));
chop $sha1;
print "SHA-1 of istat output: $sha1\n";
}
print "\nImage: $Caseman::vol2path{$vol}\n";
if (($Caseman::vol2start{$vol} == 0) && ($Caseman::vol2end{$vol} == 0)) {
print "Offset: Full image\n";
}
elsif ($Caseman::vol2end{$vol} == 0) {
print "Offset: $Caseman::vol2start{$vol} to end\n";
}
else {
print "Offset: $Caseman::vol2start{$vol} to $Caseman::vol2end{$vol}\n";
}
print "File System Type: $ftype\n";
my $date = localtime();
print "\nDate Generated: $date\n"
. "Investigator: $Args::args{'inv'}\n\n"
. "-" x 70 . "\n"
. " META DATA INFORMATION\n\n";
Exec::exec_pipe(*OUT,
"'$::TSKDIR/istat' -f $ftype $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta"
);
while ($_ = Exec::read_pipe_line(*OUT)) {
print $_;
}
close(OUT);
if ($recmode == $File::REC_YES) {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -"
);
}
else {
Exec::exec_pipe(*OUT,
"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -"
);
}
my $file_type = Exec::read_pipe_line(*OUT);
close(OUT);
$file_type = "Error getting file type"
if ((!defined $file_type) || ($file_type eq ""));
print "\nFile Type: $file_type";
print "\n"
. "-" x 70 . "\n"
. " VERSION INFORMATION\n\n"
. "Autopsy Version: $::VER\n";
print "The Sleuth Kit Version: " . ::get_tskver() . "\n";
Print::print_text_footer();
return 0;
}
# Display the meta Allocation Table
sub list {
my $ILS_GAP = 500;
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
my $img = $Caseman::vol2path{$vol};
my $offset = $Caseman::vol2start{$vol};
my $imgtype = $Caseman::vol2itype{$vol};
my $min = 0;
$min = Args::get_min() if (exists $Args::args{'min'});
my $max = $min + $ILS_GAP - 1;
# Because we can not use metas 0 and 1 for most FS, set fmin to the
# minimum for this fs
my $fmin = $min;
$fmin = $Fs::first_meta{$ftype} if ($min < $Fs::first_meta{$ftype});
Print::print_html_header(
"$Fs::meta_str{$ftype} Allocation List $fmin -&gt $max");
Print::log_host_inv(
"$Caseman::vol2sname{$vol}: $Fs::meta_str{$ftype} Allocation List for $min to $max"
);
print "<center><H2>$Fs::meta_str{$ftype}: $fmin - $max</H2>";
# Display next and previous links
my $tmp;
if ($min > $Fs::first_meta{$ftype}) {
$tmp = $min - $ILS_GAP;
print
"<a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::LIST&$Args::baseargs&min=$tmp\">"
. "<img src=\"pict/but_prev.jpg\" alt=\"previous\" "
. "width=\"89\" height=20 border=\"0\"></a> ";
}
$tmp = $min + $ILS_GAP;
print
" <a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::LIST&$Args::baseargs&min=$tmp\">"
. "<img src=\"pict/but_next.jpg\" alt=\"next\" "
. "width=\"89\" height=20 border=\"0\"></a><br>";
print "</center>\n";
# The list
local *OUT;
Exec::exec_pipe(*OUT,
"'$::TSKDIR/ils' -e -s $Caseman::ts -f $ftype -o $offset -i $imgtype $img $fmin-$max"
);
while ($_ = Exec::read_pipe_line(*OUT)) {
if (/^($::REG_META)\|([af])\|\d+\|\d+\|\d+\|\d+\|\d+\|/o) {
print
"<a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::STATS&$Args::baseargs&meta=$1\">"
. "$1:</a> ";
if ($2 eq "a") {
print "allocated<br>\n";
}
else {
print "<font color=\"$::DEL_COLOR[0]\">free</font><br>\n";
}
}
}
close(OUT);
# Display next and previous links
print "<center>\n";
if ($min > $Fs::first_meta{$ftype}) {
$tmp = $min - $ILS_GAP;
print
"<a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::LIST&$Args::baseargs&min=$tmp\">"
. "<img src=\"pict/but_prev.jpg\" alt=\"previous\" "
. "width=\"89\" height=20 border=\"0\"></a> ";
}
$tmp = $min + $ILS_GAP;
print
" <a href=\"$::PROGNAME?mod=$::MOD_META&view=$Meta::LIST&$Args::baseargs&min=$tmp\">"
. "<img src=\"pict/but_next.jpg\" alt=\"next\" "
. "width=\"89\" height=20 border=\"0\"></a><br>";
print "</center>\n";
Print::print_html_footer();
return 0;
}
# Blank Page
sub blank {
Print::print_html_header("Metadata Blank Page");
my $vol = Args::get_vol('vol');
my $ftype = $Caseman::vol2ftype{$vol};
print "<center><h3>Metadata Mode</h3><br>\n"
. "Here you can view the details about any $Fs::meta_str{$ftype} in the file system.<br>\n"
. "These are the data structures that store the file details.<br>\n"
. "Enter the address in the field on the left.\n";
Print::print_html_footer();
return 0;
}

1110
lib/Notes.pm Normal file

File diff suppressed because it is too large Load Diff

390
lib/Print.pm Normal file
View File

@ -0,0 +1,390 @@
package Print;
#
# Utilities to print information
#
# 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.
# Escape HTML entities
# Converts \n to <br>\n
sub html_encode {
my $text = shift;
$text =~ s/&/&amp;/gs;
$text =~ s/</&lt;/gs;
$text =~ s/>/&gt;/gs;
$text =~ s/\"/&quot;/gs;
$text =~ s/\n/<br>\n/gs;
# @@@ LEADING SPACES and TABS
# while ($text =~ s/^(&nbsp;)*\t/"$1&nbsp;&nbsp;&nbsp;&nbsp;"/eig) {}
# while ($text =~ s/^(&nbsp;)* /"$1&nbsp;"/eig) {}
return $text;
}
# remove control chars from printout
# this does not escape HTML entities, so you can pass this HTML code
sub print_output {
my $out = shift;
print "$out";
while (my $out = shift) {
foreach $_ (split(//, $out)) {
if ( ($_ eq "\n")
|| ($_ eq "\r")
|| ($_ eq "\f")
|| ($_ eq "\t"))
{
print "$_";
}
elsif ((ord($_) < 0x20) && (ord($_) >= 0x00)) {
print "^" . ord($_);
}
else {
print "$_";
}
}
}
}
# Added to provide output in hexdump format
# function gets called on a per-icat basis,
# The offset value is the byte offset that this data
# starts at, since the File.pm code calls it in 1024
# byte chunks)
sub print_hexdump {
my $out = shift; # data to output
my $offset = shift; # starting byte offset in file
my $buf = "";
foreach $i (split(//, $out)) {
my $idx = $offset % 16;
if ($idx == 0) {
printf("%08X: ", $offset);
}
printf("%02X", ord($i));
if (($idx % 2) == 1) {
printf(" ");
}
$buf[$idx] = $i;
if ($idx == 15) {
print " ";
for (my $j = 0; $j < 16; $j++) {
if ($buf[$j] =~ m/[ -~]/) {
print $buf[$j];
}
else {
print ".";
}
$buf[$j] = 0;
}
print "\n";
}
$offset++;
}
# print out last line if < 16 bytes long
my $l = $offset % 16;
if ($l) {
my $t = (16 - $l) * 2 + (16 - $l) / 2;
for (my $j = 0; $j < $t; $j++) {
print " ";
}
print " ";
for (my $j = 0; $j < $l; $j++) {
if ($buf[$j] =~ m/[ -~]/) {
print $buf[$j];
}
else {
print ".";
}
}
print "\n";
}
}
############################################
#
# HTTP/HTML Headers and Footers
# The page that makes the frameset does not have a body statement
# This routine is used to make the minimum required header statements
sub print_html_header_frameset {
my $text = shift;
print "Content-Type: text/html; charset=utf-8$::HTTP_NL$::HTTP_NL";
my $time = localtime();
print <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Autopsy ver. $::VER Forensic Browser -->
<!-- Page created at: $time -->
<head>
<title>$text</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="/global.css">
</head>
EOF
}
sub print_html_footer_frameset {
print "\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
}
# Create the header information with the body tag
sub print_html_header {
print_html_header_frameset(shift);
print "<body bgcolor=\"$::BACK_COLOR\">\n\n";
print "<link rel=\"SHORTCUT ICON\" href=\"/pict/favicon.ico\">\n";
}
sub print_html_footer {
print "\n</body>\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
}
# Print the header with the margins set to 0 so that the tab buttons
# are flush with the edges of the frame
sub print_html_header_tabs {
print_html_header_frameset(shift);
print "<body marginheight=0 marginwidth=0 topmargin=0 "
. "leftmargin=0 rightmargin=0 botmargin=0 bgcolor=\"$::BACK_COLOR\">\n\n";
print "<link rel=\"SHORTCUT ICON\" href=\"/pict/favicon.ico\">\n";
$is_body = 1;
}
sub print_html_footer_tabs {
print "\n</body>\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
}
# Header for front page to warn about java script
sub print_html_header_javascript {
my $text = shift;
print "Content-Type: text/html; charset=utf-8$::HTTP_NL$::HTTP_NL";
my $time = localtime();
# The write line has to stay on one line
print <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Autopsy ver. $::VER Forensic Browser -->
<!-- Page created at: $time -->
<head>
<title>$text</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="/global.css">
<script language=\"JavaScript\">
<!-- hide script from old browsers
document.write(\'<center><font color=\"red\"><p>WARNING: Your browser currently has Java Script enabled.</font><p>You do not need Java Script to use Autopsy and it is recommended that it be turned off for security reasons.<hr></center>\');
//-->
</script>
</head>
<body bgcolor=\"$::BACK_COLOR\">
<link rel=\"SHORTCUT ICON\" href=\"/pict/favicon.ico\">
EOF
}
sub print_html_footer_javascript {
print "\n</body>\n</html>\n" . "$::HTTP_NL$::HTTP_NL";
}
# For raw text outputs (Pass the name of a file if it is being saved)
sub print_text_header {
print "Content-Type: text/plain; charset=utf-8$::HTTP_NL";
if (scalar @_ > 0) {
my $fname = shift();
print "Content-Disposition: inline; " . "filename=$fname;$::HTTP_NL";
}
print "$::HTTP_NL";
}
sub print_text_footer {
print "$::HTTP_NL$::HTTP_NL";
}
# For forced save outputs
sub print_oct_header {
print "Content-Type: application/octet-stream$::HTTP_NL";
if (scalar @_ > 0) {
my $fname = shift();
print "Content-Disposition: inline; " . "filename=$fname;$::HTTP_NL";
}
print "$::HTTP_NL";
}
sub print_oct_footer {
}
# Error message that is used when an HTTP/HTML header is needed
# This escapes the characters that chould be HTML entities.
# it will also replace \n with <br> and other things that html_encode()
# can do. Do not send arbitrary HTML to this function.
sub print_check_err {
print_html_header("");
print html_encode(shift()) . "<br>\n";
print_html_footer();
sleep(1);
exit 1;
}
# Error message when header already exists
# This escapes the characters that chould be HTML entities.
# it will also replace \n with <br> and other things that html_encode()
# can do. Do not send arbitrary HTML to this function.
sub print_err {
print html_encode(shift()) . "<br>\n";
sleep(1);
print_html_footer();
exit 1;
}
##################################################################
#
# Logging
#
#
sub investig_log_fname {
return "" unless (defined $::host_dir && $::host_dir ne "");
return "" unless (exists $Args::args{'inv'} && $Args::args{'inv'} ne "");
return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.log";
}
sub investig_exec_log_fname {
return "" unless (defined $::host_dir && $::host_dir ne "");
return "" unless (exists $Args::args{'inv'} && $Args::args{'inv'} ne "");
return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.exec.log";
}
sub host_log_fname {
return "" unless (defined $::host_dir && $::host_dir ne "");
return "$::host_dir" . "$::LOGDIR/host.log";
}
sub case_log_fname {
return "" unless (defined $::case_dir && $::case_dir ne "");
return "$::case_dir" . "case.log";
}
# Log data to the investigators specific log file
sub log_host_inv {
return unless ($::USE_LOG == 1);
my $str = shift;
chomp $str;
my $date = localtime;
my $fname = investig_log_fname();
return if ($fname eq "");
open HOSTLOG, ">>$fname" or die "Can't open log: $fname";
print HOSTLOG "$date: $str\n";
close(HOSTLOG);
return;
}
sub log_host_inv_exec {
return unless ($::USE_LOG == 1);
my $str = shift;
chomp $str;
my $date = localtime;
my $fname = investig_exec_log_fname();
return if ($fname eq "");
open HOSTLOG, ">>$fname" or die "Can't open log: $fname";
print HOSTLOG "$date: $str\n";
close(HOSTLOG);
return;
}
# log data to the general log file for the host
sub log_host_info {
return unless ($::USE_LOG == 1);
my $str = shift;
chomp $str;
my $date = localtime;
my $fname = host_log_fname();
return if ($fname eq "");
open HOSTLOG, ">>$fname" or die "Can't open log: $fname";
print HOSTLOG "$date: $str\n";
close(HOSTLOG);
return;
}
sub log_case_info {
return unless ($::USE_LOG == 1);
my $str = shift;
chomp $str;
my $date = localtime;
my $fname = case_log_fname();
return if ($fname eq "");
open CASELOG, ">>$fname" or die "Can't open log: $fname";
print CASELOG "$date: $str\n";
close(CASELOG);
return;
}
sub log_session_info {
return unless ($::USE_LOG == 1);
my $str = shift;
chomp $str;
my $date = localtime;
my $lname = "autopsy.log";
open AUTLOG, ">>$::LOCKDIR/$lname" or die "Can't open log: $lname";
print AUTLOG "$date: $str\n";
close(AUTLOG);
return;
}
1;

1425
lib/Timeline.pm Normal file

File diff suppressed because it is too large Load Diff

8
lib/Vs.pm Normal file
View File

@ -0,0 +1,8 @@
package Vs;
# These need to be updated as The Sleuth Kit supports more volume systems
$Vs::type{'dos'} = 1;
$Vs::type{'bsd'} = 1;
$Vs::type{'gpt'} = 1;
$Vs::type{'mac'} = 1;
$Vs::type{'sun'} = 1;

39
lib/define.pl Normal file
View File

@ -0,0 +1,39 @@
#
$VER = '2.20b3';
$HTTP_NL = "\x0a";
$notes_file = "";
$PICTDIR = "$INSTALLDIR/pict/";
$SANITIZE_TAG = 'AutopsySanitized';
$SANITIZE_PICT = 'sanitized.jpg';
$PROGNAME = 'autopsy';
# Default directory names
$MKDIR_MASK = 0775;
$IMGDIR = 'images';
$DATADIR = 'output';
$LOGDIR = 'logs';
$REPDIR = 'reports';
# Colors
$BACK_COLOR = "#CCCC99";
$BACK_COLOR_TABLE = "#CCCCCC";
$DEL_COLOR[0] = "red";
$DEL_COLOR[1] = "#800000"; # used when meta data structure has been reallocated
$NORM_COLOR = "";
$LINK_COLOR = "blue";
$YEL_PIX = "pict/back_pix.jpg";
%m2d = (
"Jan", 1, "Feb", 2, "Mar", 3, "Apr", 4, "May", 5, "Jun", 6,
"Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12
);
@d2m = (
"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"
);
1;

51
lib/search.pl Normal file
View File

@ -0,0 +1,51 @@
#
# This file contains pre-defined search strings. A button for each will
# be displayed in the Search Mode.
#
# The $auto_srch{} hash is filled in with the search string
# The index into the hash is the name of the search.
#
# For example, $auto_srch{'foo'} = "bar"; would search for the string
# bar
#
# If the search is case sensitive, then set $auto_srch_csense to 1 (this
# is the default value if not specified. Set to 0 for insensitive
#
# If the search is a regular expression, set $auto_srch_reg to 1, else
# 0 (the default)
#
#
# If you develop patterns that you think will be useful to others, email
# them to me and I will include them in the next version (carrier@sleuthkit.org)
#
# Date / syslog search of month and date
$auto_srch{'Date'} =
"((jan)|(feb)|(mar)|(apr)|(may)|(june?)|(july?)|(aug)|(sept?)|(oct)|(nov)|(dec))([[:space:]]+[[:digit:]])?";
$auto_srch_reg{'Date'} = 1;
$auto_srch_csense{'Date'} = 0;
# IP Address
$auto_srch{'IP'} =
'[0-2]?[[:digit:]]{1,2}\.[0-2]?[[:digit:]]{1,2}\.[0-2]?[[:digit:]]{1,2}\.[0-2]?[[:digit:]]{1,2}';
$auto_srch_reg{'IP'} = 1;
$auto_srch_csense{'IP'} = 0;
# SSN in the pattern of 123-12-1234 - from Jerry Shenk
$auto_srch{'SSN1'} = '[0-9][0-9][0-9]\-[0-9]]0-9]\-[0-9][0-9][0-9][0-9]';
$auto_srch_reg{'SSN1'} = 1;
$auto_srch_csense{'SSN1'} = 0;
# SSN in the pattern of 123121234 - from Jerry Shenk
$auto_srch{'SSN2'} = '[0-9][0-9][0-9][0-9]]0-9][0-9][0-9][0-9][0-9]';
$auto_srch_reg{'SSN2'} = 1;
$auto_srch_csense{'SSN2'} = 0;
# CC # - from Jerry Shenk
$auto_srch{'CC'} =
'[0-9][0-9][0-9][0-9]]0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]]0-9]';
$auto_srch_reg{'CC'} = 1;
$auto_srch_csense{'CC'} = 0;
# This must be the last value
1;

163
man/man1/autopsy.1 Executable file
View File

@ -0,0 +1,163 @@
.TH AUTOPSY 1 "MAR 2005" "User Manuals"
.SH NAME
autopsy \- Autopsy Forensic Browser
.SH SYNOPSIS
.B autopsy [-c] [-C] [-d
.I evid_locker
.B ] [-i
device filesystem mnt
.B ] [-p
.I port
.B ]
.I [addr]
.SH DESCRIPTION
By default,
.B autopsy
starts the Autopsy Forensic Browser server on port 9999 and and accepts
connections from the localhost. If
.I -p port
is given, then the server opens on that port and if
.I addr
is given, then connections are only accepted from that host.
When the
.I -i
argument is given, then autopsy goes into live analysis mode.
The arguments are as follows:
.IP "-c"
Force the program to use cookies even for localhost.
.IP "-C"
Force the program to not use cookies even for remote hosts.
.IP "-d evid_locker"
Directory where cases and hosts are stored.
This overrides the
.B LOCKDIR
value in
.I conf.pl.
The path must be a full path (i.e. start with /).
.IP "-i device filesystem mnt"
Specify the information for the live analysis mode. This can be specified
as many times as needed. The
.I device
field is for the raw file system device, the
.I filesystem
field is for the file system type, and the
.I mnt
field is for the mounting point of the file system.
.IP "-p port"
TCP port for server to listen on.
.IP addr
IP address or host name of where investigator is located.
If localhost is used, then 'localhost' must be used in the URL.
If you use the actual hostname or IP, it will be rejected.
.PP
When started, the program will display a URL to paste into an
HTML browser. The browser must support frames and forms. The
Autopsy Forensic Browser will allow an investigator to analyze
images generated by
.BR dd(1)
for evidence. The program allows the images to be analyzed by
browsing files, blocks, inodes, or by searching the blocks.
The program also generates Autopsy reports that include collection
time, investigators name, and MD5 hash values.
.SH VARIABLES
The following variables can be set in
.I conf.pl.
.I USE_STIMEOUT
.RS
When set to 1 (default is 0), the server will exit after
.B STIMEOUT
seconds of inactivity (default is 3600). This setting is recommended if
cookies are not used.
.RE
.I BASEDIR
.RS
Directory where cases and forensic images are located.
The images must have simple
names with only letters, numbers, '_', '-', and '.'. (See FILES).
.RE
.I TSKDIR
.RS
Directory where The Sleuth Kit binaries are located.
.RE
.I NSRLDB
.RS
Location of the NIST National Software Reference Library (NSRL).
.RE
.I INSTALLDIR
.RS
Directory where Autopsy was installed.
.RE
.I GREP_EXE
.RS
Location of
.BR grep(1)
binary.
.RE
.I STRINGS_EXE
.RS
Location of
.BR strings(1)
binary.
.RE
.SH FILES
.I Evidence Locker
.RS
The Evidence Locker is where all cases and hosts will be saved to. It
is a directory that will have a directory for each case. Each case
directory will have a directory for each host.
.RE
.I <CASE_DIR>/case.aut
.RS
This file is the case configuration file for the case. It contains the
description of the case and default subdirectories for the hosts.
.RE
.I <CASE_DIR>/investigators.txt
.RS
This file contains the list of investigators that will use this case. These
are used for logging only, not authentication.
.RE
.I <HOST_DIR>/host.aut
.RS
This file is where the host configuration details are saved. It
is similar to the 'fsmorgue' file from previous versions of Autopsy.
It has an entry for each file in the host and contains the host
description.
.RE
.I md5.txt
.RS
Some directories will have this file in it. It contains MD5 values for
important files in the directory. This makes it easy to validate the
integrity of images.
.SH EXAMPLE
# ./autopsy -p 8888 10.1.34.19
.SH "SEE ALSO"
.BR dd (1),
.BR fls (1),
.BR ffind (1),
.BR ifind (1),
.BR grep (1),
.BR icat (1)
.BR md5 (1),
.BR strings (1),
.SH REQUIREMENTS
The Autopsy Forensic Browser requires
.B The Sleuth Kit
<www.sleuthkit.org/sleuthkit>
.SH HISTORY
.BR "autopsy" " first appeared in " "Autopsy" " v1.0."
.SH LICENSE
This software is distributed under the GNU Public License.
.SH AUTHOR
Brian Carrier <carrier at sleuthkit dot org>
Send documentation updates to <doc-updates at sleuthkit dot org>

BIN
pict/back_pix.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

BIN
pict/but_addnote.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
pict/but_alloc_list.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
pict/but_export.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
pict/but_force.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/but_indexdb.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
pict/but_lookup.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pict/but_new_name.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pict/but_next.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
pict/but_ok.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

BIN
pict/but_prev.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
pict/but_replace.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
pict/but_report.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
pict/but_search.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/but_view.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

BIN
pict/but_viewcont.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
pict/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pict/file_b_alldel.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
pict/file_b_allfiles.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
pict/file_b_check.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
pict/file_b_expand.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
pict/file_b_hide.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
pict/file_b_md5list.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
pict/file_h_acc_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pict/file_h_acc_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/file_h_chg_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pict/file_h_chg_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/file_h_cre_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pict/file_h_cre_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/file_h_del_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

BIN
pict/file_h_del_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

BIN
pict/file_h_gid_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

BIN
pict/file_h_gid_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

BIN
pict/file_h_meta_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/file_h_meta_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

BIN
pict/file_h_mod_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
pict/file_h_mod_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/file_h_nam_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pict/file_h_nam_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

BIN
pict/file_h_siz_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 B

BIN
pict/file_h_siz_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

BIN
pict/file_h_uid_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

BIN
pict/file_h_uid_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

BIN
pict/file_h_wr_cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
pict/file_h_wr_link.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

BIN
pict/hashdb_h_alert.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Some files were not shown because too many files have changed in this diff Show More