From ecdcab05897e9e802de1a9fae2d6c462a49927ec Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Mon, 29 Sep 2008 02:42:46 +0000 Subject: [PATCH] Initial import from CVS --- CHANGES.txt | 532 +++ COPYING | 340 ++ INSTALL.txt | 36 + Makefile | 30 + README-LIVE.txt | 119 + README.txt | 393 +++ TODO.txt | 57 + base/.perltidyrc | 5 + base/autopsy.base | 834 +++++ base/make-live-cd.base | 146 + configure | 490 +++ docs/sleuthkit-informer-13.txt | 410 +++ global.css | 19 + help/blank.html | 25 + help/caseman.html | 161 + help/data_mode.html | 97 + help/file_category.html | 99 + help/file_mode.html | 221 ++ help/fs_mode.html | 46 + help/general.html | 103 + help/grep.html | 70 + help/grep_lim.html | 75 + help/hash_db.html | 141 + help/index.html | 11 + help/int_mode.html | 29 + help/menu.html | 37 + help/meta_mode.html | 93 + help/sequencer.html | 49 + help/srch_mode.html | 68 + help/temp.html | 10 + help/timezones.html | 508 +++ help/tl.html | 183 + lib/.perltidyrc | 5 + lib/Appsort.pm | 399 +++ lib/Appview.pm | 291 ++ lib/Args.pm | 927 +++++ lib/Caseman.pm | 4151 +++++++++++++++++++++++ lib/Data.pm | 927 +++++ lib/Exec.pm | 91 + lib/File.pm | 2293 +++++++++++++ lib/Filesystem.pm | 170 + lib/Frame.pm | 336 ++ lib/Fs.pm | 160 + lib/Hash.pm | 947 ++++++ lib/Kwsrch.pm | 954 ++++++ lib/Main.pm | 357 ++ lib/Meta.pm | 788 +++++ lib/Notes.pm | 1110 ++++++ lib/Print.pm | 390 +++ lib/Timeline.pm | 1425 ++++++++ lib/Vs.pm | 8 + lib/define.pl | 39 + lib/search.pl | 51 + man/man1/autopsy.1 | 163 + pict/back_pix.jpg | Bin 0 -> 305 bytes pict/but_addnote.jpg | Bin 0 -> 1332 bytes pict/but_alloc_list.jpg | Bin 0 -> 1852 bytes pict/but_export.jpg | Bin 0 -> 2056 bytes pict/but_force.jpg | Bin 0 -> 1079 bytes pict/but_indexdb.jpg | Bin 0 -> 1568 bytes pict/but_lookup.jpg | Bin 0 -> 1458 bytes pict/but_new_name.jpg | Bin 0 -> 1435 bytes pict/but_next.jpg | Bin 0 -> 1336 bytes pict/but_ok.jpg | Bin 0 -> 881 bytes pict/but_prev.jpg | Bin 0 -> 1574 bytes pict/but_replace.jpg | Bin 0 -> 1273 bytes pict/but_report.jpg | Bin 0 -> 1339 bytes pict/but_search.jpg | Bin 0 -> 1118 bytes pict/but_view.jpg | Bin 0 -> 931 bytes pict/but_viewcont.jpg | Bin 0 -> 1924 bytes pict/favicon.ico | Bin 0 -> 1406 bytes pict/file_b_alldel.jpg | Bin 0 -> 1789 bytes pict/file_b_allfiles.jpg | Bin 0 -> 1658 bytes pict/file_b_check.jpg | Bin 0 -> 474 bytes pict/file_b_expand.jpg | Bin 0 -> 2292 bytes pict/file_b_hide.jpg | Bin 0 -> 2112 bytes pict/file_b_md5list.jpg | Bin 0 -> 2716 bytes pict/file_h_acc_cur.jpg | Bin 0 -> 1413 bytes pict/file_h_acc_link.jpg | Bin 0 -> 1153 bytes pict/file_h_chg_cur.jpg | Bin 0 -> 1409 bytes pict/file_h_chg_link.jpg | Bin 0 -> 1148 bytes pict/file_h_cre_cur.jpg | Bin 0 -> 1389 bytes pict/file_h_cre_link.jpg | Bin 0 -> 1103 bytes pict/file_h_del_cur.jpg | Bin 0 -> 941 bytes pict/file_h_del_link.jpg | Bin 0 -> 694 bytes pict/file_h_gid_cur.jpg | Bin 0 -> 953 bytes pict/file_h_gid_link.jpg | Bin 0 -> 725 bytes pict/file_h_meta_cur.jpg | Bin 0 -> 1080 bytes pict/file_h_meta_link.jpg | Bin 0 -> 911 bytes pict/file_h_mod_cur.jpg | Bin 0 -> 1364 bytes pict/file_h_mod_link.jpg | Bin 0 -> 1100 bytes pict/file_h_nam_cur.jpg | Bin 0 -> 1097 bytes pict/file_h_nam_link.jpg | Bin 0 -> 834 bytes pict/file_h_siz_cur.jpg | Bin 0 -> 1007 bytes pict/file_h_siz_link.jpg | Bin 0 -> 749 bytes pict/file_h_uid_cur.jpg | Bin 0 -> 923 bytes pict/file_h_uid_link.jpg | Bin 0 -> 685 bytes pict/file_h_wr_cur.jpg | Bin 0 -> 1336 bytes pict/file_h_wr_link.jpg | Bin 0 -> 1014 bytes pict/hashdb_h_alert.jpg | Bin 0 -> 2419 bytes pict/hashdb_h_ig.jpg | Bin 0 -> 2640 bytes pict/hashdb_h_nsrl.jpg | Bin 0 -> 1147 bytes pict/int_b_calc.jpg | Bin 0 -> 1824 bytes pict/int_b_valid.jpg | Bin 0 -> 1660 bytes pict/int_h_data.jpg | Bin 0 -> 2058 bytes pict/int_h_img.jpg | Bin 0 -> 2005 bytes pict/int_h_str.jpg | Bin 0 -> 1553 bytes pict/int_h_tl.jpg | Bin 0 -> 1124 bytes pict/int_h_unalloc.jpg | Bin 0 -> 2398 bytes pict/logo.jpg | Bin 0 -> 39208 bytes pict/main_t_dat_cur.jpg | Bin 0 -> 2140 bytes pict/main_t_dat_link.jpg | Bin 0 -> 1821 bytes pict/main_t_fil_cur.jpg | Bin 0 -> 2312 bytes pict/main_t_fil_link.jpg | Bin 0 -> 2002 bytes pict/main_t_fil_org.jpg | Bin 0 -> 1416 bytes pict/main_t_ftype_cur.jpg | Bin 0 -> 2081 bytes pict/main_t_ftype_link.jpg | Bin 0 -> 1764 bytes pict/main_t_ftype_org.jpg | Bin 0 -> 1340 bytes pict/main_t_img_cur.jpg | Bin 0 -> 2353 bytes pict/main_t_img_link.jpg | Bin 0 -> 2044 bytes pict/main_t_img_org.jpg | Bin 0 -> 1487 bytes pict/main_t_met_cur.jpg | Bin 0 -> 2151 bytes pict/main_t_met_link.jpg | Bin 0 -> 1832 bytes pict/main_t_met_org.jpg | Bin 0 -> 1399 bytes pict/main_t_srch_cur.jpg | Bin 0 -> 2497 bytes pict/main_t_srch_link.jpg | Bin 0 -> 2184 bytes pict/menu_b_add.jpg | Bin 0 -> 2208 bytes pict/menu_b_analyze.jpg | Bin 0 -> 2758 bytes pict/menu_b_back.jpg | Bin 0 -> 2410 bytes pict/menu_b_cancel.jpg | Bin 0 -> 1632 bytes pict/menu_b_ccls.jpg | Bin 0 -> 1933 bytes pict/menu_b_close.jpg | Bin 0 -> 2495 bytes pict/menu_b_cnew.jpg | Bin 0 -> 1768 bytes pict/menu_b_copen.jpg | Bin 0 -> 1913 bytes pict/menu_b_fs.jpg | Bin 0 -> 1924 bytes pict/menu_b_hashdb.jpg | Bin 0 -> 2257 bytes pict/menu_b_hcls.jpg | Bin 0 -> 1921 bytes pict/menu_b_help.jpg | Bin 0 -> 1484 bytes pict/menu_b_hnew.jpg | Bin 0 -> 1745 bytes pict/menu_b_ifnew.jpg | Bin 0 -> 3564 bytes pict/menu_b_inew.jpg | Bin 0 -> 1831 bytes pict/menu_b_int.jpg | Bin 0 -> 2108 bytes pict/menu_b_menu.jpg | Bin 0 -> 1846 bytes pict/menu_b_next.jpg | Bin 0 -> 2327 bytes pict/menu_b_note.jpg | Bin 0 -> 1871 bytes pict/menu_b_ok.jpg | Bin 0 -> 1355 bytes pict/menu_b_ref.jpg | Bin 0 -> 1672 bytes pict/menu_b_rem.jpg | Bin 0 -> 1681 bytes pict/menu_b_seq.jpg | Bin 0 -> 2451 bytes pict/menu_b_tl.jpg | Bin 0 -> 2545 bytes pict/menu_h_cdet.jpg | Bin 0 -> 1537 bytes pict/menu_h_cnew.jpg | Bin 0 -> 2960 bytes pict/menu_h_hdet.jpg | Bin 0 -> 1506 bytes pict/menu_h_hnew.jpg | Bin 0 -> 1856 bytes pict/menu_h_idet.jpg | Bin 0 -> 1553 bytes pict/menu_h_inew.jpg | Bin 0 -> 1808 bytes pict/menu_t_cg_cur.jpg | Bin 0 -> 3648 bytes pict/menu_t_cg_link.jpg | Bin 0 -> 3340 bytes pict/menu_t_cg_org.jpg | Bin 0 -> 19559 bytes pict/menu_t_hg_cur.jpg | Bin 0 -> 3573 bytes pict/menu_t_hg_link.jpg | Bin 0 -> 3260 bytes pict/menu_t_hg_org.jpg | Bin 0 -> 2418 bytes pict/menu_t_hm_cur.jpg | Bin 0 -> 3736 bytes pict/menu_t_hm_link.jpg | Bin 0 -> 3361 bytes pict/menu_t_hm_org.jpg | Bin 0 -> 2462 bytes pict/sanit_b_norm.jpg | Bin 0 -> 1448 bytes pict/sanit_b_san.jpg | Bin 0 -> 1558 bytes pict/sanitized.jpg | Bin 0 -> 18357 bytes pict/srch_b_lorig.jpg | Bin 0 -> 1963 bytes pict/srch_b_lun.jpg | Bin 0 -> 2180 bytes pict/srch_b_str.jpg | Bin 0 -> 2111 bytes pict/srch_b_un.jpg | Bin 0 -> 2445 bytes pict/tab_close.jpg | Bin 0 -> 1357 bytes pict/tab_help.jpg | Bin 0 -> 1253 bytes pict/tl_t_data_cur.jpg | Bin 0 -> 2906 bytes pict/tl_t_data_link.jpg | Bin 0 -> 2580 bytes pict/tl_t_notes_link.jpg | Bin 0 -> 2216 bytes pict/tl_t_notes_org.jpg | Bin 0 -> 1715 bytes pict/tl_t_tl_cur.jpg | Bin 0 -> 2844 bytes pict/tl_t_tl_link.jpg | Bin 0 -> 2518 bytes pict/tl_t_view_cur.jpg | Bin 0 -> 2681 bytes pict/tl_t_view_link.jpg | Bin 0 -> 2351 bytes xcode/autopsy.xcodeproj/project.pbxproj | 136 + 183 files changed, 21555 insertions(+) create mode 100644 CHANGES.txt create mode 100644 COPYING create mode 100644 INSTALL.txt create mode 100644 Makefile create mode 100644 README-LIVE.txt create mode 100644 README.txt create mode 100644 TODO.txt create mode 100755 base/.perltidyrc create mode 100644 base/autopsy.base create mode 100644 base/make-live-cd.base create mode 100755 configure create mode 100644 docs/sleuthkit-informer-13.txt create mode 100644 global.css create mode 100644 help/blank.html create mode 100644 help/caseman.html create mode 100644 help/data_mode.html create mode 100644 help/file_category.html create mode 100644 help/file_mode.html create mode 100644 help/fs_mode.html create mode 100644 help/general.html create mode 100644 help/grep.html create mode 100644 help/grep_lim.html create mode 100644 help/hash_db.html create mode 100644 help/index.html create mode 100644 help/int_mode.html create mode 100644 help/menu.html create mode 100644 help/meta_mode.html create mode 100644 help/sequencer.html create mode 100644 help/srch_mode.html create mode 100644 help/temp.html create mode 100644 help/timezones.html create mode 100644 help/tl.html create mode 100755 lib/.perltidyrc create mode 100644 lib/Appsort.pm create mode 100644 lib/Appview.pm create mode 100644 lib/Args.pm create mode 100644 lib/Caseman.pm create mode 100644 lib/Data.pm create mode 100644 lib/Exec.pm create mode 100644 lib/File.pm create mode 100644 lib/Filesystem.pm create mode 100644 lib/Frame.pm create mode 100644 lib/Fs.pm create mode 100644 lib/Hash.pm create mode 100644 lib/Kwsrch.pm create mode 100644 lib/Main.pm create mode 100644 lib/Meta.pm create mode 100644 lib/Notes.pm create mode 100644 lib/Print.pm create mode 100644 lib/Timeline.pm create mode 100644 lib/Vs.pm create mode 100644 lib/define.pl create mode 100644 lib/search.pl create mode 100755 man/man1/autopsy.1 create mode 100644 pict/back_pix.jpg create mode 100644 pict/but_addnote.jpg create mode 100644 pict/but_alloc_list.jpg create mode 100644 pict/but_export.jpg create mode 100644 pict/but_force.jpg create mode 100644 pict/but_indexdb.jpg create mode 100644 pict/but_lookup.jpg create mode 100644 pict/but_new_name.jpg create mode 100644 pict/but_next.jpg create mode 100644 pict/but_ok.jpg create mode 100644 pict/but_prev.jpg create mode 100644 pict/but_replace.jpg create mode 100644 pict/but_report.jpg create mode 100644 pict/but_search.jpg create mode 100644 pict/but_view.jpg create mode 100644 pict/but_viewcont.jpg create mode 100644 pict/favicon.ico create mode 100644 pict/file_b_alldel.jpg create mode 100644 pict/file_b_allfiles.jpg create mode 100644 pict/file_b_check.jpg create mode 100644 pict/file_b_expand.jpg create mode 100644 pict/file_b_hide.jpg create mode 100644 pict/file_b_md5list.jpg create mode 100644 pict/file_h_acc_cur.jpg create mode 100644 pict/file_h_acc_link.jpg create mode 100644 pict/file_h_chg_cur.jpg create mode 100644 pict/file_h_chg_link.jpg create mode 100644 pict/file_h_cre_cur.jpg create mode 100644 pict/file_h_cre_link.jpg create mode 100644 pict/file_h_del_cur.jpg create mode 100644 pict/file_h_del_link.jpg create mode 100644 pict/file_h_gid_cur.jpg create mode 100644 pict/file_h_gid_link.jpg create mode 100644 pict/file_h_meta_cur.jpg create mode 100644 pict/file_h_meta_link.jpg create mode 100644 pict/file_h_mod_cur.jpg create mode 100644 pict/file_h_mod_link.jpg create mode 100644 pict/file_h_nam_cur.jpg create mode 100644 pict/file_h_nam_link.jpg create mode 100644 pict/file_h_siz_cur.jpg create mode 100644 pict/file_h_siz_link.jpg create mode 100644 pict/file_h_uid_cur.jpg create mode 100644 pict/file_h_uid_link.jpg create mode 100644 pict/file_h_wr_cur.jpg create mode 100644 pict/file_h_wr_link.jpg create mode 100644 pict/hashdb_h_alert.jpg create mode 100644 pict/hashdb_h_ig.jpg create mode 100644 pict/hashdb_h_nsrl.jpg create mode 100644 pict/int_b_calc.jpg create mode 100644 pict/int_b_valid.jpg create mode 100644 pict/int_h_data.jpg create mode 100644 pict/int_h_img.jpg create mode 100644 pict/int_h_str.jpg create mode 100644 pict/int_h_tl.jpg create mode 100644 pict/int_h_unalloc.jpg create mode 100644 pict/logo.jpg create mode 100644 pict/main_t_dat_cur.jpg create mode 100644 pict/main_t_dat_link.jpg create mode 100644 pict/main_t_fil_cur.jpg create mode 100644 pict/main_t_fil_link.jpg create mode 100644 pict/main_t_fil_org.jpg create mode 100644 pict/main_t_ftype_cur.jpg create mode 100644 pict/main_t_ftype_link.jpg create mode 100644 pict/main_t_ftype_org.jpg create mode 100644 pict/main_t_img_cur.jpg create mode 100644 pict/main_t_img_link.jpg create mode 100644 pict/main_t_img_org.jpg create mode 100644 pict/main_t_met_cur.jpg create mode 100644 pict/main_t_met_link.jpg create mode 100644 pict/main_t_met_org.jpg create mode 100644 pict/main_t_srch_cur.jpg create mode 100644 pict/main_t_srch_link.jpg create mode 100644 pict/menu_b_add.jpg create mode 100644 pict/menu_b_analyze.jpg create mode 100644 pict/menu_b_back.jpg create mode 100644 pict/menu_b_cancel.jpg create mode 100644 pict/menu_b_ccls.jpg create mode 100644 pict/menu_b_close.jpg create mode 100644 pict/menu_b_cnew.jpg create mode 100644 pict/menu_b_copen.jpg create mode 100644 pict/menu_b_fs.jpg create mode 100644 pict/menu_b_hashdb.jpg create mode 100644 pict/menu_b_hcls.jpg create mode 100644 pict/menu_b_help.jpg create mode 100644 pict/menu_b_hnew.jpg create mode 100644 pict/menu_b_ifnew.jpg create mode 100644 pict/menu_b_inew.jpg create mode 100644 pict/menu_b_int.jpg create mode 100644 pict/menu_b_menu.jpg create mode 100644 pict/menu_b_next.jpg create mode 100644 pict/menu_b_note.jpg create mode 100644 pict/menu_b_ok.jpg create mode 100644 pict/menu_b_ref.jpg create mode 100644 pict/menu_b_rem.jpg create mode 100644 pict/menu_b_seq.jpg create mode 100644 pict/menu_b_tl.jpg create mode 100644 pict/menu_h_cdet.jpg create mode 100644 pict/menu_h_cnew.jpg create mode 100644 pict/menu_h_hdet.jpg create mode 100644 pict/menu_h_hnew.jpg create mode 100644 pict/menu_h_idet.jpg create mode 100644 pict/menu_h_inew.jpg create mode 100644 pict/menu_t_cg_cur.jpg create mode 100644 pict/menu_t_cg_link.jpg create mode 100644 pict/menu_t_cg_org.jpg create mode 100644 pict/menu_t_hg_cur.jpg create mode 100644 pict/menu_t_hg_link.jpg create mode 100644 pict/menu_t_hg_org.jpg create mode 100644 pict/menu_t_hm_cur.jpg create mode 100644 pict/menu_t_hm_link.jpg create mode 100644 pict/menu_t_hm_org.jpg create mode 100644 pict/sanit_b_norm.jpg create mode 100644 pict/sanit_b_san.jpg create mode 100644 pict/sanitized.jpg create mode 100644 pict/srch_b_lorig.jpg create mode 100644 pict/srch_b_lun.jpg create mode 100644 pict/srch_b_str.jpg create mode 100644 pict/srch_b_un.jpg create mode 100644 pict/tab_close.jpg create mode 100644 pict/tab_help.jpg create mode 100644 pict/tl_t_data_cur.jpg create mode 100644 pict/tl_t_data_link.jpg create mode 100644 pict/tl_t_notes_link.jpg create mode 100644 pict/tl_t_notes_org.jpg create mode 100644 pict/tl_t_tl_cur.jpg create mode 100644 pict/tl_t_tl_link.jpg create mode 100644 pict/tl_t_view_cur.jpg create mode 100644 pict/tl_t_view_link.jpg create mode 100644 xcode/autopsy.xcodeproj/project.pbxproj diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000000..46c9c6dc53 --- /dev/null +++ b/CHANGES.txt @@ -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 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 + +------------------------------------------------------------------------ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000..5b6e7c66c2 --- /dev/null +++ b/COPYING @@ -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. diff --git a/INSTALL.txt b/INSTALL.txt new file mode 100644 index 0000000000..a02e1b00eb --- /dev/null +++ b/INSTALL.txt @@ -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] + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..3a6334c196 --- /dev/null +++ b/Makefile @@ -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 diff --git a/README-LIVE.txt b/README-LIVE.txt new file mode 100644 index 0000000000..df1aaabdc6 --- /dev/null +++ b/README-LIVE.txt @@ -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] diff --git a/README.txt b/README.txt new file mode 100644 index 0000000000..6cdbce141a --- /dev/null +++ b/README.txt @@ -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 diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000000..c99588d070 --- /dev/null +++ b/TODO.txt @@ -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) diff --git a/base/.perltidyrc b/base/.perltidyrc new file mode 100755 index 0000000000..f1f2e71a01 --- /dev/null +++ b/base/.perltidyrc @@ -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 diff --git a/base/autopsy.base b/base/autopsy.base new file mode 100644 index 0000000000..15f416435f --- /dev/null +++ b/base/autopsy.base @@ -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); + } +} diff --git a/base/make-live-cd.base b/base/make-live-cd.base new file mode 100644 index 0000000000..b8c22215ce --- /dev/null +++ b/base/make-live-cd.base @@ -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"; diff --git a/configure b/configure new file mode 100755 index 0000000000..831c541a18 --- /dev/null +++ b/configure @@ -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 '' + diff --git a/docs/sleuthkit-informer-13.txt b/docs/sleuthkit-informer-13.txt new file mode 100644 index 0000000000..24d55bb371 --- /dev/null +++ b/docs/sleuthkit-informer-13.txt @@ -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 diff --git a/global.css b/global.css new file mode 100644 index 0000000000..d44dcca673 --- /dev/null +++ b/global.css @@ -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; +} + diff --git a/help/blank.html b/help/blank.html new file mode 100644 index 0000000000..3e40eb24cf --- /dev/null +++ b/help/blank.html @@ -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> diff --git a/help/caseman.html b/help/caseman.html new file mode 100644 index 0000000000..ee4fc315b8 --- /dev/null +++ b/help/caseman.html @@ -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> diff --git a/help/data_mode.html b/help/data_mode.html new file mode 100644 index 0000000000..db2d20eafd --- /dev/null +++ b/help/data_mode.html @@ -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> diff --git a/help/file_category.html b/help/file_category.html new file mode 100644 index 0000000000..6665c90b68 --- /dev/null +++ b/help/file_category.html @@ -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> diff --git a/help/file_mode.html b/help/file_mode.html new file mode 100644 index 0000000000..ca39d1d342 --- /dev/null +++ b/help/file_mode.html @@ -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> diff --git a/help/fs_mode.html b/help/fs_mode.html new file mode 100644 index 0000000000..ef8ec4d760 --- /dev/null +++ b/help/fs_mode.html @@ -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> diff --git a/help/general.html b/help/general.html new file mode 100644 index 0000000000..5d20c6bbde --- /dev/null +++ b/help/general.html @@ -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> diff --git a/help/grep.html b/help/grep.html new file mode 100644 index 0000000000..1db6060075 --- /dev/null +++ b/help/grep.html @@ -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> diff --git a/help/grep_lim.html b/help/grep_lim.html new file mode 100644 index 0000000000..d8a29d27e5 --- /dev/null +++ b/help/grep_lim.html @@ -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> diff --git a/help/hash_db.html b/help/hash_db.html new file mode 100644 index 0000000000..cddb793866 --- /dev/null +++ b/help/hash_db.html @@ -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> diff --git a/help/index.html b/help/index.html new file mode 100644 index 0000000000..c7c46aec4f --- /dev/null +++ b/help/index.html @@ -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> diff --git a/help/int_mode.html b/help/int_mode.html new file mode 100644 index 0000000000..5152b95ad0 --- /dev/null +++ b/help/int_mode.html @@ -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> diff --git a/help/menu.html b/help/menu.html new file mode 100644 index 0000000000..8b74a86594 --- /dev/null +++ b/help/menu.html @@ -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> diff --git a/help/meta_mode.html b/help/meta_mode.html new file mode 100644 index 0000000000..3a7475f713 --- /dev/null +++ b/help/meta_mode.html @@ -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> diff --git a/help/sequencer.html b/help/sequencer.html new file mode 100644 index 0000000000..6afb01e3e7 --- /dev/null +++ b/help/sequencer.html @@ -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> diff --git a/help/srch_mode.html b/help/srch_mode.html new file mode 100644 index 0000000000..43b65791be --- /dev/null +++ b/help/srch_mode.html @@ -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> diff --git a/help/temp.html b/help/temp.html new file mode 100644 index 0000000000..c3a4b95ee9 --- /dev/null +++ b/help/temp.html @@ -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> diff --git a/help/timezones.html b/help/timezones.html new file mode 100644 index 0000000000..6fa95b7c21 --- /dev/null +++ b/help/timezones.html @@ -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> diff --git a/help/tl.html b/help/tl.html new file mode 100644 index 0000000000..621165414b --- /dev/null +++ b/help/tl.html @@ -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> diff --git a/lib/.perltidyrc b/lib/.perltidyrc new file mode 100755 index 0000000000..f1f2e71a01 --- /dev/null +++ b/lib/.perltidyrc @@ -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 diff --git a/lib/Appsort.pm b/lib/Appsort.pm new file mode 100644 index 0000000000..62f84f6e74 --- /dev/null +++ b/lib/Appsort.pm @@ -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; +} + diff --git a/lib/Appview.pm b/lib/Appview.pm new file mode 100644 index 0000000000..3a407fa2e1 --- /dev/null +++ b/lib/Appview.pm @@ -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); +} + diff --git a/lib/Args.pm b/lib/Args.pm new file mode 100644 index 0000000000..705cc89a39 --- /dev/null +++ b/lib/Args.pm @@ -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; diff --git a/lib/Caseman.pm b/lib/Caseman.pm new file mode 100644 index 0000000000..5c0414eb98 --- /dev/null +++ b/lib/Caseman.pm @@ -0,0 +1,4151 @@ +# +# Case Management methods, including the windows and functions to read the +# config files +# +# Brian Carrier [carrier@sleuthkit.org] +# Copyright (c) 2001-2005 by Brian Carrier. All rights reserved +# +# This file is part of the Autopsy Forensic Browser (Autopsy) +# +# Autopsy is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Autopsy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Autopsy; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE. +# IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package Caseman; + +# If the order of these views are changed, then the order of the main +# function may have to be as well + +# Case Views +$Caseman::CASE_NEW = 1; +$Caseman::CASE_NEW_DOIT = 2; +$Caseman::CASE_OPEN = 3; +$Caseman::CASE_OPEN_LOG = 4; +$Caseman::CASE_DETAILS = 5; + +# $Caseman::CASE_DEL = 6; +my $CASE_MAX = 5; + +# Host Views +$Caseman::HOST_ADD = 7; +$Caseman::HOST_ADD_DOIT = 8; +$Caseman::HOST_OPEN = 9; +$Caseman::HOST_OPEN_LOG = 10; +$Caseman::HOST_DETAILS = 11; + +# $Caseman::HOST_DEL = 12; +my $HOST_MAX = 11; + +# Image Views +$Caseman::IMG_ADD = 13; +$Caseman::IMG_ADD_PREP = 14; +$Caseman::IMG_ADD_DOIT = 15; +$Caseman::VOL_OPEN = 16; +$Caseman::VOL_OPEN_LOG = 17; +$Caseman::VOL_DETAILS = 18; +$Caseman::IMG_DEL = 19; +$Caseman::VOL_MAKESTR = 20; +$Caseman::VOL_MAKEBLKLS = 21; +my $IMG_MAX = 21; + +# Module Variables +# %vol2par - Volume to parent volume (vol to img, str to vol) +# %vol2start - Starting sector of volume in image +# %vol2end - ending sector of volume in image +# %vol2cat - The big picture type of volume (part, disk, strings, blkls) +# %vol2ftype - The file system type (fat, dos, ntfs etc.) +# %vol2itype - The image file type (could be for a parent image) +# %vol2dtype- the disk type +# %mod2vol; # Mapping for image, given the strings or blkls +# %vol2mnt; # Mapping for mount point, given the vol name +# %vol2str; # Mapping for ASCII strings file, given the vol name +# %vol2uni; # Mapping for Unicode strings file, given the vol name +# %vol2blkls; # Mapping for blkls file, given the vol name +# %vol2path - full file path of volume +# %vol2sname - short name of volume + +sub main { + + # By default, show the case open window + $Args::args{'view'} = $Args::enc_args{'view'} = $Caseman::CASE_OPEN + unless (exists $Args::args{'view'}); + + Args::check_view(); + my $view = Args::get_view(); + + # The only live function is for the open img + if ($::LIVE == 1) { + Args::check_inv(); + if ($view == $Caseman::VOL_OPEN) { + return vol_open(); + } + + Args::check_vol('vol'); + + # Args::check_ftype(); + # Args::check_mnt(); + + if ($view == $Caseman::VOL_OPEN_LOG) { + return vol_open_log(); + } + else { + Print::print_check_err( + "Invalid Live Analysis Case Management View"); + } + return 0; + } + + # Case functions + if ($view <= $CASE_MAX) { + if ($view == $Caseman::CASE_OPEN) { + return case_open(); + } + elsif ($view == $Caseman::CASE_NEW) { + return case_new(); + } + + Args::check_case(); + $::case_dir = "$::LOCKDIR/" . Args::get_case() . "/"; + $::case_dir =~ s/\/\//\//g; + + if ($view == $Caseman::CASE_OPEN_LOG) { + return case_open_log(); + } + elsif ($view == $Caseman::CASE_NEW_DOIT) { + return case_new_doit(); + } + elsif ($view == $Caseman::CASE_DETAILS) { + return case_details(); + } + } + + Args::check_case(); + $::case_dir = "$::LOCKDIR/" . Args::get_case() . "/"; + $::case_dir =~ s/\/\//\//g; + + # Host functions + if ($view <= $HOST_MAX) { + if ($view == $Caseman::HOST_OPEN) { + return host_open(); + } + elsif ($view == $Caseman::HOST_ADD) { + return host_add(); + } + + Args::check_host(); + $::host_dir = "$::case_dir" . Args::get_host() . "/"; + $::host_dir =~ s/\/\//\//g; + if ($view == $Caseman::HOST_ADD_DOIT) { + return host_add_doit(); + } + + Caseman::read_host_config(); + if ($view == $Caseman::HOST_OPEN_LOG) { + return host_open_log(); + } + elsif ($view == $Caseman::HOST_DETAILS) { + return host_details(); + } + } + + Args::check_host(); + $::host_dir = "$::case_dir" . Args::get_host() . "/"; + $::host_dir =~ s/\/\//\//g; + Caseman::read_host_config(); + Args::check_inv(); + + if ($view <= $IMG_MAX) { + if ($view == $Caseman::VOL_OPEN) { + return vol_open(); + } + elsif ($view == $Caseman::IMG_ADD) { + return img_add(); + } + elsif ($view == $Caseman::IMG_ADD_PREP) { + return img_add_prep(); + } + elsif ($view == $Caseman::IMG_ADD_DOIT) { + return img_add_doit(); + } + + Args::check_vol('vol'); + + if ($view == $Caseman::VOL_OPEN_LOG) { + return vol_open_log(); + } + elsif ($view == $Caseman::VOL_DETAILS) { + return vol_details(); + } + + # elsif ($view == $Caseman::IMG_DEL) { + # return img_del(); + # } + elsif ($view == $Caseman::VOL_MAKESTR) { + return vol_makestr(); + } + elsif ($view == $Caseman::VOL_MAKEBLKLS) { + return vol_makeblkls(); + } + } + + Print::print_check_err("Invalid Case Management View"); +} + +#################################################################### +# General menu Functions + +sub print_menu_tabs { + + if ($::LIVE == 1) { + print "<h2>Live Analysis Mode</h2>\n"; + } + + print "<table width=\"600\" height=\"60\" background=\"$::YEL_PIX\" " + . "border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tr>\n" + . "<td align=\"center\" width=\"200\">"; + + my $view = Args::get_view(); + + # Case Gallery Tab + if ($view == $Caseman::CASE_OPEN) { + print "<img border=0 src=\"pict/menu_t_cg_cur.jpg\" " + . "width=200 height=65 alt=\"Case Gallery (Current Mode)\">\n"; + } + elsif ($::LIVE == 1) { + print "<img border=0 src=\"pict/menu_t_cg_org.jpg\" " + . "width=200 height=65 alt=\"Case Gallery\">\n"; + } + else { + print "<a href=\"$::PROGNAME?" + . "mod=$::MOD_CASEMAN&view=$Caseman::CASE_OPEN\">" + . "<img border=0 src=\"pict/menu_t_cg_link.jpg\" " + . "width=200 height=65 alt=\"Case Gallery\"></a>\n"; + } + print "</td>\n" . "<td align=\"center\" width=\"200\">"; + + # Host Gallery Tab + # Current + if ($view == $Caseman::HOST_OPEN) { + print "<img border=0 src=\"pict/menu_t_hg_cur.jpg\" " + . "width=200 height=65 alt=\"Host Gallery (Current Mode)\">\n"; + } + + # Link + elsif (($view == $Caseman::VOL_OPEN) && ($::LIVE == 0)) { + print "<a href=\"$::PROGNAME?" + . "mod=$::MOD_CASEMAN&view=$Caseman::HOST_OPEN" + . "&case=$Args::args{'case'}\">" + . "<img border=0 src=\"pict/menu_t_hg_link.jpg\" " + . "width=200 height=65 alt=\"Host Gallery\"></a>\n"; + } + + # Non-link + else { + print "<img border=0 src=\"pict/menu_t_hg_org.jpg\" " + . "width=200 height=65 alt=\"Host Gallery (Not Available)\">\n"; + } + + print "</td>\n" . "<td align=\"center\" width=\"200\">"; + + # Host Manager Tab + # Current + if ($view == $Caseman::VOL_OPEN) { + print "<img border=0 src=\"pict/menu_t_hm_cur.jpg\" " + . "width=200 height=65 alt=\"Host Manager (Current Mode)\">\n"; + } + + # non-link + else { + print "<img border=0 src=\"pict/menu_t_hm_org.jpg\" " + . "width=200 height=65 alt=\"Host Manager (Not Available)\">\n"; + } + + print "</td>\n</tr>\n" . "</table>\n"; +} + +#################################################################### +# Case Functions + +# if no args are passed, return case config using args{'case'}, +# else use the case value passed +# +# Case config: +# In case directory with case_name.case +sub case_config_fname { + if (scalar(@_) == 1) { + my $c = shift; + return "$::LOCKDIR/" . "$c/case.aut"; + } + else { + return "$::LOCKDIR/" . "$Args::args{'case'}/case.aut"; + } +} + +# Read case config and save it to $Caseman::cvals +sub read_case_config { + return if ($::LIVE == 1); + + my $case; + + if (scalar(@_) == 1) { + $case = shift; + } + else { + $case = Args::get_case(); + } + + my $fname = case_config_fname($case); + + %Caseman::cvals = (); + + open CONFIG, "<$fname" + or die "Can't open case config file ($fname)"; + + while (<CONFIG>) { + next if ((/^\#/) || (/^\s+$/)); + s/^\s+//; + s/\s+$//; + $Caseman::cvals{$1} = $2 if (/^(\S+)\s+(.*)$/); + } + close(CONFIG); + + $Caseman::cvals{'desc'} = "None Provided" + unless (exists $Caseman::cvals{'desc'}); + + $Caseman::cvals{'created'} = "unknown" + unless (exists $Caseman::cvals{'created'}); +} + +sub case_new { + Print::print_html_header("Create A New Case"); + + print <<EOF; +<br> +<br> +<center> +<img src=\"pict/menu_h_cnew.jpg\" alt=\"New Case\"> +<br><br><br> + +<table width=\"600\" background=\"$::YEL_PIX\" cellspacing=\"0\" + cellpadding=\"2\" border=0> +<form action=\"$::PROGNAME\" method=\"get\"> +<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\"> +<input type=\"hidden\" name=\"view\" value=\"$Caseman::CASE_NEW_DOIT\"> +<tr> + <td colspan=3 align=left> + 1. <b>Case Name:</b> The name of this investigation. It can contain only letters, numbers, and symbols. + </td> +</tr> +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=2><input type=\"text\" name=\"case\"></td> +</tr> + +<tr><td colspan=3>&nbsp;</td></tr> + +<tr> + <td colspan=3 align=left> + 2. <b>Description:</b> An optional, one line description of this case. + </td> +</tr> +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=2><input type=\"text\" name=\"desc\" size=32 maxlength=32></td> +</tr> + +<tr><td colspan=3>&nbsp;</td></tr> + +<tr> + <td colspan=3 align=left> + 3. <b>Investigator Names:</b> The optional names (with no spaces) of the investigators for this case. + </td> +</tr> +<tr> + <td>&nbsp;</td> + <td align=left><tt>a.</tt> <input type=\"text\" name=\"inv1\"></td> + <td align=left><tt>b.</tt> <input type=\"text\" name=\"inv2\"></td> +</tr> +<tr> + <td>&nbsp;</td> + <td align=left><tt>c.</tt> <input type=\"text\" name=\"inv3\"></td> + <td align=left><tt>d.</tt> <input type=\"text\" name=\"inv4\"></td> +</tr> +<tr> + <td>&nbsp;</td> + <td align=left><tt>e.</tt> <input type=\"text\" name=\"inv5\"></td> + <td align=left><tt>f.</tt> <input type=\"text\" name=\"inv6\"></td> +</tr> +<tr> + <td>&nbsp;</td> + <td align=left><tt>g.</tt> <input type=\"text\" name=\"inv7\"></td> + <td align=left><tt>h.</tt> <input type=\"text\" name=\"inv8\"></td> +</tr> +<tr> + <td>&nbsp;</td> + <td align=left><tt>i.</tt> <input type=\"text\" name=\"inv9\"></td> + <td align=left><tt>j.</tt> <input type=\"text\" name=\"inv10\"></td> +</tr> +</table> + +<br><br> +<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\"> +<tr> + <td align=center> + <input type=\"image\" src=\"pict/menu_b_cnew.jpg\" + alt=\"Create Case\" width=\"176\" height=20 border=0> + </td> +</form> + <td align=center> + <form action=\"$::PROGNAME\" method=\"get\"> + <input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\"> + <input type=\"hidden\" name=\"view\" value=\"$Caseman::CASE_OPEN\"> + <input type=\"image\" src=\"pict/menu_b_cancel.jpg\" + alt=\"Cancel\" width=\"167\" height=20 border=0> + </form> + </td> + <td align=center><a href=\"$::HELP_URL\" + target=\"_blank\"> + <img src=\"pict/menu_b_help.jpg\" alt=\"Help\" + width=\"167\" height=20 border=0></a> + </td> +</tr> +</table> +EOF + + Print::print_html_footer(); + return; +} + +# Create the directory and case configuration file +# Gets the input from CASE_NEW +sub case_new_doit { + Print::print_html_header("Creating Case: $Args::args{'case'}"); + my $case = $Args::args{'case'}; + + print "<h3>Creating Case: <tt>$case</tt></h3>\n"; + + # Make the directory + if (-d "$::case_dir") { + + # we can't send all of this to print_err, bc it doesn't want HTML + print "Error: $::case_dir already exists<br>" + . "Please remove the directory and its contents and try again" + . "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::CASE_OPEN\">" + . "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=\"43\" height=20 border=\"0\"></a>\n"; + Print::print_err("\n"); + } + + unless (mkdir "$::case_dir", $::MKDIR_MASK) { + Print::print_err("Error making directory $::case_dir: $!"); + } + + print "Case directory (<tt>$::case_dir</tt>) created<br>\n"; + Print::log_case_info("Case $case created"); + + my $fname = Caseman::case_config_fname(); + + open CASE_CONFIG, ">$fname" or die "Can't open case config: $fname"; + + print CASE_CONFIG "# Autopsy case config file\n" + . "# Case: $case\n\n" + . "created " + . localtime() . "\n"; + + if ((exists $Args::args{'desc'}) && ($Args::args{'desc'} ne "")) { + Print::print_err( + "Invalid Description\n" . "Use the browser's back button to fix") + if ($Args::args{'desc'} =~ /\n/); + + print CASE_CONFIG "desc $Args::args{'desc'}\n"; + } + print CASE_CONFIG "images $::IMGDIR\n"; + print CASE_CONFIG "data $::DATADIR\n"; + print CASE_CONFIG "log $::LOGDIR\n"; + print CASE_CONFIG "reports $::REPDIR\n"; + + close CASE_CONFIG; + print "Configuration file (<tt>$fname</tt>) created<br>\n"; + + my $iname = investig_fname(); + open INVES, ">>$iname" or die "Can't open investigators file: $iname"; + + my @invs; + if ( (exists $Args::args{'inv1'}) + && ($Args::args{'inv1'} ne "") + && ($Args::args{'inv1'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv2'}) + && ($Args::args{'inv2'} ne "") + && ($Args::args{'inv2'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv3'}) + && ($Args::args{'inv3'} ne "") + && ($Args::args{'inv3'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv4'}) + && ($Args::args{'inv4'} ne "") + && ($Args::args{'inv4'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv5'}) + && ($Args::args{'inv5'} ne "") + && ($Args::args{'inv5'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv6'}) + && ($Args::args{'inv6'} ne "") + && ($Args::args{'inv6'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv7'}) + && ($Args::args{'inv7'} ne "") + && ($Args::args{'inv7'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv8'}) + && ($Args::args{'inv8'} ne "") + && ($Args::args{'inv8'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv9'}) + && ($Args::args{'inv9'} ne "") + && ($Args::args{'inv9'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + if ( (exists $Args::args{'inv10'}) + && ($Args::args{'inv10'} ne "") + && ($Args::args{'inv10'} =~ /^\s*($::REG_INVESTIG)\s*$/o)) + { + print INVES "$1\n"; + push @invs, $1; + } + + close(INVES); + + Print::log_session_info("Case $case created"); + + print "<br><br>We must now create a host for this case.\n"; + + print "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_ADD\">\n" + . "<input type=\"hidden\" name=\"case\" value=\"$case\">\n"; + + if (scalar @invs == 0) { + print "<option hiddden name=\"inv\" value=\"unknown\">\n"; + } + else { + print "<br><br>Please select your name from the list: " + . "<select name=\"inv\" size=\"1\">\n"; + + foreach $i (@invs) { + print "<option value=\"$i\">$i</option>\n"; + } + print "</select>\n"; + } + + print "<br><br>" + . "<input type=\"image\" src=\"pict/menu_b_hnew.jpg\" alt=\"Add New Host\" " + . "height=20 border=\"0\"></form>\n"; + + Print::print_html_footer(); + return; +} + +# Open a Case +# This provides a form with a list of options +sub case_open { + Print::print_html_header("Open A Case"); + + # Read the directories of the Evidence Locker into an array + # Verify that there is a config file in the directory + my @cases; + opendir CASES, $::LOCKDIR or die "Can't open $::LOCKDIR directory: $!"; + foreach my $c (readdir CASES) { + next if (($c eq '.') || ($c eq '..')); + my $cfile = Caseman::case_config_fname($c); + + push @cases, $c + if ((-d "$::LOCKDIR/$c") && (-e "$cfile")); + } + closedir CASES; + + print "<br><br><center>"; + + # Were there any cases? + if (scalar @cases == 0) { + print "No cases exist in <tt>$::LOCKDIR</tt><br><br>\n" + . "Select the New Case button below to make one<br>\n"; + } + else { + + print "Select the case to open or create a new one<br>\n"; + + print_menu_tabs(); + + print "<table width=\"600\" background=\"$::YEL_PIX\" " + . " cellspacing=\"0\" cellpadding=\"2\" border=0>\n"; + + print "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::CASE_OPEN_LOG\">\n" + . Args::make_hidden() + . "<tr><th>Name</th>" + . "<th>Description</th>" + . "<td>&nbsp;</td></tr>\n"; + + my $first = 0; + foreach my $c (@cases) { + + print "<tr><td align=\"left\">" + . "<input type=\"radio\" name=\"case\" value=$c"; + if ($first == 0) { + print " CHECKED"; + $first = 1; + } + print ">$c</td>"; + + Caseman::read_case_config($c); + + print "<td>$Caseman::cvals{'desc'}</td>" + . "<td align=center>" + . "<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::CASE_DETAILS&case=$c\">" + . "details</a></td>" + . "</tr>\n"; + } + print "</table>\n"; + } + + print "<br><br>" + . "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">\n" + . "<tr>\n"; + + # Print the OK button if there were cases + if (scalar @cases != 0) { + print "<td align=center>" + . "<input type=\"image\" src=\"pict/menu_b_ok.jpg\" " + . "width=167 height=20 alt=\"Ok\" border=0>" + . "</form></td>\n\n"; + } + + # Print a 'New Case' Button + print "<td align=center>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::CASE_NEW\">\n" + . "<input type=\"image\" src=\"pict/menu_b_cnew.jpg\" " + . "width=167 height=20 alt=\"New Case\" border=0>\n" + . "</form></td>" + . + + # Print a Menu Button + "<td align=center>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"image\" src=\"pict/menu_b_menu.jpg\" " + . "width=167 height=20 alt=\"Main Menu\" border=0>\n" + . "</form></td></tr></table>\n"; + + print "<table width=600 cellspacing=\"0\" cellpadding=\"2\">\n<tr>" + . "<td>&nbsp;</td>\n" + . "<td align=center width=200><a href=\"$::HELP_URL\" " + . " target=\"_blank\">" + . "<img src=\"pict/menu_b_help.jpg\" alt=\"Help\" " + . "width=\"167\" height=20 border=0>" + . "</a></td>" + . "<td>&nbsp;</td>\n" + . "</tr>\n" + . "</table>"; + + Print::print_html_footer(); + return; +} + +# Log that a given case was opened and then proceed to open a host +sub case_open_log { + Print::log_session_info("Case $Args::args{'case'} opened"); + Print::log_case_info("Case $Args::args{'case'} opened"); + $Args::args{'view'} = $Args::enc_args{'view'} = $Caseman::HOST_OPEN; + host_open(); +} + +# Display Case Details +sub case_details { + + Print::print_html_header("Details of $Args::args{'case'}"); + + read_case_config(); + + $Caseman::cvals{'desc'} = "&nbsp;" + unless (exists $Caseman::cvals{'desc'}); + $Caseman::cvals{'created'} = "&nbsp;" + unless (exists $Caseman::cvals{'created'}); + + print "<br><br>" + . "<center>" + . "<img src=\"pict/menu_h_cdet.jpg\" alt=\"Case Details\">" + . "<br><br><br>\n" + . "<table width=\"600\" cellspacing=\"0\" background=\"$::YEL_PIX\" " + . "cellpadding=\"2\" border=0>\n" + . " <tr><td align=\"right\" width=300><b>Name:</b></td>" + . "<td align=\"left\" width=300><tt>$Args::args{'case'}</tt></td></tr>\n" + . + + # Description + " <tr><td align=\"right\"><b>Description:</b></td>" + . "<td align=\"left\"><tt>$Caseman::cvals{'desc'}</tt></td></tr>\n" + . " <tr><td align=\"right\"><b>Created:</b></td>" + . "<td align=\"left\"><tt>$Caseman::cvals{'created'}</tt></td></tr>\n"; + + # Display the valid investigators + my @invs = read_invest(); + my $cnt = 0; + print " <tr><td colspan=\"2\">&nbsp;</td></tr>\n" + if (scalar @invs > 0); + + foreach my $i (@invs) { + if ($cnt == 0) { + print " <tr><td align=\"right\"><b>Investigators:</b></td>"; + $cnt++; + } + else { + print " <tr><td>&nbsp;</td>"; + } + print "<td align=\"left\"><tt>$i</tt></td></tr>\n"; + } + + print "</table>\n" + . "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&view=$Caseman::CASE_OPEN\">" + . "<img src=\"pict/menu_b_ok.jpg\" alt=\"Ok\" " + . "width=\"167\" height=20 border=\"0\"></a>"; + + Print::print_html_footer(); + return 0; +} + +#################################################################### +# Host Functions + +# if no args are passed, return host config using args{'host'}, +# else use the host value passed +sub host_config_fname { + if (scalar(@_) == 1) { + my $h = shift; + return "$::case_dir" . "$h/host.aut"; + } + else { + return "$::host_dir" . "host.aut"; + } +} + +# Converts the original single image host config to the volume-based config +sub convert_host_config { + + return if ($::LIVE == 1); + + my $host = Args::get_host(); + + Print::log_host_info("Converting host config files"); + print STDERR "Converting host config file to new format\n"; + + # The file to convert + my $cfile = host_config_fname(); + unless (open(FILE, $cfile)) { + Print::print_check_err("Error opening $cfile"); + } + + my $tmpcfile = "$::host_dir" . "host-convert.aut"; + unless (open(FILE_TMP, ">>$tmpcfile")) { + Print::print_check_err("Error opening $tmpcfile"); + } + + my $img_cnt = 0; + my $vol_cnt = 0; + $img2vol{'qazwsxedc'} = ""; # stores the image path to partition / file name + $img2vol2{'qazwsxedc'} = + ""; # stores the image path to file name (no partitions) + + while (<FILE>) { + if ((/^\#/) || (/^\s+$/)) { + print FILE_TMP $_; + next; + } + + # remove whitespace + s/^\s+//; + s/\s+$//; + + # normal file system image entry + # + # 'image images/hda1.dd openbsd /usr + if (/^image\s+($::REG_IMG)\s+([\w\-]+)\s+([\w\-\_\.\/:\\]+)$/o) { + + my $i = $1; + my $t = $2; + my $r = $3; + + # Add trailing / to original mount point if needed + if (($r !~ /.*?\/$/) && ($r !~ /.*?\\$/)) { + $r .= '/'; + } + my $vnum = "vol" . $vol_cnt; + my $inum = "img" . $img_cnt; + $img2vol{$i} = $vnum; + $img2vol2{$i} = $inum; + + print FILE_TMP "image $inum raw $i\n"; + print FILE_TMP "part $vnum $inum 0 0 $t $r\n"; + + $img_cnt++; + $vol_cnt++; + } + + # swap + # swap images/hda3.dd + elsif (/^swap\s+($::REG_IMG)\s*$/o) { + my $i = $1; + + my $vnum = "vol" . $vol_cnt; + my $inum = "img" . $img_cnt; + $img2vol{$i} = $vnum; + $img2vol2{$i} = $inum; + + print FILE_TMP "image $inum raw $i\n"; + print FILE_TMP "part $vnum $inum 0 0 swap\n"; + $img_cnt++; + $vol_cnt++; + + } + + # raw + # raw images/hda3.dd + elsif (/^raw\s+($::REG_IMG)\s*$/o) { + my $i = $1; + $img2vol{$i} = "vol" . $vol_cnt; + $img2vol2{$i} = "img" . $img_cnt; + + print FILE_TMP "image img" . $img_cnt . " raw $i\n"; + print FILE_TMP "part vol" . $vol_cnt . " img" . $img_cnt + . " 0 0 raw\n"; + $img_cnt++; + $vol_cnt++; + } + + # entry for a strings or blkls file + # + # strings data/hda1.str images/hda1.dd + elsif (/^strings\s+($::REG_IMG)\s+($::REG_IMG)$/o) { + my $i = $1; + my $o = $2; + + if (exists $img2vol{$o}) { + my $vname = $img2vol{$o}; + print FILE_TMP "strings vol" . $vol_cnt . " $vname $i\n"; + $img2vol{$i} = "vol" . $vol_cnt; + $img2vol2{$i} = "vol" . $vol_cnt; + } + else { + print STDERR "Error: Volume for strings $o not found<br>\n"; + } + $vol_cnt++; + } + + # entry for a strings or blkls file + # + # unistrings data/hda1.str images/hda1.dd + elsif (/^unistrings\s+($::REG_IMG)\s+($::REG_IMG)$/o) { + my $i = $1; + my $o = $2; + + if (exists $img2vol{$o}) { + my $vname = $img2vol{$o}; + print FILE_TMP "unistrings vol" . $vol_cnt + . " $vname $i\n"; + $img2vol{$i} = "vol" . $vol_cnt; + $img2vol2{$i} = "vol" . $vol_cnt; + } + else { + print STDERR + "Error: Volume for unicode strings $o not found<br>\n"; + } + $vol_cnt++; + } + + # blkls entry + # blkls data/image.blkls [images/image.dd] + elsif (/^blkls\s+($::REG_IMG)\s*($::REG_IMG)$/o) { + my $i = $1; + my $o = $2; + + $img2vol{$i} = "vol" . $vol_cnt; + + if (exists $img2vol{$o}) { + my $vname = $img2vol{$o}; + print FILE_TMP "blkls vol" . $vol_cnt . " $vname $i\n"; + $img2vol{$i} = "vol" . $vol_cnt; + $img2vol2{$i} = "vol" . $vol_cnt; + } + else { + print STDERR "Error: Volume for blkls $o not found<br>\n"; + } + $vol_cnt++; + } + + # body data/body.txt + elsif (/^body\s+($::REG_IMG)$/o) { + my $i = $1; + print FILE_TMP "body vol" . $vol_cnt . " $i\n"; + $img2vol{$i} = "vol" . $vol_cnt; + $img2vol2{$i} = "vol" . $vol_cnt; + + $vol_cnt++; + } + + # timeline data/timeline.txt + elsif (/^timeline\s+($::REG_IMG)$/o) { + my $i = $1; + print FILE_TMP "timeline vol" . $vol_cnt . " $i\n"; + $img2vol{$i} = "vol" . $vol_cnt; + $img2vol2{$i} = "vol" . $vol_cnt; + $vol_cnt++; + } + + # timezone XYZ + elsif (/^timezone\s+($::REG_ZONE_ARGS)$/o) { + print FILE_TMP "$_\n"; + } + + # timeskew XYZ + elsif (/^timeskew\s+($::REG_SKEW)$/o) { + print FILE_TMP "$_\n"; + } + + # desc XYZ + elsif (/^desc\s+(.*)$/) { + print FILE_TMP "$_\n"; + } + + # hash databases + elsif (/^alert_db\s+'(.*)'$/) { + print FILE_TMP "$_\n"; + } + elsif (/^exclude_db\s+'(.*)'$/) { + print FILE_TMP "$_\n"; + } + else { + my $msg = + "Error: invalid entry in $cfile:$." . "\n" + . "image path fs_type mnt_point\n" + . "strings path orig_img\n" + . "blkls path [orig_img]\n" + . "body path\n" + . "timeline path\n" + . "timezone TZ\n" + . "desc DESCRIPTION\n"; + Print::print_check_err($msg); + } + } + + close(FILE); + close(FILE_TMP); + unless (rename $cfile, $cfile . ".bak") { + print STDERR "Error backing up original host config file\n"; + } + unless (rename $tmpcfile, $cfile) { + print STDERR "Error renaming new host config file\n"; + } + + Notes::convert(\%img2vol); + Hash::convert(\%img2vol2); +} + +# reads host config file and sets global hash values for images and other +sub read_host_config { + + if ($::LIVE == 1) { + %Caseman::mod2vol = (); + %Caseman::vol2str = (); + %Caseman::vol2uni = (); + %Caseman::vol2blkls = (); + $Caseman::tz = ""; + $Caseman::ts = 0; + $Caseman::host_desc = ""; + $Caseman::exclude_db = ""; + $Caseman::alert_db = ""; + return; + } + + my $host = Args::get_host(); + + my $cfile = host_config_fname(); + restart: + unless (open(FILE, $cfile)) { + Print::print_check_err("Error opening $cfile"); + } + + %Caseman::vol2mnt = (); + %Caseman::vol2ftype = (); + %Caseman::vol2dtype = (); + %Caseman::vol2cat = (); + %Caseman::mod2vol = (); + %Caseman::vol2str = (); + %Caseman::vol2uni = (); + %Caseman::vol2blkls = (); + %Caseman::vol2par = (); + %Caseman::vol2start = (); + %Caseman::vol2end = (); + $Caseman::vol2path = (); + $Caseman::vol2sname = (); + + $Caseman::tz = ""; + $Caseman::ts = 0; + $Caseman::host_desc = ""; + $Caseman::exclude_db = ""; + $Caseman::alert_db = ""; + + while (<FILE>) { + next if ((/^\#/) || (/^\s+$/)); + + # remove whitespace + s/^\s+//; + s/\s+$//; + + # old file system image entry + # + # 'image images/hda1.dd openbsd /usr + if (/^image\s+($::REG_IMG)\s+([\w\-]+)\s+([\w\-\_\.\/:\\]+)$/o) { + + close(FILE); + convert_host_config(); + goto restart; + } + elsif ( + /^image\s+($::REG_INAME)\s+($::REG_IMGTYPE)\s+($::REG_IMG_CONFIG)$/o + ) + { + my $me = $1; + my $t = $2; + my $i = $3; + + unless ((-e "$::host_dir$i") + || ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i"))) + { + Print::print_check_err( + "Error: image $i in ${host}.host:$. not found: " + . "$::host_dir" + . "$i \nEdit the config file and refresh your browser\n" + . "(Or your version of Perl does not support large files)" + ); + } + + if (exists $Caseman::vol2path{$me}) { + $Caseman::vol2path{$me} .= " \'$::host_dir" . "$i\'"; + } + else { + $Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'"; + $Caseman::vol2sname{$me} = $i; + $Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/); + + $Caseman::vol2par{$me} = ""; + $Caseman::vol2cat{$me} = "image"; + $Caseman::vol2itype{$me} = $t; + $Caseman::vol2ftype{$me} = ""; + + $Caseman::vol2start{$me} = 0; + $Caseman::vol2end{$me} = 0; + } + } + elsif ( +/^part\s+($::REG_VNAME)\s+($::REG_INAME)\s+(\d+)\s+(\d+)\s+($::REG_FTYPE)\s*([\w\-\_\.\/:\\]+)?$/o + ) + { + my $par = $2; + my $me = $1; + my $s = $3; + my $e = $4; + my $t = $5; + my $r = $6; # Not defined for swap and raw + + unless (exists $Fs::addr_unit{$t}) { + Print::print_check_err( + "Error: unknown type: $t in host config: $." + . "\nEdit the file and refresh your browser"); + } + + if (exists $Caseman::vol2itype{$par}) { + $Caseman::vol2itype{$me} = $Caseman::vol2itype{$par}; + } + else { + Print::print_check_err( +"Error: Image $par for partition $me was not found in config: $." + . "\nEdit the file and refresh your browser"); + } + + $Caseman::vol2ftype{$me} = $t; + $Caseman::vol2cat{$me} = "part"; + $Caseman::vol2start{$me} = $s; + $Caseman::vol2end{$me} = $e; + + # Add trailing / to original mount point if needed + if ((defined $r) && ($r !~ /.*?\/$/) && ($r !~ /.*?\\$/)) { + $r .= '/'; + } + $Caseman::vol2mnt{$me} = $r; + $Caseman::vol2par{$me} = $par; + $Caseman::vol2path{$me} = $Caseman::vol2path{$par}; + $Caseman::vol2sname{$me} = + $Caseman::vol2sname{$par} . "-" . $s . "-" . $e; + } + elsif (/^disk\s+($::REG_VNAME)\s+($::REG_INAME)\s+($::REG_FTYPE)?$/o) { + my $par = $2; + my $me = $1; + my $t = $3; + + unless (exists $Vs::type{$t}) { + Print::print_check_err( + "Error: unknown volume system type: $t in host config: $." + . "\nEdit the file and refresh your browser"); + } + + if (exists $Caseman::vol2itype{$par}) { + $Caseman::vol2itype{$me} = $Caseman::vol2itype{$par}; + } + else { + Print::print_check_err( +"Error: Image $par for disk $me was not found in config: $.\n" + . "Edit the file and refresh your browser"); + } + + $Caseman::vol2ftype{$me} = "raw"; + $Caseman::vol2dtype{$me} = $t; + $Caseman::vol2cat{$me} = "disk"; + $Caseman::vol2start{$me} = 0; + $Caseman::vol2end{$me} = 0; + $Caseman::vol2mnt{$me} = ""; + $Caseman::vol2par{$me} = $par; + $Caseman::vol2path{$me} = $Caseman::vol2path{$par}; + $Caseman::vol2sname{$me} = $Caseman::vol2sname{$par} . "-disk"; + } + + # entry for a strings or blkls file + # + # strings data/hda1.str volX + elsif (/^strings\s+($::REG_VNAME)\s+($::REG_VNAME)\s+($::REG_IMG)$/o) { + my $i = $3; + my $par = $2; + my $me = $1; + + unless ((-e "$::host_dir$i") + || ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i"))) + { + Print::print_check_err("Error: strings file not found: " + . "$::host_dir$i\nEdit host config in $::host_dir and refresh your browser" + ); + } + + unless (exists $Caseman::vol2cat{$par}) { + Print::print_check_err( +"Error: Volume $par for strings $me was not found in config: $." + . "\nEdit the file and refresh your browser"); + } + + $Caseman::vol2ftype{$me} = "strings"; + $Caseman::vol2cat{$me} = "mod"; + $Caseman::vol2itype{$me} = "raw"; + $Caseman::mod2vol{$me} = $par; + $Caseman::vol2str{$par} = $me; + $Caseman::vol2par{$me} = $par; + $Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'"; + $Caseman::vol2start{$me} = 0; + $Caseman::vol2end{$me} = 0; + $Caseman::vol2sname{$me} = $i; + $Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/); + + } + + # entry for a strings or blkls file + # + # unistrings data/hda1.str volX + elsif (/^unistrings\s+($::REG_VNAME)\s+($::REG_VNAME)\s+($::REG_IMG)$/o) + { + my $i = $3; + my $par = $2; + my $me = $1; + + unless ((-e "$::host_dir$i") + || ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i"))) + { + Print::print_check_err("Error: Unicode strings file not found: " + . "$::host_dir$i\nEdit host config in $::host_dir and refresh your browser" + ); + } + + unless (exists $Caseman::vol2cat{$par}) { + Print::print_check_err( +"Error: Volume $par for unistrings $me was not found in config: $." + . "\nEdit the file and refresh your browser"); + } + + $Caseman::vol2ftype{$me} = "strings"; + $Caseman::vol2cat{$me} = "mod"; + $Caseman::vol2itype{$me} = "raw"; + $Caseman::mod2vol{$me} = $par; + $Caseman::vol2uni{$par} = $me; + $Caseman::vol2par{$me} = $par; + $Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'"; + $Caseman::vol2start{$me} = 0; + $Caseman::vol2end{$me} = 0; + $Caseman::vol2sname{$me} = $i; + $Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/); + } + + # blkls entry + # blkls themname myname + elsif (/^blkls\s+($::REG_VNAME)\s+($::REG_VNAME)\s+($::REG_IMG)$/o) { + my $i = $3; + my $par = $2; + my $me = $1; + + unless ( + (-e "$::host_dir$i") + || ( (-l "$::host_dir$i") + && (-e readlink "$::host_dir$i")) + ) + { + Print::print_check_err("Error: blkls file not found: " + . "$::host_dir$i \nEdit host config in $::host_dir and refresh your browser" + ); + } + + unless (exists $Caseman::vol2cat{$par}) { + Print::print_check_err( +"Error: Volume $par for blkls $me was not found in config: $." + . "\nEdit the file and refresh your browser"); + } + + $Caseman::vol2ftype{$me} = "blkls"; + $Caseman::vol2cat{$me} = "mod"; + $Caseman::vol2itype{$me} = "raw"; + $Caseman::vol2mnt{$me} = ""; + $Caseman::vol2par{$me} = $par; + $Caseman::mod2vol{$me} = $par; + $Caseman::vol2blkls{$par} = $me; + $Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'"; + $Caseman::vol2start{$me} = 0; + $Caseman::vol2end{$me} = 0; + $Caseman::vol2sname{$me} = $i; + $Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/); + + } + + # body data/body.txt + elsif (/^body\s+($::REG_VNAME)\s+($::REG_IMG)$/o) { + my $me = $1; + my $i = $2; + + unless ((-e "$::host_dir$i") + || ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i"))) + { + Print::print_check_err("Error: body file not found: " + . "$::host_dir$i <br>Edit host config in $::host_dir and refresh your browser" + ); + } + + $Caseman::vol2cat{$me} = "timeline"; + $Caseman::vol2ftype{$me} = "body"; + $Caseman::vol2itype{$me} = "raw"; + $Caseman::vol2path{$me} = "\'$::host_dir" . "$i\'"; + $Caseman::vol2start{$me} = 0; + $Caseman::vol2end{$me} = 0; + $Caseman::vol2sname{$me} = $i; + $Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/); + } + + # timeline data/timeline.txt + elsif (/^timeline\s+($::REG_VNAME)\s+($::REG_IMG)$/o) { + my $me = $1; + my $i = $2; + + unless ((-e "$::host_dir$i") + || ((-l "$::host_dir$i") && (-e readlink "$::host_dir$i"))) + { + Print::print_check_err("Error: timeline file not found: " + . "$::host_dir$i \nEdit host config in $::host_dir and refresh your browser" + ); + } + + $Caseman::vol2cat{$me} = "timeline"; + $Caseman::vol2ftype{$me} = "timeline"; + $Caseman::vol2itype{$me} = "raw"; + +# We do not add the quotes to the path for timeline because it is opened only by the Perl code and it doesn't like the quotes + $Caseman::vol2path{$me} = "$::host_dir" . "$i"; + $Caseman::vol2start{$me} = 0; + $Caseman::vol2end{$me} = 0; + $Caseman::vol2sname{$me} = $i; + $Caseman::vol2sname{$me} = $1 if ($i =~ /\/($::REG_FILE)$/); + + } + + # timezone XYZ + elsif (/^timezone\s+($::REG_ZONE_ARGS)$/o) { + $Caseman::tz = "\'$1\'"; + } + + # timeskew XYZ + elsif (/^timeskew\s+($::REG_SKEW)$/o) { + $Caseman::ts = "\'$1\'"; + } + + # desc XYZ + elsif (/^desc\s+(.*)$/) { + $Caseman::host_desc = "$1"; + } + + # hash databases + elsif (/^alert_db\s+'(.*)'$/) { + $Caseman::alert_db = "$1"; + } + elsif (/^exclude_db\s+'(.*)'$/) { + $Caseman::exclude_db = "$1"; + } + else { + my $msg = "Error: invalid entry in $cfile:$." . "\n" . "$_\n"; + Print::print_check_err($msg); + } + } + close(FILE); +} + +# Add a new image entry to the host config and return its id +sub add_img_host_config { + my $type = shift; + my $other = shift; + my $id = shift; + + my $read = host_config_fname(); + my $write = $read . "-" . rand(); + + unless (open(READ, "<$read")) { + Print::print_check_err("Error opening $read"); + } + + unless (open(WRITE, ">$write")) { + Print::print_check_err("Error opening $write"); + } + + my $maxcnt = 0; + + while (<READ>) { + s/^\s+//; + s/\s+$//; + if (/^\w+\s+img(\d+)\s+.*$/) { + $maxcnt = $1 if ($1 > $maxcnt); + } + print WRITE "$_\n"; + } + $maxcnt++; + if ($id eq "") { + $id = "img" . $maxcnt; + } + print WRITE "$type $id $other\n"; + + Print::log_host_info("Image added: $type $id $other"); + + close(READ); + close(WRITE); + unless (rename $write, $read) { + print STDERR "Error renaming temp host config file\n"; + } + + return $id; +} + +# Add a new volume entry to the host config and return its id +sub add_vol_host_config { + my $type = shift; + my $other = shift; + + my $read = host_config_fname(); + my $write = $read . "-" . rand(); + + unless (open(READ, "<$read")) { + Print::print_check_err("Error opening $read"); + } + + unless (open(WRITE, ">$write")) { + Print::print_check_err("Error opening $write"); + } + + # We want to find the max count ... not just the unused + # ones because we could end up reusing one and that could + # mess up the notes + my $maxcnt = 0; + + while (<READ>) { + s/^\s+//; + s/\s+$//; + if (/^\w+\s+vol(\d+)\s+.*$/) { + $maxcnt = $1 if ($1 > $maxcnt); + } + print WRITE "$_\n"; + } + $maxcnt++; + print WRITE "$type vol" . $maxcnt . " $other\n"; + Print::log_host_info("Volume added: $type vol" . $maxcnt . " $other"); + + close(READ); + close(WRITE); + unless (rename $write, $read) { + print STDERR "Error renaming temp host config file\n"; + } + + return "vol" . $maxcnt; +} + +# Delete anentry from the host config +# DOES NOT WORK RIGHT NOW +sub del_host_config_BLAH { + return; + my $type = shift; + my $other = shift; + + my $read = host_config_fname(); + my $write = $read . "-" . rand(); + + unless (open(READ, "<$read")) { + Print::print_check_err("Error opening $read"); + } + + unless (open(WRITE, ">$write")) { + Print::print_check_err("Error opening $write"); + } + + while (<READ>) { + s/^\s+//; + s/\s+$//; + print WRITE "$_\n" + unless ((/^(\w+)\s+($::REG_IMG)/o) + && ($2 eq $img) + && ($1 ne 'desc') + && ($1 ne 'timezone')); + } + + if ($type ne "") { + if (defined $ref) { + print WRITE "$type $img $ref\n"; + } + else { + print WRITE "$type $img\n"; + } + } + + close(READ); + close(WRITE); + unless (rename $write, $read) { + print STDERR "Error renaming temp host config file\n"; + } + + return; +} + +# Given the image and md5, it is saved to the MD5.txt file and any other +# references to the image are removed +# +# if $md5 is "", then nothing is written +sub update_md5 { + my $vol = shift; + my $md5 = shift; + $md5 =~ tr/[a-f]/[A-F]/; + + my $read = "$::host_dir/md5.txt"; + my $write = $read . "-" . rand(); + + unless (open(WRITE, ">$write")) { + Print::print_check_err("Error opening $write"); + } + + if (-e "$read") { + unless (open(READ, "<$read")) { + Print::print_check_err("Error opening $read"); + } + + while (<READ>) { + s/^\s+//; + s/\s+$//; + print WRITE "$_\n" + unless ((/^$::REG_MD5\s+($::REG_VNAME)/o) && ($1 eq $vol)); + } + close(READ); + } + + print WRITE "$md5 $vol\n" if ($md5 ne ""); + + close(WRITE); + + unless (rename $write, $read) { + print STDERR "Error renaming temp MD5 hash file\n"; + } + return; +} + +sub host_add { + Print::print_html_header("Add A New Host To $Args::args{'case'}"); + + print "<b>Case: </b> $Args::args{'case'}<br><br>\n"; + + print "<center>" + . "<img src=\"pict/menu_h_hnew.jpg\" alt=\"Add Host\">" + . "<br><br><br>\n"; + + print "<table width=\"600\" cellspacing=\"0\" background=\"$::YEL_PIX\" " + . "cellpadding=\"2\" border=0>\n" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_ADD_DOIT\">\n" + . Args::make_hidden() + . "<tr><td colspan=\"2\">&nbsp;</td></tr>" + . + + # Host name +"<tr><td align=\"left\" colspan=2>1. <b>Host Name:</b> The name of the computer being investigated. It can contain only letters, numbers, and symbols.</td></tr>" + . "<tr><td align=\"left\">&nbsp;&nbsp;&nbsp;</td>" + . "<td align=\"left\"><input type=\"text\" name=\"host\" size=32 maxlength=32 value=\"host1\"></td></tr>\n" + . + + # Description +"<tr><td align=\"left\" colspan=2>2. <b>Description:</b> An optional one-line description or note about this computer.</td></tr>" + . "<tr><td align=\"left\">&nbsp;&nbsp;&nbsp;</td>" + . "<td align=\"left\">" + . "<input type=\"text\" name=\"desc\" size=32 maxlength=32></td></tr>\n" + . + + # Empty line + "<tr><td colspan=\"2\">&nbsp;</td></tr>" . + + # Timezone +"<tr><td align=\"left\" colspan=2>3. <b>Time zone:</b> An optional timezone value (i.e. EST5EDT). If not given, it defaults to the local setting. A list of time zones can be found in the help files.</td></tr>" + . "<tr><td align=\"left\">&nbsp;&nbsp;&nbsp;</td>" + . "<td align=\"left\">" + . "<input type=\"text\" name=\"tz\" size=16 maxlength=64></td></tr>\n" + . + + # Timeskew +"<tr><td align=\"left\" colspan=2>4. <b>Timeskew Adjustment:</b> An optional value to describe how many seconds this computer's clock was out of sync. For example, if the computer was 10 seconds fast, then enter -10 to compensate.</td></tr>" + . "<tr><td align=\"left\">&nbsp;&nbsp;&nbsp;</td>" + . "<td align=\"left\">" + . "<input type=\"text\" name=\"ts\" size=8 maxlength=16 value=\"0\">" + . "</td></tr>\n" + . + + # Spacer + "<tr><td colspan=\"2\">&nbsp;</td></tr>" . + + # Alert +"<tr><td align=\"left\" colspan=2>5. <b>Path of Alert Hash Database:</b> An optional hash database of known bad files.</td></tr>" + . "<tr><td align=\"left\">&nbsp;&nbsp;&nbsp;</td>" + . "<td align=\"left\">" + . "<input type=\"text\" name=\"alert_db\" size=32 maxlength=512>" + . "</td></tr>\n" + . + + # Ignore +"<tr><td align=\"left\" colspan=2>6. <b>Path of Ignore Hash Database:</b> An optional hash database of known good files.</td></tr>" + . "<tr><td align=\"left\">&nbsp;&nbsp;&nbsp;</td>" + . "<td align=\"left\">" + . "<input type=\"text\" name=\"exclude_db\" size=32 maxlength=512>" + . "</td></tr>\n" + . + + # Spacer + "<tr><td colspan=\"2\">&nbsp;</td></tr>" . "</table>\n"; + + if (exists $Args::args{'inv'}) { + print + "<input type=\"hidden\" name=\"inv\" value=\"$Args::args{'inv'}\">\n"; + } + + # Ok Button + print "<br><br><table width=\"600\" cellspacing=\"8\" cellpadding=\"2\">\n" + . "<tr><td align=center>" + . "<input type=\"image\" src=\"pict/menu_b_hnew.jpg\" " + . "width=167 height=20 alt=\"Add Host\" border=0>\n" + . "</form></td>\n" + . + + # Cancel Button + "<td align=center>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN\">\n" + . "<input type=\"hidden\" name=\"case\" value=\"$Args::args{'case'}\">\n" + . "<input type=\"image\" src=\"pict/menu_b_cancel.jpg\" " + . "alt=\"Cancel\" width=\"167\" height=20 border=0>\n" + . "</form></td>\n" + . + + # Help Button + "<td align=center><a href=\"$::HELP_URL\" " + . "target=\"_blank\">" + . "<img src=\"pict/menu_b_help.jpg\" alt=\"Help\" " + . "width=\"167\" height=20 border=0></a>" + . "</td></tr>\n" + . "</table>"; + + Print::print_html_footer(); + + return 0; +} + +# Make the directories and config files for a host +sub host_add_doit { + Args::check_tz() + if ((exists $Args::args{'tz'}) && ($Args::args{'tz'} ne "")); + Args::check_ts(); + Print::print_html_header( + "Adding Host $Args::args{'host'} to $Args::args{'case'}"); + + print "<h3>Adding host: <tt>$Args::args{'host'}</tt> to " + . "case <tt>$Args::args{'case'}</tt></h3>\n"; + + # Do some sanity checks before we start making the directories and such + if ( (exists $Args::args{'alert_db'}) + && ($Args::args{'alert_db'} ne "")) + { + + unless ($Args::args{'alert_db'} =~ /^$::REG_HASHDB$/o) { + print "Invalid Alert Database path\n" + . "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::HOST_ADD&case=$Args::args{'case'}\">" + . "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=\"43\" height=20 border=\"0\"></a>\n"; + return 1; + } + + unless (-e "$Args::args{'alert_db'}") { + print "Alert Database Not Found: $Args::args{'alert_db'}" + . "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::HOST_ADD&case=$Args::args{'case'}\">" + . "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=\"43\" height=20 border=\"0\"></a>\n"; + return 1; + } + } + + if ( (exists $Args::args{'exclude_db'}) + && ($Args::args{'exclude_db'} ne "")) + { + unless ($Args::args{'exclude_db'} =~ /^$::REG_HASHDB$/o) { + print "Invalid Exclude Database path\n" + . "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::HOST_ADD&case=$Args::args{'case'}\">" + . "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=\"43\" height=20 border=\"0\"></a>\n"; + return 1; + } + + unless (-e "$Args::args{'exclude_db'}") { + print "Exclude Database Not Found: $Args::args{'exclude_db'}" + . "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::HOST_ADD&case=$Args::args{'case'}\">" + . "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=\"43\" height=20 border=\"0\"></a>\n"; + return 1; + } + } + + # Make the directory + if (-d "$::host_dir") { + + print "Error: $::host_dir already exists<br>" + . "Please remove the directory and its contents and try again" + . "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::HOST_OPEN&case=$Args::enc_args{'case'}\">" + . "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=\"43\" height=20 border=\"0\"></a>\n"; + Print::print_err("\n"); + } + unless (mkdir "$::host_dir", $::MKDIR_MASK) { + Print::print_err("Error making directory $::host_dir: $!"); + } + + print "Host Directory (<tt>$::host_dir</tt>) created<p>\n"; + Print::log_case_info("Host $Args::args{'host'} added to case"); + + # Images directory + unless (mkdir "$::host_dir" . "$::IMGDIR", $::MKDIR_MASK) { + rmdir "$::host_dir"; + Print::print_err("Error making $::host_dir" . "$::IMGDIR"); + } + + # Output Directory + unless (mkdir "$::host_dir" . "$::DATADIR", $::MKDIR_MASK) { + rmdir "$::host_dir" . "$::IMGDIR"; + rmdir "$::host_dir"; + Print::print_err("Error making $::host_dir" . "$::DATADIR"); + } + + # Log Directory + unless (mkdir "$::host_dir" . "$::LOGDIR", $::MKDIR_MASK) { + rmdir "$::host_dir" . "$::DATADIR"; + rmdir "$::host_dir" . "$::IMGDIR"; + rmdir "$::host_dir"; + Print::print_err("Error making $::host_dir" . "$::LOGDIR"); + } + + # Reports directory + unless (mkdir "$::host_dir" . "$::REPDIR", $::MKDIR_MASK) { + rmdir "$::host_dir" . "$::LOGDIR"; + rmdir "$::host_dir" . "$::DATADIR"; + rmdir "$::host_dir" . "$::IMGDIR"; + rmdir "$::host_dir"; + Print::print_err("Error making $::host_dir" . "$::REPDIR"); + } + + # Make a directory for mounting the image in loopback + unless (mkdir "$::host_dir" . "mnt", $::MKDIR_MASK) { + rmdir "$::host_dir" . "$::REPDIR"; + rmdir "$::host_dir" . "$::LOGDIR"; + rmdir "$::host_dir" . "$::DATADIR"; + rmdir "$::host_dir" . "$::IMGDIR"; + rmdir "$::host_dir"; + Print::print_err("Error making $::host_dir" . "mnt"); + } + + Print::log_host_info( + "Host $Args::args{'host'} added to case $Args::args{'case'}"); + + # Create config file + my $fname = Caseman::host_config_fname(); + open HOST_CONFIG, ">$fname" or die "Can't open host config: $fname"; + + print HOST_CONFIG "# Autopsy host config file\n" + . "# Case: $Args::args{'case'} Host: $Args::args{'host'}\n" + . "# Created: " + . localtime() . "\n\n"; + + if ((exists $Args::args{'desc'}) && ($Args::args{'desc'} ne "")) { + Print::print_err( + "Invalid Description\n" . "Use the browser's back button to fix") + if ($Args::args{'desc'} =~ /\n/); + + print HOST_CONFIG "desc $Args::args{'desc'}\n"; + } + + print HOST_CONFIG "timezone " . Args::get_tz() . "\n" + if ((exists $Args::args{'tz'}) && ($Args::args{'tz'} ne "")); + print HOST_CONFIG "timeskew " . Args::get_ts() . "\n"; + + if ( (exists $Args::args{'alert_db'}) + && ($Args::args{'alert_db'} ne "")) + { + + # Index it if it is not + unless (-e "$Args::args{'alert_db'}-md5.idx") { + print +"Alert Database has not been indexed - it will be as an md5sum file<br>\n"; + + print "<hr>\n"; + Hash::index_md5sum($Args::args{'alert_db'}); + print "<hr>\n"; + } + + # only print it if it was successful + print HOST_CONFIG "alert_db \'$Args::args{'alert_db'}\'\n" + if (-e "$Args::args{'alert_db'}-md5.idx"); + } + + if ( (exists $Args::args{'exclude_db'}) + && ($Args::args{'exclude_db'} ne "")) + { + + # Index it if it is not + unless (-e "$Args::args{'exclude_db'}-md5.idx") { + print +"Exclude Database has not been indexed - it will be as an md5sum file<br>\n"; + + print "<hr>\n"; + Hash::index_md5sum($Args::args{'exclude_db'}); + print "<hr>\n"; + } + + # only print it if it was successful + print HOST_CONFIG "exclude_db \'$Args::args{'exclude_db'}\'\n" + if (-e "$Args::args{'exclude_db'}-md5.idx"); + } + + close HOST_CONFIG; + + print "Configuration file (<tt>$fname</tt>) created<br><br>\n"; + + print "We must now import an image file for this host\n"; + + print "<br><br><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::HOST_OPEN_LOG&$Args::baseargs\">" + . "<img src=\"pict/menu_b_inew.jpg\" alt=\"Add Image\" " + . " height=20 border=\"0\"></a>\n"; + + Print::print_html_footer(); + return 0; +} + +# Open a host in the given case +sub host_open { + Print::print_html_header("Open Host In $Args::args{'case'}"); + + # Create an array of directories in the case, verifying that there is + # a config file + my @hosts; + opendir HOSTS, $::case_dir or die "Can't open $::case_dir directory: $!"; + foreach my $h (readdir HOSTS) { + next if (($h eq '.') || ($h eq '..')); + + my $hfile = Caseman::host_config_fname($h); + push @hosts, $h + if ((-d "$::case_dir" . "$h") && (-e "$hfile")); + } + closedir HOSTS; + + print "<b>Case:</b> $Args::args{'case'}<br><br>\n"; + + print "<center>"; + + if (scalar @hosts == 0) { + print "No hosts have been added to the case yet" + . "<br><br>Select the Add Host button below to create one.<br>\n"; + } + else { + + print "Select the host to open or create a new one<br>\n"; + + print_menu_tabs(); + + print "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\" " + . "background=\"$::YEL_PIX\" border=0>\n"; + + print "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN_LOG\">\n" + . Args::make_hidden() + . "<tr><th>Name</th>" + . "<th>Description</th><th>&nbsp;</th></tr>\n"; + + my $first = 0; + foreach my $h (@hosts) { + + print "<tr><td align=\"left\">" + . "<input type=\"radio\" name=\"host\" value=$h"; + if ($first == 0) { + print " CHECKED"; + $first = 1; + } + print "> $h </td>"; + + my $fname = Caseman::host_config_fname($h); + open CONFIG, "<$fname" + or die "Can't open host config file ($fname)"; + + my $desc = "None Provided"; + while (<CONFIG>) { + s/^\s+//; + s/\s+$//; + + if (/^desc\s+(.*)$/) { + $desc = $1; + last; + } + } + close CONFIG; + + print "<td align=left>$desc</td>" + . "<td align=center>" + . "<a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::HOST_DETAILS&$Args::baseargs&" + . "host=$h\">details</a></td></tr>\n"; + } + print "</table>\n"; + + # Display pulldown of investigators + my @invs = read_invest(); + if (scalar @invs == 0) { + print "<input type=\"hidden\" name=\"inv\" value=\"unknown\">\n"; + } + else { + print "<br>Investigator (for reports only): "; + my $cur_inv = ""; + $cur_inv = $Args::args{'inv'} if (exists $Args::args{'inv'}); + + print "<select name=\"inv\" size=\"1\">\n"; + + if (($cur_inv eq "") && (scalar @invs != 1)) { + print "<option value=\"\" selected>Select One" . "</option>\n"; + } + foreach my $i (@invs) { + print "<option value=\"$i\""; + print " selected" if ($cur_inv eq $i); + print ">$i</option>\n"; + } + print "</select>\n"; + } + } + print "<br><br><table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">\n" + . "<tr>\n"; + + # Make a table for the buttons. The table will either be 3 or 2 + # entries wide, depending on if there is an 'Ok' button or not + + unless (scalar @hosts == 0) { + print "<td align=center>" + . "<input type=\"image\" src=\"pict/menu_b_ok.jpg\" " + . "alt=\"Ok\" width=\"167\" height=20 border=0>\n" + . "</form>\n</td>\n"; + } + + # Add Host + print "<td align=center>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_ADD\">\n" + . "<input type=\"hidden\" name=\"case\" value=\"$Args::args{'case'}\">\n" + . "<input type=\"image\" src=\"pict/menu_b_hnew.jpg\" " + . "alt=\"Add Host\" width=\"176\" height=20 border=0>\n" + . "</form></td>" + . + + # Close Button + "<td align=center>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::CASE_OPEN\">\n" + . "<input type=\"image\" src=\"pict/menu_b_ccls.jpg\" " + . "alt=\"Close Case\" width=\"176\" height=20 border=0>\n" + . "</form></td></tr></table>\n"; + + print "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">\n" + . "<tr><td>&nbsp;</td>" + . "<td align=center><a href=\"$::HELP_URL\" " + . " target=\"_blank\">" + . "<img src=\"pict/menu_b_help.jpg\" alt=\"Help\" " + . "width=\"167\" height=20 border=0>" + . "</a></td><td>&nbsp;</td></tr>\n" + . "</table>\n"; + + Print::print_html_footer(); + return 0; +} + +# Log that a given host was opened and then proceed to open an image +sub host_open_log { + unless ((exists $Args::args{'inv'}) && ($Args::args{'inv'} ne "")) { + my @invs = read_invest(); + if (scalar @invs == 0) { + $Args::args{'inv'} = $Args::enc_args{'inv'} = 'unknown'; + } + else { + Print::print_html_header("Missing Investigator"); + print "<br>An investigator must be selected<p>\n" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN_LOG\">\n" + . Args::make_hidden(); + + print "Select one of the following:"; + print "<select name=\"inv\" size=\"1\">\n"; + + print "<option value=\"\" selected>Select One" . "</option>\n"; + + foreach my $i (@invs) { + print "<option value=\"$i\">$i</option>\n"; + } + print "</select><p>\n" + . "<input type=\"image\" src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=43 height=20 border=\"0\">\n" + . "</form>\n"; + + Print::print_html_footer(); + return 0; + } + } + + Args::check_inv(); + Print::log_case_info( + "Host $Args::args{'host'} opened by $Args::args{'inv'}"); + Print::log_host_info( + "Host $Args::args{'host'} opened by $Args::args{'inv'}"); + Print::log_host_inv("Host $Args::args{'host'} opened"); + + $Args::args{'view'} = $Args::enc_args{'view'} = $Caseman::VOL_OPEN; + vol_open(); +} + +# Provide details about the configuration of a host. This window is +# a link from the HOST_OPEN window +sub host_details { + Print::print_html_header( + "Details of $Args::args{'case'}:$Args::args{'host'}"); + + print "<b>Case: </b>$Args::args{'case'}<br><br>" + . "<center>" + . "<img src=\"pict/menu_h_hdet.jpg\" alt=\"Host Details\">" + . "<br><br><br>\n" + . "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\" " + . "background=\"$::YEL_PIX\" border=0>\n" + . + + # Name + "<tr><td align=\"right\" width=300><b>Name:</b></td>" + . "<td align=\"left\" width=300><tt>$Args::args{'host'}</tt></td></tr>\n" + . + + # Description + "<tr><td align=\"right\"><b>Description:</b></td>" + . "<td align=\"left\"><tt>" + . (($Caseman::host_desc ne "") ? $Caseman::host_desc : "&nbsp;") + . "</tt></td></tr>\n" + . + + # Timezone + "<tr><td align=\"right\"><b>Time zone: </b></td>" + . "<td align=\"left\"><tt>$Caseman::tz</tt></td></tr>\n" + . + + # Timeskew + "<tr><td align=\"right\"><b>Timeskew:</b></td>" + . "<td align=\"left\"><tt>$Caseman::ts</tt></td></tr>\n" + . "<tr><td colspan=2>&nbsp;</td></tr>\n" + . + + # Actual Directory + "<tr><td align=\"right\"><b>Directory:</b></td>" + . "<td align=\"left\"><tt>$::host_dir</tt></td></tr>\n" + . "<tr><td colspan=2>&nbsp;</td></tr>\n" + . + + # Alert Database + "<tr><td align=\"right\"><b>Alert Hash Database:</b></td>" + . "<td align=\"left\"><tt>" + . (($Caseman::alert_db ne "") ? $Caseman::alert_db : "&nbsp;") + . "</tt></td></tr>\n" + . + + # Exclude Database + "<tr><td align=\"right\"><b>Exclude Hash Database:</b></td>" + . "<td align=\"left\"><tt>" + . (($Caseman::exclude_db ne "") ? $Caseman::exclude_db : "&nbsp;") + . "</tt></td></tr>\n" + . "</table>\n"; + + # Final Button + print "<br><br><form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN\">\n" + . Args::make_hidden() + . "<input type=\"image\" src=\"pict/menu_b_ok.jpg\" " + . "alt=\"Ok\" width=\"167\" height=20 border=\"0\">\n</form>"; + + Print::print_html_footer(); + + return; +} + +# Read the investigators file and return a sorted list +sub read_invest { + my $fname = investig_fname(); + open INVES, "<$fname" or return; + + my @investigs; + while (<INVES>) { + chomp; + s/^\s+//; + s/\s+$//; + push @investigs, $1 + if (/^($::REG_INVESTIG)$/o); + } + close(INVES); + sort { lc($a) cmp lc($b) } @investigs; +} + +# File of investigators name in list +sub investig_fname { + return "$::case_dir" . "investigators.txt"; +} + +#################################################################### +# Image Functions + +# Types of modes for fname (i.e. can we overwrite it if it exists) +my $FNAME_MODE_INIT = 0; +my $FNAME_MODE_OVER = 1; + +my $MD5_NOTHING = 1; +my $MD5_CALC = 2; +my $MD5_ADD = 3; + +my $IMG_ADD_SYM = 1; +my $IMG_ADD_COPY = 2; +my $IMG_ADD_MOVE = 3; + +# Open an image that has been configured +sub vol_open { + Print::print_html_header( + "Open Image In $Args::args{'case'}:$Args::args{'host'}"); + + print "<b>Case:</b> $Args::args{'case'}<br>\n"; + print "<b>Host:</b> $Args::args{'host'}<br>\n"; + print "<center>\n"; + + # the images have been loaded from reading the host config file in + # autopsy_main + if (scalar(keys %Caseman::vol2ftype) == 0) { + print "No images have been added to this host yet<br><br>\n" + . "Select the Add Image File button below to add one\n"; + goto EGRESS; + } + + if ($::LIVE == 1) { + print "Select a volume to analyze.<br>\n"; + } + else { + print "Select a volume to analyze or add a new image file.<br>\n"; + } + + print_menu_tabs(); + + print "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\" " + . "background=\"$::YEL_PIX\" border=0>\n"; + + # We want to sort, so rearrange the hash + my %mnt2vol; + my %par2disk; + + # Cycle through each image we read from the host config + foreach my $i (keys %Caseman::vol2cat) { + if ($Caseman::vol2cat{$i} eq "disk") { + $mnt2vol{"1disk--AUTOPSY--$i"} = $i; + } + elsif ($Caseman::vol2cat{$i} eq "part") { + if ( ($Caseman::vol2ftype{$i} eq "raw") + || ($Caseman::vol2ftype{$i} eq "swap")) + { + $mnt2vol{"2$Caseman::vol2ftype{$i}--AUTOPSY--$i"} = $i; + } + else { + $mnt2vol{"2$Caseman::vol2mnt{$i}--AUTOPSY--$i"} = $i; + } + } + } + + # sort via parent volume, then starting location, + # and then mount point (which includes the name) + my @mnt = sort { + ($Caseman::vol2par{$mnt2vol{$a}} cmp $Caseman::vol2par{$mnt2vol{$b}}) + or ($Caseman::vol2start{$mnt2vol{$a}} <=> + $Caseman::vol2start{$mnt2vol{$b}}) + or (lc($a) cmp lc($b)) + } keys %mnt2vol; + + # It is possible to have only the blkls image and not the original + # We need to search for those now because they will not be in the + # list that we just made (which are arranged via mount point) + my @orphan_blkls; + + # cycle through each image and check its type and original + foreach my $k (keys %Caseman::vol2ftype) { + if ( ($Caseman::vol2ftype{$k} eq "blkls") + && (!exists $Caseman::mod2vol{$k})) + { + push @orphan_blkls, $k; + } + } + + print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_OPEN_LOG\">\n" + . Args::make_hidden() + + . "<tr><th>&nbsp;</th>" + . "<th align=left>mount</th>" + . "<th align=left>name</th>" + . # vol name + "<th align=left>fs type</th></tr>\n"; + + my $prev_par = ""; + + for (my $i = 0; $i <= $#mnt; $i++) { + my $vol = $mnt2vol{$mnt[$i]}; + + if ($Caseman::vol2par{$vol} ne $prev_par) { + print "<tr><td colspan=5><hr></td></tr>\n" if ($i != 0); + $prev_par = $Caseman::vol2par{$vol}; + } + + # Mount Point + # If we have the dummy string at the end of the duplicate + # entry, then take it off and print the original + $mnt[$i] = $1 if ($mnt[$i] =~ /^\d(.*?)--AUTOPSY--$::REG_VNAME$/o); + print "<tr>" . "<td><input type=\"radio\" name=\"vol\" value=$vol"; + print " CHECKED" if ($i == 0); + print "></td>" . "<td><tt>$mnt[$i]</tt></td>"; + + # image name and ftype + print +"<td><tt>$Caseman::vol2sname{$vol}</tt></td><td>$Caseman::vol2ftype{$vol}</td>"; + if ($::LIVE == 0) { + print "<td align=center><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::VOL_DETAILS&$Args::baseargs&" + . "vol=$vol\">details</a></td>" + . "</tr>\n"; + } + else { + print "<td>&nbsp;</td></tr>\n"; + } + } + + # If we are done with the regular images and have some orphan + # blkls images, print them + my @sort = sort @orphan_blkls; + for (my $i = 0; $i <= $#sort; $i++) { + print +"<tr><td>&nbsp;</td><td>&nbsp;</td><td>(<input type=\"radio\" name=\"vol\" " + . "value=$sort[$i]"; + print " CHECKED" if ($#mnt == 0); + print +"> unalloc)</td><td><tt>$Caseman::vol2sname{$sort[$i]}</tt></td><td>$Caseman::vol2ftype{$sort[$i]}</td></tr>\n"; + } + + # Begin Button + print "</table>\n"; + + EGRESS: + + print "<br><br>" + . "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">\n"; + + # Ok Button + if (scalar(keys %Caseman::vol2ftype) == 0) { + print "<tr><td width=200>&nbsp;</td>\n"; + } + else { + print "<tr><td align=center width=200>" + . "<input type=\"image\" src=\"pict/menu_b_analyze.jpg\" " + . "alt=\"Analyze\" width=\"167\" height=20 border=0>\n" + . "</form></td>\n"; + } + + # Image Add Button + if ($::LIVE == 0) { + print "<td align=center width=200>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD\">\n" + . Args::make_hidden() + . "<input type=\"image\" src=\"pict/menu_b_ifnew.jpg\" " + . "alt=\"Add Image\" width=167 height=20 border=0></form></td>\n" + . + + # Cancel Button + "<td align=center width=200>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::HOST_OPEN\">\n" + . "<input type=\"hidden\" name=\"case\" value=\"$Args::args{'case'}\">\n" + . "<input type=\"image\" src=\"pict/menu_b_hcls.jpg\" " + . "width=167 height=20 alt=\"Close Host\" border=0>\n" + . "</form></td></tr>"; + } + else { + print "<td width=200>&nbsp;</td><td width=200>&nbsp;</td></tr>\n"; + } + + # Help Button + print +"<td width=200>&nbsp;</td><td align=center width=200><a href=\"$::HELP_URL\" " + . " target=\"_blank\">" + . "<img src=\"pict/menu_b_help.jpg\" alt=\"Help\" " + . "width=\"167\" height=20 border=0>" + . "</a></td><td width=200>&nbsp;</td></tr>\n" + . "</table>\n"; + + # Other features that can be done on a host + + if ($::LIVE == 0) { + print "<hr><p>" + . "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">\n" + . "<tr>\n"; + + # Timeline of file activity + print "<td align=\"center\" width=200>" + . "<a href=\"$::PROGNAME?${Args::baseargs_novol}&" + . "mod=$::MOD_TL&view=$Timeline::FRAME\">" + . "<img border=0 " + . "src=\"pict/menu_b_tl.jpg\" " + . "width=\"167\" height=20 " + . "alt=\"File Activity Timelines\"></a></td>\n"; + + # verify the integrity of the images + print "<td align=\"center\" width=200>" + . "<a href=\"$::PROGNAME?${Args::baseargs_novol}&" + . "mod=$::MOD_HASH&view=$Hash::IMG_LIST_FR\">" + . "<img border=0 " + . "src=\"pict/menu_b_int.jpg\" " + . "width=\"167\" height=20 " + . "alt=\"Image Integrity\"></a></td>\n" + . + + # Hashdatabases + "<td align=\"center\" width=200>" + . "<a href=\"$::PROGNAME?${Args::baseargs_novol}&" + . "mod=$::MOD_HASH&view=$Hash::DB_MANAGER\">" + . "<img border=0 " + . "src=\"pict/menu_b_hashdb.jpg\" " + . "width=\"167\" height=20 " + . "alt=\"Hash Databases\"></a></td>\n" + . "</tr></table>\n"; + + # Notes + if ($::USE_NOTES == 1) { + print "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\">\n" + . "<tr>\n" + . "<td align=\"center\" width=300>" + . "<a href=\"$::PROGNAME?${Args::baseargs_novol}&mod=$::MOD_NOTES&view=$Notes::READ_NORM\">" + . "<img border=0 " + . "src=\"pict/menu_b_note.jpg\" " + . "width=\"167\" height=20 " + . "alt=\"View Notes\"></a></td>\n" + . + + "<td width=300 align=\"center\">" + . "<a href=\"$::PROGNAME?${Args::baseargs_novol}&mod=$::MOD_NOTES&view=$Notes::READ_SEQ\">" + . "<img border=0 " + . "src=\"pict/menu_b_seq.jpg\" " + . "width=\"167\" height=20 " + . "alt=\"Event Sequencer\"></a></td>\n" + . + + "</tr>\n" . "</table>\n"; + } + + # If LIVE + } + else { + print "<a href=\"./about\"><br>\n" + . "<img src=\"pict/logo.jpg\" border=0 alt=\"Logo\"></a><br>\n"; + + } + + Print::print_html_footer(); + + return 0; +} + +# Log in the host log that a given image was opened by what user +# then open the main window +sub vol_open_log { + + # These will be stopped in the func during LIVE + Print::log_host_info( + "Image $Args::args{'vol'} opened by $Args::args{'inv'}"); + Print::log_host_inv("$Args::args{'vol'}: volume opened"); + + $Args::args{'mod'} = $Args::enc_args{'mod'} = $::MOD_FRAME; + $Args::args{'view'} = $Args::enc_args{'view'} = $Frame::IMG_FRAME; + Frame::main(); +} + +# Menu to add a new image to the host +# +# The list of new images is determined by looking in the images directory +# and seeing which is not yet configured +# +sub img_add { + Print::print_html_header( + "Add Image To $Args::args{'case'}:$Args::args{'host'}"); + + print "<b>Case:</b> $Args::args{'case'}<br>\n" + . "<b>Host:</b> $Args::args{'host'}<br>\n"; + + print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD_PREP\">\n" + . Args::make_hidden(); + + print <<EOF1; +<center> +<img src=\"pict/menu_h_inew.jpg\" alt=\"Add Image\"> +<br><br><br> + +<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" background=\"$::YEL_PIX\" border=0> +<tr> + <td colspan=4>&nbsp;</td> +</tr> + +<tr> + <td align=left colspan=4> + 1. <b>Location</b><br>Enter the full path (starting with <tt>/</tt>) to the image file.<br> + If the image is split (either raw or EnCase), then enter '*' for the extension. + </td> +</tr> +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=3> + <input type=\"text\" name=\"img_path\" size=36 maxlength=256> + </td> +</tr> +<tr><td colspan=4>&nbsp;</td><tr> +<tr> + <td align=left colspan=4>2. <b>Type</b><br>Please select if this image file is for a disk or a single partition.</td> +</tr> +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left> + <input type=\"radio\" name=\"imgtype\" value="disk" CHECKED> + Disk + </td> + <td align=left> + <input type=\"radio\" name=\"imgtype\" value="volume"> + Partition + </td> + <td align=left>&nbsp; + </td> +</tr> + +<tr><td colspan=4>&nbsp;</td><tr> +<tr> + <td align=left colspan=4>3. <b>Import Method</b><br>To analyze the image file, it must be located in the evidence locker. It can be imported from its current location using a symbolic link, by copying it, or by moving it. Note that if a system failure occurs during the move, then the image could become corrupt.</td> +</tr> +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left> + <input type=\"radio\" name=\"sort\" value=$IMG_ADD_SYM CHECKED> + Symlink + </td> + <td align=left> + <input type=\"radio\" name=\"sort\" value=$IMG_ADD_COPY> + Copy + </td> + <td align=left> + <input type=\"radio\" name=\"sort\" value=$IMG_ADD_MOVE> + Move + </td> +</tr> + + +<tr> + <td colspan=4>&nbsp;</td> +</tr> + +</table> + +<br> +<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\"> +<tr> + <td align=center colspan=2> + <input type=\"image\" src=\"pict/menu_b_next.jpg\" alt=\"Next Step\" width=\"167\" height=20 border=0> + </td> +</tr> + +</form> + +EOF1 + + print "<tr><td colspan=2>&nbsp;</td></tr>\n" + . "<td align=center>\n" + . " <form action=\"$::PROGNAME\" method=\"get\">\n" + . " <input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . " <input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_OPEN\">\n" + . + + Args::make_hidden() + . " <input type=\"image\" src=\"pict/menu_b_cancel.jpg\" " + . "alt=\"Cancel\" width=\"167\" height=20 border=0></form>\n" + . " </td>\n" + . + + # HELP + " <td align=center>\n" + . " <a href=\"$::HELP_URL\" target=\"_blank\">\n" + . " <img src=\"pict/menu_b_help.jpg\" alt=\"Help\" " + . "width=\"167\" height=20 border=0></a>\n" + . " </td>\n" + . "</tr>\n" + . "</table>\n"; + + Print::print_html_footer(); + + return 0; +} + +# List the images from the glob - called from img_add_prep if spl_conf is not set +sub img_add_split_conf { + my $img_path = Args::get_img_path_wild(); + my $img_type = $Args::args{'imgtype'}; + + print "<center><br><br><b>Split Image Confirmation</b><br><br>\n"; + + my @spl_img = glob($img_path); + if (scalar(@spl_img) == 0) { + print "No images were found at this location ($img_path)<br>\n" + . "Use the back button and fix the path<br>\n"; + return; + } + + print <<EOF1; +The following images will be added to the case.<br> +If this is not the correct order, then you should change the naming convention.<br> +Press the Next button at the bottom of the page if this is correct.<br><br> + +<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" background=\"$::YEL_PIX\" border=0> +<tr> + <td colspan=2>&nbsp;</td> +</tr> +EOF1 + + my $a = 0; + foreach $i (@spl_img) { + + # We need to do this when we analyze the image, so do it here too to show + # what will be analyzed + $i = $1 if ($i =~ /^($::REG_IMG_PATH)$/); + print +"<tr><td align=\"center\">$a</td><td align=\"left\"><tt>$i</tt></td></tr>\n"; + $a++; + } + + my $vs = ""; + $vs = "&vstype=$Args::args{'vstype'}" + if (exists $Args::args{'vstype'}); + + # Print the Ok Button + print "</table><br><br>\n" + . "<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" border=0>" + . "<tr><td width=\"300\" align=\"center\"><a href=\"$::PROGNAME?${Args::baseargs_novol}&" + . "mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD_PREP&spl_conf=1&sort=$Args::args{'sort'}&" + . "img_path=$img_path&imgtype=$Args::args{'imgtype'}$vs\">" + . "<img src=\"pict/menu_b_next.jpg\" alt=\"Next\" " + . "width=\"167\" height=20 border=0></a></td>\n" + . "<td width=\"300\" align=\"center\"><a href=\"$::PROGNAME?${Args::baseargs_novol}&" + . "mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD\">" + . "<img src=\"pict/menu_b_cancel.jpg\" alt=\"cancel\" width=\"167\" height=\"20\" border=\"0\">" + . "</a></td></tr></table>\n"; + + return 0; +} + +# Run the autodetect stuff and get confirmation from the user +sub img_add_prep { + Args::check_img_path_wild(); + Args::check_sort(); + unless ((exists $Args::args{'imgtype'}) + && ($Args::args{'imgtype'} =~ /^\w+$/)) + { + Print::print_check_err("Invalid image type"); + } + + Print::print_html_header("Collecting details on new image file"); + + my $img_path = Args::get_img_path_wild(); + + my $img_type = $Args::args{'imgtype'}; + my $spl_conf = 0; + $spl_conf = 1 + if ((exists $Args::args{'spl_conf'}) && ($Args::args{'spl_conf'} == 1)); + + # If we have a wildcard then it is a split image, so we verify it first and + # then make a string of the images so we can test it. + if ($img_path =~ /[\*\?]/) { + if ($spl_conf == 0) { + return img_add_split_conf(); + } + else { + $img_tmp = ""; + foreach my $i (glob($img_path)) { + if ($i =~ /^($::REG_IMG_PATH)$/) { + $img_tmp .= "\"$1\" "; + } + } + $img_path = $img_tmp; + } + } + else { + unless ((-f $img_path) + || (-d $img_path) + || (-l $img_path) + || (-b $img_path) + || (-c $img_path)) + { + Print::print_err("Image file not found ($img_path)"); + } + $img_path = "\"$img_path\""; + } + + # Get the image type + local *OUT; + Exec::exec_pipe(*OUT, "'$::TSKDIR/img_stat' -t $img_path"); + my $itype = Exec::read_pipe_line(*OUT); + if (defined $itype) { + chomp $itype; + $itype = $1 if ($itype =~ /^(\w+)$/); + } + else { + print +"The image format type could not be determined for this image file<br>\n"; + return; + } + close(OUT); + + # The plan here is to collect the needed info and then we print it + + my $conflict = 0; + my $cnt = 0; + $start[0] = ""; + $end[0] = ""; + $type[0] = ""; + $desc[0] = ""; + $active[0] = ""; + + my $vstype = ""; + + my $vstype_flag = ""; + my $mmls_out = ""; # Will contain output of mmls (if disk image) + if ($img_type eq "disk") { + my $out; + + if ( (exists $Args::args{'vstype'}) + && ($Args::args{'vstype'} =~ /^(\w+)$/)) + { + $vstype = $Args::args{'vstype'}; + $vstype_flag = "-t $vstype"; + } + + # Get the type + else { + + Exec::exec_pipe(*OUT, "'$::TSKDIR/mmstat' -i $itype $img_path"); + + $vstype = Exec::read_pipe_line(*OUT); + close(OUT); + + chomp $vstype if (defined $vstype); + + if ( (!defined $vstype) + || ($vstype =~ /^Error determining/) + || ($vstype eq "") + || (!exists $Vs::type{$vstype}) + || ($vstype !~ /^\w+$/)) + { + print +"<table><tr><td colspan=2><font color=\"$::DEL_COLOR[0]\">Warning:</font> Autopsy could not determine the volume system type for the disk image (i.e. the type of partition table).<br>\n" + . "Please select the type from the list below or reclassify the image as a volume image instead of as a disk image.</td></tr>\n" + . "<tr><td colspan=2>&nbsp;</td></tr>\n" + . "<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD_PREP\">\n" + . "<input type=\"hidden\" name=\"spl_conf\" value=\"1\">\n" + . "<input type=\"hidden\" name=\"img_path\" value=\"$Args::args{'img_path'}\">\n" + . "<input type=\"hidden\" name=\"sort\" value=\"$Args::enc_args{'sort'}\">\n" + . Args::make_hidden() + . "<tr><td>Disk Image <input type=\"radio\" name=\"imgtype\" value=\"disk\" CHECKED></td>\n" + . "<td>Volume Image<input type=\"radio\" name=\"imgtype\" value=\"volume\"></td></tr>\n" + . "<tr><td>Volume System Type (disk image only): <select name=\"vstype\">\n"; + + foreach my $vs (sort keys %Vs::type) { + print "<option value=\"$vs\""; + print " selected" if ($vs eq 'dos'); + print ">${vs}</option>\n"; + } + + print "</select></td>" + . "<td>&nbsp;</td></tr>" + . "<tr><td colspan=2>&nbsp;</td></tr>" + . "</table><br><br>\n" + . "<input type=\"image\" src=\"pict/menu_b_ok.jpg\" alt=\"Ok\" width=\"176\" height=20 border=0>" + . "</form>\n"; + return; + } + $vstype = $1 if ($vstype =~ /^(\w+)$/); + $vstype_flag = "-t $vstype"; + } + + # Run 'mmls' on the image + Exec::exec_pipe(*OUT, + "'$::TSKDIR/mmls' -a -i $itype -aM $vstype_flag -r $img_path"); + + # cycle through results and add each to table with file system type + my $part_type = ""; + + while ($_ = Exec::read_pipe_line(*OUT)) { + $mmls_out .= "$_"; # Save the line + last if (/^Error determining partition/); + + if (/^\d+:\s+[\d:]+\s+(\d+)\s+(\d+)\s+\d+\s+(\S.*)$/) { + $start[$cnt] = $1; + $end[$cnt] = $2; + $desc[$cnt] = $3; + $active[$cnt] = 1; + } + elsif ((/^DOS Partition/) + || (/^BSD Disk/) + || (/^Sun VTOC/) + || (/^MAC Partition/) + || (/^GUID Partition/)) + { + $part_type = $_; + + #print "<tr><td colspan=7>&nbsp;</td></tr>\n"; + #print "<tr><td colspan=7>$_</td></tr>\n"; + next; + } + elsif (/^Sector:/) { + + #print "<tr><td colspan=7>$_</td></tr>\n"; + next; + } + else { + next; + } + + # Skip the BSD partition for the full disk + next + if ( ($part_type =~ /^BSD Disk/) + && ($start[$cnt] == 0) + && ($desc[$cnt] =~ /^Unused/)); + + # Skip if this is an extended DOS partition + next + if ( ($part_type =~ /^DOS Partition/) + && ($desc[$cnt] =~ /Extended \(/)); + + # Get rid of the leading 0s + $start[$cnt] = $1 + if ($start[$cnt] =~ /^0+([1-9]\d*)$/); + $end[$cnt] = $1 + if ($end[$cnt] =~ /^0+([1-9]\d*)$/); + + # Do we already have this partition? + my $i; + for ($i = 0; $i < $cnt; $i++) { + next if ($active[$i] == 0); + + if ($start[$i] == $start[$cnt]) { + $conflict = 1; + + if ($end[$i] == $end[$cnt]) { + last; + } + + #The previous was the BSD partition - skip it */ + if ( ($desc[$i] =~ /^FreeBSD \(0xA5\)/) + || ($desc[$i] =~ /^OpenBSD \(0xA6\)/) + || ($desc[$i] =~ /^NetBSD \(0xA9\)/)) + { + $active[$i] = 0; + + # if the current one is the BSD partition for + # the full partition/disk then skip it + if ($desc[$cnt] =~ /^Unused /) { + $active[$cnt] = 0; + } + } + } + + # Do we start inside of another? + if (($start[$i] > $start[$cnt]) && ($end[$i] < $start[$cnt])) { + $conflict = 1; + } + + # Do we end inside of another? + elsif (($start[$i] < $end[$cnt]) && ($end[$i] > $end[$cnt])) { + $conflict = 1; + } + } + if (($end[$i] == $end[$cnt]) && ($i != $cnt)) { + next; + } + + local *OUT2; + my $out2; + + # Run 'fstat -t' on the image + Exec::exec_pipe(*OUT2, + "'$::TSKDIR/fsstat' -o $start[$cnt] -i $itype -t $img_path"); + + $type[$cnt] = Exec::read_pipe_line(*OUT2); + close(OUT2); + + if ( (!exists $type[$cnt]) + || (!defined $type[$cnt]) + || ($type[$cnt] =~ /^Cannot determine/) + || ($type[$cnt] eq "")) + { + $type[$cnt] = "Unknown"; + } + chomp $type[$cnt]; + + $cnt++; + } + close(OUT); + + if ($conflict == 1) { + print +"<tr><td colspan=2><font color=\"$::DEL_COLOR[0]\">Warning:</font> Conflicts in the partitions were detected.<br>The full <tt>mmls</tt> output is given at the bottom of the page</td></tr>\n" + . "<tr><td colspan=2>&nbsp;</td></tr>\n"; + } + } + + # If a volume, then run fsstat on it + elsif ($img_type eq "volume") { + + # Run 'fstat -t' on the image + Exec::exec_pipe(*OUT, "'$::TSKDIR/fsstat' -t -i $itype $img_path"); + + $type[0] = Exec::read_pipe_line(*OUT); + close(OUT); + + if ( (!defined $type[0]) + || ($type[0] =~ /^Cannot determine/) + || ($type[0] eq "")) + { + $type[0] = "Unknown"; + print +"<font color=\"$::DEL_COLOR[0]\">Warning:</font> The file system type of the volume image file could not be determined.<br>\n" + . "If this is a disk image file, return to the previous page and change the type.<br><br>\n"; + } + chomp $type[0]; + $start[0] = 0; + $end[0] = 0; + $active[0] = 1; + $desc[0] = $type[0]; + $cnt++; + close(OUT); + } + else { + Print::print_err("Unknown image type: $img_type"); + } + + my $sname = $img_path; + $sname = "$::IMGDIR/" . "$1" if ($sname =~ /\/($::REG_FILE)\"$/); + +# Now that we have the information about the partitions and disks, print the fields + print <<EOF1; + +<form action=\"$::PROGNAME\" method=\"get\" target=\"_top\"> +<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\"> +<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_ADD_DOIT\"> +<input type=\"hidden\" name=\"img_path\" value=\"$Args::args{'img_path'}\"> +<input type=\"hidden\" name=\"num_img\" value=\"$cnt\"> +<input type=\"hidden\" name=\"sort\" value=\"$Args::enc_args{'sort'}\"> + + +<center> +<h3>Image File Details</h3> +<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" background=\"$::YEL_PIX\" border=0> +<tr> + <td align=left colspan=4> + <b>Local Name: </b> $sname + </td> +</tr> + +EOF1 + + # We do not currently offer integrity options for non-raw files + if (($itype eq "raw") || ($itype eq "split")) { + + print <<EOF1b; +<tr> + <td align=left colspan=4> + <b>Data Integrity: </b> An MD5 hash can be used to verify the + integrity of the image. (With split images, this hash is for the full image file) + </td> +</tr> + +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=3> + <input type=\"radio\" name=\"do_md5\" value=\"$MD5_NOTHING\" CHECKED> + <u>Ignore</u> the hash value for this image. + </td> +</tr> + +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=3> + <input type=\"radio\" name=\"do_md5\" value=\"$MD5_CALC\"> + <u>Calculate</u> the hash value for this image. + </td> +</tr> + +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=3> + <input type=\"radio\" name=\"do_md5\" value=\"$MD5_ADD\"> + <u>Add</u> the following MD5 hash value for this image: + </td> +</tr> + +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=3>&nbsp;&nbsp;&nbsp;&nbsp; + <input type=\"text\" name=\"md5\" size=36 maxlength=32> + </td> +</tr> + +<tr> + <td>&nbsp;&nbsp;</td> + <td align=left colspan=3>&nbsp;&nbsp;&nbsp;&nbsp; + <input type=\"checkbox\" name=\"ver_md5\" value=\"1\"> + &nbsp;Verify hash after importing? + </td> +</tr> +EOF1b + } + else { + print + "<input type=\"hidden\" name=\"do_md5\" value=\"$MD5_NOTHING\">\n"; + } + + print <<EOF1c; +</table> + +<h3>File System Details</h3> +<table width=\"600\" cellpadding=\"2\" cellspacing=\"0\" background=\"$::YEL_PIX\" border=0> + +<tr> + <td colspan=2 align=left>Analysis of the image file shows the following partitions:</td> +</tr> +<tr> + <td colspan=2>&nbsp;</td> +</tr> + +EOF1c + + print Args::make_hidden(); + + print "<input type=\"hidden\" name=\"vstype\" value=\"$vstype\">\n" + if ($vstype ne ""); + + my $idx = 1; + my $ms_cnt = 0; + my @ms_name = ("C:", "D:", "E:", "F:", "G:", "H:", "I:", "J:"); + for (my $i = 0; $i < $cnt; $i++) { + next if ($active[$i] == 0); + print +"<tr><td colspan=2><u>Partition $idx</u> (Type: $desc[$i])</td><tr>\n"; + + if ($cnt > 1) { + print "<tr><td colspan=2>&nbsp;&nbsp;Add to case? " + . "<input type=\"checkbox\" name=\"yes-${idx}\" value=1 CHECKED></td></tr>\n"; + } + else { + print "<input type=\"hidden\" name=\"yes-${idx}\" value=1>\n"; + } + + unless (($start[$i] == 0) && ($end[$i] == 0)) { + print "<tr><td colspan=2>&nbsp;&nbsp;Sector Range: " + . "$start[$i] to $end[$i]" + . "</td></tr>\n"; + } + + print + "<input type=\"hidden\" name=\"start-${idx}\" value=\"$start[$i]\">" + . "<input type=\"hidden\" name=\"end-${idx}\" value=\"$end[$i]\">\n" + . "<tr><td>&nbsp;&nbsp;Mount Point: <input type=\"text\" name=\"mnt-${idx}\" size=\"6\""; + if (($type[$i] =~ /^ntfs/) || ($type[$i] =~ /^fat/)) { + print " value=\"$ms_name[$ms_cnt]\"" + if ($ms_cnt < 8); + $ms_cnt++; + } + elsif (($type[$i] =~ /^raw/) + || ($type[$i] =~ /^swap/)) + { + print " value=\"N/A\""; + } + else { + print " value=\"/$idx/\""; + } + print "></td>\n" + . "<td>File System Type: <select name=\"ftype-${idx}\">\n"; + + foreach my $fs (@Fs::types) { + print "<option value=\"$fs\""; + print " selected" if ($fs eq $type[$i]); + print ">${fs}</option>\n"; + } + + # The following do not have 'metas' but should be in the list + print "<option value=\"\">======</option>\n"; + if ($type[$i] eq "Unknown") { + print "<option value=\"raw\" selected>raw</option>\n"; + } + else { + print "<option value=\"raw\">raw</option>\n"; + } + + print "<option value=\"swap\">swap</option>\n" + . "</select></td></tr>\n" + . "<tr><td colspan=2>&nbsp;</td></tr>\n"; + + $idx++; + } + + print "</table>\n"; + + print <<EOF2; +<br><br> +<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\"> +<tr> + <td align=center> + <input type=\"image\" src=\"pict/menu_b_add.jpg\" + alt=\"Add\" width=\"176\" height=20 border=0> + </td> +</form> + <td align=center> + <form action=\"$::PROGNAME\" method=\"get\"> +EOF2 + print Args::make_hidden(); + print <<EOF3; + <input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\"> + <input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_OPEN\"> + <input type=\"image\" src=\"pict/menu_b_cancel.jpg\" + alt=\"Cancel\" width=\"167\" height=20 border=0> + </form> + </td> + <td align=center><a href=\"$::HELP_URL\" + target=\"_blank\"> + <img src=\"pict/menu_b_help.jpg\" alt=\"Help\" + width=\"167\" height=20 border=0></a> + </td> +</tr> +</table> +EOF3 + + if ($img_type eq "disk") { + print +"</center><p>For your reference, the <tt>mmls</tt> output was the following:<br><pre>$mmls_out</pre>\n"; + } + + Print::print_html_footer(); + + return 0; +} + +# Add the image to the configuration by adding it to the host config file +# and the md5.txt file if that data was provided +sub img_add_doit { + + Args::check_num_img(); + Args::check_img_path_wild(); + Args::check_sort(); + Args::check_do_md5(); + + my $num_img = Args::get_num_img(); + my $img_path = Args::get_img_path_wild(); + my $import_type = Args::get_sort(); + + Print::print_html_header("Add a new image to an Autopsy Case"); + + my $err = 0; + my $add_num = 0; + $start[0] = 0; + $end[0] = 0; + $ftype[0] = ""; + $mnt[0] = ""; + + # We need a string with all images in it for the hashes and file system testing + my $img_path_full; + if ($img_path =~ /[\*\?]/) { + $img_path_full = ""; + foreach my $i (glob($img_path)) { + if ($i =~ /^($::REG_IMG_PATH)$/) { + $img_path_full .= "\"$1\" "; + } + } + } + else { + $img_path_full = "\"$img_path\""; + } + + # Get the image type + local *OUT; + Exec::exec_pipe(*OUT, "'$::TSKDIR/img_stat' -t $img_path_full"); + my $itype = Exec::read_pipe_line(*OUT); + if (defined $itype) { + chomp $itype; + $itype = $1 if ($itype =~ /^(\w+)$/); + } + else { + print +"The image format type could not be determined for this image file<br>\n"; + return; + } + close(OUT); + + # Check the hash of the image if that is the plan + my $do_md5 = Args::get_do_md5(); + my $act_md5 = ""; + unless ($do_md5 == $MD5_NOTHING) { + + # Do we need to calculate an MD5? + if ( + ($do_md5 == $MD5_CALC) + || ( ($do_md5 == $MD5_ADD) + && (exists $Args::args{'ver_md5'}) + && ($Args::args{'ver_md5'} == 1)) + ) + { + + print "<p>Calculating MD5 (this could take a while)<br>\n"; + $act_md5 = Hash::calc_md5_split($img_path_full); + unless ($act_md5 =~ /^$::REG_MD5$/o) { + print "Error calculating MD5: $act_md5<br>\n"; + return 1; + } + print "Current MD5: <tt>$act_md5</tt><br>\n"; + } + + # And md5 value was given so we can add it to the md5.txt file + if (($do_md5 == $MD5_ADD) && (exists $Args::args{'md5'})) { + + my $md5 = $Args::args{'md5'}; + unless ($md5 =~ /^$::REG_MD5$/o) { + if ($md5 eq "") { + print "MD5 value missing<br>\n"; + } + else { + print "Invalid MD5 value (32 numbers or letters a-f)<br>\n"; + } + print "<p><a href=\"$::PROGNAME?" + . "mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD&" + . "$Args::baseargs\">" + . "<img src=\"pict/menu_b_back.jpg\" border=\"0\" " + . "width=\"167\" height=20 alt=\"Back\"></a>\n"; + return 1; + } + $md5 =~ tr/[a-f]/[A-F]/; + + # They also want us to validate the MD5 + if ( (exists $Args::args{'ver_md5'}) + && ($Args::args{'ver_md5'} == 1)) + { + + if ($act_md5 eq $md5) { + print "Integrity Check Passed<br>\n"; + Print::log_host_info("Integrity check passed on new image"); + } + else { + print "<font color=\"$::DEL_COLOR[0]\">" + . "Integrity Check Failed<br></font><br>\n" + . "Provided: <tt>$md5</tt><br>\n" + . "Image not added to case<br>\n"; + + Print::log_host_info("Integrity check failed on new image"); + return 1; + } + } + + # set the act_md5 value to what was given and verified + $act_md5 = $md5; + } + + # We will add the MD5 to the config file after we get its ID + } + + # Proces the image arguments to make sure they are all there and test the + # file system type + print "Testing partitions<br>\n"; + for (my $i = 0; $i <= $num_img; $i++) { + + next + unless ((exists $Args::args{"yes-" . $i}) + && ($Args::args{"yes-" . $i} == 1)); + + if ( (exists $Args::args{"start-" . $i}) + && ($Args::args{"start-" . $i} =~ /^(\d+)$/)) + { + $start[$add_num] = $1; + } + else { + print "Missing starting address for partition $i<br>\n"; + $err = 1; + last; + } + + if ( (exists $Args::args{"end-" . $i}) + && ($Args::args{"end-" . $i} =~ /^(\d+)$/)) + { + $end[$add_num] = $1; + } + else { + print "Missing ending address for partition $i<br>\n"; + $err = 1; + last; + } + + if ( (exists $Args::args{"mnt-" . $i}) + && ($Args::args{"mnt-" . $i} =~ /^($::REG_MNT)$/)) + { + $mnt[$add_num] = $1; + } + else { + print "Missing mount point for partition $i<br>\n"; + $err = 1; + last; + } + + if ( (exists $Args::args{"ftype-" . $i}) + && ($Args::args{"ftype-" . $i} =~ /^($::REG_FTYPE)$/)) + { + $ftype[$add_num] = $1; + } + else { + print "Missing file system type for partition $i<br>\n"; + $err = 1; + last; + } + + # Test the File System + if (($ftype[$add_num] ne 'swap') && ($ftype[$add_num] ne 'raw')) { + + local *OUT; + my $out; + + # Run 'fsstat' and see if there is any output - else there was + # an error and the data went to STDERR + Exec::exec_pipe(*OUT, +"'$::TSKDIR/fsstat' -o $start[$add_num] -i $itype -f $ftype[$add_num] $img_path_full" + ); + unless (read(OUT, $out, 1)) { + print +"<p>Partition $i is not a <tt>$ftype[$add_num]</tt> file system<br>\n"; + $err = 1; + last; + } + close(OUT); + } + $add_num++; + } + + # Go back if we got an error + if ($err == 1) { + print "Use the browser's back button to fix the data<br>\n"; + return 1; + } + + ################################################## + # Copy the images and add them to the config file + + if ($import_type == $IMG_ADD_SYM) { + Print::print_err("ERROR: /bin/ln missing") + unless (-x '/bin/ln'); + + print "Linking image(s) into evidence locker<br>\n"; + } + elsif ($import_type == $IMG_ADD_COPY) { + Print::print_err("ERROR: /bin/cp missing") + unless (-x '/bin/cp'); + + print +"Copying image(s) into evidence locker (this could take a little while)<br>\n"; + } + elsif ($import_type == $IMG_ADD_MOVE) { + Print::print_err("ERROR: /bin/mv missing") + unless (-x '/bin/mv'); + + print "Moving image(s) into evidence locker<br>\n"; + } + else { + Print::print_err("Invalid Import Type: $import_type\n"); + } + + my $imgid = ""; + foreach my $i (glob($img_path)) { + + # remove the tainting + $i = $1 if ($i =~ /^($::REG_IMG_PATH)$/); + + # Deterine the local (target) name + my $img = ""; + if ($i =~ /\/($::REG_FILE)$/) { + $img = "$::IMGDIR/$1"; + } + else { + Print::print_err("Error Parsing Image Path ($i)\n"); + } + + # Get the full path of the destination + my $img_dst = "$::host_dir" . "$img"; + if ((-e "$img_dst") || (-l "$img_dst")) { + Print::print_err( +"An image by the same name already exists in the Host directory ($img)\n" + . "Use the browser's back button to fix the name or delete the existing file." + ); + } + + my $orig_size = (stat("$i"))[7]; + + # Copy, Move, or link it + if ($import_type == $IMG_ADD_SYM) { + + Print::log_host_info( +"Sym Linking image $img_path into $Args::args{'case'}:$Args::args{'host'}" + ); + + Exec::exec_sys("/bin/ln -s '$i' '$img_dst'"); + } + elsif ($import_type == $IMG_ADD_COPY) { + Print::log_host_info( +"Copying image $img_path into $Args::args{'case'}:$Args::args{'host'}" + ); + + Exec::exec_sys("/bin/cp '$i' '$img_dst'"); + } + elsif ($import_type == $IMG_ADD_MOVE) { + Print::log_host_info( +"Moving image $img_path into $Args::args{'case'}:$Args::args{'host'}" + ); + + Exec::exec_sys("/bin/mv '$i' '$img_dst'"); + } + + my $new_size = (stat("$img_dst"))[7]; + + if ($new_size != $orig_size) { + Print::print_err( +"Original image size ($orig_size) is not the same as the destination size ($new_size)" + ); + } + + # Add the disk and partition images to the config file + $imgid = Caseman::add_img_host_config("image", "$itype $img", $imgid); + } + print "Image file added with ID <tt>$imgid</tt><br>\n"; + + # AFM files have raw files that we also need to copy + # This approach is not the best, since it may copy more than + # is needed + if ($itype eq "afm") { + my $afm_base_path = ""; + + if ($img_path =~ /^(.*?)\.afm/i) { + $afm_base_path = $1; + $afm_base_path .= ".[0-9][0-9][0-9]"; + } + else { + Print::print_err( + "Error parsing out base name of AFM file $img_path"); + } + + print "BASE: $afm_base_path<br>\n"; + + my $copied = 0; + + foreach my $i (glob($afm_base_path)) { + $copied++; + + # remove the tainting + $i = $1 if ($i =~ /^($::REG_IMG_PATH)$/); + + # Deterine the local (target) name + my $img = ""; + if ($i =~ /\/($::REG_FILE)$/) { + $img = "$::IMGDIR/$1"; + } + else { + Print::print_err("Error Parsing Image Path ($i)\n"); + } + + # Get the full path of the destination + my $img_dst = "$::host_dir" . "$img"; + if ((-e "$img_dst") || (-l "$img_dst")) { + Print::print_err( +"An image by the same name already exists in the Host directory ($img) (AFM import)\n" + . "Use the browser's back button to fix the name or delete the existing file." + ); + } + + my $orig_size = (stat("$i"))[7]; + + # Copy, Move, or link it + if ($import_type == $IMG_ADD_SYM) { + + Print::log_host_info( +"Sym Linking image $img_path into $Args::args{'case'}:$Args::args{'host'}" + ); + + Exec::exec_sys("/bin/ln -s '$i' '$img_dst'"); + } + elsif ($import_type == $IMG_ADD_COPY) { + Print::log_host_info( +"Copying image $img_path into $Args::args{'case'}:$Args::args{'host'}" + ); + + Exec::exec_sys("/bin/cp '$i' '$img_dst'"); + } + elsif ($import_type == $IMG_ADD_MOVE) { + Print::log_host_info( +"Moving image $img_path into $Args::args{'case'}:$Args::args{'host'}" + ); + + Exec::exec_sys("/bin/mv '$i' '$img_dst'"); + } + + my $new_size = (stat("$img_dst"))[7]; + + if ($new_size != $orig_size) { + Print::print_err( +"Original image size ($orig_size) is not the same as the destination size ($new_size) after AFM import" + ); + } + } + if ($copied == 0) { + Print::print_err( +"No AFM raw files were found with the same base name and a numeric extension" + ); + } + else { + print "$copied AFM raw files imported<br>\n"; + } + } + + Caseman::update_md5("$imgid", "$act_md5") + unless (($do_md5 == $MD5_NOTHING) || ($imgid eq "")); + + # Add a disk entry if the image is of a disk + unless (($add_num == 1) && ($end[0] == 0) && ($start[0] == 0)) { + unless ((exists $Args::args{'vstype'}) + && ($Args::args{'vstype'} =~ /^(\w+)$/)) + { + Print::print_err("Missing Volume System Type"); + } + my $vstype = $Args::args{'vstype'}; + + my $diskid = Caseman::add_vol_host_config("disk", "$imgid $vstype"); + print "<p>Disk image (type $vstype) added with ID <tt>$diskid</tt>\n"; + } + + # Add the file system / partition entries + for (my $i = 0; $i < $add_num; $i++) { + my $volid = + Caseman::add_vol_host_config("part", + "$imgid $start[$i] $end[$i] $ftype[$i] $mnt[$i]"); + print +"<p>Volume image ($start[$i] to $end[$i] - $ftype[$i] - $mnt[$i]) added with ID <tt>$volid</tt>\n"; + } + + print <<EOF; +<p> +<center> +<table width=600> +<tr> + <td width=300 align=center> + <a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&view=$Caseman::VOL_OPEN&${Args::baseargs_novol}\"> + <img src=\"pict/menu_b_ok.jpg\" alt=\"Ok\" width=\"167\" height=20 border=\"0\"> + </a> + </td> + <td width=300 align=center> + <a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&view=$Caseman::IMG_ADD&${Args::baseargs_novol}\"> + <img src=\"pict/menu_b_inew.jpg\" alt=\"Ok\" width=\"167\" height=20 border=\"0\"> + </a> + </td> +</tr> +</table> +</center> + +EOF + Print::print_html_footer(); + + return 0; +} + +# Display details of image based on config values +# provides links to remove the config of the image and to get the file +# system details + +sub vol_details { + Print::print_html_header("Details of $Args::args{'vol'}"); + + Args::get_unitsize(); + + my $vol = Args::get_vol('vol'); + + my $mnt = $Caseman::vol2mnt{$vol}; + my $ftype = $Caseman::vol2ftype{$vol}; + + print "<center>" + . "<img src=\"pict/menu_h_idet.jpg\" alt=\"Image Details\">" + . "<br><br><br>\n" + . "<table width=\"600\" cellspacing=\"0\" cellpadding=\"2\" " + . "background=\"$::YEL_PIX\" border=0>\n" + . " <tr><td colspan=\"2\">&nbsp;</td></tr>\n" + . + + # Name + " <tr><td align=\"right\" width=\"300\"><b>Name:</b></td>" + . "<td align=\"left\"><tt>$Caseman::vol2sname{$vol}</tt></td></tr>\n" + . "<tr><td align=\"right\" width=\"300\"><b>Volume Id:</b></td>" + . "<td align=\"left\"><tt>$vol</tt></td></tr>\n" + . "<tr><td align=\"right\" width=\"300\"><b>Parent Volume Id:</b></td>" + . "<td align=\"left\"><tt>$Caseman::vol2par{$vol}</tt></td></tr>\n" + . "<tr><td align=\"right\" width=\"300\"><b>Image File Format:</b></td>" + . "<td align=\"left\"><tt>$Caseman::vol2itype{$vol}</tt></td></tr>\n" + + # Mount + . " <tr><td align=\"right\"><b>Mounting Point:</b></td>" + . "<td align=\"left\"><tt>$mnt</tt></td></tr>\n" + . + + # Type + " <tr><td align=\"right\"><b>File System Type:</b></td>" + . "<td align=\"left\"><tt>$ftype</tt></td></tr>\n"; + + # Host Directory + print " <tr><td colspan=\"2\">&nbsp;</td></tr>\n" + + # Strings File + . " <tr><td colspan=2 align=\"center\"><b>External Files</b></td></tr>\n" + . " <tr><td align=\"right\"><b>ASCII Strings:</b></td>" + . "<td align=\"left\"><tt>" + . ( + (exists $Caseman::vol2str{$vol}) + ? $Caseman::vol2sname{$Caseman::vol2str{$vol}} + : "&nbsp;" + ) + . "</tt></td></tr>\n" + . + + # Unicode Strings File + " <tr><td align=\"right\"><b>Unicode Strings:</b></td>" + . "<td align=\"left\"><tt>" + . ( + (exists $Caseman::vol2uni{$vol}) + ? $Caseman::vol2sname{$Caseman::vol2uni{$vol}} + : "&nbsp;" + ) + . "</tt></td></tr>\n"; + + if (($ftype ne "raw") && ($ftype ne "swap")) { + + # blkls file + print +" <tr><td align=\"right\"><b>Unallocated $Fs::addr_unit{$ftype}s:</b></td>" + . "<td align=\"left\"><tt>" + . ( + (exists $Caseman::vol2blkls{$vol}) + ? $Caseman::vol2sname{$Caseman::vol2blkls{$vol}} + : "&nbsp;" + ) + . "</tt></td></tr>\n"; + + # Strings of blkls + print + " <tr><td align=\"right\"><b>ASCII Strings of Unallocated:</b></td>" + . "<td align=\"left\"><tt>" + . ( + ( + (exists $Caseman::vol2blkls{$vol}) + && (exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}}) + ) + ? $Caseman::vol2sname{$Caseman::vol2str{$Caseman::vol2blkls{$vol}}} + : "&nbsp;" + ) + . "</tt></td></tr>\n"; + + # Unicodde Strings of blkls + print +" <tr><td align=\"right\"><b>Unicode Strings of Unallocated:</b></td>" + . "<td align=\"left\"><tt>" + . ( + ( + (exists $Caseman::vol2blkls{$vol}) + && (exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}}) + ) + ? $Caseman::vol2sname{$Caseman::vol2uni{$Caseman::vol2blkls{$vol}}} + : "&nbsp;" + ) + . "</tt></td></tr>\n"; + } + + print " <tr><td colspan=\"2\">&nbsp;</td></tr>\n" + . "</table>\n<a name=\"extract\"\n"; + + # Section for Strings file and 'blkls' file + + if ( + (!(exists $Caseman::vol2str{$vol})) + || (!(exists $Caseman::vol2uni{$vol})) + || (!(exists $Caseman::vol2blkls{$vol})) + || ( + (exists $Caseman::vol2blkls{$vol}) + && ( (!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}})) + || (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}}))) + ) + ) + { + print "<hr><table width=600>\n<tr>"; + } + + # Strings File + if ( (!(exists $Caseman::vol2str{$vol})) + || (!(exists $Caseman::vol2uni{$vol}))) + { + + print +"<td align=\"center\" width=280><h3>Extract Strings of<br>Entire Volume</h3>" + . "Extracting the ASCII and Unicode strings from a file system will " + . "make keyword searching faster.<br><br>\n" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "Generate MD5? " + . "<input type=\"checkbox\" name=\"md5\" value=\"1\" CHECKED><br><br>" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_MAKESTR\">\n" + . "<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n" + . Args::make_hidden(); + + if (!(exists $Caseman::vol2str{$vol})) { + print +"ASCII: <input type=\"checkbox\" name=\"str\" value=\"1\" CHECKED> \n"; + } + if (!(exists $Caseman::vol2uni{$vol})) { + print +" Unicode: <input type=\"checkbox\" name=\"uni\" value=\"1\" CHECKED>\n"; + } + + print "<br><br><input type=\"image\" src=\"pict/srch_b_str.jpg\" " + . "alt=\"Extract Strings\" border=\"0\">\n</form></td>\n" + . "<td width=40>&nbsp;</td>\n"; + } + + if (($ftype eq 'blkls') || ($ftype eq 'swap') || ($ftype eq 'raw')) { + + # Place holder for types that have no notion of unallocated + } + + # Unallocated Space File + elsif (!(exists $Caseman::vol2blkls{$vol})) { + + print +"<td align=\"center\" width=280><h3>Extract Unallocated $Fs::addr_unit{$ftype}s</h3>" + . "Extracting the unallocated data in a file system allows " + . "more focused keyword searches and data recovery.<br><br>\n" + . "(Note: This Does Not Include Slack Space)<br>\n" + . "<form action=\"$::PROGNAME\" method=\"get\">\n"; + + print "Generate MD5? " + . "<input type=\"checkbox\" name=\"md5\" value=\"1\" CHECKED><br><br>" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_MAKEBLKLS\">\n" + . + + "<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n" + . Args::make_hidden() + . "<input type=\"image\" src=\"pict/srch_b_un.jpg\" " + . "alt=\"Extract Unallocated Data\" border=\"0\">\n<br></form>\n"; + } + + # strings of 'blkls' + elsif ((!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}})) + || (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}}))) + { + + print +"<td align=\"center\" width=280><h3>Extract Strings of<br>Unallocated $Fs::addr_unit{$ftype}s</h3>" + . "Extracting the ASCII strings from the unallocated data will make " + . "keyword searching faster.<br><br>\n" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "Generate MD5? " + . "<input type=\"checkbox\" name=\"md5\" value=\"1\" CHECKED><br><br>" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_MAKESTR\">\n" + . + +"<input type=\"hidden\" name=\"vol\" value=\"$Caseman::vol2blkls{$vol}\">\n" + . "<input type=\"hidden\" name=\"fname_mode\" value=\"$FNAME_MODE_INIT\">\n" + . Args::make_hidden(); + + if (!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}})) { + print +"ASCII: <input type=\"checkbox\" name=\"str\" value=\"1\" CHECKED> \n"; + } + if (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}})) { + print +" Unicode: <input type=\"checkbox\" name=\"uni\" value=\"1\" CHECKED>\n"; + } + print "<br><br><input type=\"image\" src=\"pict/srch_b_str.jpg\" " + . "alt=\"Extract Strings\" border=\"0\">\n</form></td>\n"; + } + if ( + (!(exists $Caseman::vol2str{$vol})) + || (!(exists $Caseman::vol2uni{$vol})) + || (!(exists $Caseman::vol2blkls{$vol})) + || ( + (exists $Caseman::vol2blkls{$vol}) + && ( (!(exists $Caseman::vol2str{$Caseman::vol2blkls{$vol}})) + || (!(exists $Caseman::vol2uni{$Caseman::vol2blkls{$vol}}))) + ) + ) + { + print "</tr></table><hr>\n"; + } + + print "<p>" + . "<table width=\"400\" cellspacing=\"0\" cellpadding=\"2\">\n" + . + + # Ok + "<tr><td align=center width=200>" + . "<form action=\"$::PROGNAME\" method=\"get\">\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$Caseman::VOL_OPEN\">\n" + . Args::make_hidden() + . "<input type=\"image\" src=\"pict/menu_b_close.jpg\" " + . "alt=\"Close\" width=\"167\" height=20 border=0></form></td>\n"; + + print "<td align=center width=200>"; + if (($ftype ne "raw") && ($ftype ne "swap")) { + + # File System Details + print "<form action=\"$::PROGNAME\" method=\"get\" target=\"_blank\">\n" + . Args::make_hidden() + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FRAME\">\n" + . "<input type=\"hidden\" name=\"submod\" value=\"$::MOD_FS\">\n" + . "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n" + . "<input type=\"image\" src=\"pict/menu_b_fs.jpg\" " + . "width=167 height=20 " + . "alt=\"File System\" border=0></form></td>\n"; + } + else { + print "&nbsp;</td>\n"; + } + +# Remove Image +# THis was removed 12/03 because it causes problems because the image still +# exists and config entries and ... it becomes a mess +# print +# "<td align=center width=200>". +# "<form action=\"$::PROGNAME\" method=\"get\">\n". +# "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_CASEMAN\">\n". +# "<input type=\"hidden\" name=\"view\" value=\"$Caseman::IMG_DEL\">\n". +# Args::make_hidden(). +# "<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n". +# "<input type=\"hidden\" name=\"mnt\" value=\"$Args::args{'mnt'}\">\n". +# "<input type=\"image\" src=\"pict/menu_b_rem.jpg\" ". +# "width=167 height=20 alt=\"Remove\" border=0></form>". +# "</td>\n". +# "</tr></table>\n"; + + Print::print_html_footer(); + return 0; +} + +# remove the config files +sub img_del { + Args::check_vol('vol'); + + # Args::check_ftype(); + Print::print_html_header( + "Removing Configuration Settings for $Args::args{'vol'}"); + + Caseman::del_host_config("", $Args::args{'vol'}, ""); + Caseman::update_md5($Args::args{'vol'}, ""); + + print "Settings for <tt>$Args::args{'vol'}</tt> removed from " + . "<tt>$Args::args{'case'}:$Args::args{'host'}</tt>.\n" + . "<p>NOTE: The actual file still exists in the host directory.\n"; + + print "<p><a href=\"$::PROGNAME?mod=$::MOD_CASEMAN&" + . "view=$Caseman::VOL_OPEN&${Args::baseargs_novol}\">" + . "<img src=\"pict/but_ok.jpg\" alt=\"Ok\" " + . "width=\"43\" height=20 border=\"0\"></a>\n"; + + Print::print_html_footer(); + + return 0; +} + +# Make a strings -t d file for the image to decrease the search time +# Can make both ASCII and Unicode strings files +sub vol_makestr { + Print::print_html_header("Extracting Strings"); + + my $ascii = 0; + my $uni = 0; + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + if ((exists $Args::args{'str'}) && ($Args::args{'str'} == 1)) { + if (exists $Caseman::vol2str{$vol}) { + Print::print_err( +"Image already has an ASCII strings file: $Caseman::vol2sname{$vol}" + ); + } + $ascii = 1; + } + + if ((exists $Args::args{'uni'}) && ($Args::args{'uni'} == 1)) { + if (exists $Caseman::vol2uni{$vol}) { + Print::print_err( +"Image already has a Unicode strings file: $Caseman::vol2sname{$vol}" + ); + } + + $uni = 1; + } + if (($uni == 0) && ($ascii == 0)) { + goto str_egress; + } + + my $base_name = $Caseman::vol2sname{$vol}; + + if ($ascii == 1) { + my $fname_rel = "$::DATADIR/${base_name}-$ftype.asc"; + my $fname = "$::host_dir" . "$fname_rel"; + + if (-e "$fname") { + my $i = 1; + $i++ while (-e "$::host_dir" + . "$::DATADIR/" + . "${base_name}-$ftype-$i.asc"); + + $fname_rel = "$::DATADIR/${base_name}-$ftype-$i.asc"; + $fname = "$::host_dir" . "$fname_rel"; + } + + print +"Extracting ASCII strings from <tt>$Caseman::vol2sname{$vol}</tt><br>\n"; + + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Saving ASCII strings to $fname_rel"); + + local *OUT; + + my $hit_cnt = 0; + $SIG{ALRM} = sub { + if (($hit_cnt++ % 5) == 0) { + print "+"; + } + else { + print "-"; + } + alarm(5); + }; + + alarm(5); + + if ($ftype eq "blkls") { + Exec::exec_pipe(*OUT, + "'$::TSKDIR/srch_strings' -a -t d $img > '$fname'"); + } + elsif ((($ftype eq "raw") || ($ftype eq "swap")) + && ($Caseman::vol2end{$vol} != 0)) + { + Exec::exec_pipe(*OUT, + "'$::TSKDIR/blkls' -e -f $ftype -i $imgtype $img " + . $Caseman::vol2start{$vol} . "-" + . $Caseman::vol2end{$vol} + . " | '$::TSKDIR/srch_strings' -a -t d > '$fname'"); + } + else { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d > '$fname'" + ); + } + alarm(0); + $SIG{ALRM} = 'DEFAULT'; + + print $_ while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + + print "<br>\n" if ($hit_cnt != 0); + + # Verify that it worked + unless (open(STR, "$fname")) { + print( "Error opening $fname<br>\n" + . "Either an error occurred while generating the file or " + . "no ASCII strings exist<br>"); + goto str_uni; + } + + # append to config + my $strvol = + Caseman::add_vol_host_config("strings", "$vol $fname_rel"); + print "Host configuration file updated<br>"; + + $Caseman::vol2ftype{$strvol} = "strings"; + $Caseman::mod2vol{$strvol} = $vol; + $Caseman::vol2str{$vol} = $strvol; + $Caseman::vol2cat{$strvol} = "mod"; + $Caseman::vol2itype{$strvol} = "raw"; + + $Caseman::vol2par{$strvol} = $vol; + $Caseman::vol2path{$strvol} = "$::host_dir" . "$fname_rel"; + $Caseman::vol2start{$strvol} = 0; + $Caseman::vol2end{$strvol} = 0; + $Caseman::vol2sname{$strvol} = $fname_rel; + + # Calculate MD5 + if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) { + print "Calculating MD5 Value<br><br>\n"; + my $m = Hash::int_create_wrap($strvol); + print "MD5 Value: <tt>$m</tt><br><br>\n"; + } + } + + str_uni: + + if ($uni == 1) { + + my $fname_rel = "$::DATADIR/${base_name}-$ftype.uni"; + my $fname = "$::host_dir" . "$fname_rel"; + + if (-e "$fname") { + my $i = 1; + $i++ while (-e "$::host_dir" + . "$::DATADIR/" + . "${base_name}-$ftype-$i.uni"); + + $fname_rel = "$::DATADIR/${base_name}-$ftype-$i.uni"; + $fname = "$::host_dir" . "$fname_rel"; + } + + print "<hr>\n" if ($ascii == 1); + + print +"Extracting Unicode strings from <tt>$Caseman::vol2sname{$vol}</tt><br>\n"; + + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Saving Unicode strings to $fname_rel"); + + local *OUT; + + my $hit_cnt = 0; + $SIG{ALRM} = sub { + if (($hit_cnt++ % 5) == 0) { + print "+"; + } + else { + print "-"; + } + alarm(5); + }; + + alarm(5); + if ($ftype eq "blkls") { + Exec::exec_pipe(*OUT, + "'$::TSKDIR/srch_strings' -a -t d -e l $img > '$fname'"); + } + elsif ((($ftype eq "raw") || ($ftype eq "swap")) + && ($Caseman::vol2end{$vol} != 0)) + { + Exec::exec_pipe(*OUT, + "'$::TSKDIR/blkls' -e -f $ftype -i $imgtype $img " + . $Caseman::vol2start{$vol} . "-" + . $Caseman::vol2end{$vol} + . " | '$::TSKDIR/srch_strings' -a -t d -e l > '$fname'"); + } + + else { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/blkls' -e -f $ftype -o $offset -i $imgtype $img | '$::TSKDIR/srch_strings' -a -t d -e l > '$fname'" + ); + } + + alarm(0); + $SIG{ALRM} = 'DEFAULT'; + + print $_ while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + + print "<br>\n" if ($hit_cnt != 0); + + # Verify that it worked + unless (open(STR, "$fname")) { + print "Error opening $fname<br>\n" + . "Either an error occurred while generating the file or " + . "no Unicode strings exist"; + goto str_egress; + } + + # append to config + my $strvol = + Caseman::add_vol_host_config("unistrings", "$vol $fname_rel"); + print "Host configuration file updated<br>"; + + $Caseman::vol2ftype{$strvol} = "strings"; + $Caseman::mod2vol{$strvol} = $vol; + $Caseman::vol2uni{$vol} = $strvol; + $Caseman::vol2cat{$strvol} = "mod"; + $Caseman::vol2itype{$strvol} = "raw"; + + $Caseman::vol2par{$strvol} = $vol; + $Caseman::vol2path{$strvol} = "$::host_dir" . "$fname_rel"; + $Caseman::vol2start{$strvol} = 0; + $Caseman::vol2end{$strvol} = 0; + $Caseman::vol2sname{$strvol} = $fname_rel; + + # Calculate MD5 + if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) { + print "Calculating MD5 Value<br><br>\n"; + $m = Hash::int_create_wrap($strvol); + print "MD5 Value: <tt>$m</tt><br><br>\n"; + } + } + + str_egress: + + my $dest_vol = $vol; + + # We need to return with a real image to VOL_DETAILS so check the mod + $dest_vol = $Caseman::mod2vol{$vol} + if (exists $Caseman::mod2vol{$vol}); + + print "<hr><a href=\"$::PROGNAME?$Args::baseargs_novol&mod=$::MOD_CASEMAN&" + . "view=$Caseman::VOL_DETAILS&vol=$dest_vol\" target=_top>Image Details</a><p>\n"; + + print +"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_KWSRCH&$Args::baseargs\"" + . " target=\"_top\">Keyword Search</a>\n"; + + Print::print_html_footer(); + + return 0; +} + +sub vol_makeblkls { + Print::print_html_header("Extracting Unallocated Space"); + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $base_name = $Caseman::vol2sname{$vol}; + $base_name = $1 if ($base_name =~ /^(.*?)\.dd$/); + my $fname_rel = "$::DATADIR/${base_name}-$ftype.unalloc"; + my $fname = "$::host_dir" . "$fname_rel"; + + if (-e "$::host_dir" . "$fname_rel") { + my $i = 1; + $i++ while (-e "$::host_dir" + . "$::DATADIR/" + . "${base_name}-$ftype-$i.unalloc"); + + $fname_rel = "$::DATADIR/${base_name}-$ftype-$i.unalloc"; + $fname = "$::host_dir" . "$fname_rel"; + } + + Print::log_host_inv( + "$Args::args{'vol'}: Saving unallocated data to $fname_rel"); + + print +"Extracting unallocated data from <tt>$Caseman::vol2sname{$vol}</tt><br>\n"; + + local *OUT; + + my $hit_cnt = 0; + $SIG{ALRM} = sub { + if (($hit_cnt++ % 5) == 0) { + print "+"; + } + else { + print "-"; + } + alarm(5); + }; + + alarm(5); + + Exec::exec_pipe(*OUT, + "'$::TSKDIR/blkls' -f $ftype -o $offset -i $imgtype $img > '$fname'"); + + alarm(0); + $SIG{ALRM} = 'DEFAULT'; + + print "$_" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + + print "<br>\n" + if ($hit_cnt != 0); + + # append to config + my $blklsvol = Caseman::add_vol_host_config("blkls", "$vol $fname_rel"); + print "Host configuration file updated<br>"; + + $Caseman::vol2ftype{$blklsvol} = "blkls"; + $Caseman::mod2vol{$blklsvol} = $vol; + $Caseman::vol2blkls{$vol} = $blklsrvol; + $Caseman::vol2cat{$blklsvol} = "mod"; + $Caseman::vol2itype{$blklsvol} = "raw"; + + $Caseman::vol2par{$blklsvol} = $vol; + $Caseman::vol2path{$blklsvol} = "$::host_dir" . "$fname_rel"; + $Caseman::vol2start{$blklsvol} = 0; + $Caseman::vol2end{$blklsvol} = 0; + $Caseman::vol2sname{$blklsvol} = $fname_rel; + + # Calculate MD5 + if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) { + print "Calculating MD5 Value<br>\n"; + my $m = Hash::int_create_wrap($blklsvol); + print "MD5 Value: <tt>$m</tt><br><br>\n"; + } + + print "<a href=\"$::PROGNAME?$Args::baseargs&mod=$::MOD_CASEMAN&" + . "view=$Caseman::VOL_DETAILS\" target=_top>Image Details</a><p>\n"; + + print +"<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_KWSRCH&$Args::baseargs_novol&" + . "vol=$fname_rel\" target=\"_top\">Keyword Search</a>\n"; + + Print::print_html_footer(); + return 0; +} + +1; diff --git a/lib/Data.pm b/lib/Data.pm new file mode 100644 index 0000000000..f8e2ef43fe --- /dev/null +++ b/lib/Data.pm @@ -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; +} diff --git a/lib/Exec.pm b/lib/Exec.pm new file mode 100644 index 0000000000..e138712756 --- /dev/null +++ b/lib/Exec.pm @@ -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; diff --git a/lib/File.pm b/lib/File.pm new file mode 100644 index 0000000000..fc6d618fee --- /dev/null +++ b/lib/File.pm @@ -0,0 +1,2293 @@ +# +# File name layer functions +# +# Brian Carrier [carrier@sleuthkit.org] +# Copyright (c) 2001-2005 by Brian Carrier. All rights reserved +# +# This file is part of the Autopsy Forensic Browser (Autopsy) +# +# Autopsy is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Autopsy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Autopsy; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE. +# IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Updated 1/15 + +package File; + +# If the order of these views are changed, then the checks in main +# must be as well +$File::BLANK = 0; +$File::FRAME = 1; +$File::DIR_LIST = 2; +$File::FILE_LIST_DIR = 3; +$File::FILE_LIST_FILE = 4; +$File::FILE_LIST_DEL = 5; +$File::FILE_LIST = 6; +$File::CONT = 7; +$File::CONT_FR = 8; +$File::CONT_MENU = 9; +$File::REPORT = 10; +$File::EXPORT = 11; +$File::MD5LIST = 12; +$File::CONT_IMG = 13; + +$File::REC_NO = 0; +$File::REC_YES = 1; + +sub main { + + # By default, show the main frame + $Args::args{'view'} = $Args::enc_args{'view'} = $File::FRAME + unless (exists $Args::args{'view'}); + + Args::check_view(); + my $view = Args::get_view(); + + if ($view == $File::BLANK) { + blank(); + return 0; + } + + # Check Basic Args + Args::check_vol('vol'); + + # These windows don't need the meta data address + if ($view < $File::FILE_LIST) { + + if ($view == $File::FRAME) { + return frame(); + } + + Args::check_dir(); + if ($view == $File::DIR_LIST) { + return dir_list(); + } + elsif ($view == $File::FILE_LIST_DIR) { + return file_list_dir(); + } + elsif ($view == $File::FILE_LIST_DEL) { + return file_list_del(); + } + elsif ($view == $File::FILE_LIST_FILE) { + return file_list_file(); + } + } + + # These windows need the meta data address + Args::check_dir(); + Args::check_meta('meta'); + + if ($view < $File::REPORT) { + if ($view == $File::FILE_LIST) { + return file_list(); + } + elsif ($view == $File::CONT) { + return content(); + } + elsif ($view == $File::CONT_FR) { + return content_fr(); + } + elsif ($view == $File::CONT_MENU) { + return content_menu(); + } + } + else { + if ($view == $File::REPORT) { + return report(); + } + elsif ($view == $File::EXPORT) { + return export(); + } + elsif ($view == $File::MD5LIST) { + return md5list(); + } + elsif ($view == $File::CONT_IMG) { + return content_img(); + } + } + + Print::print_check_err("Invalid File View"); +} + +# Sorting and display types +my $FIL_SORT_ASC = 0; +my $FIL_SORT_STR = 1; +my $FIL_SORT_HEX = 2; + +# Methods of sorting the file listings +my $SORT_DTYPE = 0; # type according to dentry +my $SORT_ITYPE = 1; # type according to meta +my $SORT_NAME = 2; +my $SORT_MOD = 3; +my $SORT_ACC = 4; +my $SORT_CHG = 5; +my $SORT_CRT = 6; +my $SORT_SIZE = 7; +my $SORT_GID = 8; +my $SORT_UID = 9; +my $SORT_META = 10; +my $SORT_DEL = 11; + +my $DIRMODE_SHOW = 1; +my $DIRMODE_NOSHOW = 2; + +# +# Make the three frames and fill them in +# +sub frame { + my $vol = Args::get_vol('vol'); + my $mnt = $Caseman::vol2mnt{$vol}; + + my $ftype = $Caseman::vol2ftype{$vol}; + + # If we were not given the meta, then look up the root + unless (exists $Args::args{'meta'}) { + $Args::args{'meta'} = $Args::enc_args{'meta'} = $Fs::root_meta{$ftype}; + } + + unless (exists $Args::args{'dir'}) { + $Args::enc_args{'dir'} = $Args::args{'dir'} = "/"; + } + + Args::check_meta('meta'); + Args::check_dir(); + + my $meta = Args::get_meta('meta'); + my $dir = Args::get_dir(); + + Print::print_html_header_frameset("$mnt$dir on $Args::args{'vol'}"); + + my $sort = $SORT_NAME; + $sort = $Args::args{'sort'} if (exists $Args::args{'sort'}); + + my $dirmode = $DIRMODE_NOSHOW; + $dirmode = $Args::args{'dirmode'} if (exists $Args::args{'dirmode'}); + + print "<frameset cols=\"175,*\">\n"; + + # Directory Listing on Left + my $url = + "$::PROGNAME?$Args::baseargs&dir=$dir&" . "sort=$sort&dirmode=$dirmode"; + + print "<frame src=\"$url&mod=$::MOD_FILE&view=$File::DIR_LIST\">\n"; + + # File frameset on right + print "<frameset rows=\"50%,50%\">\n"; + + # File Listings on top + print + "<frame src=\"$url&mod=$::MOD_FILE&view=$File::FILE_LIST&meta=$meta\" " + . "name=\"list\">\n"; + + # File Contents + print "<frame src=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::BLANK&" + . "$Args::baseargs\" name=\"content\">\n" + . "</frameset>\n" + . "</frameset>\n"; + + Print::print_html_footer_frameset(); + return 0; +} + +# +# Print the directory names for the lhs frame and other +# Search forms +# + +sub dir_list { + Args::check_sort(); + Args::check_dirmode(); + + Print::print_html_header(""); + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $sort = Args::get_sort(); + my $dirmode = Args::get_dirmode(); + my $mnt = $Caseman::vol2mnt{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $lcldir = ""; + my $prev_plus = ""; # previous number of '+' directory spacers + my $prev_fname = ""; + my $prev_meta = ""; + + # Field to enter a directory into: + print "<p><form action=\"$::PROGNAME\" method=\"get\" target=\"list\">\n" + . "<center><b>Directory Seek</b></center><br>" + . "Enter the name of a directory that you want to view.<br>" + . "<tt>$mnt</tt>" + . "<input type=\"text\" name=\"dir\" size=24 maxlength=100>\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FILE\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$File::FILE_LIST_DIR\">\n" + . "<input type=\"hidden\" name=\"vol\" value=\"$vol\">\n" + . "<input type=\"hidden\" name=\"sort\" value=\"$Args::args{'sort'}\">\n" + . "<input type=\"hidden\" name=\"dirmode\" value=\"$Args::args{'dirmode'}\">\n" + . Args::make_hidden() + . + + # View Button + "<br><input type=\"image\" src=\"pict/but_view.jpg\" " + . "width=45 height=22 alt=\"View\" border=\"0\"></form>\n"; + + # Field to enter a name into: + print + "<hr><p><form action=\"$::PROGNAME\" method=\"get\" target=\"list\">\n" + . "<center><b>File Name Search</b></center><br>" + . "Enter a Perl regular expression for the file names you want to find.<br><br>\n" + . "<input type=\"text\" name=\"dir\" size=24 maxlength=100>\n" + . "<input type=\"hidden\" name=\"mod\" value=\"$::MOD_FILE\">\n" + . "<input type=\"hidden\" name=\"view\" value=\"$File::FILE_LIST_FILE\">\n" + . "<input type=\"hidden\" name=\"vol\" value=\"$Args::args{'vol'}\">\n" + . "<input type=\"hidden\" name=\"sort\" value=\"$Args::args{'sort'}\">\n" + . "<input type=\"hidden\" name=\"dirmode\" value=\"$Args::args{'dirmode'}\">\n" + . Args::make_hidden() + . "<br>\n" + . + + # Search Button + "<input type=\"image\" src=\"pict/but_search.jpg\" " + . "width=61 height=22 alt=\"Search\" border=\"0\"></form>\n"; + + print "<p><hr><p>\n"; + + my $base_url = "$::PROGNAME?$Args::baseargs&sort=$sort"; + + # All deleted files button + print "<a href=\"$base_url&mod=$::MOD_FILE&view=$File::FILE_LIST_DEL&" + . "dir=&dirmode=$dirmode\" target=\"list\">" + . "<img border=\"0\" src=\"pict/file_b_alldel.jpg\" width=\"127\" " + . "alt=\"Show All Deleted Files\">" + . "</a><p>\n"; + + # The dirmode arg shows if we should expand the whole directory listing + # or not + if ($dirmode == $DIRMODE_NOSHOW) { + print "<a href=\"$base_url&mod=$::MOD_FILE&view=$File::FRAME&" + . "dirmode=$DIRMODE_SHOW\" target=\"_parent\">" + . "<img src=\"pict/file_b_expand.jpg\" alt=\"Expand All Directories\" " + . "border=\"0\"></a><p><hr>\n"; + + return; + } + else { + print "<a href=\"$base_url&mod=$::MOD_FILE&view=$File::FRAME&" + . "dirmode=$DIRMODE_NOSHOW\" target=\"_parent\">" + . "<img src=\"pict/file_b_hide.jpg\" alt=\"Hide All Directories\" " + . "border=\"0\"></a><p><hr>\n"; + } + + $base_url .= "&dirmode=$dirmode"; + + Print::log_host_inv("$Args::args{'vol'}: List of all directories"); + + # We need to maintain state to create dir and this is done by + # counting the + marks. + local *OUT; + Exec::exec_pipe(*OUT, + "'$::TSKDIR/fls' -f $ftype -ruD -o $offset -i $imgtype $img"); + + # Print root + my $url = + "$base_url&mod=$::MOD_FILE&view=$File::FILE_LIST&" + . "meta=$Fs::root_meta{$ftype}&dir="; + print "<p><a href=\"$url\" target=\"list\">$mnt</a><br>\n"; + + while ($_ = Exec::read_pipe_line(*OUT)) { + if ( +/^(\*)?(\+*)\s*[\-d]\/[\-d]\s*(\d+)\-?\d*\-?\d*\s*(\(realloc\))?:\t(.+)$/ + ) + { + + my $del = $1; + my $plus = $2; + my $meta = $3; + my $re = $4; + my $fname = $5; + + # Adjust the dir value using the '++' values to determine + # how "deep" we are + unless ($prev_plus eq $plus) { + + # are we in 1 more + if ($plus eq $prev_plus . '+') { + $lcldir .= ($prev_fname . "/"); + } + + # we are back (at least one) + elsif (defined $plus) { + my @dirs = split('/', $lcldir); + my $idx = -1; + $lcldir = ""; + + while (($idx = index($plus, '+', $idx + 1)) != -1) { + $lcldir .= ($dirs[$idx] . "/"); + } + } + } + + $prev_plus = $plus; + $prev_fname = $fname; + $prev_meta = $meta; + + $url = + "$base_url&mod=$::MOD_FILE&view=$File::FILE_LIST&" + . "meta=$meta&dir=" + . Args::url_encode($lcldir . $fname . "/"); + + print "<font color=\"$::DEL_COLOR[0]\">" if defined $del; + print "+$plus<a href=\"$url\" target=\"list\"><tt>/" + . Print::html_encode($fname) + . "</tt></a><br>\n"; + print "</font>" if defined $del; + } + } + close(OUT); + Print::print_html_footer(); + return 0; + +}; # end of FIL_DIR + +# Print the files and directories for the upper rhs frame +# These can be sorted in any format +# +# We need to find a way to cache this data +# +sub file_list { + Args::check_sort(); + Args::check_dirmode(); + + my $vol = Args::get_vol('vol'); + my $sort = Args::get_sort(); + my $ftype = $Caseman::vol2ftype{$vol}; + my $meta = Args::get_meta('meta'); + my $mnt = $Caseman::vol2mnt{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $fname = "$mnt$Args::args{'dir'}"; + $fname =~ s/\/\//\//g; + + my $sp = "&nbsp;&nbsp;"; + + Print::print_html_header("Entries in $fname"); + + my (@itype, @dtype, @name, @mod, @acc, @chg, @crt, @size, @gid, @uid, + @meta); + my (@dir, @entry, @del, @realloc, @meta_int); + + my $tz = ""; + $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); + + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Directory listing of $fname ($meta)"); + + local *OUT; + + # execute command + Exec::exec_pipe(*OUT, +"'$::TSKDIR/fls' -f $ftype -la $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" + ); + + # Make the big table, small table, and start the current directory + + my $iurl = +"$::PROGNAME?$Args::baseargs&dirmode=$Args::enc_args{'dirmode'}&sort=$sort"; + + # base number of columns in table + my $cols = 15; + $cols += 2 if ($Fs::has_ctime{$ftype}); + $cols += 2 if ($Fs::has_crtime{$ftype}); + $cols += 2 if ($Fs::has_mtime{$ftype}); + + print <<EOF1; +<!-- Big Table --> +<table cellspacing=\"0\" cellpadding=\"2\" border=0> + +<!-- Small Table --> +<tr> + <td colspan=$cols> + <table border=0 align=\"left\" cellspacing=\"0\" cellpadding=\"2\" width=500> + <tr> + <td colspan=2><b>Current Directory:</b> <tt> + + <a href=\"${iurl}&mod=$::MOD_FILE&view=$File::FILE_LIST&meta=$Fs::root_meta{$ftype}&dir=\">$mnt</a>&nbsp; + +EOF1 + + # Each file in the path will get its own link + $iurl .= "&mod=$::MOD_FILE&view=$File::FILE_LIST_DIR"; + my $path = ""; + my @dir_split = split('/', $Args::args{'dir'}); + while (scalar @dir_split > 1) { + my $d = shift @dir_split; + + next if ($d eq ''); + + $path .= "$d/"; + print " <a href=\"${iurl}&dir=$path\">/${d}/</a>&nbsp;\n"; + } + print " /$dir_split[0]/&nbsp;\n" + if (scalar @dir_split == 1); + + print " </tt></td>\n" . " </tr>\n"; + + # Add Note Button + $iurl = +"&$Args::baseargs&dir=$Args::enc_args{'dir'}&meta=$Args::enc_args{'meta'}"; + if ($::USE_NOTES == 1) { + + print <<EOF2; + <tr> + <td width=\"100\" align=left> + <a href=\"$::PROGNAME?mod=$::MOD_NOTES&view=$Notes::ENTER_FILE$iurl\" target=\"_blank\"> + <img border=\"0\" src=\"pict/but_addnote.jpg\" width=\"89\" height=20 alt=\"Add Note About Directory\"> + </a> + </td> +EOF2 + + } + + # Generate MD5 List Button + print <<EOF3; + + <td width=\"206\" align=left> + <a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::MD5LIST$iurl\" target=\"_blank\"> + <img border=\"0\" src=\"pict/file_b_md5list.jpg\" width=\"206\" alt=\"Generate list of MD5 values\"> + </a> + </td> + </tr> + <!-- END of Little Table --> + </table> + </td> +</tr> +<tr> + <td colspan=$cols><hr></td> +</tr> + +EOF3 + + # Make the Table and Headers + my $url = + "$::PROGNAME?mod=$::MOD_FILE&view=$File::FRAME&" + . "$Args::baseargs&meta=$Args::enc_args{'meta'}" + . "&dir=$Args::enc_args{'dir'}&dirmode=$Args::enc_args{'dirmode'}"; + + print "<tr valign=\"MIDDLE\" " . "background=\"$::YEL_PIX\">\n"; + + # Print the Headers - If the sorting mode is set to it, then don't + # make it a link and print a different button + if ($sort == $SORT_DEL) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_del_cur.jpg\" " + . "width=\"49\" height=20 " + . "alt=\"Deleted Files\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_DEL"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_del_link.jpg\" " + . "width=\"28\" height=20 " + . "alt=\"Deleted Files\">" + . "</a></td>\n"; + } + + # type only gets one column for two 'types' + print " <td background=\"$::YEL_PIX\">$sp</td>\n" + . " <th align=\"center\" background=\"$::YEL_PIX\">" + . "&nbsp;&nbsp;Type&nbsp;&nbsp;<br>"; + + if ($sort == $SORT_DTYPE) { + print "dir"; + } + else { + $iurl = $url . "&sort=$SORT_DTYPE"; + print "<a href=\"$iurl\" target=\"_parent\">dir</a>"; + } + + print "&nbsp;/&nbsp;"; + + if ($sort == $SORT_ITYPE) { + print "in</th>\n"; + } + else { + $iurl = $url . "&sort=$SORT_ITYPE"; + print "<a href=\"$iurl\" target=\"_parent\">in</a></th>\n"; + } + + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + + if ($sort == $SORT_NAME) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_nam_cur.jpg\" " + . "width=\"76\" height=20 " + . "alt=\"File Name\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_NAME"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_nam_link.jpg\" " + . "width=\"50\" height=20 " + . "alt=\"File Name\">" + . "</a></td>\n"; + } + + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + + # Modified / Written + if ($Fs::has_mtime{$ftype}) { + if ($sort == $SORT_MOD) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_wr_cur.jpg\" " + . "width=\"89\" height=20 " + . "alt=\"Modified/Written Time\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_MOD"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_wr_link.jpg\" " + . "width=\"60\" height=20 " + . "alt=\"Modified/Written Time\">" + . "</a></td>\n"; + } + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + } + + # Accessed + if ($sort == $SORT_ACC) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_acc_cur.jpg\" " + . "width=\"90\" height=20 " + . "alt=\"Access Time\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_ACC"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_acc_link.jpg\" " + . "width=\"66\" height=20 " + . "alt=\"Access Time\">" + . "</a></td>\n"; + } + + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + + # Change + if ($Fs::has_ctime{$ftype}) { + if ($sort == $SORT_CHG) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_chg_cur.jpg\" " + . "width=\"90\" height=20 " + . "alt=\"Change Time\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_CHG"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_chg_link.jpg\" " + . "width=\"62\" height=20 " + . "alt=\"Change Time\">" + . "</a></td>\n"; + } + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + } + + # Create + if ($Fs::has_crtime{$ftype}) { + if ($sort == $SORT_CRT) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_cre_cur.jpg\" " + . "width=\"84\" height=20 " + . "alt=\"Create Time\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_CRT"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_cre_link.jpg\" " + . "width=\"59\" height=20 " + . "alt=\"Create Time\">" + . "</a></td>\n"; + } + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + } + + # Size + if ($sort == $SORT_SIZE) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_siz_cur.jpg\" " + . "width=\"53\" height=20 " + . "alt=\"Size\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_SIZE"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_siz_link.jpg\" " + . "width=\"31\" height=20 " + . "alt=\"Size\">" + . "</a></td>\n"; + } + + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + + # UID + if ($sort == $SORT_UID) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_uid_cur.jpg\" " + . "width=\"49\" height=20 " + . "alt=\"UID\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_UID"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_uid_link.jpg\" " + . "width=\"27\" height=20 " + . "alt=\"UID\">" + . "</a></td>\n"; + } + + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + + # GID + if ($sort == $SORT_GID) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_gid_cur.jpg\" " + . "width=\"49\" height=20 " + . "alt=\"GID\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_GID"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_gid_link.jpg\" " + . "width=\"28\" height=20 " + . "alt=\"GID\">" + . "</a></td>\n"; + } + + print " <td background=\"$::YEL_PIX\">$sp</td>\n"; + + # meta + if ($sort == $SORT_META) { + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_meta_cur.jpg\" " + . "width=\"62\" height=20 " + . "alt=\"Meta\">" + . "</td>\n"; + } + else { + $iurl = $url . "&sort=$SORT_META"; + print " <td align=\"left\" background=\"$::YEL_PIX\">" + . "<a href=\"$iurl\" target=\"_parent\">" + . "<img border=\"0\" " + . "src=\"pict/file_h_meta_link.jpg\" " + . "width=\"41\" height=20 " + . "alt=\"Meta\">" + . "</a></td>\n"; + } + print "</tr>\n"; + + my $cnt = 0; + my %seen; + + # sort fls into arrays + while ($_ = Exec::read_pipe_line(*OUT)) { + if ( +/^($::REG_MTYPE)\/($::REG_MTYPE)\s*(\*?)\s*($::REG_META)(\(realloc\))?:\t(.+?)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o + ) + { + + my $lcldir = $Args::args{'dir'}; + $dtype[$cnt] = $1; + $itype[$cnt] = $2; + $del[$cnt] = $3; + $meta[$cnt] = $4; + $realloc[$cnt] = ""; + $realloc[$cnt] = $5 if (defined $5); + $name[$cnt] = $6; + $mod[$cnt] = $7; + $acc[$cnt] = $8; + $chg[$cnt] = $9; + $crt[$cnt] = $10; + $size[$cnt] = $11; + $gid[$cnt] = $12; + $uid[$cnt] = $13; + + if ($meta[$cnt] =~ /^(\d+)(-\d+(-\d+)?)?$/) { + $meta_int[$cnt] = $1; + } + else { + $meta_int[$cnt] = $meta[$cnt]; + } + + # See if we have already seen this file yet + if (exists $seen{"$name[$cnt]-$meta[$cnt]"}) { + my $prev_cnt = $seen{"$name[$cnt]-$meta[$cnt]"}; + + # If we saw it while it was deleted, & it + # is now undel, then update it + if ( ($del[$cnt] eq "") + && ($del[$prev_cnt] eq '*')) + { + $del[$prev_cnt] = $del[$cnt]; + } + next; + + # Add it to the seen list + } + else { + $seen{"$name[$cnt]-$meta[$cnt]"} = $cnt; + } + + # We must adjust the dir for directories + if ($itype[$cnt] eq 'd') { + + # special cases for .. and . + if ($name[$cnt] eq '..') { + my @dirs = split('/', $lcldir); + my $i; + $lcldir = ""; + for ($i = 0; $i < $#dirs; $i++) { + $lcldir .= ($dirs[$i] . '/'); + } + } + elsif ($name[$cnt] ne '.') { + $lcldir .= ($name[$cnt] . '/'); + } + $name[$cnt] .= '/'; + } + else { + $lcldir .= $name[$cnt]; + } + + # format the date so that the time and time zone are on the + # same line + $mod[$cnt] = "$1&nbsp;$2" + if ($mod[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + + $acc[$cnt] = "$1&nbsp;$2" + if ($acc[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + + $chg[$cnt] = "$1&nbsp;$2" + if ($chg[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + + $crt[$cnt] = "$1&nbsp;$2" + if ($crt[$cnt] =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + + $dir[$cnt] = Args::url_encode($lcldir); + $entry[$cnt] = $cnt; + $cnt++; + + } + + # We missed it for some reason + else { + print +"<tr><td colspan=10>Error Parsing File (Invalid Characters?):<br>$_</td></tr>\n"; + } + } + close(OUT); + + if ($cnt == 0) { + print "</table>\n<center>No Contents</center>\n"; + return 0; + } + + # Sort the above array based on the sort argument + my @sorted; # an array of indices + + if ($sort == $SORT_DTYPE) { + @sorted = + sort { $dtype[$a] cmp $dtype[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_ITYPE) { + @sorted = + sort { $itype[$a] cmp $itype[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_NAME) { + @sorted = sort { lc($name[$a]) cmp lc($name[$b]) } @entry; + } + elsif ($sort == $SORT_MOD) { + @sorted = + sort { $mod[$a] cmp $mod[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_ACC) { + @sorted = + sort { $acc[$a] cmp $acc[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_CHG) { + @sorted = + sort { $chg[$a] cmp $chg[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_CRT) { + @sorted = + sort { $crt[$a] cmp $crt[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_SIZE) { + @sorted = + sort { $size[$a] <=> $size[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_UID) { + @sorted = + sort { $uid[$a] <=> $uid[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_GID) { + @sorted = + sort { $gid[$a] <=> $gid[$b] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + elsif ($sort == $SORT_META) { + @sorted = sort { + $meta_int[$a] <=> $meta_int[$b] + or lc($name[$a]) cmp lc($name[$b]) + } @entry; + } + elsif ($sort == $SORT_DEL) { + @sorted = + sort { $del[$b] cmp $del[$a] or lc($name[$a]) cmp lc($name[$b]) } + @entry; + } + + # print them based on sorting + my $row = 0; + foreach my $i (@sorted) { + my $url; + my $target; + my $color; + my $lcolor; + if ($del[$i] eq '*') { + $color = + "<font color=\"" . $::DEL_COLOR[$realloc[$i] ne ""] . "\">"; + $lcolor = $color; + } + else { + $color = "<font color=\"$::NORM_COLOR\">"; + $lcolor = "<font color=\"$::LINK_COLOR\">"; + } + + # directories have different targets and view values + if ($itype[$i] eq 'd') { + $target = "list"; + $url = + "$::PROGNAME?mod=$::MOD_FILE&view=$File::FILE_LIST&" + . "$Args::baseargs&meta=$meta_int[$i]" + . "&sort=$sort&dir=$dir[$i]&dirmode=$Args::enc_args{'dirmode'}"; + } + else { + $target = "content"; + $url = + "$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&" + . "$Args::baseargs&meta=$meta[$i]" + . "&sort=$sort&dir=$dir[$i]&dirmode=$Args::enc_args{'dirmode'}"; + if ($del[$i] eq '*') { + $url .= "&recmode=$File::REC_YES"; + } + else { + $url .= "&recmode=$File::REC_NO"; + } + } + + if (($row % 2) == 0) { + print +"<tr valign=\"TOP\" bgcolor=\"$::BACK_COLOR\">\n <td align=\"center\">"; + } + else { + print +"<tr valign=\"TOP\" bgcolor=\"$::BACK_COLOR_TABLE\">\n <td align=\"center\">"; + } + + print "<img src=\"pict/file_b_check.jpg\" border=\"0\">\n" + if ($del[$i] eq '*'); + + print "</td>\n" + . " <td>$sp</td>\n" + . " <td align=\"center\">${color}$dtype[$i]&nbsp;/&nbsp;$itype[$i]</td>\n" + . " <td>$sp</td>\n"; + + # for valid files and directories make a link + # Special rule for $OrphanFiles directory, which has a size of 0 + if ( ($meta_int[$i] >= $Fs::first_meta{$ftype}) + && (($size[$i] > 0) || ($name[$i] =~ /^\$Orphan/)) + && ( ($itype[$i] eq 'r') + || ($itype[$i] eq 'd') + || ($itype[$i] eq 'v'))) + { + print " <td><a href=\"$url\" target=\"$target\">$lcolor"; + } + else { + print " <td>$color"; + } + print "<tt>" + . Print::html_encode($name[$i]) + . "</tt></td>\n" + . " <td>$sp</td>\n"; + print " <td>${color}$mod[$i]</td>\n" . " <td>$sp</td>\n" + if ($Fs::has_mtime{$ftype}); + print " <td>${color}$acc[$i]</td>\n" . " <td>$sp</td>\n"; + print " <td>${color}$chg[$i]</td>\n" . " <td>$sp</td>\n" + if ($Fs::has_ctime{$ftype}); + print " <td>${color}$crt[$i]</td>\n" . " <td>$sp</td>\n" + if ($Fs::has_crtime{$ftype}); + print " <td>${color}$size[$i]</td>\n" + . " <td>$sp</td>\n" + . " <td>${color}$uid[$i]</td>\n" + . " <td>$sp</td>\n" + . " <td>${color}$gid[$i]</td>\n" + . " <td>$sp</td>\n"; + + # for a valid meta, make a link to meta browsing mode + if ($meta_int[$i] >= $Fs::first_meta{$ftype}) { + my $iurl = +"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&meta=$meta[$i]"; + print "<td><a href=\"$iurl\" target=\"_top\">$lcolor"; + } + else { + print "<td>$color"; + } + print "$meta[$i]</a> $realloc[$i]</td>\n</tr>\n"; + + $row++; + } + + print "</table>\n"; + Print::print_html_footer(); + return 0; + +}; #end of FIL_LIST + +# This takes a directory name as an argument and converts it to +# the meta value and calls FIL_LIST +# +# The meta value can be anything when this is run, it will be +# overwritten +sub file_list_dir { + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $dir = Args::get_dir(); + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + Print::log_host_inv( + "$Args::args{'vol'}: Finding meta data address for $dir"); + + # Use 'ifind -n' to get the meta data address for the given name + local *OUT; + Exec::exec_pipe(*OUT, + "'$::TSKDIR/ifind' -f $ftype -n '$dir' -o $offset -i $imgtype $img"); + my $meta; + + while ($_ = Exec::read_pipe_line(*OUT)) { + $meta = $1 + if (/^($::REG_META)$/); + } + close(OUT); + + Print::print_check_err("Error finding meta data address for $dir") + unless (defined $meta); + + Print::print_check_err("Error finding meta data address for $dir: $meta") + unless ($meta =~ /^$::REG_META$/); + + # Verify it is a directory with istat + Exec::exec_pipe(*OUT, + "'$::TSKDIR/istat' -f $ftype -o $offset -i $imgtype $img $meta"); + + while ($_ = Exec::read_pipe_line(*OUT)) { + + # This is a directory + if ( (/mode:\s+d/) + || (/File Attributes: Directory/) + || (/^Flags:.*?Directory/)) + { + close(OUT); + + # Set the meta variables + $Args::enc_args{'meta'} = $Args::args{'meta'} = $meta; + + $Args::args{'dir'} .= "/" + unless ($Args::args{'dir'} =~ /.*?\/$/); + $Args::enc_args{'dir'} .= "/" + unless ($Args::enc_args{'dir'} =~ /.*?\/$/); + + # List the directory contents + file_list(); + + return 0; + } + } + close(OUT); + + # This is not a directory, so just give a link + Print::print_html_header(""); + + my $meta_int = $meta; + $meta_int = $1 if ($meta_int =~ /(\d+)-\d+(-\d+)?/); + + 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/); + if ($_ =~ /^$meta\|f/) { + $recmode = $File::REC_YES; + } + elsif ($_ =~ /^$meta\|a/) { + $recmode = $File::REC_NO; + } + else { + Print::print_err("Error parsing ils output: $_"); + } + } + close(OUT); + + print <<EOF; + +<tt>$dir</tt> ( +<a href=\"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&meta=$meta&recmode=$recmode\" target=\"_top\"> +meta $meta</a>) is not a directory. + +<p> +<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&$Args::baseargs&meta=$meta&dir=$dir&recmode=$recmode\" target=\"content\"> + <img src=\"pict/but_viewcont.jpg\" height=20 width=123 alt=\"view contents\" border=\"0\"> +</a> + +EOF + + Print::print_html_footer(); + return 1; + +} + +# List the files that meet a certain pattern +sub file_list_file { + Args::check_sort(); + Args::check_dirmode(); + Args::check_dir(); + + my $vol = Args::get_vol('vol'); + my $mnt = $Caseman::vol2mnt{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + my $ftype = $Caseman::vol2ftype{$vol}; + my $meta = $Fs::root_meta{$ftype}; + my $sort = Args::get_sort(); + my $dirmode = Args::get_dirmode(); + my $dir = Args::get_dir(); + + Print::print_html_header( + "Filtered files on $Caseman::vol2sname{$vol} $mnt"); + + my $tz = ""; + $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); + + my $sp = "&nbsp;&nbsp;"; + + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Listing all files with $dir"); + + local *OUT; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/fls' -f $ftype -lpr $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" + ); + + print "<b>All files with \'<tt>$dir</tt>\' in the name</b><p>\n" + . "<a href=\"$::PROGNAME?$Args::baseargs&dirmode=$Args::enc_args{'dirmode'}" + . "&sort=$sort&mod=$::MOD_FILE&view=$File::FILE_LIST" + . "&meta=$Fs::root_meta{$ftype}&dir=\">" + . "<img border=\"0\" src=\"pict/file_b_allfiles.jpg\" width=\"112\" " + . "alt=\"Show All Files\"></a>\n" . "<hr>" + . "<table cellspacing=\"0\" cellpadding=\"2\" border=0>\n" + . "<tr valign=\"MIDDLE\" align=\"left\" " + . "background=\"$::YEL_PIX\">\n"; + + # deleted + print "<td align=\"left\">" + . "<img border=\"0\" src=\"pict/file_h_del_link.jpg\" " + . "width=\"28\" height=20 alt=\"Deleted Files\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # Type + print "<th align=\"center\">&nbsp;&nbsp;Type&nbsp&nbsp;<br>" + . "dir&nbsp;/&nbsp;in</th>" + . "<td>$sp</td>\n"; + + # Name + print " <td><img border=\"0\" " + . "src=\"pict/file_h_nam_link.jpg\" " + . "width=\"50\" height=20 " + . "alt=\"File Name\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # Mod / Written + print " <td><img border=\"0\" "; + if ($Fs::mtime_str{$ftype} eq 'Modified') { + print "src=\"pict/file_h_mod_link.jpg\" " + . "width=\"62\" height=20 " + . "alt=\"Modified Time\">"; + } + else { + print "src=\"pict/file_h_wr_link.jpg\" " + . "width=\"60\" " + . "alt=\"Written Time\">"; + } + print "</td>\n" . "<td>$sp</td>\n"; + + # Access + print " <td><img border=\"0\" " + . "src=\"pict/file_h_acc_link.jpg\" " + . "width=\"66\" height=20 " + . "alt=\"Access Time\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # Change / Create + print " <td><img border=\"0\" "; + if ($Fs::ctime_str{$ftype} eq 'Changed') { + print "src=\"pict/file_h_chg_link.jpg\" " + . "width=\"62\" height=20 " + . "alt=\"Change Time\">"; + } + else { + print "src=\"pict/file_h_cre_link.jpg\" " + . "width=\"59\" height=20 " + . "alt=\"Create Time\">"; + } + print "</td>\n" . "<td>$sp</td>\n"; + + # Size + print " <td><img border=\"0\" " + . "src=\"pict/file_h_siz_link.jpg\" " + . "width=\"31\" height=20 " + . "alt=\"Size\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # UID + print " <td><img border=\"0\" " + . "src=\"pict/file_h_uid_link.jpg\" " + . "width=\"27\" height=20 " + . "alt=\"UID\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # GID + print " <td><img border=\"0\" " + . "src=\"pict/file_h_gid_link.jpg\" " + . "width=\"28\" height=20 " + . "alt=\"GID\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # Meta + print " <td><img border=\"0\" " + . "src=\"pict/file_h_meta_link.jpg\" " + . "width=\"41\" height=20 " + . "alt=\"Meta\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + my $row = 0; + while ($_ = Exec::read_pipe_line(*OUT)) { + + if ( +/^($::REG_MTYPE)\/($::REG_MTYPE)\s*(\*?)\s*($::REG_META)(\(realloc\))?:\t(.+?)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o + ) + { + + # We have to remove the / from the beginning of the file name so + # save all values so they aren't lost + my $dt = $1; + my $it = $2; + my $d = $3; + my $i = $4; + my $r = 0; + $r = 1 if (defined $5); + my $n = $6; + my $m = $7; + my $a = $8; + my $c = $9; + my $s = $10; + my $g = $11; + my $u = $12; + + if ($n =~ /^\/(.*)/) { + $n = $1; + } + + my $p = ""; + my $f = $n; + + if ($n =~ /^(.+?)\/([^\/]+)$/) { + $p = $1; + $f = $2; + } + + next unless ($f =~ /$dir/i); + + my $enc_n = Args::url_encode($n); + my $iurl = +"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&meta=$i"; + my $i_int = $i; + $i_int = $1 if ($i =~ /(\d+)-\d+-\d+/); + + if (($row % 2) == 0) { + print "<tr valign=\"TOP\" bgcolor=\"$::BACK_COLOR\">\n"; + } + else { + print "<tr valign=\"TOP\" bgcolor=\"$::BACK_COLOR_TABLE\">\n"; + } + + print "<td align=\"left\">\n"; + + my $color; + my $lcolor; + if ($d eq '*') { + $color = "<font color=\"" . $::DEL_COLOR[$r] . "\">"; + $lcolor = $color; + + print "<img src=\"pict/file_b_check.jpg\" border=\"0\">\n"; + + } + else { + $color = "<font color=\"$::NORM_COLOR\">"; + $lcolor = "<font color=\"$::LINK_COLOR\">"; + print "&nbsp;"; + } + + print "</td><td>$sp</td>"; + + print "<td align=\"center\">$color" + . "$dt&nbsp;/&nbsp;$it</td>" + . "<td>$sp</td>\n"; + + if ($it eq 'd') { + my $url = + "$::PROGNAME?mod=$::MOD_FILE&" + . "view=$File::FILE_LIST&$Args::baseargs&meta=$i" + . "&sort=$sort&dir=$enc_n&dirmode=$dirmode"; + + print "<td>"; + if ($i_int >= $Fs::first_meta{$ftype}) { + print "<a href=\"$url\" target=\"_self\">$lcolor"; + } + else { + print "$color"; + } + print "<tt>" + . Print::html_encode($mnt . $n) + . "</tt></td>" + . "<td>$sp</td>\n"; + } + else { + my $url = + "$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&" + . "$Args::baseargs&meta=$i&sort=$sort&dir=$enc_n"; + + if ($d eq '*') { + $url .= "&recmode=$File::REC_YES"; + } + else { + $url .= "&recmode=$File::REC_NO"; + } + + print "<td>"; + if (($i_int >= $Fs::first_meta{$ftype}) && ($it eq 'r')) { + print "<a href=\"$url\" target=\"content\">$lcolor"; + } + else { + print "$color"; + } + print "<tt>$mnt$n</tt></td>" . "<td>$sp</td>\n"; + } + + $m = "$1&nbsp;$2" + if ($m =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + $a = "$1&nbsp;$2" + if ($a =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + $c = "$1&nbsp;$2" + if ($c =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + + print "<td>$color$m</td>" + . "<td>$sp</td>\n" + . "<td>$color$a</td>" + . "<td>$sp</td>\n" + . "<td>$color$c</td>" + . "<td>$sp</td>\n" + . "<td>$color$s</td>" + . "<td>$sp</td>\n" + . "<td>$color$g</td>" + . "<td>$sp</td>\n" + . "<td>$color$u</td>" + . "<td>$sp</td>\n"; + + print "<td>"; + if ($i_int >= $Fs::first_meta{$ftype}) { + print "<a href=\"$iurl\" target=\"_top\">"; + print "$lcolor$i</a>"; + } + else { + print "$color$i"; + } + print " (realloc)" if $r; + print "</td></tr>\n"; + } + else { + print "Error Parsing File (invalid characters?)<br>: $_\n<br>"; + } + + $row++; + } + close(OUT); + print "</table>\n"; + + print "<center>No files found with that pattern</center>\n" + if ($row == 0); + + Print::print_html_footer(); + return 0; +} + +# display deleted files only +# +# Sorting should be added to this +sub file_list_del { + Args::check_sort(); + Args::check_dirmode(); + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $mnt = $Caseman::vol2mnt{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $meta = $Fs::root_meta{$ftype}; + my $sort = Args::get_sort(); + my $dirmode = Args::get_dirmode(); + + Print::print_html_header("Deleted files on $Caseman::vol2sname{$vol} $mnt"); + + my $tz = ""; + $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); + + my $sp = "&nbsp;&nbsp;"; + + Print::log_host_inv("$Caseman::vol2sname{$vol}: Listing all deleted files"); + + local *OUT; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/fls' -f $ftype -ldr $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" + ); + + print "<b>All Deleted Files</b><p><hr>" + . "<table cellspacing=\"0\" cellpadding=\"2\" border=0>\n" + . "<tr valign=\"MIDDLE\" align=\"left\" " + . "background=\"$::YEL_PIX\">\n"; + + # Type + print "<th align=\"center\">&nbsp;&nbsp;Type&nbsp&nbsp;<br>" + . "dir&nbsp;/&nbsp;in</th>" + . "<td>$sp</td>\n"; + + # Name + print " <td><img border=\"0\" " + . "src=\"pict/file_h_nam_link.jpg\" " + . "width=\"50\" height=20 " + . "alt=\"File Name\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # Mod / Written + print " <td><img border=\"0\" "; + if ($Fs::mtime_str{$ftype} eq 'Modified') { + print "src=\"pict/file_h_mod_link.jpg\" " + . "width=\"62\" height=20 " + . "alt=\"Modified Time\">"; + } + else { + print "src=\"pict/file_h_wr_link.jpg\" " + . "width=\"60\" " + . "alt=\"Written Time\">"; + } + print "</td>\n" . "<td>$sp</td>\n"; + + # Access + print " <td><img border=\"0\" " + . "src=\"pict/file_h_acc_link.jpg\" " + . "width=\"66\" height=20 " + . "alt=\"Access Time\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # Change / Create + print " <td><img border=\"0\" "; + if ($Fs::ctime_str{$ftype} eq 'Changed') { + print "src=\"pict/file_h_chg_link.jpg\" " + . "width=\"62\" height=20 " + . "alt=\"Change Time\">"; + } + else { + print "src=\"pict/file_h_cre_link.jpg\" " + . "width=\"59\" height=20 " + . "alt=\"Create Time\">"; + } + print "</td>\n" . "<td>$sp</td>\n"; + + # Size + print " <td><img border=\"0\" " + . "src=\"pict/file_h_siz_link.jpg\" " + . "width=\"31\" height=20 " + . "alt=\"Size\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # UID + print " <td><img border=\"0\" " + . "src=\"pict/file_h_uid_link.jpg\" " + . "width=\"27\" height=20 " + . "alt=\"UID\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # GID + print " <td><img border=\"0\" " + . "src=\"pict/file_h_gid_link.jpg\" " + . "width=\"28\" height=20 " + . "alt=\"GID\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + # Meta + print " <td><img border=\"0\" " + . "src=\"pict/file_h_meta_link.jpg\" " + . "width=\"41\" height=20 " + . "alt=\"Meta\">" + . "</td>\n" + . "<td>$sp</td>\n"; + + my $row = 0; + while ($_ = Exec::read_pipe_line(*OUT)) { + + if ( +/^($::REG_MTYPE)\/($::REG_MTYPE)\s*(\*?)\s*($::REG_META)(\(realloc\))?:\t(.+?)\t($::REG_DATE)\t($::REG_DATE)\t($::REG_DATE)\t(\d+)\t(\d+)\t(\d+)$/o + ) + { + + # We have to remove the / from the beginning of the file name so + # save all values so they aren't lost + my $dt = $1; + my $it = $2; + my $d = $3; + my $i = $4; + my $r = 0; + $r = 1 if (defined $5); + my $n = $6; + my $m = $7; + my $a = $8; + my $c = $9; + my $s = $10; + my $g = $11; + my $u = $12; + + if ($n =~ /^\/(.*)/) { + $n = $1; + } + my $enc_n = Args::url_encode($n); + my $iurl = +"$::PROGNAME?mod=$::MOD_FRAME&submod=$::MOD_META&$Args::baseargs&meta=$i"; + my $i_int = $i; + $i_int = $1 if ($i =~ /(\d+)-\d+-\d+/); + + if (($row % 2) == 0) { + print "<tr valign=\"TOP\" bgcolor=\"$::BACK_COLOR\">\n"; + } + else { + print "<tr valign=\"TOP\" bgcolor=\"$::BACK_COLOR_TABLE\">\n"; + } + + print "<td align=\"center\"><font color=\"$::DEL_COLOR[$r]\">" + . "$dt&nbsp;/&nbsp;$it</td>" + . "<td>$sp</td>\n"; + + if ($it eq 'd') { + my $url = + "$::PROGNAME?mod=$::MOD_FILE&" + . "view=$File::FILE_LIST&$Args::baseargs&meta=$i" + . "&sort=$sort&dir=$enc_n&dirmode=$dirmode"; + + print "<td>"; + if ($i_int >= $Fs::first_meta{$ftype}) { + print "<a href=\"$url\" target=\"_self\">"; + } + print "<font color=\"$::DEL_COLOR[$r]\"><tt>" + . Print::html_encode($mnt . $n) + . "</tt></td>" + . "<td>$sp</td>\n"; + } + else { + my $url = + "$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_FR&" + . "$Args::baseargs&meta=$i&sort=$sort&dir=$enc_n" + . "&recmode=$File::REC_YES"; + + print "<td>"; + if (($i_int >= $Fs::first_meta{$ftype}) && ($it eq 'r')) { + print "<a href=\"$url\" target=\"content\">"; + } + print "<font color=\"$::DEL_COLOR[$r]\"><tt>" + . Print::html_encode($mnt . $n) + . "</tt></td>" + . "<td>$sp</td>\n"; + } + + $m = "$1&nbsp;$2" + if ($m =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + $a = "$1&nbsp;$2" + if ($a =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + $c = "$1&nbsp;$2" + if ($c =~ /($::REG_DAY\s+$::REG_TIME)\s+($::REG_ZONE2)/o); + + print "<td><font color=\"$::DEL_COLOR[$r]\">$m</td>" + . "<td>$sp</td>\n" + . "<td><font color=\"$::DEL_COLOR[$r]\">$a</td>" + . "<td>$sp</td>\n" + . "<td><font color=\"$::DEL_COLOR[$r]\">$c</td>" + . "<td>$sp</td>\n" + . "<td><font color=\"$::DEL_COLOR[$r]\">$s</td>" + . "<td>$sp</td>\n" + . "<td><font color=\"$::DEL_COLOR[$r]\">$g</td>" + . "<td>$sp</td>\n" + . "<td><font color=\"$::DEL_COLOR[$r]\">$u</td>" + . "<td>$sp</td>\n"; + + print "<td>"; + if ($i_int >= $Fs::first_meta{$ftype}) { + print "<a href=\"$iurl\" target=\"_top\">"; + } + print "<font color=\"$::DEL_COLOR[$r]\">$i</a>"; + print " (realloc)" if $r; + print "</td></tr>\n"; + } + else { + print "Error Parsing File (invalid characters?)<br>: $_\n<br>"; + } + + $row++; + } + close(OUT); + print "</table>\n"; + + print "<center>None</center>\n" + if ($row == 0); + + Print::print_html_footer(); + return 0; +} + +# Content Frame +# This creates two frames for the lower rhs frame +# +sub content_fr { + Print::print_html_header_frameset(""); + + my $meta = Args::get_meta('meta'); + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + print "<frameset rows=\"65,*\">\n"; + + my $recmode = $File::REC_NO; + + if (exists $Args::enc_args{'recmode'}) { + $recmode = $Args::enc_args{'recmode'}; + } + else { + + # We need to get the allocation status of this structure + my $meta_int = $meta; + $meta_int = $1 if ($meta_int =~ /(\d+)-\d+(-\d+)?/); + + local *OUT; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/ils' -f $ftype -e -o $offset -i $imgtype $img $meta_int" + ); + while ($_ = Exec::read_pipe_line(*OUT)) { + chop; + next unless ($_ =~ /^$meta/); + if ($_ =~ /^$meta\|f/) { + $recmode = $File::REC_YES; + } + elsif ($_ =~ /^$meta\|a/) { + $recmode = $File::REC_NO; + } + else { + Print::print_check_err("Error parsing ils output: $_"); + } + } + } + close(OUT); + + # Get the file type so we can show the thumb nails automatically + if ($recmode == $File::REC_YES) { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" + ); + } + else { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" + ); + } + + my $apptype = Exec::read_pipe_line(*OUT); + close(OUT); + + $apptype = "Error getting file type" + if ((!defined $apptype) || ($apptype eq "")); + + # The menu for the different viewing options + print "<frame src=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_MENU&" + . "$Args::baseargs&dir=$Args::enc_args{'dir'}" + . "&meta=$Args::enc_args{'meta'}&sort=$FIL_SORT_ASC&recmode=$recmode\">\n"; + + # Print the image thumbnail + if (($apptype =~ /image data/) || ($apptype =~ /PC bitmap data/)) { + print "<frame src=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT_IMG" + . "&$Args::baseargs&dir=$Args::enc_args{'dir'}" + . "&meta=$Args::enc_args{'meta'}" + . "&sort=$FIL_SORT_ASC&recmode=$recmode\" name=\"cont2\">\n</frameset>"; + } + else { + + # Where the actual content will be displayed + print "<frame src=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT" + . "&$Args::baseargs&dir=$Args::enc_args{'dir'}" + . "&meta=$Args::enc_args{'meta'}" + . "&sort=$FIL_SORT_ASC&recmode=$recmode\" name=\"cont2\">\n</frameset>"; + } + + Print::print_html_footer_frameset(); + return 0; +} + +# This is the index for the lower rhs frame +# Choose the content display type here +sub content_menu { + Args::check_sort(); + Args::check_recmode(); + + Print::print_html_header(""); + + my $meta = Args::get_meta('meta'); + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + my $recmode = Args::get_recmode(); + + # Get the file type + if ($recmode == $File::REC_YES) { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" + ); + } + else { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" + ); + } + + my $apptype = Exec::read_pipe_line(*OUT); + close(OUT); + + $apptype = "Error getting file type" + if ((!defined $apptype) || ($apptype eq "")); + + # We already have the path in the content window below, so save space + # print "<center><tt>$mnt$Args::args{'dir'}</tt>\n"; + print "<center>\n"; + + my $url = + "&$Args::baseargs&dir=$Args::enc_args{'dir'}" + . "&meta=$Args::enc_args{'meta'}&recmode=$recmode"; + + # Print the options for output display + print "<table cellspacing=\"0\" cellpadding=\"2\">\n<tr>\n" + . "<td>ASCII (<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT&" + . "sort=$FIL_SORT_ASC$url\" target=\"cont2\">display</a> - " + . "<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::REPORT&" + . "sort=$FIL_SORT_ASC$url\" target=\"_blank\">report</a>)</td>\n" + . "<td>*</td>\n" + . "<td>Hex (" + . "<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT&" + . "sort=$FIL_SORT_HEX$url\" target=\"cont2\">display</a> - " + . "<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::REPORT&" + . "sort=$FIL_SORT_HEX$url\" target=\"_blank\">report</a>)</td>\n" + . "<td>*</td>\n" + . "<td>ASCII Strings (" + . "<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::CONT&" + . "sort=$FIL_SORT_STR$url\" target=\"cont2\">display</a> - " + . "<a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::REPORT&" + . "sort=$FIL_SORT_STR$url\" target=\"_blank\">report</a>)</td>\n" + . "<td>*</td>\n" + . "<td><a href=\"$::PROGNAME?mod=$::MOD_FILE&view=$File::EXPORT&$url\">" + . "Export</a></td>\n"; + + # if the file is either image or HTML, then let them view it + if ( ($apptype =~ /image data/) + || ($apptype =~ /PC bitmap data/)) + { + print "<td>*</td>\n<td><a href=\"$::PROGNAME?" + . "mod=$::MOD_FILE&view=$File::CONT_IMG$url\"" + . "target=\"cont2\">View</a></td>\n"; + } + elsif ($apptype =~ /HTML document text/) { + print "<td>*</td>\n<td><a href=\"$::PROGNAME?" + . "mod=$::MOD_APPVIEW&view=$Appview::CELL_FRAME$url\"" + . "target=\"_blank\">View</a></td>\n"; + } + + print "<td>*</td>\n" + . "<td><a href=\"$::PROGNAME?mod=$::MOD_NOTES&view=$Notes::ENTER_FILE$url\" target=\"_blank\">" + . "Add Note</a></td>\n" + if ($::USE_NOTES == 1); + + print "</tr></table>\n"; + + print "File Type: $apptype\n"; + print + "<br><font color=\"$::DEL_COLOR[0]\">Deleted File Recovery Mode</font>\n" + if ($recmode == $File::REC_YES); + print "</center>\n"; + + Print::print_html_footer(); + return 0; +} + +# +# Display the actual content here +# +# NOTE: This has a media type of raw text +# +sub content { + Args::check_sort(); + Args::check_recmode(); + + Print::print_text_header(); + + my $sort = Args::get_sort(); + my $meta = Args::get_meta('meta'); + my $vol = Args::get_vol('vol'); + my $mnt = $Caseman::vol2mnt{$vol}; + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $recflag = ""; + $recflag = " -r " if (Args::get_recmode() == $File::REC_YES); + + my $fname = "$mnt$Args::args{'dir'}"; + $fname =~ s/\/\//\//g; + + local *OUT; + if ($sort == $FIL_SORT_ASC) { + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Viewing $fname ($meta) as ASCII"); + + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" + ); + + print "Contents Of File: $fname\n\n\n"; + Print::print_output($_) + while ($_ = Exec::read_pipe_data(*OUT, 1024)); + close(OUT); + } + elsif ($sort == $FIL_SORT_HEX) { + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Viewing $fname ($meta) as Hex"); + + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" + ); + + print "Hex Contents Of File: $fname\n\n\n"; + my $offset = 0; + while ($_ = Exec::read_pipe_data(*OUT, 1024)) { + Print::print_hexdump($_, $offset * 1024); + $offset++; + } + close(OUT); + } + elsif ($sort == $FIL_SORT_STR) { + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Viewing $fname ($meta) as strings"); + + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a" + ); + + print "ASCII String Contents Of File: $fname\n\n\n\n"; + Print::print_output($_) + while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + } + + Print::print_text_footer(); + + return 0; +} + +sub content_img { + + Print::print_html_header("image content"); + + my $vol = Args::get_vol('vol'); + my $mnt = $Caseman::vol2mnt{$vol}; + my $fname = "$mnt$Args::args{'dir'}"; + $fname =~ s/\/\//\//g; + + my $url = + "&$Args::baseargs&meta=$Args::enc_args{'meta'}" + . "&dir=$Args::enc_args{'dir'}&" + . "cell_mode=2&recmode=$Args::enc_args{'recmode'}"; + + print "<tt>$fname</tt><br><br>\n" + . "<table><tr>\n" + . "<td width=250 align=\"center\">" + . "<b>Thumbnail:</b><br>" + . "<img src=\"$::PROGNAME?mod=$::MOD_APPVIEW&view=$Appview::CELL_CONT${url}\" width=\"200\"></td>\n" + . "<td valign=top>" + . "<a href=\"$::PROGNAME?mod=$::MOD_APPVIEW&view=$Appview::CELL_CONT${url}\" " + . "target=_blank>View Full Size Image</a><br>\n</td>\n" + . "</tr></table>\n"; + + Print::print_html_footer(); + + return 0; +} + +# Export the contents of a file +sub export { + + my $meta = Args::get_meta('meta'); + my $vol = Args::get_vol('vol'); + my $mnt = $Caseman::vol2mnt{$vol}; + + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $fname = "$mnt$Args::args{'dir'}"; + $fname =~ s/\/\//\//g; + + my $recflag = ""; + + $recflag = " -r " + if ( (exists $Args::enc_args{'recmode'}) + && ($Args::enc_args{'recmode'} == $File::REC_YES)); + + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Saving contents of $fname ($meta)"); + + local *OUT; + Exec::exec_pipe(*OUT, + "'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" + ); + + # We can't trust the mnt and dir values (since there + # could be bad ASCII values, so only allow basic chars into name + $fname =~ tr/a-zA-Z0-9\_\-\@\,/\./c; + $fname = $1 if ($fname =~ /^\.(.*)$/); + + Print::print_oct_header("$vol-${fname}"); + + print "$_" while ($_ = Exec::read_pipe_data(*OUT, 1024)); + + Print::print_oct_footer(); + + return 0; +} + +# Display a report for a file +# This is intended to have its own window +# +sub report { + Args::check_sort(); + + my $sort = Args::get_sort(); + my $vol = Args::get_vol('vol'); + my $meta = Args::get_meta('meta'); + my $mnt = $Caseman::vol2mnt{$vol}; + + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + my $type; + my $fname = "$mnt$Args::args{'dir'}"; + $fname =~ s/\/\//\//g; + my $tz = ""; + $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); + + my $recflag = ""; + + $recflag = " -r " + if ( (exists $Args::enc_args{'recmode'}) + && ($Args::enc_args{'recmode'} == $File::REC_YES)); + + # We can't trust the mnt and dir values (since there + # could be bad ASCII values, so only allow basic chars into name + $fname =~ tr/a-zA-Z0-9\_\-\@\,/\./c; + $fname = $1 if ($fname =~ /^\.+(.*)$/); + $fname = $1 if ($fname =~ /^(.*?)\.+$/); + + Print::print_text_header("filename=$Args::args{'vol'}-${fname}.txt"); + + $fname = "$mnt$Args::args{'dir'}"; + if ($sort == $FIL_SORT_ASC) { + Print::log_host_inv( +"$Caseman::vol2sname{$vol}: Generating ASCII report for $fname ($meta)" + ); + $type = "ASCII"; + } + elsif ($sort == $FIL_SORT_HEX) { + Print::log_host_inv( + "$Args::args{'vol'}: Generating Hex report for $fname ($meta)"); + $type = "Hex"; + } + elsif ($sort == $FIL_SORT_STR) { + Print::log_host_inv( +"$Args::args{'vol'}: Generating ASCII strings report for $fname ($meta)" + ); + $type = "string"; + } + else { + print "\n\ninvalid sort value"; + return 1; + } + + # NOTE: There is a space in the beginning of the separator lines in + # order to make clear@stamper.itconsult.co.uk time stamping happy + # I think it confuses the lines that begin at the lhs with PGP + # headers and will remove the second line. + # + print " Autopsy $type Report\n\n" + . "-" x 70 . "\n" + . " GENERAL INFORMATION\n\n" + . "File: $fname\n"; + + # Calculate the MD5 value + local *OUT; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::MD5_EXE'" + ); + my $md5 = Exec::read_pipe_line(*OUT); + close(OUT); + + $md5 = "Error getting MD5 Value" + if ((!defined $md5) || ($md5 eq "")); + + chomp $md5; + if ($recflag eq "") { + print "MD5 of file: $md5\n"; + } + else { + print "MD5 of recovered file: $md5\n"; + } + + if ($::SHA1_EXE ne "") { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -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 "")); + + chomp $sha1; + if ($recflag eq "") { + print "SHA-1 of file: $sha1\n"; + } + else { + print "SHA-1 of recovered file: $sha1\n"; + } + } + + if ($sort == $FIL_SORT_STR) { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a | '$::MD5_EXE'" + ); + $md5 = Exec::read_pipe_line(*OUT); + close(OUT); + + $md5 = "Error getting MD5 Value" + if ((!defined $md5) || ($md5 eq "")); + + chomp $md5; + print "MD5 of ASCII strings: $md5\n"; + + if ($::SHA1_EXE ne "") { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a | '$::SHA1_EXE'" + ); + $sha1 = Exec::read_pipe_line(*OUT); + close(OUT); + + $sha1 = "Error getting SHA-1 Value" + if ((!defined $sha1) || ($sha1 eq "")); + + chomp $sha1; + print "SHA-1 of ASCII strings: $sha1\n"; + } + } + + print "\nImage: $Caseman::vol2path{$vol}\n"; + if (($Caseman::vol2start{$vol} == 0) && ($Caseman::vol2end{$vol} == 0)) { + print "Offset: Full image\n"; + } + elsif ($Caseman::vol2end{$vol} == 0) { + print "Offset: $Caseman::vol2start{$vol} to end\n"; + } + else { + print "Offset: $Caseman::vol2start{$vol} to $Caseman::vol2end{$vol}\n"; + } + print "File System Type: $ftype\n"; + + my $date = localtime(); + print "\nDate Generated: $date\n" + . "Investigator: $Args::args{'inv'}\n\n" + . "-" x 70 . "\n" + . " META DATA INFORMATION\n\n"; + + # Get the meta details + Exec::exec_pipe(*OUT, +"'$::TSKDIR/istat' -f $ftype $tz -s $Caseman::ts -o $offset -i $imgtype $img $meta" + ); + print $_ while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + + # File Type + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::FILE_EXE' -z -b -" + ); + my $apptype = Exec::read_pipe_line(*OUT); + close(OUT); + + $apptype = "Error getting file type" + if ((!defined $apptype) || ($apptype eq "")); + + print "\nFile Type: $apptype"; + + print "\n" . "-" x 70 . "\n"; + if ($sort == $FIL_SORT_ASC) { + print " CONTENT (Non-ASCII data may not be shown)\n\n"; + } + else { + print " CONTENT\n\n"; + } + + if ($sort == $FIL_SORT_ASC) { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" + ); + Print::print_output($_) + while ($_ = Exec::read_pipe_data(*OUT, 1024)); + close(OUT); + } + elsif ($sort == $FIL_SORT_HEX) { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta" + ); + my $offset = 0; + while ($_ = Exec::read_pipe_data(*OUT, 1024)) { + Print::print_hexdump($_, $offset * 1024); + $offset++; + } + close(OUT); + } + elsif ($sort == $FIL_SORT_STR) { + Exec::exec_pipe(*OUT, +"'$::TSKDIR/icat' -f $ftype $recflag -o $offset -i $imgtype $img $meta | '$::TSKDIR/srch_strings' -a" + ); + Print::print_output($_) + while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + } + + print "\n" + . "-" x 70 . "\n" + . " VERSION INFORMATION\n\n" + . "Autopsy Version: $::VER\n"; + print "The Sleuth Kit Version: " . ::get_tskver() . "\n"; + + Print::print_text_footer(); + return 0; +} + +# Generate the MD5 value for every file in a given directory and save +# them to a text file +sub md5list { + my $vol = Args::get_vol('vol'); + my $meta = Args::get_meta('meta'); + my $mnt = $Caseman::vol2mnt{$vol}; + + my $ftype = $Caseman::vol2ftype{$vol}; + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $fname = "$mnt$Args::args{'dir'}"; + $fname = 'root' if ($fname eq '/'); + $fname =~ s/\/\//\//g; + + # We can't trust the mnt and dir values (since there + # could be bad ASCII values, so only allow basic chars into name + $fname =~ tr/a-zA-Z0-9\_\-\@\,/\./c; + + # remove .'s at beginning and end + $fname = $1 if ($fname =~ /^\.+(.*)$/); + $fname = $1 if ($fname =~ /^(.*?)\.+$/); + + Print::print_text_header("filename=$fname.md5"); + + $fname = "$mnt$Args::args{'dir'}"; + $fname =~ s/\/\//\//g; + + local *OUT; + Exec::exec_pipe(*OUT, + "'$::TSKDIR/fls' -f $ftype -Fu -o $offset -i $imgtype $img $meta"); + + print "MD5 Values for files in $fname ($Caseman::vol2sname{$vol})\n\n"; + + while ($_ = Exec::read_pipe_line(*OUT)) { + + # area for allocated files + if ( (/r\/[\w\-]\s+([\d\-]+):\s+(.*)$/) + || (/-\/r\s+([\d\-]+):\s+(.*)$/)) + { + my $in = $1; + my $name = $2; + + local *OUT_MD5; + Exec::exec_pipe(*OUT_MD5, +"'$::TSKDIR/icat' -f $ftype -r -o $offset -i $imgtype $img $in | '$::MD5_EXE'" + ); + my $md5out = Exec::read_pipe_line(*OUT_MD5); + + $md5out = "Error calculating MD5" + if ((!defined $md5out) || ($md5out eq "")); + + chomp $md5out; + print "$md5out\t" . Print::html_encode($name) . "\n"; + close(OUT_MD5); + } + elsif (/[\w\-]\/[\w\-]\s+([\d\-]+):\s+(.*)$/) { + + # ignore, non-file types such as sockets or symlinks that do not have + # MD5 values that make sense + } + + # Hmmmm + else { + print "Error parsing file (invalid characters?): $_\n"; + } + } + close(OUT); + + Print::print_text_footer(); + + return 0; +} + +# Blank Page +sub blank { + Print::print_html_header(""); + print "<br><center><h3>File Browsing Mode</h3><br>\n" + . "<p>In this mode, you can view file and directory contents.</p>\n" + . "<p>File contents will be shown in this window.<br>\n" + . "More file details can be found using the Metadata link at the end of the list (on the right).<br>\n" + . "You can also sort the files using the column headers</p>\n"; + Print::print_html_footer(); + return 0; +} + diff --git a/lib/Filesystem.pm b/lib/Filesystem.pm new file mode 100644 index 0000000000..935a22b11b --- /dev/null +++ b/lib/Filesystem.pm @@ -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; diff --git a/lib/Frame.pm b/lib/Frame.pm new file mode 100644 index 0000000000..20e107f457 --- /dev/null +++ b/lib/Frame.pm @@ -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> + + +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 < +






+ To start analyzing this volume, choose an analysis mode from the tabs above. + + +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 "
\n"; + + # Files + print "\n" . "\n" . "\n" . "\n" . "\n" . "\n" + . "\n"; + + # Close + print "\n"; + + print "
"; + if ($special == 0) { + + print +""; + + # Current + if ($submod == $::MOD_FILE) { + print ""; + } + + # Link + else { + print ""; + } + } + + # non-link + else { + print ""; + } + + # Search + print ""; + + print +""; + + if ($submod == $::MOD_KWSRCH) { + print ""; + } + else { + print ""; + } + + # File Type + print ""; + + if (($special == 0) && ($::LIVE == 0)) { + + print +""; + + # Current + if ($submod == $::MOD_APPSORT) { + print ""; + } + else { + print ""; + } + } + else { + print ""; + } + + # Image Details + print ""; + + if (($special == 0) || ($Caseman::vol2cat{$vol} eq "disk")) { + + print +""; + + if ($submod == $::MOD_FS) { + print ""; + } + else { + print ""; + } + } + else { + print ""; + } + + # Meta Data + print ""; + + if ($special == 0) { + print +""; + + if ($submod == $::MOD_META) { + print ""; + } + else { + print ""; + } + } + else { + print ""; + } + + # Data Units + print ""; + + print +""; + + # Current + if ($submod == $::MOD_DATA) { + print ""; + } + + # Link + else { + print ""; + } + + # Help - set to current mode + print "" + . "" + . "" + . "" + . "" + . "
\n"; + + Print::print_html_footer_tabs(); + return 0; +} diff --git a/lib/Fs.pm b/lib/Fs.pm new file mode 100644 index 0000000000..1e6edf8b32 --- /dev/null +++ b/lib/Fs.pm @@ -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; diff --git a/lib/Hash.pm b/lib/Hash.pm new file mode 100644 index 0000000000..640e38548e --- /dev/null +++ b/lib/Hash.pm @@ -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 "$_
\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 "$_
\n"; + } + close(OUT); +} + +# Manager/status Window from HOST Manager +sub db_manager { + Print::print_html_header("Hash Database Manager"); + + print < +To edit the location of the databases, you must manually edit the +host.aut file in the host directory. + +
+
+\"Alert +
+

Overview
+These files are known to be bad 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 "

Details
\n"; + if ($Caseman::alert_db eq "") { + print "Location: Not Configured
\n"; + } + elsif (-e "$Caseman::alert_db") { + print "Location: $Caseman::alert_db
\n"; + if (-e "$Caseman::alert_db" . "-md5.idx") { + print "Status: MD5 Index File Exists
\n"; + } + else { + print "Status: Database has not been MD5 indexed
\n"; + } + + # Index Button + print "

" + . "\"Index" + . "\n"; + + # Lookup Button + if (-e "$Caseman::alert_db" . "-md5.idx") { + print "

Lookup
" + . "

" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n\n" + . "\n" + . "\n
Enter MD5 Value: " + . "" + . "\n" + . "
\n" + . "
"; + } + } + else { + print "Location: $Caseman::alert_db
\n" + . "ERROR: Database not found
\n"; + } + + print < +
+\"Ignore +
+

Overview
+These files are known to be good 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 "

Details
\n"; + if ($Caseman::exclude_db eq "") { + print "Location: Not Configured
\n"; + } + elsif (-e "$Caseman::exclude_db") { + print "Location: $Caseman::exclude_db
\n"; + if (-e "$Caseman::exclude_db" . "-md5.idx") { + print "Status: MD5 Index File Exists
\n"; + } + else { + print "Status: Database has not been MD5 indexed
\n"; + } + + # Index Button + print "

" + . "\"Index" + . "\n"; + + # Lookup Button + if (-e "$Caseman::exclude_db" . "-md5.idx") { + print "

Lookup
" + . "

" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n\n" + . "\n" + . "\n
Enter MD5 Value: " + . "" + . "\n" + . "
\n" + . "
"; + } + } + else { + print "Location: $Caseman::exclude_db
\n" + . "ERROR: Database not found
\n"; + } + + print < +
+\"NSRL +
+

Overview
+These files are known to be good and bad. 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 "

Details
\n"; + if ($::NSRLDB eq "") { + print "Location: Not Configured
\n"; + } + elsif (-e "$::NSRLDB") { + print "Location: $::NSRLDB
\n"; + if (-e "$::NSRLDB" . "-md5.idx") { + print "Status: MD5 Index File Exists
\n"; + } + else { + print "Status: Database has not been MD5 indexed
\n"; + } + + # Index Button + print "

" + . "\"Index" + . "\n"; + + # Lookup Button + if (-e "$::NSRLDB" . "-md5.idx") { + print "

Lookup
" + . "

" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n\n" + . "\n" + . "\n
Enter MD5 Value: " + . "" + . "\n" + . "
\n" + . "
"; + } + } + else { + print "Location: $::NSRLDB
\n" + . "ERROR: Database not found
\n"; + } + + print <
+ + + + + +
+ + \"Close\" + + + + \"Help\" + +
+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 "
Exclude Database Indexing

\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 "


Alert Database Indexing

\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 "


NSRL Database Indexing

\n"; + index_nsrl(); + } + + print "

Indexing Complete
\n" + . "


\n\n" + . "\"Hash\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 "


NSRL Lookup

\n"; + + if (-e "$::NSRLDB") { + local *OUT; + Exec::exec_pipe(*OUT, + "'$::TSKDIR/hfind' '$::NSRLDB' $Args::args{'md5'}"); + print "$_
\n" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + Print::log_host_inv("NSRL Lookup ($Args::args{'md5'})"); + } + else { + print "NSRL Database Missing
\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 "


Exclude Database Lookup

\n"; + + if (-e "$Caseman::exclude_db") { + local *OUT; + Exec::exec_pipe(*OUT, + "'$::TSKDIR/hfind' '$Caseman::exclude_db' $Args::args{'md5'}"); + print "$_
\n" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + Print::log_host_inv("Exclude Database Lookup ($Args::args{'md5'})"); + } + else { + print "Exclude Database Missing
\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 "


Alert Database Lookup

\n"; + + if (-e "$Caseman::alert_db") { + local *OUT; + Exec::exec_pipe(*OUT, + "'$::TSKDIR/hfind' '$Caseman::alert_db' $Args::args{'md5'}"); + print "$_
\n" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + Print::log_host_inv("Alert Database Lookup ($Args::args{'md5'})"); + } + else { + print "Alert Database Missing
\n"; + Print::log_host_inv( + "Alert Database Lookup ($Args::args{'md5'}) - Database Missing" + ); + } + } + + print "


\n" + . "If any of the hash databases need to be re-indexed, use the " + . "Hash Database Manager

" + . "\n" + . "\"Hash\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 +"$Caseman::vol2sname{$sort[$i]}\n"; + + # It already exists, so make verify button + if (exists $md5s{$sort[$i]}) { + print "$md5s{$sort[$i]}" + . "

\n" + . "\n" + . Args::make_hidden() + . "\n" + . "\n" + . "\n" + . "
\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 +"Integrity checks for image type $Caseman::vol2itype{$sort[$i]} not yet supported\n"; + } + + # Generate New button + else { + print " " + . "
\n" + . "\n" + . Args::make_hidden() + . "\n" + . "\n" + . "\n" + . "
\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 "\n"; + + # Block List + print "\n" + . "\n" + . "\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 () { + 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: $_
\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 "
"; + + # image files + if (scalar @img > 0) { + print "\n"; + my @sort = sort { $a cmp $b } @img; + int_menu_print(\%md5s, \@sort); + } + + # Unallocated (blkls) images + if (scalar @blkls > 0) { + print "\n" + . "\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 "\n" + . "\n"; + my @sort = sort { $a cmp $b } @str; + int_menu_print(\%md5s, \@sort); + + } + + # timeline body files + if (scalar @body > 0) { + print "\n" + . "\n"; + my @sort = sort { $a cmp $b } @body; + int_menu_print(\%md5s, \@sort); + } + + # timeline files + if (scalar @tl > 0) { + print "\n" + . "\n"; + my @sort = sort { $a cmp $b } @tl; + int_menu_print(\%md5s, \@sort); + } + + print < +

+

" + . "\"Image" + . "
 
" + . "\"Unallocated" + . "
 
" + . "\"Strings" + . "
 
" + . "\"Timeline" + . "
 
" + . "\"Timelines\"" + . "
+ + + + + +
+ \"close\" + + + \"Refresh\" + + + + \"Help\" + +
+ +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
\n"; + return ""; + } + + while () { + 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: $_
\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 $Caseman::vol2sname{$vol} was not found
" + . "It can be calculated by pressing the button below." + . "

\n
\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n
"; + return 1; + } + + Print::log_host_inv("$Caseman::vol2sname{$vol}: Checking image integrity"); + + print "Original MD5: $md5
\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: $cur

\n"; + + if ($cur eq $md5) { + print "Pass
\n"; + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Image integrity check PASSED"); + } + else { + print "Fail: Restore from backup" + . "
\n"; + + Print::log_host_inv( + "$Caseman::vol2sname{$vol}: Image integrity check FAILED"); + } + Print::print_html_footer(); + return 0; + } + else { + print "$cur
\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 "
\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 "
\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 $Caseman::vol2sname{$vol}
\n"; + Print::log_host_inv("$Caseman::vol2sname{$vol}: Calculating MD5 value"); + + my $m = int_create_wrap($vol); + + print "MD5: $m
\n"; + print "
Value saved to host file

\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 () { + 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 () { + 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 "\n"; + Print::print_html_footer(); + return 0; +} diff --git a/lib/Kwsrch.pm b/lib/Kwsrch.pm new file mode 100644 index 0000000000..07b9347701 --- /dev/null +++ b/lib/Kwsrch.pm @@ -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 "

Keyword Search of Unallocated Space

\n"; + } + elsif ($ftype eq 'swap') { + print "

Keyword Search of swap partition

\n"; + } + elsif ($ftype eq 'raw') { + print "

Keyword Search of raw data

\n"; + } + elsif ($Caseman::vol2cat{$vol} eq "disk") { + print "

Keyword Search of disk

\n"; + } + else { + print +"

Keyword Search of Allocated and Unallocated Space

\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 "
\n" + . "Enter the keyword string or expression to search for:


\n" + . Args::make_hidden() + . "\n" + . "\n" + . "\n"; + + print "\n" + . "" + . "\n" + . "\n" + . "
" + . "ASCII \n" + . "Unicode
" + . "Case Insensitive\n" + . "grep Regular Expression
\n" + . "\n
\n"; + + if ($::LIVE == 0) { + print "\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 "\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 "\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 "\n"; + } + + # Unallocated Space Button + if ( ($Fs::is_fs{$ftype}) + && (!(exists $Caseman::vol2blkls{$vol}))) + { + print "\n"; + } + + print "
" + . "
\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n
" + . "
\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n
" + . "
\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n
" + . "
\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n
\n"; + } + + print "" + . "Regular Expression Cheat Sheet\n

\n"; + + print "

NOTE: The keyword search runs " + . "grep on the image.
\n" + . "A list of what will and " + . "what will not be found is available " + . "here.
\n"; + + # Section for previous searches + if ($::LIVE == 0) { + my $srch_name = get_srch_fname(0); + if (-e $srch_name) { + print "


Previous Searches

\n" . "\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 () { + 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 "\n" if ($row_idx == 0); + + print " \n"; + $row_idx = 0; + } + else { + $row_idx++; + } + } + print "
\n" + . "
\n" + . "\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden(); + + print "" + . "
\n"; + + if ($row_idx == 3) { + print "
\n"; + } + } + + # Predefined expressions from search.pl + print "

Predefined Searches

\n"; + print "\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 "\n" if ($row_idx == 0); + + # @@@ Make a unicode option in predefined + + print " \n"; + + if ($row_idx == 3) { + print "\n"; + $row_idx = 0; + } + else { + $row_idx++; + } + } + print "
\n" + . "
\n" + . "\n" + . "\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden(); + + if ($Kwsrch::auto_srch_reg{$r} == 1) { + print + "\n"; + } + if ($Kwsrch::auto_srch_csense{$r} == 0) { + print +"\n"; + } + print "
\n" . "
\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 "\n"; + + my $srch_case = ""; + $srch_case = "&srch_case=$Args::args{'srch_case'}" + if (exists $Args::args{'srch_case'}); + + my $regexp = ""; + $regexp = "®exp=$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 "\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 "\n"; + + # Block List + print "\n"; + } + + # Block Contents + print "\n" + . "\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
\n"; + return 1; + } + + my $srch_name = get_srch_fname($Args::args{'srchidx'}); + + print "New Search\n

"; + + 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
\n"; + print "New Search\n

"; + 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
\n"; + print "New Search\n

"; + 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 "Searching for ASCII: "; + } + else { + print "Searching for Unicode: "; + } + + # 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
\n"; + } + else { + print "Error parsing grep result: $_
\n"; + } + } + close(OUT); + + print " Done
"; + my $cnt = scalar(@results); + + my $srch_name = ""; + if ($::LIVE == 0) { + print "Saving: "; + + # 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 " Done
\n"; + } + if ($i == 0) { + print "$cnt hits"; + print "- link to results" if ($cnt > 0); + print "
\n"; + } + else { + print "$cnt hits"; + print "- link to results" if ($cnt > 0); + print "
\n"; + } + print "


\n"; + } + + print "New Search\n

"; + + 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 () { + + # 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 "


\n"; + if ($type == 0) { + print "\n"; + } + else { + print "\n"; + } + + if ($cnt == 0) { + print "$grep_str_html was not found
\n"; + } + elsif ($cnt == 1) { + print +"1 occurrence of $grep_str_html was found
\n"; + } + else { + print +"$cnt occurrences of $grep_str_html were found
\n"; + } + + print "Search Options:
\n"; + if ($type == 0) { + print "  ASCII
\n"; + } + else { + print "  Unicode
\n"; + } + + if ($grep_flag =~ /\-i/) { + print "  Case Insensitive
\n"; + } + else { + print "  Case Sensitive
\n"; + } + if ($grep_flag =~ /\-E/) { + print "  Regular Expression
\n"; + } + + print "
\n"; + + if ($cnt > 1000) { + print "There were more than 1000 hits.
\n"; + print "Please revise the search to a managable amount.\n"; + print + "

The $cnt hits can be found in: $srch_name
\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 "
\n$addr_str $blk (
Hex - " + . "" + . "Ascii"; + + print +" - Original" + if ( ($ftype eq 'blkls') + && (exists $Caseman::mod2vol{$vol})); + + print ")
"; + $prev = $blk; + } + + my $occ = $. - 1; + if ($str ne "") { + $str = Print::html_encode($str); + print "$occ: $off ($str)
\n"; + } + else { + print "$occ: $off
\n"; + } + } + + close(SRCH); + return 0; +} + +# Blank Page +sub blank { + Print::print_html_header(""); + print "\n"; + Print::print_html_footer(); + return 0; +} + +1; diff --git a/lib/Main.pm b/lib/Main.pm new file mode 100644 index 0000000000..88c39f67a7 --- /dev/null +++ b/lib/Main.pm @@ -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 "

\n"; + + # This problem has not been seen with the 1 second delay + if ((0) && ($] >= 5.008)) { + print +"

Warning: You are using Perl v5.8.
\n" + . " Some buffer problems have been reported with Autopsy and Perl 5.8 " + . "where output is not shown.
\n" + . "Perl 5.6 should be used if available.\n" + . "If data is missing, reload the page


\n"; + } + + print < + + + + Autopsy Forensic Browser $::VER + + + +   + + + + + Logo + + + + +   + + + + + http://www.sleuthkit.org/autopsy/ + + + +  + + + + \"Open + + + + + \"New + + + + + \"Help\" + + + + + +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; diff --git a/lib/Meta.pm b/lib/Meta.pm new file mode 100644 index 0000000000..69ac1032e6 --- /dev/null +++ b/lib/Meta.pm @@ -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 "\n"; + + # Print the frame where an addres can be entered and a frame for the + # contents + if (exists $Args::enc_args{'meta'}) { + print +"\n" + . "\n\n"; + } + else { + print +"\n" + . "\n\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 "
\n" + . "$Fs::meta_str{$ftype} Number:
    " + . "\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . + + # View Button + "

\n"; + + # Allocation List + print "

" + . "" + . "\"Allocation" + . "\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 "

\n"; + print +"" + . "\"previous\"\n" + unless ($prev < $Fs::first_meta{$ftype}); + + print +"" + . "\"next\"\n
"; + + # Report + print "\n" + . "\n"; + + # View (File Mode) + print "\n"; + + # Export + print ""; + + # Notes + print "" + if ($::USE_NOTES == 1); + + print "
" + . "\"report\"" + . "" + . "\"view" + . "" + . "\"export\"" + . "" + . "\"Add" + . "
\n
\n"; + + my $tmpr = $Caseman::vol2mnt{$vol}; + + if ($ftype =~ /fat/) { + print +"Search for File Name

"; + } + else { + + print "Pointed to by file:
\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("" + . Print::html_encode($tmpr . $2) + . " (deleted)

\n"); + } + elsif (/^\/(.*)$/) { + Print::print_output("" + . Print::html_encode($tmpr . $1) + . "

\n"); + } + else { + Print::print_output(Print::html_encode($_) . "

\n"); + } + $cnt++; + } + close(OUT); + if ($cnt == 0) { + print "
Invalid $Fs::meta_str{$ftype} value

\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 "File Type (Recovered):
$file_type
\n"; + } + else { + print "File Type:
$file_type

\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 "MD5 of recovered content:
$md5out

\n"; + } + else { + print "MD5 of content:
$md5out

\n"; + } + + # Hash Database Lookups + if ( + ( + ($::NSRLDB ne "") + || ($Caseman::alert_db ne "") + || ($Caseman::exclude_db ne "") + ) + && ($md5out =~ /^$::REG_MD5$/o) + ) + { + + print "
\n" + . Args::make_hidden() + . "\n" + . "\n" + . "\n" + . "\n"; + + if ($::NSRLDB ne "") { + print "\n"; + } + if ($Caseman::alert_db ne "") { + print "\n"; + } + if ($Caseman::exclude_db ne "") { + print "\n"; + } + print "
" + . "" + . "NSRL" + . "" + . "Alert Database" + . "" + . "Exclude Database" + . "" + . "
\n
\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 +"SHA-1 of recovered content:
$sha1out

\n"; + } + else { + print "SHA-1 of content:
$sha1out

\n"; + } + } + + # istat output + print "Details:

\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 "$_
\n"; + next; + } + elsif (/^Recover/) { + print "$_
\n"; + next; + } + elsif (/^Type: (\S+) \((\d+\-\d+)\) (.*)$/) { + print "$1 (" + . "$2) $3
\n"; + next; + } + + my $blk; + foreach $blk (split(/ /, $_)) { + if ($blk =~ /^\d+$/) { + print +"$blk "; + } + else { + print "$blk "; + } + } + print "
\n"; + } + else { + if (/^Not Allocated$/) { + print "$_
\n"; + } + else { + print "$_
\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 "
\n" + . Args::make_hidden() + . "\n" + . "\n" + . "\n" + . "\n"; + + print +"Enter number of $Fs::addr_unit{$ftype}s to display: \n"; + + print " (because the size is 0)\n
\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 "Pointed to by file:
\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("" + . Print::html_encode($tmpr . $2) + . " (deleted)
\n"); + } + elsif (/^\/(.*)$/) { + Print::print_output( + "" . Print::html_encode($tmpr . $1) . "
\n"); + } + else { + Print::print_output(Print::html_encode($_) . "
\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 -> $max"); + + Print::log_host_inv( +"$Caseman::vol2sname{$vol}: $Fs::meta_str{$ftype} Allocation List for $min to $max" + ); + + print "

$Fs::meta_str{$ftype}: $fmin - $max

"; + + # Display next and previous links + my $tmp; + if ($min > $Fs::first_meta{$ftype}) { + $tmp = $min - $ILS_GAP; + print +"" + . "\"previous\" "; + } + $tmp = $min + $ILS_GAP; + print +" " + . "\"next\"
"; + print "
\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 +"" + . "$1: "; + if ($2 eq "a") { + print "allocated
\n"; + } + else { + print "free
\n"; + } + } + } + close(OUT); + + # Display next and previous links + print "
\n"; + if ($min > $Fs::first_meta{$ftype}) { + $tmp = $min - $ILS_GAP; + print +"" + . "\"previous\" "; + } + $tmp = $min + $ILS_GAP; + print +" " + . "\"next\"
"; + print "
\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 "

Metadata Mode


\n" + . "Here you can view the details about any $Fs::meta_str{$ftype} in the file system.
\n" + . "These are the data structures that store the file details.
\n" + . "Enter the address in the field on the left.\n"; + Print::print_html_footer(); + return 0; +} + diff --git a/lib/Notes.pm b/lib/Notes.pm new file mode 100644 index 0000000000..b81efbeaa9 --- /dev/null +++ b/lib/Notes.pm @@ -0,0 +1,1110 @@ +# +# Notes and sequencer 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 Notes; + +use POSIX; + +$Notes::ENTER_FILE = 1; +$Notes::ENTER_DATA = 2; +$Notes::WRITE_FILE = 3; +$Notes::WRITE_DATA = 4; +$Notes::WRITE_SEQ_MAN = 5; +$Notes::READ_NORM = 6; +$Notes::READ_SEQ = 7; + +sub main { + + # There is no default for Notes + Args::check_view(); + + Print::print_check_error("Notes option is not enabled") + if ($::USE_NOTES == 0); + + my $view = Args::get_view(); + + if ($view == $Notes::ENTER_FILE) { + return enter_file(); + } + elsif ($view == $Notes::ENTER_DATA) { + return enter_data(); + } + elsif ($view == $Notes::WRITE_FILE) { + return write_file(); + } + elsif ($view == $Notes::WRITE_DATA) { + return write_data(); + } + elsif ($view == $Notes::WRITE_SEQ_MAN) { + return write_seq_man(); + } + elsif ($view == $Notes::READ_NORM) { + return read_norm(); + } + elsif ($view == $Notes::READ_SEQ) { + return read_seq(); + } + else { + Print::print_check_err("Invalid Notes View"); + } +} + +sub investig_notes_fname { + return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.notes"; +} + +sub investig_seq_notes_fname { + return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.seq.notes"; +} + +# window where user can enter a normal and sequencer note for a file +# or meta data structure. +sub enter_file { + Args::check_vol('vol'); + Args::check_meta('meta'); + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $mnt = $Caseman::vol2mnt{$vol}; + my $meta = Args::get_meta('meta'); + + # A file will have a 'dir' argument and a meta structure will not + if (exists $Args::args{'dir'}) { + my $fname = "$mnt$Args::args{'dir'}"; + Print::print_html_header("Notes for file $fname"); + print "
Enter a note for $fname ($meta):" + . "

\n"; + } + else { + Print::print_html_header("Notes for $Fs::meta_str{$ftype} $meta"); + print "
Enter a note for $Fs::meta_str{$ftype} $meta:" + . "

\n"; + } + print +"A note works like a bookmark and allows you to later find this data more easily.

\n"; + + # Setup the form + print "
\n" + . "
\n" + . "\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden(); + + print "\n" + if (exists $Args::args{'dir'}); + + # Option to add a normal note + print "\n" + . " Add a Standard Note
\n"; + + # Sequencer notes - which requires the MAC times for the files + if ("$Caseman::tz" ne "") { + $ENV{TZ} = $Caseman::tz; + POSIX: tzset(); + } + + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $meta_int = $meta; + $meta_int = $1 if ($meta_int =~ /^(\d+)-\d+(-\d+)?$/); + local *OUT; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/ils' -s $Caseman::ts -f $ftype -e -o $offset -i $imgtype $img $meta_int" + ); + + # Get the fourth line + my $tmp = Exec::read_pipe_line(*OUT); + $tmp = Exec::read_pipe_line(*OUT); + $tmp = Exec::read_pipe_line(*OUT); + $tmp = Exec::read_pipe_line(*OUT); + close(OUT); + unless ((defined $tmp) + && ($tmp =~ /^$::REG_META\|\w\|\d+\|\d+\|(\d+)\|(\d+)\|(\d+)\|/o)) + { + Print::print_err("Error parsing 'ils' output"); + } + + my $mtime = $1; + my $atime = $2; + my $ctime = $3; + + $mtime = localtime($mtime); + $atime = localtime($atime); + $ctime = localtime($ctime); + + # Print the Times + print "

Add a Sequencer Event:

\n" + . "A sequencer event will be sorted based on the time so that event reconstruction will be easier

\n" + . "" + . "  M-Time ($mtime)
\n" + . "" + . "  A-Time ($atime)
\n" + . "" + . "  C-Time ($ctime)


\n"; + + # The OK Button + print "
\n
\n"; + + Print::print_html_footer(); + return 0; +} + +# data unit comment +sub enter_data { + Args::check_vol('vol'); + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $block = Args::get_block(); + my $len = Args::get_len(); + + Print::print_html_header("Notes for $Fs::addr_unit{$ftype} $block"); + + print + "
Enter a note for $Fs::addr_unit{$ftype} $block

\n" + . "A note works like a bookmark and allows you to later find this data more easily.

\n" + . "
\n" + . "
\n" + . "\n" + . "\n" + . "\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "
\n
\n"; + + Print::print_html_footer(); + return 0; + +} + +# Write the note to the note file +sub write_data { + Args::check_vol('vol'); + Args::check_block(); + Args::check_len(); + Args::check_note(); + + Print::print_html_header("Write a note"); + + my $vol = Args::get_vol('vol'); + my $ftype = $Caseman::vol2ftype{$vol}; + my $img_sh = $Caseman::vol2sname{$vol}; + my $block = Args::get_block(); + my $len = Args::get_len(); + + Print::log_host_inv( + "$img_sh: Creating note for $Fs::addr_unit{$ftype} $block"); + + my $notes_file = investig_notes_fname(); + open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; + print "Note added to $notes_file:

\n\n"; + + # Date + my $tmp = localtime(); + print NOTES "$tmp\n"; + print "$tmp
\n"; + + print NOTES "Volume: $vol $Fs::addr_unit{$ftype}: $block Len: $len\n"; + print "Volume: $vol $Fs::addr_unit{$ftype}: $block Len: $len
\n"; + + # The actual notes and a line at the bottom + print NOTES "\n$Args::args{'note'}\n\n" . "-" x 70 . "\n"; + print "

$Args::args{'note'}

"; + + close(NOTES); + + print "


\n" + . "You can view the notes from the Host Manager View

" + . "" + . "\"View\n"; + + Print::print_html_footer(); + + return 0; +} + +sub write_file { + Args::check_vol('vol'); + Args::check_meta('meta'); + Args::check_note(); + + # Get rid of carriage returns that Netscape adds + $Args::args{'note'} =~ tr/\r//d; + + my $vol = Args::get_vol('vol'); + my $mnt = $Caseman::vol2mnt{$vol}; + + my $ftype = $Caseman::vol2ftype{$vol}; + my $img_sh = $Caseman::vol2sname{$vol}; + my $meta = Args::get_meta('meta'); + + my $img = $Caseman::vol2path{$vol}; + my $offset = $Caseman::vol2start{$vol}; + my $imgtype = $Caseman::vol2itype{$vol}; + + my $fname = ""; + my $type = ""; + + if (exists $Args::args{'dir'}) { + $Args::args{'dir'} .= "/" + if ($Args::args{'dir'} eq ""); + $fname = "$mnt$Args::args{'dir'}"; + + if (($Args::args{'dir'} =~ /\/$/) || ($Args::args{'dir'} eq "")) { + Print::log_host_inv( + "$img_sh: Creating note for directory $fname ($meta)"); + $type = "dir"; + } + else { + Print::log_host_inv( + "$img_sh: Creating note for file $fname ($meta)"); + $type = "file"; + } + } + + else { + Print::log_host_inv( + "$img_sh: Creating note for $Fs::meta_str{$ftype} $meta"); + $type = "$Fs::meta_str{$ftype}"; + } + + Print::print_html_header("Writing a note / event"); + + # Get the times for the meta + # Set the timezone to the host zone + if ("$Caseman::tz" ne "") { + $ENV{TZ} = "$Caseman::tz"; + POSIX::tzset(); + } + + my $meta_int = $meta; + $meta_int = $1 if ($meta_int =~ /^(\d+)-\d+(-\d+)?$/); + local *OUT; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/ils' -s $Caseman::ts -f $ftype -e -o $offset -i $imgtype $img $meta_int" + ); + + # Skip to the fourth line + my $tmp = Exec::read_pipe_line(*OUT); + $tmp = Exec::read_pipe_line(*OUT); + $tmp = Exec::read_pipe_line(*OUT); + $tmp = Exec::read_pipe_line(*OUT); + unless ((defined $tmp) + && ($tmp =~ /^$::REG_META\|\w\|\d+\|\d+\|(\d+)\|(\d+)\|(\d+)\|/o)) + { + Print::print_err("Error parsing 'ils' output"); + } + my $mtime = $1; + my $atime = $2; + my $ctime = $3; + close(OUT); + + # Create a "normal" note + if ((exists $Args::args{'norm_note'}) && ($Args::args{'norm_note'} == 1)) { + + my $notes_file = investig_notes_fname(); + open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; + print "Note added to $notes_file:

\n\n"; + + # Date + my $tmp = localtime(); + print NOTES "$tmp\n"; + print "$tmp\n"; + + # We have a file name + if ($fname ne "") { + if ($type eq 'dir') { + print NOTES "Directory: $fname\n"; + print "Directory: $fname
\n"; + } + else { + print NOTES "File: $fname\n"; + print "File: $fname
\n"; + } + } + if ($meta ne "") { + print NOTES "Volume: $vol Meta: $meta\n"; + print "Volume: $vol Meta: $meta
\n"; + } + print NOTES "M-time: " . localtime($mtime) . "\n"; + print "M-time: " . localtime($mtime) . "
\n"; + print NOTES "A-time: " . localtime($atime) . "\n"; + print "A-time: " . localtime($atime) . "
\n"; + print NOTES "C-time: " . localtime($ctime) . "\n"; + print "C-time: " . localtime($ctime) . "
\n"; + + # The actual notes and a line at the bottom + print NOTES "\n$Args::args{'note'}\n\n" . "-" x 70 . "\n"; + print "

$Args::args{'note'}

"; + + close(NOTES); + } + + # Create a sequencer event - if there are any + unless (((exists $Args::args{'mtime'}) && ($Args::args{'mtime'} == 1)) + || ((exists $Args::args{'atime'}) && ($Args::args{'atime'} == 1)) + || ((exists $Args::args{'ctime'}) && ($Args::args{'ctime'} == 1))) + { + + print "


\n" + . "You can view the notes from the Host Manager View

" + . "" + . "\"View\n"; + + Print::print_html_footer(); + + return 0; + } + + # Get rid of the carriage returns + $Args::args{'note'} =~ s/\n/
/gs; + + my $notes_file = investig_seq_notes_fname(); + open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; + + if ((exists $Args::args{'mtime'}) && ($Args::args{'mtime'} == 1)) { + + my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = + localtime($mtime); + $year += 1900; + $mon += 1; + $mday = "0$mday" if ($mday < 10); + $hour = "0$hour" if ($hour < 10); + $min = "0$min" if ($min < 10); + $sec = "0$sec" if ($sec < 10); + + print NOTES "'$year','$mon','$mday','$hour','$min','$sec'," + . "'$Args::args{'host'}','$vol','$fname','$meta',''," + . "'$type','[M-Time]$Args::args{'note'}'\n"; + + Print::log_host_inv( + "$img_sh: M-Time note added for meta $Args::args{'meta'}"); + print "M-Time sequence event added
\n"; + } + + if ((exists $Args::args{'atime'}) && ($Args::args{'atime'} == 1)) { + my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = + localtime($atime); + $year += 1900; + $mon += 1; + $mday = "0$mday" if ($mday < 10); + $hour = "0$hour" if ($hour < 10); + $min = "0$min" if ($min < 10); + $sec = "0$sec" if ($sec < 10); + + print NOTES "'$year','$mon','$mday','$hour','$min','$sec'," + . "'$Args::args{'host'}','$vol','$fname','$meta',''," + . "'$type','[A-Time]$Args::args{'note'}'\n"; + + Print::log_host_inv( + "$img_sh: A-Time note added for meta $Args::args{'meta'}"); + print "A-Time sequence event added
\n"; + } + + if ((exists $Args::args{'ctime'}) && ($Args::args{'ctime'} == 1)) { + my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = + localtime($ctime); + $year += 1900; + $mon += 1; + $mday = "0$mday" if ($mday < 10); + $hour = "0$hour" if ($hour < 10); + $min = "0$min" if ($min < 10); + $sec = "0$sec" if ($sec < 10); + + print NOTES "'$year','$mon','$mday','$hour','$min','$sec'," + . "'$Args::args{'host'}','$vol','$fname','$meta',''," + . "'$type','[C-Time]$Args::args{'note'}'\n"; + + Print::log_host_inv( + "$img_sh: C-Time note added for meta $Args::args{'meta'}"); + print "C-Time sequence event added
\n"; + } + + close(NOTES); + + print "


\n" + . "You can view the notes and events from the Host Manager View

"; + + if ((exists $Args::args{'norm_note'}) && ($Args::args{'norm_note'} == 1)) { + print +"" + . "\"View\n"; + } + + print +"" + . "\"Event\n"; + + Print::print_html_footer(); + + return 0; +} + +# Display the contents of the "normal" notes file +sub read_norm { + Print::print_html_header("Contents of Notes File"); + + my $notes_file = investig_notes_fname(); + + Print::log_host_inv("Viewing contents of notes file ($notes_file)"); + if ((!(-e "$notes_file")) || (-z "$notes_file")) { + print "No notes have been entered yet.
\n" + . "They can be entered using the Add Note link within each analysis mode.
\n"; + return; + } + + open NOTES, "<$notes_file" or die "Can't open log: $notes_file"; + + my $file = ""; + my $dir = ""; + + print "\n" + . "\n\n
\n"; + + my $row = 0; + + # This will need to change whenever the log format changes + while () { + + # we need to extract mnt from here + $file = $1 if (/^File: (.*)$/); + $dir = $1 if (/^Directory: (.*)$/); + + # Reset the $file if we are at the end of the current note + if (/^\-+$/) { + $file = ""; + $dir = ""; + if (($row++ % 2) == 0) { + print +"
\n"; + } + else { + print "
\n"; + } + } + else { + print "$_
"; + } + + if (/^Volume: ($::REG_VNAME) Meta: ([0-9\-]+)/o) { + $vol = $1; + $meta = $2; + next unless (exists $Caseman::vol2cat{$vol}); + + # file note + if ($file ne "") { + + # extract the prepended mnt value + my $mnt = $Caseman::vol2mnt{$vol}; + my $fname = ""; + $fname = $1 if ($file =~ /^$mnt\/?(.*)$/); + print "" + . "\"view\"
\n"; + } + + # directory note + elsif ($dir ne "") { + + # extract the prepended mnt value + my $mnt = $Caseman::vol2mnt{$vol}; + my $fname = ""; + $fname = $1 if ($dir =~ /^$mnt\/?(.*)$/); + print "" + . "\"view\"
\n"; + + } + + # meta note + else { + print "" + . "\"view\"
\n"; + + } + } + + # block note + elsif (/^Volume: ($::REG_VNAME) \w+: ([0-9]+) Len: (\d+)/o) { + $vol = $1; + $blk = $2; + $len = $3; + next unless (exists $Caseman::vol2cat{$vol}); + + print "" + . "\"view\"
\n"; + + } + } + + print "
\n"; + + # Ok and refresh buttons + print "

\n" + . "
\n" + . "" + . "\"close\"\n" + . "\n" + . "" + . "\"refresh\"\n" + . "
\n"; + + close(NOTES); + + Print::print_html_footer(); + + return 0; +} + +######################################################################### +# Sequencer Code + +# Write a sequence event that was manually entered +sub write_seq_man { + + Args::check_note(); + + Print::print_html_header("Writing Sequencer Event"); + + # Get rid of carriage returns that Netscape adds + $Args::args{'note'} =~ tr/\r//d; + $Args::args{'note'} =~ s/\n/
/gs; + + if ($Args::args{'note'} eq "") { + print( "A comment must be given for the event
\n" + . "

" + . ""); + Print::print_err("\n"); + } + + # Check the args and add them to the final string that will be written + my $str = ""; + unless ((exists $Args::args{'year'}) + && ($Args::args{'year'} =~ /^(\d\d\d\d)$/)) + { + Print::print_err("Invalid year"); + } + $str .= "'$1',"; + + unless ((exists $Args::args{'mon'}) && ($Args::args{'mon'} =~ /^(\d\d?)$/)) + { + Print::print_err("Invalid month"); + } + $str .= "'$1',"; + + unless ((exists $Args::args{'day'}) && ($Args::args{'day'} =~ /^(\d\d?)$/)) + { + Print::print_err("Invalid day"); + } + $str .= "'$1',"; + + unless ((exists $Args::args{'hour'}) + && ($Args::args{'hour'} =~ /^(\d\d?)$/)) + { + Print::print_err("Invalid hour"); + } + $str .= "'$1',"; + + unless ((exists $Args::args{'min'}) && ($Args::args{'min'} =~ /^(\d\d?)$/)) + { + Print::print_err("Invalid min"); + } + $str .= "'$1',"; + + unless ((exists $Args::args{'sec'}) && ($Args::args{'sec'} =~ /^(\d\d?)$/)) + { + Print::print_err("Invalid sec"); + } + $str .= "'$1',"; + + # There are no image, meta, file name, or data unit for this type + $str .= "'$Args::args{'host'}','','','','',"; + + unless ((exists $Args::args{'src'}) && ($Args::args{'src'} =~ /^(\w+)$/)) { + Print::print_err("Invalid src"); + } + $str .= "'$1','$Args::args{'note'}'\n"; + + # Write the string to the notes file + my $notes_file = investig_seq_notes_fname(); + open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; + print NOTES $str; + close(NOTES); + + # Send a message to the user + print "Event Added to Sequencer file:

\n" + . "$::d2m[$Args::args{'mon'}] $Args::args{'day'}, $Args::args{'year'} " + . "$Args::args{'hour'}:$Args::args{'min'}:$Args::args{'sec'}

\n" + . "$Args::args{'note'}
\n" + . "

" + . "\"Ok\"\n"; + + Print::print_html_footer(); + return 0; +} + +# View the sequencer file +sub read_seq { + + Print::print_html_header("Event Sequencer"); + + print "

\n" . "

Event Sequencer

\n"; + + my $cnt = 0; + my @entry; + my ( + @year, @mon, @day, @hour, @min, @sec, @host, + @vol, @fname, @meta, @data, @type, @note + ); + + # Read the sequencer file into arrays that will be sorted + my $notes_file = investig_seq_notes_fname(); + if (-e $notes_file) { + + open NOTES, "$notes_file" or die "Can't open log: $notes_file"; + while () { + + unless ( +/^'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?($::REG_HOST)'?,'?($::REG_VNAME)?'?,'?(.*?)'?,'?($::REG_META)?'?,'?(\d+)?'?,'?([\w\s]+)'?,'?(.*?)'?$/ + ) + { + Print::print_err("Error parsing sequence event entry: $_"); + } + + $year[$cnt] = $1; + $mon[$cnt] = $2; + $day[$cnt] = $3; + $hour[$cnt] = $4; + $min[$cnt] = $5; + $sec[$cnt] = $6; + $host[$cnt] = $7; + $vol[$cnt] = $8; + $fname[$cnt] = ""; + $fname[$cnt] = $9 if (defined $9); + $meta[$cnt] = ""; + $meta[$cnt] = $10 if (defined $10); + $data[$cnt] = ""; + $data[$cnt] = $11 if (defined $11); + $type[$cnt] = $12; + $note[$cnt] = $13; + + $entry[$cnt] = $cnt; + $cnt++; + } + + close(NOTES); + + # Sort the values by date, source, and then note + my @sorted = sort { + $year[$a] <=> $year[$b] + or $mon[$a] <=> $mon[$b] + or $day[$a] <=> $day[$b] + or $hour[$a] <=> $hour[$b] + or $min[$a] <=> $min[$b] + or $sec[$a] <=> $sec[$b] + or lc($type[$a]) cmp lc($type[$b]) + or lc($note[$a]) cmp lc($note[$b]) + } @entry; + + # Table and header + print "\n" + . "\n" + . "\n" + . "\n" + . "\n"; + + # Cycle through the sorted events + my $row = 0; + foreach my $i (@sorted) { + + # Alternate row colors + if (($row % 2) == 0) { + print "\n"; + } + else { + print "\n"; + } + + # Date & Time + print "" + . "\n"; + + # Print the actual note + $note[$i] = " " if ($note[$i] eq ""); + print "\n"; + + $row++; + } + + print "
Date & TimeSourceEvent & Note
\n" + . "$::d2m[$mon[$i]] $day[$i], $year[$i]" + . " $hour[$i]:$min[$i]:$sec[$i]\n"; + + # If there is as name, then we will show it + # @@@ Why does an error message come up from here: + # Use of uninitialized value in string ne at + if ($fname[$i] ne "") { + + if ( (exists $vol[$i]) + && (defined $vol[$i]) + && ($vol[$i] ne "") + && (exists $Caseman::vol2mnt{$vol[$i]}) + && (exists $meta[$i])) + { + + # extract the prepended mnt value + my $mnt = $Caseman::vol2mnt{$vol[$i]}; + my $fname = ""; + $fname = $1 if ($fname[$i] =~ /^$mnt\/?(.*)$/); + + # Check if it is a directory + if ($type[$i] eq 'dir') { + print "\n" + . "$fname[$i]\n"; + } + else { + print "\n" + . "$fname[$i]\n"; + } + } + else { + print "$fname[$i]\n"; + } + } + + # Display the meta value if there was no name + elsif (($vol[$i] ne "") && (defined $meta[$i]) && ($meta[$i] ne "")) + { + my $ftype = $Caseman::vol2ftype{$vol[$i]}; + + # Include a link if we can + if (exists $Caseman::vol2mnt{$vol[$i]}) { + print "\n" + . "$Fs::meta_str{$ftype}: $meta[$i]\n"; + } + else { + print "$Fs::meta_str{$ftype}: $meta[$i]\n"; + } + } + + # Otherwise, just give the source type + else { + print "$type[$i]\n"; + } + print "$note[$i]
\n"; + + } + + # End of if file exists + else { + print "No events currently exist
\n"; + } + + # Ok and refresh buttons + print "

\n" + . "
\n" + . "" + . "\"close\"\n" + . "\n" + . "" + . "\"refresh\"\n" + . "
\n"; + + # Manually add a new event + print "


\n" + . "Add a New Event

\n" + . "
\n" + . "
\n" + . "\n" + . "\n" + . Args::make_hidden(); + + # Month + print "\n" . "\n"; + + # Type + print "\n" + . "\n"; + + print +"
\n"; + print "

Date: " . "\n"; + + # Day + print " \n"; + + # Year + $prev = 1900 + (localtime())[5]; + $prev = $Args::args{'year'} + if ((exists $Args::args{'year'}) && ($Args::args{'year'} =~ /^\d+$/)); + + print " \n"; + + # Hour + print "  \n"; + + # Min + print ":\n"; + + # Sec + print ":

 
Event Source:
 
\n
\n"; + + Print::print_html_footer(); + return 0; +} + +# Conver the 'image' format to the 'volume' format +sub convert { + my %img2vol = %{shift()}; + + my @invs = Caseman::read_invest(); + if (scalar @invs == 0) { + push @invs, "unknown"; + } + + foreach $i (@invs) { + my $notes_file = "$::host_dir" . "$::LOGDIR/$i.notes"; + + if ((!(-e "$notes_file")) || (-z "$notes_file")) { + next; + } + Print::log_host_info( + "Converting format of notes file for $i ($notes_file)"); + + open NOTES, "<$notes_file" or die "Can't open log: $notes_file"; + + my $notes_file_new = $notes_file . ".new"; + open NOTES_NEW, ">$notes_file_new" + or die "Can't open writing log: $notes_file_new"; + + while () { + + if (/Image: ($::REG_IMG)\s+(.*)$/) { + my $img = $1; + my $addr = $2; + + unless (exists $img2vol{$img}) { + print STDERR +"Error finding image during notes conversion: $img. Not converting\n"; + next; + } + my $vol = $img2vol{$img}; + + # Convert old description to last versions + $addr =~ s/Inode:/Meta:/; + print NOTES_NEW "Volume: $vol $addr\n"; + } + else { + print NOTES_NEW $_; + } + } + + close(NOTES); + close(NOTES_NEW); + rename $notes_file, $notes_file . ".bak"; + rename $notes_file_new, $notes_file; + } + + # NOw do sequence notes + foreach $i (@invs) { + my $notes_file = "$::host_dir" . "$::LOGDIR/$i.seq.notes"; + if ((!(-e "$notes_file")) || (-z "$notes_file")) { + next; + } + + open NOTES, "$notes_file" or die "Can't open log: $notes_file"; + + $notes_file_new = $notes_file . ".new"; + open NOTES_NEW, ">$notes_file_new" + or die "Can't open log for updating: $notes_file_new"; + + while () { + + # No image in entry + if (/^'\d+','\d+','\d+','\d+','\d+','\d+','$::REG_HOST','','/) { + print NOTES_NEW $_; + } + elsif ( +/^('\d+','\d+','\d+','\d+','\d+','\d+','$::REG_HOST',')($::REG_IMG)(','.*)$/ + ) + { + my $pre = $1; + my $img = $2; + my $post = $3; + unless (exists $img2vol{$img}) { + print STDERR +"Error finding image during notes conversion: $img. Not converting\n"; + next; + } + my $vol = $img2vol{$img}; + print NOTES_NEW $pre . $vol . $post . "\n"; + } + else { + print NOTES_NEW "$_"; + return; + } + } + + close(NOTES); + close(NOTES_NEW); + rename $notes_file, $notes_file . ".bak"; + rename $notes_file_new, $notes_file; + } + + return 0; +} diff --git a/lib/Print.pm b/lib/Print.pm new file mode 100644 index 0000000000..6b702966a2 --- /dev/null +++ b/lib/Print.pm @@ -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
\n +sub html_encode { + my $text = shift; + $text =~ s/&/&/gs; + $text =~ s//>/gs; + $text =~ s/\"/"/gs; + $text =~ s/\n/
\n/gs; + + # @@@ LEADING SPACES and TABS + # while ($text =~ s/^( )*\t/"$1    "/eig) {} + # while ($text =~ s/^( )* /"$1 "/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 < + + + + + $text + + + + +EOF +} + +sub print_html_footer_frameset { + print "\n\n" . "$::HTTP_NL$::HTTP_NL"; +} + +# Create the header information with the body tag +sub print_html_header { + print_html_header_frameset(shift); + print "\n\n"; + print "\n"; +} + +sub print_html_footer { + print "\n\n\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 "\n\n"; + print "\n"; + $is_body = 1; +} + +sub print_html_footer_tabs { + print "\n\n\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 < + + + + + $text + + + + + + + + +EOF +} + +sub print_html_footer_javascript { + print "\n\n\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
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()) . "
\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
and other things that html_encode() +# can do. Do not send arbitrary HTML to this function. +sub print_err { + print html_encode(shift()) . "
\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; diff --git a/lib/Timeline.pm b/lib/Timeline.pm new file mode 100644 index 0000000000..4cd676af93 --- /dev/null +++ b/lib/Timeline.pm @@ -0,0 +1,1425 @@ +# +# Timeline 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 Timeline; + +use POSIX; # needed for tzset + +# Changing the order of this may affect the main function ordering + +$Timeline::BLANK = 0; +$Timeline::FRAME = 1; +$Timeline::TABS = 2; +$Timeline::BODY_ENTER = 3; +$Timeline::BODY_RUN = 4; +$Timeline::TL_ENTER = 5; +$Timeline::TL_RUN = 6; +$Timeline::VIEW_FR = 7; +$Timeline::VIEW_MENU = 8; +$Timeline::VIEW_IDX = 9; +$Timeline::VIEW_SUM = 10; +$Timeline::VIEW = 11; + +# Types of modes for fname (i.e. can we overwrite it if it exists) +my $FNAME_MODE_INIT = 0; +my $FNAME_MODE_OVER = 1; + +sub main { + + return if ($::LIVE == 1); + + # By default, show the main frame + $Args::args{'view'} = $Args::enc_args{'view'} = $Timeline::FRAME + unless (exists $Args::args{'view'}); + + Args::check_view(); + my $view = Args::get_view(); + + if ($view < $Timeline::VIEW_FR) { + if ($view == $Timeline::BLANK) { + return blank(); + } + elsif ($view == $Timeline::FRAME) { + return frame(); + } + elsif ($view == $Timeline::TABS) { + return tabs(); + } + elsif ($view == $Timeline::BODY_ENTER) { + return body_enter(); + } + elsif ($view == $Timeline::BODY_RUN) { + return body_run(); + } + elsif ($view == $Timeline::TL_ENTER) { + return tl_enter(); + } + elsif ($view == $Timeline::TL_RUN) { + return tl_run(); + } + } + else { + if ($view == $Timeline::VIEW_FR) { + return view_fr(); + } + elsif ($view == $Timeline::VIEW_MENU) { + return view_menu(); + } + elsif ($view == $Timeline::VIEW_IDX) { + return view_idx(); + } + elsif ($view == $Timeline::VIEW_SUM) { + return view_sum(); + } + elsif ($view == $Timeline::VIEW) { + return view(); + } + } + Print::print_check_err("Invalid Timeline View"); +} + +# Call the appropriate function based on the value of sort +sub frame { + Print::print_html_header_frameset( + "Timeline: $Args::args{'case'}:$Args::args{'host'}"); + + print "\n"; + + my $submod = $Timeline::BLANK; + $submod = Args::get_submod() if (exists $Args::args{'submod'}); + + # Listing + print "\n"; + + my $str = ""; + + # Contents + if ($submod == $Timeline::BLANK) { + print +"\n\n"; + return; + } + elsif ($submod == $Timeline::TL_ENTER) { + $str .= "&body=$Args::args{'body'}" if (exists $Args::args{'body'}); + } + elsif ($submod == $Timeline::VIEW_FR) { + $str .= "&tl=$Args::args{'tl'}" if (exists $Args::args{'tl'}); + } + + print +"\n\n"; + + Print::print_html_footer_frameset(); + return 0; +} + +# The tabs / button images in timeline view +sub tabs { + Args::check_submod(); + Print::print_html_header_tabs("Timeline Mode Tabs"); + + my $submod = Args::get_submod(); + + print "
\n"; + + # Create Datafile + print "\n" + . "\n" + . "\n" . "\n"; + } + else { + print "\n"; + } + + # Help - set to current submod + print "\n"; + + # Close + print "\n" + . "
" + . ""; + + if ($submod == $Timeline::BODY_ENTER) { + print "\n"; + } + else { + print "\n"; + } + + print "" + . ""; + + # Create Timeline + if ($submod == $Timeline::TL_ENTER) { + print "\n"; + } + else { + print "\n"; + } + print "" + . ""; + + # View Timeline + if (($submod == $Timeline::VIEW_FR) || ($submod == $Timeline::VIEW_MENU)) { + print "\n"; + } + else { + print "\n"; + } + + # Notes + print ""; + if ($::USE_NOTES == 1) { + print +"" + . "" + . "" + . "" + . "" + . "
\n"; + + Print::print_html_footer_tabs(); + return 0; +} + +sub body_enter { + Print::print_html_header("Enter Data to Make Body File"); + + my $i; + my %mnt2img; + + # Cycle through each image we read from fsmorgue + foreach $i (keys %Caseman::vol2mnt) { + next + unless ($Caseman::vol2cat{$i} eq "part"); + next + if ( ($Caseman::vol2ftype{$i} eq "swap") + || ($Caseman::vol2ftype{$i} eq "raw")); + $mnt2vol{"$Caseman::vol2mnt{$i}--$i"} = $i; + } + +# sort via parent volume, then starting location, and then mount point (which includes the name) + my @mnt = sort { + ($Caseman::vol2par{$mnt2vol{$a}} cmp $Caseman::vol2par{$mnt2vol{$b}}) + or ($Caseman::vol2start{$mnt2vol{$a}} <=> + $Caseman::vol2start{$mnt2vol{$b}}) + or (lc($a) cmp lc($b)) + } keys %mnt2vol; + + print "
\n" + . "\n" + . "\n" + . Args::make_hidden() + . "

Here we will process the file system images, collect the temporal data, and save the data to a single file." + . "

1. Select one or more of the following images to collect data from:\n" + . ""; + + for (my $i = 0; $i <= $#mnt; $i++) { + my $vol = $mnt2vol{$mnt[$i]}; + + print "" + . "\n"; + } + + print "
" + . "$Caseman::vol2mnt{$vol}$Caseman::vol2sname{$vol}$Caseman::vol2ftype{$vol}

2. Select the data types to gather:
\n" + . "" + . "" + . "" + . "
" + . "Allocated Files" + . "Unallocated Files
\n" + . "

3. Enter name of output file (body):
" + . "$::DATADIR/" + . "\n" + . "\n" + . "

4. Generate MD5 Value? " + . ""; + + print "

\n"; + + Print::print_html_footer(); + return 0; +} + +sub body_run { + Args::check_fname(); + Args::check_fname_mode(); + Print::print_html_header("Make Body File"); + + my $fname_rel = Args::get_fname_rel(); + my $fname = Args::get_fname(); + + my $fname_mode = $Args::args{'fname_mode'}; + + if ((-e "$fname") && ($FNAME_MODE_INIT == $fname_mode)) { + print "File Already Exists: $fname_rel\n"; + + my $hidden = Args::make_hidden(); + + $hidden .= + "\n" + . "\n"; + + my $i; + foreach $i (%Caseman::vol2mnt) { + $hidden .= "\n" + if (exists $Args::args{$i}); + } + + $hidden .= + "\n" + if (exists $Args::args{'al_file'}); + $hidden .= + "\n" + if (exists $Args::args{'unal_file'}); + $hidden .= + "\n" + if (exists $Args::args{'md5'}); + + # Make a new name + print "
\n" + . "New Name: " + . "\n"; + + # Overwrite it + print "
" + . "\n" + . "$hidden" + . "\n" + . "
\n" + . "
\n" + . "\n" + . "\n" + . "$hidden" + . "
"; + + return 0; + } + + # we will be appending to the file so we should del it now + if (-e "$fname") { + unlink($fname); + } + + my $log_files = ""; + my $log_type = ""; + + # What kind of data are we collecting? + my $al_file = 0; + if (exists $Args::args{'al_file'}) { + $al_file = $Args::args{'al_file'}; + $log_type .= "Allocated Files"; + } + + my $unal_file = 0; + if (exists $Args::args{'unal_file'}) { + $unal_file = $Args::args{'unal_file'}; + $log_type .= ", " if ($log_type ne ""); + $log_type .= "Unallocated Files"; + } + + if (($unal_file == 0) && ($al_file == 0)) { + print + "No data types were selected. You must select at least one.
\n"; + return 1; + } + + my $tz = ""; + $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); + + my $i; + my $found = 0; + local *OUT; + + # Analyze each image - the image names are passed as an argument + foreach $i (keys %Caseman::vol2mnt) { + if (exists $Args::args{$i}) { + + $found = 1; + my $ftype = $Caseman::vol2ftype{$i}; + my $img = $Caseman::vol2path{$i}; + my $offset = $Caseman::vol2start{$i}; + my $imgtype = $Caseman::vol2itype{$i}; + my $mnt = $Caseman::vol2mnt{$i}; + + $log_files .= ", " if ($log_files ne ""); + $log_files .= "$i"; + + if (($al_file) && ($unal_file)) { + print "Running fls -r -m on $i
\n"; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/fls' $tz -s $Caseman::ts -m '$mnt' -f $ftype -r -o $offset -i $imgtype $img >> '$fname'" + ); + print "$_
\n" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + } + elsif ($al_file) { + print "Running fls -ru -m on $i
\n"; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/fls' $tz -s $Caseman::ts -m '$mnt' -f $ftype -ru -o $offset -i $imgtype $img >> '$fname'" + ); + print "$_
\n" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + } + elsif ($unal_file) { + print "Running fls -rd -m on $i
\n"; + Exec::exec_pipe(*OUT, +"'$::TSKDIR/fls' $tz -s $Caseman::ts -m '$mnt' -f $ftype -rd -o $offset -i $imgtype $img >> '$fname'" + ); + print "$_
\n" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + } + } + } + + unless ($found) { + print +"No images were given for analysis. At least one must be selected.
\n"; + return 1; + } + + Print::log_host_inv( + "Saving timeline data for $log_type for $log_files to $fname_rel"); + + # append to host config + my $bod_vol = Caseman::add_vol_host_config("body", $fname_rel); + $Caseman::vol2cat{$bod_vol} = "timeline"; + $Caseman::vol2ftype{$bod_vol} = "body"; + $Caseman::vol2itype{$bod_vol} = "raw"; + $Caseman::vol2path{$bod_vol} = $fname; + $Caseman::vol2start{$bod_vol} = 0; + $Caseman::vol2end{$bod_vol} = 0; + $Caseman::vol2sname{$bod_vol} = $fname_rel; + + print "
Body file saved to $fname

\n" + . "Entry added to host config file

\n"; + + # Calculate MD5 + if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) { + print "Calculating MD5 Value

\n"; + my $m = Hash::int_create_wrap($bod_vol); + print "MD5 Value: $m

\n"; + } + + print "

The next step is to sort the data into a timeline." + . "

\n" + . "\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n
\n"; + + Print::print_html_footer(); + return 0; +} + +my $OTYPE_NORM = 1; +my $OTYPE_HOURLY = 2; +my $OTYPE_DAILY = 3; + +sub tl_enter { + Print::print_html_header("Enter data for timeline"); + + my @body; + + # Find the body files if we will be looking for them + unless ((exists $Args::args{'body'}) + && (exists $Caseman::vol2cat{$Args::args{'body'}})) + { + foreach my $k (keys %Caseman::vol2cat) { + if ( ($Caseman::vol2cat{$k} eq "timeline") + && ($Caseman::vol2ftype{$k} eq "body")) + { + push @body, $k; + } + } + + if (scalar(@body) == 0) { + print "There are currently no body files " + . "for this host.
You must create the intermediate " + . "data file before you can perform this step
\n" + . "

" + . "\"Ok\"" + . "\n"; + return 1; + } + } + print "Now we will sort the data and save it to a timeline.

\n" + . "

\n" + . "\n" + . "\n" + . Args::make_hidden() + . "1. Select the data input file (body):\n" + . ""; + + # if the body file was specified then just print it + if (exists $Args::args{'body'}) { + print "\n"; + } + else { + my @body_sort = sort { lc($a) cmp lc($b) } @body; + my $chk = " CHECKED"; + for (my $i = 0; $i <= $#body_sort; $i++) { + print "\n"; + $chk = ""; + } + } + + my $cur_mon = 1 + (localtime())[4]; + my $cur_year = 1900 + (localtime())[5]; + + # STARTING DATE + print "
" + . "$Caseman::vol2sname{$Args::args{'body'}}
$Caseman::vol2sname{$body_sort[$i]}
\n" + . "

2. Enter the starting date:
\n" + . "None:
" + . "Specify: " + . "" + . "" + . "\n"; + + # END DATE + print "

3. Enter the ending date:
\n" + . "None:
\n" + . "Specify: \n" + . "\n" + . "" + . "\n"; + + # FILE NAME + print "

4. Enter the file name to save as:
" + . "$::DATADIR/
\n" + . "\n"; + + # Get only the UNIX images - since only they have /etc/passwd and group + my @unix_imgs; + my $root_vol = ""; + foreach my $i (keys %Caseman::vol2ftype) { + my $f = $Caseman::vol2ftype{$i}; + + next + unless (($f =~ /^ext/) + || ($f =~ /^ufs/) + || ($f =~ /^linux/) + || ($f =~ /bsd$/) + || ($f =~ /^solaris$/) + || ($f =~ /^bsdi$/)); + + push @unix_vols, $i; + + # Keep a reference to an image with '/' as the mounting point + $root_vol = $i + if ($Caseman::vol2mnt{$i} eq '/'); + } + + my $cnt = 5; + if (scalar @unix_vols > 0) { + + print +"

$cnt. Select the UNIX image that contains the /etc/passwd and /etc/group files:
\n"; + $cnt++; + + print "\n"; + } + + print "

$cnt. Choose the output format:
\n"; + $cnt++; + print +"  Tabulated (normal)
\n" + . "  Comma delimited with hourly summary
\n" + . "  Comma delimited with daily summary
\n"; + + print "

$cnt. Generate MD5 Value? "; + $cnt++; + + print "\n"; + + # Create Button + print "

\n

\n"; + + Print::print_html_footer(); + return 0; +} + +sub tl_run { + Args::check_fname(); + Args::check_body(); + Args::check_sort(); + + Print::print_html_header("Make Timeline"); + + my $body = Args::get_body(); + my $fname = Args::get_fname(); + my $fname_rel = Args::get_fname_rel(); + my $otype = Args::get_sort(); + + my $fname_mode = $Args::args{'fname_mode'}; + + if ((-e "$fname") && ($FNAME_MODE_INIT == $fname_mode)) { + print "File Already Exists: $fname_rel
\n"; + + my $hidden = + "" + . Args::make_hidden(); + + $hidden .= + "\n" + if (exists $Args::args{'st_none'}); + $hidden .= + "\n" + if (exists $Args::args{'st_year'}); + $hidden .= + "\n" + if (exists $Args::args{'st_day'}); + $hidden .= + "\n" + if (exists $Args::args{'st_mon'}); + $hidden .= + "\n" + if (exists $Args::args{'end_none'}); + $hidden .= + "\n" + if (exists $Args::args{'end_year'}); + $hidden .= + "\n" + if (exists $Args::args{'end_day'}); + $hidden .= + "\n" + if (exists $Args::args{'end_mon'}); + $hidden .= + "\n" + if (exists $Args::args{'tz'}); + $hidden .= + "\n" + if (exists $Args::args{'pw_vol'}); + $hidden .= + "\n" + if (exists $Args::args{'md5'}); + $hidden .= + "\n" + if (exists $Args::args{'sort'}); + + # Make a new name + print "
\n" + . "New Name: " + . "\n"; + + # Overwrite it + print "
" + . "\n" + . "\n" + . "\n" + . "$hidden\n" + . "\n" + . "
\n" + . "
\n" + . "\n" + . "\n" + . "\n" + . "\n" . "$hidden\n" . "
"; + + return 0; + } + + my $mon; + my $day; + my $year; + + my $date = ""; + + # Get the start date + unless ((exists $Args::args{'st_none'}) && ($Args::args{'st_none'} == 1)) { + + if (exists $Args::args{'st_mon'}) { + Args::check_st_mon(); + $mon = Args::get_st_mon(); + if (($mon < 1) || ($mon > 12)) { + print("Invalid starting month\n"); + return 1; + } + if ($mon < 10) { + $mon = "0" . $mon; + } + } + if (exists $Args::args{'st_year'}) { + Args::check_st_year(); + $year = Args::get_st_year(); + if (($year < 1970) || ($year > 2020)) { + print("Invalid starting year\n"); + return 1; + } + } + if ( (exists $Args::args{'st_day'}) + && ($Args::args{'st_day'} =~ /^(\d\d?)$/)) + { + $day = $1; + if (($day < 1) || ($day > 31)) { + print("Invalid starting day\n"); + return 1; + } + if ($day < 10) { + $day = "0" . $day; + } + } + else { + print("Invalid start day\n"); + return 1; + } + + $date = "$year-$mon-$day"; + } + + unless ((exists $Args::args{'end_none'}) && ($Args::args{'end_none'} == 1)) + { + + if ($date eq "") { + print "Begin date must be given if ending date is given
"; + return 1; + } + + if ( (exists $Args::args{'end_mon'}) + && ($Args::args{'end_mon'} =~ /^(\d\d?)$/)) + { + $mon = $1; + if (($mon < 1) || ($mon > 12)) { + print("Invalid end month\n"); + return 1; + } + if ($mon < 10) { + $mon = "0" . $mon; + } + } + else { + print("Invalid end month\n"); + return 1; + } + if ( (exists $Args::args{'end_year'}) + && ($Args::args{'end_year'} =~ /^(\d\d\d\d)$/)) + { + $year = $1; + if (($year < 1970) || ($year > 2020)) { + print("Invalid ending year\n"); + return 1; + } + + } + else { + print("Invalid end year\n"); + return 1; + } + if ( (exists $Args::args{'end_day'}) + && ($Args::args{'end_day'} =~ /^(\d\d?)$/)) + { + $day = $1; + if (($day < 1) || ($day > 31)) { + print("Invalid end day\n"); + return 1; + } + if ($day < 10) { + $day = "0" . $day; + } + } + else { + print("Invalid end day\n"); + return 1; + } + + $date .= "..$year-$mon-$day"; + } + + # temp strings for the password and group files + my $pw_tmp = ""; + my $gr_tmp = ""; + my $mac_args = ""; + my $log = ""; + + local *OUT; + + # Password and Group Files + if ((exists $Args::args{'pw_vol'}) && ($Args::args{'pw_vol'} ne "")) { + Args::check_vol('pw_vol'); + my $pw_vol = Args::get_vol('pw_vol'); + + my $ftype = $Caseman::vol2ftype{$pw_vol}; + my $img = $Caseman::vol2path{$pw_vol}; + my $offset = $Caseman::vol2start{$pw_vol}; + my $imgtype = $Caseman::vol2itype{$pw_vol}; + + $log .= "Password & Group File ($pw_vol) "; + + # Get the passwd file meta and copy the file + Exec::exec_pipe(*OUT, +"'$::TSKDIR/ifind' -f $ftype -n 'etc/passwd' -o $offset -i $imgtype $img" + ); + my $pwi = Exec::read_pipe_line(*OUT); + close(OUT); + + $pwi = "Error getting meta for passwd" + if ((!defined $pwi) || ($pwi eq "")); + + # Do the Taint Checking + if ($pwi =~ /^($::REG_META)$/) { + $pwi = $1; + + $log .= "Password Meta Address ($pwi) "; + + # Find a temp name that we can call it + my $i; + for ($i = 0;; $i++) { + unless (-e "$fname.pw-$i") { + $pw_tmp = "$fname.pw-$i"; + last; + } + } + + Exec::exec_sys( +"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $pwi > '$pw_tmp'" + ); + $mac_args .= " -p \'$pw_tmp\' "; + + } + else { + print( +"Error finding /etc/passwd meta in $Caseman::vol2sname{$pw_vol} ($pwi)
" + ); + Print::log_host_inv( +"$Caseman::vol2sname{$pw_vol}: /etc/passwd file not found for timeline" + ); + } + + # Get the group file meta and copy the file + Exec::exec_pipe(*OUT, +"'$::TSKDIR/ifind' -f $ftype -n 'etc/group' -o $offset -i $imgtype $img" + ); + my $gri = Exec::read_pipe_line(*OUT); + close(OUT); + + $gri = "Error getting meta for group" + if ((!defined $gri) || ($gri eq "")); + + # Do the Taint Checking + if ($gri =~ /^($::REG_META)$/) { + $gri = $1; + + $log .= "Group Meta Address ($gri) "; + + # Find a temp name that we can call it + my $i; + for ($i = 0;; $i++) { + unless (-e "$fname.gr-$i") { + $gr_tmp = "$fname.gr-$i"; + last; + } + } + Exec::exec_sys( +"'$::TSKDIR/icat' -f $ftype -o $offset -i $imgtype $img $gri > '$gr_tmp'" + ); + $mac_args .= " -g \'$gr_tmp\' "; + } + else { + print( +"Error finding /etc/group meta in $Caseman::vol2sname{$pw_vol} ($gri)
" + ); + Print::log_host_inv( +"$Caseman::vol2sname{$pw_vol}: /etc/group file not found for timeline" + ); + } + } + + if ($date eq "") { + print + "Creating Timeline using all dates (Time Zone: $Caseman::tz)
\n"; + Print::log_host_inv( +"$Caseman::vol2sname{$body}: Creating timeline using all dates (TZ: $Caseman::tz) ${log}to $fname_rel" + ); + } + else { + print "Creating Timeline for $date (Time Zone: $Caseman::tz)
\n"; + Print::log_host_inv( +"$Caseman::vol2sname{$body}: Creating timeline for $date (TZ: $Caseman::tz) ${log}to $fname_rel" + ); + } + + my $tz = ""; + $tz = "-z '$Caseman::tz'" unless ("$Caseman::tz" eq ""); + + # mactime needs the path to run the 'date' command + $ENV{PATH} = "/bin:/usr/bin"; + local *OUT; + if ($otype == $OTYPE_NORM) { + Exec::exec_pipe(*OUT, +"LANG=C LC_ALL=C '$::TSKDIR/mactime' -b $Caseman::vol2path{$body} $tz -i day '${fname}.sum' $mac_args $date > '$fname'" + ); + } + elsif ($otype == $OTYPE_HOURLY) { + Exec::exec_pipe(*OUT, +"LANG=C LC_ALL=C '$::TSKDIR/mactime' -b $Caseman::vol2path{$body} $tz -d -i hour '${fname}.sum' $mac_args $date > '$fname'" + ); + } + elsif ($otype == $OTYPE_DAILY) { + Exec::exec_pipe(*OUT, +"LANG=C LC_ALL=C '$::TSKDIR/mactime' -b $Caseman::vol2path{$body} $tz -d -i day '${fname}.sum' $mac_args $date > '$fname'" + ); + } + else { + Print::print_err("Unknown output type"); + } + + print "$_
\n" while ($_ = Exec::read_pipe_line(*OUT)); + close(OUT); + $ENV{PATH} = ""; + + # Remove the password and group files + unlink("$pw_tmp") if ($pw_tmp ne ""); + unlink("$gr_tmp") if ($gr_tmp ne ""); + + print "
Timeline saved to $fname

\n"; + + # append to fsmorgue if a normal timeline + if ($otype == $OTYPE_NORM) { + my $tl_vol = Caseman::add_vol_host_config("timeline", $fname_rel); + print "Entry added to host config file

\n"; + + $Caseman::vol2cat{$tl_vol} = "timeline"; + $Caseman::vol2ftype{$tl_vol} = "timeline"; + $Caseman::vol2itype{$tl_vol} = "raw"; + $Caseman::vol2path{$tl_vol} = "$fname"; + $Caseman::vol2start{$tl_vol} = 0; + $Caseman::vol2end{$tl_vol} = 0; + $Caseman::vol2sname{$tl_vol} = $fname_rel; + + # Calculate MD5 + if ((exists $Args::args{'md5'}) && ($Args::args{'md5'} == 1)) { + print "Calculating MD5 Value

\n"; + my $m = Hash::int_create_wrap($tl_vol); + print "MD5 Value: $m

\n"; + } + + print "
\n" + . "\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . "\n
\n" + . "(NOTE: It is easier to view the timeline in a text editor than here)"; + } + else { + print + "Comma delimited files cannot be viewed from within Autopsy.
\n" + . "Open it in a spreadsheet or other data processing tool.
\n"; + } + Print::print_html_footer(); + return 0; +} + +sub view_menu { + Print::print_html_header("View Timeline Menu"); + + my @tl; + + # Find the timelines in the images hash + foreach my $k (keys %Caseman::vol2cat) { + if ( ($Caseman::vol2cat{$k} eq "timeline") + && ($Caseman::vol2ftype{$k} eq "timeline")) + { + push @tl, $k; + } + } + + if (scalar(@tl) == 0) { + print "There are currently no timeline files in the " + . "host config file.
One must first be created before you " + . "can view it
\n"; + + print "

" + . "\"Ok\"" + . "\n"; + + return 1; + } + + print "

\n" + . "\n" + . "\n" + . Args::make_hidden() + . "1. Select the timeline file:\n" + . "\n"; + + my @tl_sort = sort { lc($a) cmp lc($b) } @tl; + for (my $i = 0; $i <= $#tl_sort; $i++) { + print "\n"; + } + + print "
$Caseman::vol2sname{$tl_sort[$i]}
\n" + . "\n
\n"; + + Print::print_html_footer(); + return 0; +} + +sub view_fr { + Args::check_tl(); + + Print::print_html_header_frameset(""); + my $tl_vol = Args::get_tl(); + my $tl = $Caseman::vol2path{$tl_vol}; + my $url = ""; + + unless (exists $Args::args{'st_mon'}) { + + unless (open(TL, $tl)) { + print("Error opening $tl"); + return (1); + } + + my $beg_mon; + my $beg_year; + my $cnt = 0; + while () { + $cnt++; + if (/^(?:\w\w\w )?(\w\w\w)\s+\d\d\s+(\d\d\d\d)\s+\d\d:\d\d:\d\d/) { + $url = "tl=$tl_vol&st_mon=$::m2d{$1}&st_year=$2"; + + } + last; + } + close(TL); + + if ($cnt == 0) { + print "Empty timeline
\n"; + return 1; + } + if ($url eq "") { + print "Invalid Timeline
\n"; + return 1; + } + } + else { + $url = + "tl=$tl_vol&st_mon=$Args::enc_args{'st_mon'}&" + . "st_year=$Args::enc_args{'st_year'}"; + } + + print "\n" + . "\n" + . "\n"; + + Print::print_html_footer(); + return 0; +} + +sub view_idx { + Args::check_st_mon(); + Args::check_st_year(); + Args::check_tl(); + + Print::print_html_header("View Timeline Index"); + + my $mon = Args::get_st_mon(); + my $year = Args::get_st_year(); + my $tl_vol = Args::get_tl(); + my $tl = $Caseman::vol2path{$tl_vol}; + + print "
"; + my $url = + "$::PROGNAME?$Args::baseargs&mod=$::MOD_TL&view=$Timeline::VIEW_FR&" + . "tl=$tl_vol"; + + # Next and Previous pointers + my $pyear = $year; + my $pmon = $mon - 1; + if ($pmon == 0) { + $pmon = 12; + $pyear--; + } + print "\n" + . "\n" + . "\n"; + + if (-e "${tl}.sum") { + print "\n" + . "\n"; + } + + my $nyear = $year; + my $nmon = $mon + 1; + if ($nmon == 13) { + $nmon = 1; + $nyear++; + } + + print "
" + . "" + . "<- $::d2m[$pmon] $pyear " + . "Summary " + . "" + . "$::d2m[$nmon] $nyear ->
\n"; + + # Make a form to enter the next month and year to show. + # it defaults to the current location + print "
\n" + . "\n" + . "\n" + . "\n" + . Args::make_hidden() + . + + "\n" + . "" + . "" + . "\n" + . "
" + . "" + . "" + . "
\n"; + + Print::print_html_footer(); + return 0; +} + +# Display the contents of the summary file (hits per day) and show +# it as hits per month +sub view_sum { + Args::check_tl(); + + Print::print_html_header("View Timeline Summary"); + + my $tl_vol = Args::get_tl(); + my $tl = $Caseman::vol2path{$tl_vol}; + + $tl .= ".sum"; + + open(TL, "<$tl") or die "Can not open $tl"; + my $url = + "$::PROGNAME?$Args::baseargs&mod=$::MOD_TL&" + . "view=$Timeline::VIEW_FR&tl=$tl_vol"; + + print "

This page provides a monthly summary of activity.
" + . "Each day that has activity is noted with the number of events
\n"; + + my $p_year = ""; + my $p_mon = ""; + + print "

\n"; + + while () { + my @a = split(/ /, $_); + next unless (scalar(@a) == 5); + my $mon = $::m2d{$a[1]}; + my $year = $a[3]; + $year = $1 if ($year =~ /^(\d{4,4}):$/); + + if (($p_year ne $year) || ($p_mon ne $mon)) { + print "\n"; + + $p_year = $year; + $p_mon = $mon; + } + print "" + . "\n"; + } + print "
" + . "" + . "$a[1] $year
  $a[0]$a[1]$a[2]$year($a[4])
\n"; + + close(TL); + + Print::print_html_footer(); + return 0; +} + +# display a given month of the timeline +sub view { + Args::check_tl(); + Args::check_st_mon(); + Args::check_st_year(); + + my $tl_vol = Args::get_tl(); + my $tl = $Caseman::vol2path{$tl_vol}; + my $st_mon = Args::get_st_mon(); + my $st_year = Args::get_st_year(); + + Print::print_html_header("View $st_mon, $st_year of Timeline"); + + unless (open(TL, "$tl")) { + print("Error opening $tl"); + return (1); + } + + Print::log_host_inv( + "$Args::args{'tl'}: Viewing timeline for $::d2m[$st_mon] $st_year"); + + print "\n"; + + # zone identifies if we should be printing or not + my $zone = 0; + my $row = 0; + while () { + if ( +/^(?:(\w\w\w\s+)?(\w\w\w\s+\d\d\s+\d\d\d\d)\s+(\d\d:\d\d:\d\d))?\s+(\d+)\s+([macb\.]+)\s+([-\/\?\w]+)\s+([\d\w\/]+)\s+([\d\w\/]+)\s+($::REG_META)\s+(.*)$/o + ) + { + + my $day = ""; + $day = $1 if (defined $1); + my $date = ""; + $date = $2 if (defined $2); + my $time = ""; + $time = $3 if (defined $3); + my $sz = $4; + my $mac = $5; + my $p = $6; + my $u = $7; + my $g = $8; + my $i = $9; + my $f = $10; + + # we must break this down to see if we can skip it or not + if ($date ne "") { + if ($date =~ /^(\w\w\w)\s+\d\d\s+(\d\d\d\d)$/) { + if ($2 < $st_year) { + next; + } + elsif (($2 == $st_year) && ($::m2d{$1} < $st_mon)) { + next; + } + elsif ($2 > $st_year) { + last; + } + elsif (($2 == $st_year) && ($::m2d{$1} > $st_mon)) { + last; + } + else { + $zone = 1; + } + } + } + + # we need to print this entry + if ($zone) { + + # the deleted meta entries screw up in HTML + $f = "<$1 >" if ($f =~ /^<(.*?)>$/); + + if (($row % 2) == 0) { + print "\n"; + } + else { + print + "\n"; + } + + print "" + . "" + . "\n"; + + $row++; + } + } + else { + print "Error parsing timeline: " + . Print::html_encode($_) + . "
\n"; + } + } + close(TL); + print "
$day $date $time$sz$mac$p$u$g$i" + . Print::html_encode($f) + . "
"; + + Print::print_html_footer(); + return 0; +} + +# Blank Page +sub blank { + Print::print_html_header(""); + print "

File Activity Timelines

\n" + . "Here you can create a timeline of file activity.
\n" + . "This process requires two steps:

\n" + . "1. Create Data File from file system data  ->" + . "  2. Create Timeline from the data file\n" + . "

Use the tabs above to start.\n"; + Print::print_html_footer(); + return 0; +} diff --git a/lib/Vs.pm b/lib/Vs.pm new file mode 100644 index 0000000000..2ce43f3fb0 --- /dev/null +++ b/lib/Vs.pm @@ -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; diff --git a/lib/define.pl b/lib/define.pl new file mode 100644 index 0000000000..09ea125ce0 --- /dev/null +++ b/lib/define.pl @@ -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; diff --git a/lib/search.pl b/lib/search.pl new file mode 100644 index 0000000000..4ea1b363d1 --- /dev/null +++ b/lib/search.pl @@ -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; diff --git a/man/man1/autopsy.1 b/man/man1/autopsy.1 new file mode 100755 index 0000000000..39f983d6a7 --- /dev/null +++ b/man/man1/autopsy.1 @@ -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.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 /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.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 + + +.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 + +Send documentation updates to diff --git a/pict/back_pix.jpg b/pict/back_pix.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a5da64c9bda1ad2cec4418a7c7b055b97e2f7da GIT binary patch literal 305 zcma*h&kBM-5C-sXbX`qX-9-gap%)1vilBOnvQto}4xPI6U>K=o#vH~ShxfSY zz~kHtgzpEwFQoWHiYS(GB$6aelcXxkvg)@X*L6b?=2GTGrm~`4{5$9d$}>-rO$wGG iTai9vVdOh5QHLBZI|8U5(KiU2%w=0)i0!yM>gyYs(iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%cTl9^GEfk}{&S&;Gn5r$R< z24)6kMxZm{fQ6NbjU6b&geuIy!o6C0J;3k88n8QEA_;KqQA6a*?05*7&zS`^IUm{_RPc+tt||1Aa{kbQ#8f(-Ty z?+P9`OT73pKT;}5v1^f%-rK7UFQqPKdcej@3^=v!eYVq^p?kuxc zHQnzf_m}sk)jo^f<;_&2W2EXX!+6|~tK#9*tb?XeG3-|~X0&F$+T34$Stu{)ZI5)G ze^W!SveLS;iC2zpHTiI^v*T}u@x_HlBEnr1W~mo}ob^2P-L2i*-J;VE&8c~DcdK+s zD$wdN_n#RCjQ>Q)R$JJDl2sw!W@d#j`+^+Iyv{Nimu1( zgdkJfTcPXy&(CGkp1j=Xq>e`q)2=+5mCeah${x-PHu|CJCdO{Vlp!+DLzH{+OJ2>j zU;I{Vxtnr4uO#}!6knGo{I$1`W(8D5uLG?eJfMw z#Jw$Y<}0_^TAS#GJ=5LBy+k%k+^A%|AM?h?EO|Tbgch8cz#*pecqq}d{qmzO$#B^l z0WVv#;x5ZYySCi@9m8X?LFVe--1rM6#LFO&2tencIL+`rhq;A-A|-S<|HH{~=IM%Sesd&(qa zBNS#>W$UKK;=54kz5iAtl@_*CrRPEWPns+Zt(4Do=RdVt-2K+Oym+sh3Dff~t-ZbX zMA=PWTT#C^w=9~zR4iHX;K9wOu^lb@xc9BL^URCdA^vPn@ShK=oed1lGM$w;r%FUdvM=M(j7scO+-rRS0pJ<9*Xi9C2=AT>a>qW(ne$8b+ z_3}T%+2jMA%P!eu=pRrhndEV@?}=&YoyM6LQV&dP_H&H)D-V0Nl{2E< z?yQP?%A{bX+PUgM$CUZ2iqvj+C2gO^6jYp4QFke0-wG|yL!19hI~JR{Fse@Z3Gc?8 zvp>7c_lbS@scYKh{`pLEuGQzSP+q3@;is$HoSGjZ+4kG72woPis9Chw&#s2cbpGvE z951`~*aZeIm$ze;I{)@7OUcoD@)|2ZntRi~{c5sGde1*4B=h+BMz_tsYaL|`%iB+B znLK`eU~%N%eGB?#>^}TdRI2dvgTOWa?gzMoZSJ-B`9T9@v66BClgH}*)$1R>a1s(Z g{yF@>iRSiOO9P*rG)(;UG=J@aRbQ8Ey#D_t09T0=Qvd(} literal 0 HcmV?d00001 diff --git a/pict/but_alloc_list.jpg b/pict/but_alloc_list.jpg new file mode 100644 index 0000000000000000000000000000000000000000..525fd081f3ff28dd75136354110695c71f43986d GIT binary patch literal 1852 zcma)0c{J3E9{>GjWyUfymh4@G@Y1t%uW;*<-6bZbJCU72X2A>=)T4OUP2TBC==hym#K~yno&~@AEz1bH3;E{eC{*51+@M0x-6gHkJSg0RUe? z0sLhEYfkeCx(a{*3;+NV0rd$GGxa5V`vJaO0R!^KfLH(lgTdf11RRbKMhF@$gg^+P zMNlX-3MGOO`4=!EV&WKaF%by~Nl6I_1$lXSg~Q(gB9TZ@5m6ZoMn+BwD<$`R@&68d zE`SvRBmpWE!~zg32*rZ@Rv-ZYpdbi91v&o%7#s>h5XgVBg8nan5EvAW0YE4e0!6?O z|JHyIC=3fn061j{NnMqEUnw;wJ!zz=7d6IPb=6E?@JpbBLt&8b_W%~Eoae2oYl@SA zd8tS`QDgL;nLX&A=8pm*P*9K!iUm#sd#OVI7)u=N0DaelPalQORDk6rO#ga%sp^ae zm9n2aq_q@CdrppB}<>)S>xk5_-$g+w%iD{D_2gg9F$!-7Tj?50=)8JTrlRl>Prw&Lh*vYjS|dC2 zZKiTtKaM=6;!k6avF6pO`fjI!@a~KdPDh~PuN>JZ2CiMPp*ancIEg3K7CFx>fRgLj zyd++tjn#}&13^5h>9gbnp>}IqZj0uT#G9hbENE1zJPSoDl*Q9e4fu`+_ZaM_rhmN2 z-~;n!^`a4rJrS|u?d{Tk7-ZRXQfmXFaC0rpr%&yY@k{I`t^>tdqxd-iA(m^iucQ;ELoX0KVoO+T60`obXBo{Q{5WBN&IYK8jf z6cv+@?h{`Ir%@%w@s8il`oGB48{(p`6E8IMnq0MNqp@{imSm9+hmLc~-cLG&crb_R zgp)3r;|ZRPE%Be?oJn?CPf8N~$l*piIab+T$O1bbd5)u7$bI?t@&n`@RsdV2lJTvsZ~E-k-`Zzy4>Vg6uu1n$JEGmZ+sbxx z`@J^nA{#S`CmM2cv%3!#&j&{<(s$?!{e#gLXa_-Cg~eXm1G&Q9-^d+gy2eWS_%)@U zmvDVL_YL<@T6f==r5_P$yBBfa1ydbvTk0S+Lt3fw?4H}Tluf zYp=;$vyIDFs7%W1%5gT!52wPyPh=fV?mCmi&Pz|5gg1+?4Gpx{WFA^7)tsW_mEEcQ zusZ-f@yzoiJW-=%oVgt>$3f28#4g>{;ijnIcvR7&rH!2vp%mL7PJ*GL#iZU?!F{n% zfDin=(U|2?yr$JK>=dw<64}IkjxK7P!zs`S52-w5r{?$$F|C&+#r}1Ss!bPkSkhS) zzj(utU&uK+LQ%Iw6 zA}7C?%qev}W2>W@^@u!#6J#3B&Cq$g@7Tx%)=v7XLFJbP ziE`IGeP-(LLTwqs8&Q3jJ#27)7IS#D+TaZ?_BOX9PjPg0B$e4qaUPL<$&RgRosMN! z_(wPeOdLPHx3o_m316}I|8hNSt0zZ;-q^cyWH0*B>Qe99q13P88<)h%>+Xs_(){Fi z^%9slf2Mz-8fi z>Cwsl$3HjqM1%?a$RGbynw)Piy0X~$)Bkej?$QjuI`3}^q?*RN`l-Q<*=GhKH$Ibg eSO<|O>R+$$0r!)=`rV(SZ^&9zmwV>&-~I)~;y8K$ literal 0 HcmV?d00001 diff --git a/pict/but_export.jpg b/pict/but_export.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4cbc75a024be2c929a5f8acdad048169b7d2573c GIT binary patch literal 2056 zcmc&vdpOezAOHP!W5#UEn$6*zON%5_#FAW3Zn;G+M@%l^Oe|~Wl9XYDH?007u0qm}`*P1uRha3HK##(>gsAOk?aU@$lg0f!@y2w9`# z5eRvdqJjcSK|v9t_+MZY(aIQQw4$mi4yUTBK_ZbfwEhMtCnu+*s6@bE2t+lk8u4%8 ze_f=#09GEr0m)Dh3qY_S6bnlEKnVaqpdbj!?)(b~C=3n(p_>26{gg{{+90Pz* zC@&4xH0$ifV`UZ)0YiWgxj!u+ zfQ3NGRVtx6FcTY3Ra$&{p*GI8$@GK3i&1?SE*%3Dp`h$WC>F2=zAUq-9j8i>yZrfa zqZCpUw)WwyEt?K=ynD^Z$NnW(xscW$g$bFp$^WDkI}|Tqz{K8)yBjUG>x1*yXC8e0 z$qP!H!P;Wy1@2J3(oXHU*_69$?zWF2kKvl#YV<;x~(^la8gY>XG5GwloUHW`JzE~ zU63%s>6G8cbhcl5xHdy=nQgLuhm1drEn+cWACuBXn)m2@MSL(%o=`Z zthqeaSM2KaB*Vh1<|cB^%l2iCXHDRD>m8Br-O+{=Wnb^5e$l-KDezXZ(4zOTM72e} zcq>&LEp)@@7?m7HN$_2-iqbR2@AglMlQ>7de+pw!gKx|vclbwg3z#D{`Yg+Z#Dz51 zf92%MucL$=PlnjjwE6~%0WKYX)(+-;M;B)>AAJ}hUOKn8s}QsU^n9~9N1f`3 zC31vEqqVZE?4GjYbDo0!Fq&KZ74$Xpv4nK*HJz}-U)O`2Th1`#*W~pbec@V6p6{|& zck7GW&muo0i|iK4PT;$q58NUQWloFIuFVjS%q5mLNCX1f&*6eyhvTy80m=$Ht<2VE z4mAygwE0D;4-@GAqb*|N74>cK_FA`CZ_0te2;!A|VqW(1q9<5Xc<_xpi%q8brHBJF zV7EPoj6CD0x?Dn(yl2{qEFL#bk5?F+EFXA1=OAqK%wI&jIp%~`_a_99Bihv52b?Co zN)A3ARrC# zKVsYGSZdJ?aXjH=rez>6&II9ivn!dM8Ot-RGL`IV?#PjRB5Ub)*fP{l ze7>FZ@#0L1r%L>r1;K%-h|obpbYu#@e z)1(d$p43DJMhGY*%x#Cmj@1S);V*dixrL?scOKjF-K9_sfGYTuHFqdXHIsad1(hY{ z+Kll@-LLZ1Mo#Z@=ivTUl5_Jo>~(a)A3SPzV#W#{DlyMO=Ula=bGlYM{zz>TKbYy;~jZ+ByP#v{eFj_9YtixTm@jkf%rafzKLT=w`a{dS>=x zSnt!v7>&oY8}=G!5j`*5Y`wxDGF}sTg#n_&f-RL+;iZcQ)3rZuCYrW->`jk7QgbI( za(imL3qMhL?v&5d{k(7r!PT^2@CZl30dFgl!gn0uevg{+_P03Ae+ug?M9+>1$_e#;TBZ>+|qN z0P?ie3Ex!4YD)pUuxW)_fw~<3@Vuo^myC;$0v?9R&!2rg^P6H1%%jJ*U_@NwTY0Er zqTiw~oo!8t8L0@m#b3fFQFb$1ugHoox8wZgm1f~SQ~m6Bra2TMi&2C~R`W&i*H literal 0 HcmV?d00001 diff --git a/pict/but_force.jpg b/pict/but_force.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a92475c71feecd87e414c36c993dba5eaea0966 GIT binary patch literal 1079 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBl$lYGfk}{&S&;Gn5rzps z_pvepU5NmUEUawoOpFXn%#0`!ER0OdtZV`djLghTOdPB*UCfM3EP_I;3~Y+RhKWjx zL{e1Q9Sa*(L>F!}a%vV61S)3)`JEkV0V9JT6SJb@!X#xD!$Kk9#Kwb49|AXuO#E2X zbV!Bu|1Aa{W}wxA%z_N|40n{L$;c$8&8ayp^~t))GH{J+l#>4GxVlh>O<$f`<;jK? z*1dn*v*PhQHf^1XO;as}Zgx#u5K?sMUAf-r;76}6ni>mrCMEr6SfSlF`GEYv2&MP3 zEA8SX&$*J%>Ma z@7D=V1ruMpth%_iXw|FKutL5hhbN63^H`MhKHoBWHjO2whf}z*Xr4x&_|$3t8MJR) z*PiX)8|=8+K<3DH6%Lns;tW8;3TKOnd9ln?S+B!r;o%i!Hw2LcNue!1_!1avB zr(g+}X$7-?Y>cn9Hou+!ddC%TWnQmGyTC6#<`33up~={cb)oc(Z;XpW^zW>? z`sa4tu1nP&)#u~GBOV+(fBImUNqWM|w9q&1Tcx*|+2^@VE2&B7*r&tj!DOS^n|)K} zq-sxQpUS?c>1OZe>RuN5&)_uqME{c`@u|m82IMX~bbit9oE0-=YHIZK^3HZj{%E}6 zbI7CP+v*#tNz;tX98Aq{8zerBPQOX0+Xu3Eq6GdWYV&`+1pHSeHM!wEbduzEh#%<1bPC)^C39 zzkVcaZ`h?>&$jiy`{Hl5JLRk2rmq~HL^52q%LGzP;yw}dZzWn>TT~f7cR!?4i@BGK6|2F}JKb!6V literal 0 HcmV?d00001 diff --git a/pict/but_indexdb.jpg b/pict/but_indexdb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5e51b780546e75ec6d474bdeec4f29dd7e5b6b47 GIT binary patch literal 1568 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 literal 0 HcmV?d00001 diff --git a/pict/but_next.jpg b/pict/but_next.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c5639baeb50091ab6043b3d8a97d66125f3f8468 GIT binary patch literal 1336 zcma)2e^AnQ82)_uts?RbFi+T(BoLEJ)3oniPt^ zz~(e*Vx*fPlFM`~wYe5~9XcPvG#@Jx2 zX@|pLaCUfGTRU4@JQ4pdh4D#&+ zgg~NTG+2aj@v0&57+7*Zc$|P9DXsP{a>PaKp}^K(Au(tK_CEvbX1E&Z;N;NKX-NEmDYcdLIS`0;d;NQpXnl7hI>LGYWMYOY=%b~5_QUE-#y z+aIb%-CyD61h0F72q*}&EKbkP=TmbgAVm@!{msHa7p(^S9)W>@)sP3w3#Uta=}zDch~uouPsx;1(0 z$-vC#qLP}MjX7+2&ehUq^XFSr%;1>PUr z@-pw0U>jE#;?GIdRdu7nkEtU(^Pj99N-106zPT}`LP%jV_!m^C6Vz(9RJz$GYLBd# z<4*N3U39{>R$@COOc(8bn@hjf%AdYIAHO-*$iH#9;7C40yGdXkDc*tqWVXO|jw$6N zr19C2PrF4kWx}*(!zJU!ec7i{UalH5Y@hP?tedm%F{Pj26+$0>eLXjJ*O3~a!nbox3fUB95`>kn_LR{1Sxvt!giI?J>$>d+9;(G%F74*TGUIA5g?44% ztT$qSCcBXlnu^fWp7)-q=EgKE%PN(M@;qJ+Ja3cNTm*w94(#!tTo*+R#c*1J6mVn~&30x~G?BtMf+M zINx;*Y-s3a;iwTQ!z`T2M3@JiQfm0*#5Q3C^AJU)l(9W|!TPx4ZQgt!hKlhJPD2^BBnIm;0F-&Tivd8z*thiA; zanUB_a`<$6jbZqp*lAO}rops( zhF;fXvwXdn`%BIiAL;wI%BIZnLq-c&?`4iwJboamKg_&H;2+*yxDX}!yO&@AEy|uP J1ofb0_#X*(CD{M~ literal 0 HcmV?d00001 diff --git a/pict/but_ok.jpg b/pict/but_ok.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bb2996fa2f3ccd958b8f3ccdbf788406799b6ef GIT binary patch literal 881 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%Ero0(CNfk}{&S&;Gn5r$5n zvzZwgfzE^hRt6R}Ms`L9CRAZ&7NDP5*#sCEnVDFaIGNa?>KU1sSycs3@dSxgIaB-G4sMy-9o*1m@SkDb&CI1IR#>&q{8A*< zX(hdJ+MQ`~6V~dg9-GG0w)v!UdmQ(&vknHw1>%`D?>aZRyDoaOo~PLt6D^+~nOrlr z&AN72rFoJ}Nrlip`3ZAlBV^W0Xqd^vb)i9ZQYdGSnpNK=_k=^!%3a>LwdZlB*spYd z`|exfy86#6wLhMJyHsbVPFsM;1|#PA4_or5si?i`OxRHFYqe4A`?7l?8Edb8Q?&M( z?Q=JGdUKwIoc9^sOVhrxs(Up}u}HXbn>lcuyPw{_){xf|CQRVlSYFy&7OS*9s!S;J zvsU-AW4&H^!KzQ(TfV(szw1+o)E)Z-ufB+)zIUs>9KFMSw7yfS@GntpQwh#C-G?u_Nf#-J!$vo$6Z0CsDtfSs+7Y+7DVt~ zUA_8DpR#}$r!6yw(41wgSNY{H{Ab|b|FZqd{9Mfy)vLGK`>)A+U-Z{z)B9u9ePL^2 z|4jSsm)Cn&_t~rdixtpS3cdpqH1S(^7^I+N&Elb1OSD?Hyi)} literal 0 HcmV?d00001 diff --git a/pict/but_prev.jpg b/pict/but_prev.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46c4f397005d169866102814cac08802f19acc4c GIT binary patch literal 1574 zcma)2do+;i^v+|TEp&$*g@%?KcE;`ng@ z0trBjwt!|Dz-)eWf&d@@8UWy~rIbK#V@%SnSP*kt%OErZ;5fjd(P#`Bi@{)Zu-Yc# zu~{AdVFavVOvhf z^ogLy`250*z2|b)pbFZ{BRjIq_Isz8c2(5&dpe75j3GW3phN8EnZ;40MEMDJZd4eCWyL<*lAC<&WsI=YSu!}Zs%S`ew`yurm1GN3 zWM~$}7y21uY!;s$zc^+pi>rs6Hn`tRpXv#x_|xh=1pO|$aOFf>a67AfpRA?y;0Mgk z9kYaZ(w4@7vq2*46yP4XA?Alita}2z^WfbgELhAE8OFCvO}t0_8U|V{_sBg@jzr66 zOU_pM`1BGA@F~VFr}FW_VvqUYbuUd_y1nOkRz7owE={el*_`=)W>8gG(&WMueasuk zQR+YZaaX`|+Xbo-A}u$-w%W)}A7<8+R&td7qEtc+z52`?$9L$t>-Lo!f-=+cDOt>= zlfFH=hwk@EP6tM)S^E{b0^GHyhkovV725NL=Vlq3Z$FWgYm6UZbR;`u1aC{8XWl<| zF2Zg?qP=$9{|?9Z!`;?-VoY%++Yu_ZbBiUO9cNM}E6VH}xOpqwMf#)P>vP#n?s-91 zPaoM(758}g?ems-E7_8fj_86=mojtv*VZ$K>|9l9s$b7|M|M{sKXloI(sMPdzgZ}- z9Z=ts?K{hgj&eAj%epK^7q0IppyfRfF{ISYgi!HIMurYC5?y<6A3byGg7HW64kw57 zlZK1N<(Vz(qHFa`ZkAasd1Eu!$rmJe6fF4mUEYauoBiy>s`lPnRW4ncn zC&qF7a`Jwu?LKO0*R*~E>wfJ46Gg$oh_6wsEv903t*bPvNkKLLqm!O*v2uL_+jZOJ zAByV|k8O8e{O)!jln=FLvlBv+DE@VP`5Ct&7%j&vN|t0OuGp`giJIG-l^&V6kl3N< zgeStfmiwgZ^i*WH;8X6|iM`iK2ZN6u3-B<-73g?!U2zqs?v4@2`iGn8?uQNIoz$hO zBW;%T!(FC3q!qH9;8a;z*^Ka8NJ$wKwK=Z8I?ZctlS?1HetBWD29%}OJYS$+N~Jx> z@|=aT%oSO2DWfI*`69m5)|&e^=mSg0Wg6I2_Avv;Aa=FddEim_Y+#N~+Vs3QEG7GL zyLI1@+<5pIP1GIlFj?){=7VXqC1b7f*f?HtpOU?o9^MjkVdd%8i?OQKuM+w{24*@z zVOMIpxE*));-tELss-;R!%_Z)>S0I1sWnQgcoS-U=qlo1k|1OP4!_7Xx627%y^V(0H)-wQe8e|%^FaLr29=P z?tGmzDK#5b{Oab+-`4OE7yTTO`O>7R96k#PV3 literal 0 HcmV?d00001 diff --git a/pict/but_replace.jpg b/pict/but_replace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c17557a59ec5367fe5e1970346c8b71060b3fcd GIT binary patch literal 1273 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBiJ4K5fk}{&S&;Gn5rzp2 z3`|VSj6i3?0V@+5BQpy-BLg!dBZ>qQGYccD00Sd46DtEJ6FXD`6Hu`rD}$ntFq@%c zpwc3d6jk;_r$(coreqUQL7-|zc1Bh&p#8`$e}_IWEW(*f!V7{l(0u{Vcxc z0xP2)v+)IK#OoDm8YLP%@x0*nDB+5v@!Ctt2Cw_lZZMxSQw;uHe4bm;;LXwXNumt> z57c>!*NJ`ZxNII>+_yG^QL#y9(&|a#L24>lA@VwVxoRf9=L-C}o`3Srr|-(XZ)=P# z&;7>l!IzTi6vb7#&LS&B{8(IvK!1f#pP`g?GSQ&$&pf_{QOc(w$s~+jidux22r&5TuLvQCLp4WZ$mJf>( zcUqZVyYofO!}X=_iG*8BI;|WRrUZt~3@tde)FE1D{>fsM>O%)U#aWl6Ufp)4+cfg> z?x(T2S9wD(ug(pddTGo0H07u*kIr#?_UAI3+C9H^-~G+SACAr2@GCa;h5Tx*_)jvL z;r0FN#X6Y!{ATjp=({wbNpn`9mdlFHj$<2I6H*gcGkT4+%F4C8W7wYay*;vYw^Hh> zo1D_ty~|?WItoQQbe);z>f`XOZ{=c}%{~F26*bO83gs!pS@+L+@%V&brPmLA;U{Hk zp)0qUr|fy`zjfD>)k&L9?MiWa?8Kn|$|b6NuHK&TiKmtur`&pXvR*=Exl{7fKhyr% zf7I!i<7T}1ne_G>Wjg~GMYAMqx#2Nc;_)isH`~}g1^iz1xZ7{u9991>N?8U!d|J1C z6W_i0qDjT3)46YEuX#T)yw&vB!-z@uEftOPxmWu3BwS^QEd0w5^?TupR^fFsrX3Hq zoZViQG+WnaXVI!J_5C~NaPuDSX%1K#*%soxhU2ZxLdm147d6d3yNkv;R5C|teb0`& zlVNkpXu|A?YRbnCe2-XW@s%NM(|?AW=1-^1KCk?!ykeroWV6UmK^#VPNn9rjB4*rv zW||-E!Nj|6uKQ)b_bD0ITGWNI(inep$IL5PsxiNGvYyhF)4uzBG|RRtPFyABQ~N@1 z&-Wn4O0}C(Y$YqcKDIYol5)iJkHo*#{z6k4x0o;5{IdMZ`mdV5cN^T~za4m9e%GsV zd;KNl<=THj*4k}7UKwlteeNG|i`cO5k$ZyP=YNfpNx6Bo>Hhx3BGvV)K0E-j&A%k| zgT$q+Hn{!k34Hr+_2K69Fpm2dyKMJgttiNObx``3q5Jk<>-l)+Mkv?2X%+rwICWpP kdh5FAEtlih8hrU>xx02%>HdvV{@5Ka`7F2T!}R|*0et=MwEzGB literal 0 HcmV?d00001 diff --git a/pict/but_report.jpg b/pict/but_report.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e283c36212ec407630b1956482b898960f305bf3 GIT binary patch literal 1339 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%ELf|*f}fk}{&S&;Gn5rzp2 z3`|VSj6i3?0V@*=BQqO2BLh$zMS_`;iG`I-fPs;jiJ66+l@qE1BrM3vAjGEVxJcMg zNhC#7m3^YoB>0jiB(%#JdxR-+eOVu=)fs!DyWiI8V@Gu6#ZuGh@-MbO z^hvco@}GgpbyexpW?vP3!M^l;4^sOD0+a1LoxTM!4Mc+MHd?6#`t*(@I@lNUZ?P3#W@UbaWMSobpG2g%B z;I7xM7XI3K+n#fjI0>pSM%}shF7>R-TC=2iUh}WTH!WwWYTZ$_-Fq76@~#pk$NmkU zZUwApkALP8v-ah^9V^!wM03`s+F5Mg5sD2WmMjgpIX+5(;qAbT9F@hERciINt~KF-g`V$J<)3f_X)+&-jtsp11QdQ$8Jc z+A4J=d+ts%HLmDMX?MET#_rFY@MODHMrBU+yp9zev+H@%*6TeIe(5r!NyIv&e#QMf zp_evT944V%lR?(QF`$LnNSn}W2r?W<3>1v9o?+4gZ^sqCwe*AsFdZ|r+qyk+vC zV;*f4$63!6J`-KFuIrJOt)S$!vwm9(Zsff@!13tF#i`pqKfM|jqL!PsMSEMl|2o0N zuN7k-v%M^wD|=vb%)|{%LY#|~7=;XGiEz&Pv@U&B?wytUCf_?ULt+}kE#05bM0)q^ zo>Q&wbaC5{vR>2Nwgo(%$z5!|2^Tw7rE#vU+Ii;2(^VzcW&R$GDOSB>newaTM8`&} z$im6b%x|~sN@JRQYR2I^Erxn2uB)e7nW;%`-?kuZwTwxM*U{6Pp8Dn0+`oSL=bK|^ zuXq05@k?j6zW&wOSM@&q`+B&i%5q&SZ_V_@r+;7PiF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%eJmYGqIfk}{&S&;Gn5r#=X z_pvYoU5Nlp%xvt8EUb(SOw5do2w?^W7Dgs!RyF|!MrI}!CJq*Ms2npR6N?}#gOD(r zqKM-}CFS7BA?${M#-fRh3pZZ;=qw0S&&a~T!UnU2kwK7&Sy5<_h@oSlQjl;kOJL$g zqYo1o9xPIBOq%rn76T76&~8CyK?Zw^T1n>2GjL|<*T6iJ+~L; zC1nSTHoHA5`p+;o(&u)84%J$pARz)8g?CwutYQ1#CV@aaY#*9x}4~GP9&6*Of z&hohDdGNQ)wCQ&<{jBF7TAuT0_mTPAb$6H9J*eFx)Nu3L>_37!8WWDq-OlCRay+Zo zZr)7U(8FIA5P`Q#~_*H81Fxa`zg5Ky*Kx1w{! zs^dDX*0bW?H>pjov$(x?^%)ko!u%6e=68cy^ll~9c~|GM-_b66FuQd3&6J|(1MJ=% z$KIt+w^EcB4bjOf*t)oi^~9@>ZgL6Wl z^Y5I^(N6@-JshUp%$e6v(Ju99iS-S`olml-bf~z7yzp9QzVdF+)aT~S-JCr43^(2F zTPbDCn;iN4YtY)g>9?CVXE@(7uZW(iyNSJUPJ&Fv=QZhDW*sZOxalj$-j=*Nt!|eW zVM`--Z{qBjig zGyjs0SpKwU-BPZH%O6}Vf7@=oBG~wQthKD-&Crz+)%v^(bYq#SmjBEZiSt0VyyRwTfsm;e0j!>27wl`Eo)%NByQL z^u<6m6h71fDscYGGRZw=^}OIuU%uxZ0U4upc*p8h(-fvpx_{#7m3NyE&KlPs` av)g^r`Q(?MJ>%aM^Osj{iF_OX|0V#?!K@wt literal 0 HcmV?d00001 diff --git a/pict/but_view.jpg b/pict/but_view.jpg new file mode 100644 index 0000000000000000000000000000000000000000..90a0ae9b60482d54a3956a2f8fd60039dadcfd3a GIT binary patch literal 931 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%czmzhzJfk}{&S&;Gn5r!V1 z`&b!)u0#Mv7FITPW<~~P1|We1m{}N^SlI*^7@3)wnOIoZp^{9D%q)UJtPH|zih+(3 zl|_t#Cx;j&7B+4)7GoC#h7&U@D?2O97)GGYip-8e!Ym?&g-St-0uviIIu!*^ylB*< z{QnjM570&?L1sY)dxkr$g$9P|R<$c`C-~dFymlcc=xO{(fvRt^W6ITk z-iH@Iia2Ad*l^72_P0w{Yt7AHZq52}KVm@rjTR8(Wdid|uepRF%zY;VbnWS4nV`S9t)iZ$P4{xirPRkfdT)Y~L> zC)eAhY_?ZK;xpD;$F07~zHQyw8EKL$_`g&zd@q|Xsj_ME`dH=G&A)3!_1s0y&G9o4 zG7M%>-ag%P>#-9vGp#48D=Ti{I~uoE*ERpeJgJ>K+nRn@?we7__;P-h35)9jzz-*`eh09aB{s#=K+o<$|F78?z_zf3|!0Bs^k!PqqK-@XFpj9wrsD zL#tZ67pkLlbOu##lKP) zv(2~nbX&Ci=oP^Y&+p1#)|D{%`OC{x)J|`~gd5snFWvL|mqi(57Jr$-b2Pqtg>oMM rrtRfR|1;do`cv}uSJvz)1&LLGx4FwTHx^5L+-bdA$t?fg{{J@tvKB*Y literal 0 HcmV?d00001 diff --git a/pict/but_viewcont.jpg b/pict/but_viewcont.jpg new file mode 100644 index 0000000000000000000000000000000000000000..76f58842eee5c730cac18badbefdcf86db88006a GIT binary patch literal 1924 zcmc&udoa*e{47nxfDnPkZ?F00Y@SbNEM`_ zG0I4!G6suAW6)?U4*Or=u-nvdYTK}QJb{46YiVj~YVG_BAPR+2#j28UI1+^j5h;HO z|0|Jq0gy640Fq!J1Smlu3!HgAOHgu<8LUz;2;8t13(x| z2@Z$BF@H)*APf#6kbt_5DHl&A1nSuxMY;LiG-F>b;CIvgf6^sxhZG(V2~!4Ph(A3b z04c#tZ>sz2!gbv6c7BRqsu_X*+tDb=GM(Ea9|y27P>~V_0f&L5rYTYAfesz(e9CD= z0@dWzz3P&)y=*T7NsQ>5r(vX3D_Kxe5O!eNqH9FPnQ2J8o2!kX3A=RJ|eWqd#U0BQpyT`Cp3{g1t zGfC7d8uf~HML(;s!m3cWuIxGe%)K^#s_dqBx3-^=95|P=cKNj}re)!gcdPY}i~2>^ zkKX52ul)WZakyD!#icSKt!c)>j2vh}`}VSr4cGZzaOj?Uu{o1m{lUiM?8wRZu?gXG zbhFz0SDoGEk<>v<7>~yFmZhxs#Pr8rfk~~@eqMfHz&njm~_gxfJ( zPnQ^-_7aOO{qmC-mI19K?#rdY;04!hd-c^U7<1w=Q4L$*h~8d$0z(eqWs@ zufYdpa-F&GG_z&7xg+kjb&>f{6UR0?PGC^KXm`?d!Si|Xt06`oJFWEh@422L9_Vu0sgI2*=o7klZVNIpiiEQ|(sK;%WM41AHT3V-rT-u>TQNwr z>G2pXn{Ew=G-6E3RBL!V;w;O}{cB*jV@2+Q%i-MxGpUu%Y5HcRWI>Jei2M2##;4FC z;Y`hHx10A!oww|8`uT=O&w`hd#!jy~wI(s==9r`-I4YM*Wp7c$tm6&ks4PR4VhG`r0s^E$~IMebNF8;^(E-|_PGG?9i@QdpDn0YZpx=}J~ zy?uQ$U%)N!&+#X)o$Zq{Wielvqpa%j8VVme$c~=%4tjU0x9t-#(=;qScYZb5(6E(M zvS-{%RXYJj~9&d z-(ULR4_HWOYwH#z+`IpJH83?C`P{&u{Lx9V9N^l!1K2$cCg>*~;z%)lki5Z& z&^LP6TkS`1=(k<|uB$=+(X)62{Jf~jYCeDIhK`Lx%DN?|vV@i<#l(*D<2R!V4?e!Y zZfP&Ls8JqGiLh!%XmbSakwL(4vL?HEBD_#SZ((6X|DG6LqcH<;Hn(t#ZmHgk zlE^Ck#?-D+jVFBHvqdU2EBd6X+3Yl>z92m8VMxx49SRC(G?tjs z!w$<3Uy5Q%4S(t$`>0JkXCd~xJ#*p=Vv49{DhqSsSU=p*H}Ywd4Ofz!+oHa$-aK|T>tPFVUOzvPqh_Zoo9Le$MVMb zrKNAmTC3)V8d*#u{{GGLz5_;92DVmZq-INHo|4Q_w$gHFayQJlo1k|wWL;QXKP+ne zU`cq3M9ggEk2bpTObrht7-vVf)523Bb6wVnijUb|bM$X(tA^Ij-;aw;D*i0I|MgW! zSERso(@m@uAqP4-C7lKK4U=xCep1lE=?h`4-zXj zOpdp1HddKOGyk8|>6jdFl{tQR&Dyc#lc^?cs9o9FI_TE++34li_b#{NFATHH#s#_sMB(XgyP?=R4T#LHy+%-tD;H5TpsTAL+d3*pFg9fca{s+uG4Z(stu3n8XRJ! zPyp`~v5q@z|Jdf()kpM&Raa5!2$G5!|^7<#Wf~Z*NInDL-h&h%@U8rAYMh7*STJQ zf$!~xRiJpR0VHt~(j?uU2e+&b9MhBAcUA}V?_R{bhE(L3s literal 0 HcmV?d00001 diff --git a/pict/file_b_alldel.jpg b/pict/file_b_alldel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e82f225dddcf276465c90e7be790bbeddf72efea GIT binary patch literal 1789 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 literal 0 HcmV?d00001 diff --git a/pict/file_b_check.jpg b/pict/file_b_check.jpg new file mode 100644 index 0000000000000000000000000000000000000000..68049e674a4b13538ad1e65aa330177c31571ef3 GIT binary patch literal 474 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMpiYkC{=Bfk}{&S&;Gn5rz^5 zMn<3;kpL?jBLg$47$XZSg8f(-Tydrp<-_*p&sbn(HXyxd5A zRc%kFSVIQIP3sF)`Z=?NxFu`VBBQPg#THMVF3b`US*~597i{$C^_lx(a%q=@opW{u z=B1zAD(Lam%7p#dbd8sbTe_c|K9YAYE%f{C1plpX>!ykAW2sc?OMCVv^=qL1l*N7x Y{=PAm!NSL{3a`59rLpvy5c~g|0MHm`@Bjb+ literal 0 HcmV?d00001 diff --git a/pict/file_b_expand.jpg b/pict/file_b_expand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..86b720efa5126dae8d836e156b9cfa4f92a87626 GIT binary patch literal 2292 zcmbtTXHb)i68%CN1PFO&zpH?XJ>ZKp4~aKGrKjhH3ML5tdCd&5Fr2{ z3j)}B4`3}50>YC42mk{Bz(hdt0JJ$d+CLB=KM^pHEe>!AK)_%yI1B-YBSa8_6ct7w zghj1O7P8e16bk&oArOJh-+%}~;RqN~Ktlhk0fS=z2ox#=ML^*q z|4ax$pfD^P0c=y%#hI&>Ns{q?Qb@-OdipzJbMMp-&#GHUV+H4eB47w10Qt`hL|{M_ zs(WXfzdFp^F&F0-dqK@fvR?1Q)8X0mLup%Y05RylHBc;Y5a8Qh;uxkq)%rr1GQ zu(G6R6)6Qf_H=Alu}smX|9P$x^zM~3ix`_l20X}rA>%>EnblnOZ*9(4^{m}dRnO~~ zOCiie>r^xa8cz)lYClwcK^%?EO!7>y+Us&mvik0sBqM&Pa)#!ki9<2uiS^FJ7@Le^ z#dzeRdKSUV!qQovIqX~;#@)}$)G4lB1+jUgj}Zyy$GFq-=Xa3Bw_TUwGJA>g@qFetMpBbU%ZB_(PjZD}g|({fcEhfP4HMST z+b@Tu##5r}Qq3s2RFM$PH;*qml{PY$D|FjB-Dy?ox}8z@=dde)NEhNZ`8BYu!Y0l3 z>3%no3#E}!hA>!1Y3RRKwm|p!uSFzhETnyZ(4TF_mVsI9&_dPrI)ynSWPSd;`{b?P z;j!>5Z3AnKr<$6({Vej94?KnX-?LN~$h1Dp-!=3V)1hr@3UoVzim!4;7G!q9qtsW# zUY()(IZ!9Equ7schWhNU6&(Ak2BK3}#A7hlh(@9{o5xaPJV@qChf^4vUX$teJq{u- zEnMc@k6H?L>9%puDTlkm{)&z}LMMuezQAtA4Q4p(b>s`Bk?rNJ=53wvL9i1O=ojj1gq|7JF2j^g793&%gyIU8utzsDLz%O$g-a@lK$S|Ch@Hy(ev&b2`sg|thH&z zjR3EVCa#bUYTE`6%+y&R2#!~O-m)+}DNCX@!aQkGq3g_s#C57t`UvBiiQT!fI!;TO zIzO%Q`uQa=A{zfpHp+k#$({b@l*u2CN)gfvI~&-2@KeTGOkQXEn$I>zzTa=X`#&yD=%#_6^0^JszkcX@&Ye|D6Vfn^&Y~)l^9u(;64b za^7665z%}gb8Y;O`$?|`gC!_mWzPrfwmI;y7p*Mfcd|uq_S1dQP!*b%K9Ij;)0BgH zrmBC^q}={-Rv&xRhf{dHCqD7x?U?b~rz21r1P2y{&beax-O}$LqB0k=;#7q3&CF!D>}V zQn*$5k_s-6vcQ>K+$SX|r)v&c@@mM`g#E8y(^{*ZC|sA6UwL^09j0Wy6mzLF;sm3` zz^i1aKP0$cbg|~R8}XW?t2g*0*@r<5lr@VtD&&^&e4QPFqcscrx+Z2tXt(A15mPhl z?s$iuI?igtU%Pm&MnSzaJ&$d>T0`nMdbia`Rv44##(>L@x2N+9tH71)kj_mrG+?8~Aca!El3}=P0R_H6oL!T>Y6VC7eNQ6Qm}$54tN zU+sF^%x6t}KiE*cr^qFADf9#9=zOg)|CBc?mapfV&-v+g#a?k-quq9R_1C?ws_gLm z6ZmDp`?}1Ik_`K6^FF7ZtNE}}PG1=BPciLyO^F|V5f{F|Ql93v?F(6IG5qLzBYMME z$>5YX{p%i5)3;hQeJ|7gbW!>LyV;@L_SJ`9M_<|SxQPiJO-WwE?@7Hqr=kuF8e8mH Pmx}$-xUxs?+!p(97y|ry literal 0 HcmV?d00001 diff --git a/pict/file_b_hide.jpg b/pict/file_b_hide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5689c05b18cb36ce96a771a697cde40c99d137b7 GIT binary patch literal 2112 zcmd6hc~Fyw7RA5h%R(T8ge0<65CRCYD9Dyn>*3<= z0zjYuz?2Uln*(svgk#Yh00O`O0N5jsJ^>g9=Bco7fY~fhATkM%4j^DK7#xOx!x1Qi ze3cXs2n8jyqN0+bA{vYSudry03RVS!#^VVDJpLOkEv;{Kz6ydwB9+m~>R7D0CJ{%} z{CfC*jjS2KDF6f@2ZZ1NC=LSRAhPE`ft(Kxfygnx3JSvD2nbRhg8zGffG{W=3qU{+ z3L-!R@}CA&9^+Ku0K%dIuj>#>U>fKVk-qE;b(UN5ZuL!&cI)Hh6$lc9!eQV)6$pTX zg1Q#BRKrLx2VZ{2L)mh_m11i;}Ax#Jsgx)(bmZrgYwx5R2)zcY9z1GnQdJXzwr z@j2$b(XZ5T!?swGDr$~@`B`E*Kc4f^(lk-OBkI^OeKE5ytB+WvpzQ06nYx>Rh=U6Y zqK~BEjwk3gO+49}IXAR~_102M+sxzeA_>>iG9yLY6v5MrheAX&X?Lv43MzTNU$hhv z$}PgMM3-vO#{&|a)#?b>2-Ww>IIgpobt>|_4JWtIAJj zG~d^^Z4;g_Vnx-kY7B{xXq`t{bWm$O#ca2vgC#WdVQv$djSP@Dc@DGO`B6b|(G|bc zfg$#x5@(#Cii(>r>8-Z^H{V4Bb`~lFrPvho-+5HcU_0Mg8VMMk`TS9%-69L2&g*@E+b) zVVC?}O8QjIyT_AC20L{TcAc<9GUd;0xzL4O4fzv`UZg`2GdI%IsR=00A4NhNjOnV8 zq^4kA$G-&sA3^%tniMKa9AvHSF9W((x99F{WtA;HVz|2VE6D>P#Nh$`U2e)1H>=B( zCI~dD;LFnj+RdLWSLJA^&71W$B)_2coM!WKvy^m7KFY`QuvVqrD;m%a*kTx|p zOmWOn1?xELnNuxoky3hRM>CS8qz^eS#Xsg4c6PdSzbME{Bq)s72IRc$Y$$H3EOSXU zxtEkm`7DULJ(V49fqrlHOx&eyB`ke22%6Q|9$ZacEIDsZ8IrV2a-XD96ua7AqEs^c zWPs29L)qiCAC{_7?271$b9tXVqJ!T)@srZTpE@G0OnQ<6T zGFZj@l<)+1W3@Eg%){8g)t}5G+35Mqyjm64-1c@{+%T0PRrFgWr4~}Oho~chUQSPhP z9t{NdYLq=v!IzXWbako;Z)oNv_*#mX6yk9~!YT@55BhPSWk>kaz8_D|#)li-;9WUK zJ|Bx%$iC4wzdDkW)N@5~vU&0$yL>ynH5vZV|L9Et)qVYdYOl75<@CYr zvyZF-e)&#%fIU4Nzk}*kz%zSbqGW%n`)o&PZneenFmbZ?x91Zr_X~}q?gd?%DcMm$ zPx-6JT;q9q2SdadpX)So|Ni;gCk#)E(jtwW=AU9H7R;RZOSH}WUcHkW>s4?H6BX+p zD_ESke?~koO)8X}N^A>sDg31&Fz9-KNzAp&w=@^1!{r_$-gyRx=`x`3vsvH|XPcJC zzF61mE|{*pTeAzf`(mlge%&sKR-a0kA1aaBtPSnk$&>p0CGh-xFo08%9O(1@f!%6C zNE3Ta(;{eD2GDydd++1VxfuOhJ>id;HhYz+FVvbb?@#s1s|jay!1eX}qgT65a;r8I N*lW?Rj#|n_{swoso7w;X literal 0 HcmV?d00001 diff --git a/pict/file_b_md5list.jpg b/pict/file_b_md5list.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9dac25518acf9deaa84115d9156f7e9b62f0dc34 GIT binary patch literal 2716 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 U40*P>7TnkN?8n1yz3q{I0^4lZ&j0`b literal 0 HcmV?d00001 diff --git a/pict/file_h_acc_cur.jpg b/pict/file_h_acc_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8907e17b7b98daaf1e579501ba8d72243b0a4888 GIT binary patch literal 1413 zcma)$cTm%J7{JcyF2)4Zz?4 zu;c|~%K-97j*L4BU;qgKaFt7MfHH-3Bq9p1Zp#&zObRjq8i_=rkZ2SNt%#O4RsoGx zz~YpYuu4ieJnnDsIAs;QiZYHsAQA}#Z7nS=ZJkfRFc{1h+?K6){8mj8MAH0Z{NF)# z8$b$x2p9+$1mF-10l{Sb;4}bmI07b*`3X1@1w&xaFd*0eW5DDN0*wbS1Of?Aa3toR z6F3ZkgivUpr%JG*gcC_*>phA3n6#qt2=@#%=&x-#sDD4f00dV>AoZ;FP|}LR$%Mqp z8$AIi*)+h(Q@|kv1U?6^LsFs-_BW()I=kvU6JMM`l52!7s)UAwvEUP_x3;c{8Kz%z zk?tkV3p~+uRsOA-^)a&QmHZq_`{CGHFy zEv}|i_DgGny!9Q|f_)=roF^<%ItE7-?`|JBbL0lLg4$};l*&N$-6+G z=jCpOT{)BL(ZS zMKhEK7n83(inzHah!{j_P`f-5vW|ueme0Gb8kTsQ+vPTzv8f9hjf!XIodW)ls4bDi zTKQB5Ml6GVj7{KtRmaCC#`vRrz9spwXXkn!biejk8ZVCud)e%iKq6HWH*dGOgqLxf z(e5(f+Fuu#7_|QCOKTcd^Bd+s!SBhKkQ|}8!z8bCg-)mKeRMZ+=Hw%N#q5OT`j?U1 z`Csgh7u3^i@@a=dEhBxqH55w?9FaE2LZOv&m6B0~L_O+&MZ{a;>j%oJp#J4e62-{s~rSa{)k-ezd-;`C7FevNd+ z6E(#RgUu?vO&uqnF3_cxcW<^koN8FDe&A>!-DNuy-bJ?XJWqn@w1~S(*0v>OGaK?d z8@bm$WD#Qb$4z-gn-*;jd-fgXGNZ0{?C!8iJfz)D+c%`liysdo!sk`KTNzC@u=4w0d`$+* z_++{ZQPdEm<}X^X=1J&z1${K{XS&-7Z4}3!7wy8#?5D3rtToO_0w)<7N6!yNBn7P| zE;iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBiJ4K5fk}{&S&;Gn5r$?4 z1}0`kpeqr8iJ66!oe>BaP$U>Z;%ov8jLgg|KsF~-6B8pd3j-^gprVklqoGKkl4xR~ zQIm48Nr)J`AOj-{NHr5P)Nn=yK_+G)!$20r#)*!JO2UN)7j6vte~W# z!>h=$)Wjoi8;kbtTjN^zu#ZJ)$*PBoR;hJ<<9Z)2?k*QLt?OHQLPyd1nD=4XF@e*I z=S#5!g$PbmeReZ9WV?&Aso>RYfptN;0-hl!cte7UV)9J4?w-@V#Z0$fUo72HaY4e> zQeW0fDy(1PT~}$&v}lM=^Eqt2v|Q`x&BRXrIE8IT76$daJelEmQ1oI5r?-Suk@-5in-6XffPPcwJpYA(s$)`g-)>~>$U=Q(hnYby)MVC`l+}}i|nln-O@{Q#; zWe-(W#_983i<(){EO}F-Rd)N5O)L-AomkM~v1E3|f<=dy__r8$eD(Sk+qvPR!Pi&J z{#-A7WtO>2tmD#(x++u6ACvk3WJ=-5kBeu&aeB+K?DMN{D;1ZPZxr{Fu`GJJzE`VO zIQ_`>hcS=dybjtiZMyl{f|zcDQ`7f8*dDR=!kr|+U6+F{IbU{|J*hV4Ky$ZOgI4sf zRpE<|KRGn(Kf{&I*Dua4dVMo;&Ngnoi(Tp0zUKt%eG52Ie}1FZl{=|*R)U+{xaEpt zk6*ueMK(=s#jgC=Zv9nGPDaPotmGbl+bH2<+@88rTYA5F#pWluNrrQhjEinoOQ-%g z;j>fmfZ`05+Q81M0)Zw^U+mWU@krcR(%Jasr{u?FAqRF?d{Ny z_#n**x}S6(B?Xxm(dB`|dO2h8v9_2IQU7UTla$g6{&+FjuL>wbOO9J{n^$F+$ru7V;ifr1c9 H{Qpe=p7Oib literal 0 HcmV?d00001 diff --git a/pict/file_h_chg_cur.jpg b/pict/file_h_chg_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0f987ce883e1a3c8714efb32b5eaf8452c551064 GIT binary patch literal 1409 zcma)2dpOg382|qE+eI_B+0-(cRur9uE=NV2GIO6?MiDZWByvrujxKXM5ssD1q!4PD ztP?6n%G{#Us*&4?#7V7?gX*MqcFxn&^PKi;OZvc@Q7Zi2`KmZ8(&(ISBXwjYJ|*NHhwCUW8Vqx*8g- zrjEm6)v;I{0rxKmI88hOuZbg($Yc^pmrAAT(!K%0U@#gu4GMuk(a|Pq>wFXbZ=q}k zL^VJLJ}^WC2qFX%A*B=~tNfuLNM-XIAQ*{4BQPowhW?{K2pEM%5M10?))3ZWVx zqR?QumKljmU!lFtZ98T6D#o^+ixTe2+M@+|ZlL|!f8qjLkv&6{Q`&A9~Om7JF z7j=2Th2#!M9Bo@_)-KK-h)dhoY5BU1GQ%&m9>XptZLP?{H>`GWW6Fc)erK096};+o z97DT)4CC-t<+bi93prZ+hF)P3pUCPA@Vfr4u0Zc_d`<&<_piGK(xnw4c4`s=h(kK|qh+i;HV@f1k5%!p&F z&vD7|a@M#VhFG~oo9i)H(Y9fgSS-R=w-^GW9WYBOGIx+x~E#&lo4x7Yshs`!Jpr(``yu6Y*0zIHjXw2gRJPwjKbdz^*m;wOUvO*dRawAbiiPhY~MZT<4pII8Ya zOd(#;c#p+^@r`#E9qQsuT6A}womSJX-63z@(e0-l=$iU8!TrLml)s1EhXta*z8V-mZ_O5Sykh627C6*~N zu$xhWIJmF9;pYX<3^?@I+)b#g$1#u@#2-gWVYuqB-NibL8!#X}yA) zaj|vni+L)md}>Rc7r!T{pCQyg{fE!6ozSHaHQUf{GRnPOq6DPfReioo%SoZ3RV6yi z4XL4o$ICC<*e7Re(5iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBj+s%Afk}{&S&;Gn5un2u zn3$LufzE^j7Di?!R(3W)7Ih3v z6k#u%=p@L%$P84*$O$umkwK72QHa?w&@i!3m__MBaUOe3)&(JmRI%%JWx)MeVj3A#{HM;k3IUh)UcGLTy^@5 zX%5_3GmaGV*-mkq)m<>DIBmoAEvk|K88#TQcz&77P`BWq+hf6%laJ5wb+-zey;`PW z`M+quVXuT&*-w z%vFA6uxaLvCHrP)7@n9UvBSIVRrHJ_OV@j^yB?j@Vs`560+prb8#k$y3;sFREYmH( z8}wlE`ZE?&XZ7rkH+Q^p*^qbBZckN~DQ^tiS(T;FxBa^K@e|Xv=`TXwxfd*{tQS@> zd^~G`M<9pk#!Mq7pLY|Q^xiJ=-mvZWTdV!&C*HbQ!&R=lBb;67@tXx_I#O22*%~w4 zp77PnVOf$A=SJI!#>Rpx3R9|cS8YF9X}x2eZ`1RgdhT6EYo5wH%{sYhs-?!}*e$mUMGzcsKdUocfuc$_sDvuZVD7KE;|p zRa+yqC2ZD_g+^+OdXXxz2`-Pfe_pp^)1zZ5j5{B%(D6F+Skr83RQ4bCxrcwM=}p;m z*Uq_Y&VJ)bSt@-~s}AY0vDSO+J*9A+dJB~EGeHan`M`# z?Of$qe`T&yJJ0+&xv!G*H2>ZEMnS8(P`837qS>s^It#x{kr6{#-7AG58~c0x|0wyJKX2`nYbw#9Tx=`DZ99J L^a@HT{l5tSPz1a0 literal 0 HcmV?d00001 diff --git a/pict/file_h_cre_cur.jpg b/pict/file_h_cre_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0df3fc9a0e82d51b3fe13e458784b6fe6a05471a GIT binary patch literal 1389 zcma)1doQIyF=Wb88A(x;_p>$z->5x%Vo_ST0WlOVjcK3A7{~f0DyyvS^(Ot@VKxD5Z<9;Ams?)0t^a;LZdKfG)5hxYE3K# zgVn@oXlQC^;0U{W^9vv(3XMUiK>&gLuYiD%st*W2wE!VdXh{8^ z6BUhubBwNpZIW!N6Jz}ZL*R;?pYC=3GmuK@&Lgbvbx;fZ2}Qi%y? zif>vwz4fAz(8^~3hg7-3NEqw}OMT1lv+j+Tb?LfZxsWXRldZ5CznE1fOwoc&kUmwW zX8tc9QKC7fyassiLamM|MZ3#kZ#G0FY_m7s(;86xcxPgv;X@=2q3p$m=@2D^9X_kJ0@JJ|dFb@6nkTiD^dWBoJ zT*cMPF_+^#ZcObJo_anlCEhZix#l@^o<_6stErADhne%yNh9gsk2}T@JR4*8rw1i& zYl^h)HsX%1>k5n?{QY_^KlsB$vt`gP-s{Dw`Cd{T!LcDxni4Fw4?JloWXlET zFdIaErWf_ojK-&`#rz(y_iR5t?qPzd@G8|uZE3neI6FTVX+pZcjCkzf)eR{In z-hCudtZhRnePCl5)+NpT&Al}vkWl4HT&Uz%U7I&P>?^!Dd%xh7JXWB$%}~3w#7Lg+ zNF!9we}##^J=NGEw+OGe0YMf<-#>d!ujes5Vzcc@!p zJPDatOj-=6jc1e&TZ~8CiaBE27-_$=)037U+e>8CFD}$?UwBiOJK4nH5CCUD_S#9i(y~km!f*bF&!$6-iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBnwe3Mfk}{&S&;Gn5r$3% z1|~*Upeqr8g^7`wm5rT|k%5^JNFV?s6Eh1dn*akN3nMc#11C%uP&rVTK~P9hN!ZXa zFtN}{L{w~IkqNuFAOj;a6EhnNJIoA520i%5q2L?~3x6Zw4)7CJX;oWSdNz4ANt;t<$ zvP|oMyHRAd&<@7jR|Umu!a^A5gz+BAj0xjWf6sfMLXhK@!oCcqwGFK0r*!W#R zwj=V0)wk~E$*kY5PSl&b@94*9YXBeVO#rXx3rtRsJVFzIx8Mn%iT-or1t) z2fyFS=nxGRn8-7^O^E%SlF0BzuZ|~xo`nF=>a>dXohw^5>-Btd3YyPvH z-%cM`@y^{~$+PG#vlm;QUJ)pn;1R8+=17YtP#CPN~{^(yaH6%*xM7yJHR)DYq0QwkvOPe3)AC z@d?|h-{to&UNgOR|IVQ~a*K}l)oClIMdm-)yzNF>`h9Ika7cy^mpNAPZhllew;M4<~^-jpmpkY*Rj+m zrp1elf-4QYl|($1>Ozb{LY`eJWsSYE&uU4j*yEBJCl@Ld-wK&sWXRCt6t8(8@3d{z zrEOD>ue_uZ7Lla9^^BR@#T}2Ea!=)6eX!4ea@Vh_SKmwn-=9<>P- zzq~c;KZEv(KQVS6Z2mI{{wbcWZa@9W^XGr(RM+l0|9kE3f2VdCYrc8-oayu UT%_#c*3l~{rDWog(f$7>077@D6aWAK literal 0 HcmV?d00001 diff --git a/pict/file_h_del_cur.jpg b/pict/file_h_del_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38a713b9ab044ac68e3479d4a1acbeef7d355cf5 GIT binary patch literal 941 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBkeN}Cfk}{&S&;Gn5r$@< z1KAmY1OhNJF|)9;voSI-F*BmbFfy^QGP4OVFfuc-GO@6*L$xpi#RXXz6orJ@3`HCh zmDmd#RYWHmEpkq7Ruu#)1_D;N>5L45OhU{oiiVDXi4z+)DjBip1%AG&c;?xEfjflZFgY$BaiF0LWj*Av$-3e}uvQ(~y9apeKu(`kFwHAIJM zvD-ZSyf%3k*IS8zF89{;lfLvk(fCwx=kVK|>+`!qwL4CWJ(y}T{qvg{yM<)0yr}8! zKdW$*@41jC&pL+<>XI^FrIhFOy6wzfDz@5hM$4LW)=jn|EeCI`-f@CO(<5U zI;SyNFJIEt>Gh+c@-f#t!K?*YT~`>(ZY-E3A<)L6*vOfDXZ@nBpN=g0qY|mH_xQW4 zpAS#13*tSrX7}IzZT@@8?yfC*Z}#o=-9F%LT8h{=W$T)*Vr! literal 0 HcmV?d00001 diff --git a/pict/file_h_del_link.jpg b/pict/file_h_del_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..253db16e8c571653a3bf19303e99d324defedf21 GIT binary patch literal 694 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%ErhM7^2fk}{&S&;Gn5r!HD z1}0{pBar~mmF$cR%#1*QB+A6h!pg`dz`)4N%*4tBQ~&|Yj7%&Hf~-PphQh`oqKfQ} ziAu^Us-a>)E0};vS>R>^15A)v(NM@SkR`Ek;zlJS;s3W7c$gW1PGJ^guxGfq>E5G+ zk24QFI4Q5FuOhI?k(o`Tv&zLaB>Vb=>o@hLeO=%0&pWd+g89mo*V_VkvsDh>ueK}G zsdP+T%q8gYVe6;3iE~=z7aw~jKkeDx{bH-)Chm!8-0{);^H*ERknWvUa*u9*_Aqol zd1R8a_5>ZyWA3(Y9nTjBu8V%@y6bkUa$@Nn!M73?))L2-OQi=t$mhx5IaBs{-@$cZ zEPHY)e8NsKh;k@d^hFC^-+nbu^rG9b8&1ZB3ipnjd16rHuvax$_wBS#6J?6;v&P%i zRk@{=NE9j8S$N7inHfx)@zAFG=;?()Ta!NB^CU<(&v*SBmQ^Cm%QmR+DshM@tO6X xW;g%&&rtg?{^|byJM7`X{_)E%|DM|XbGg>jAK#}vySk+~U`ne12+se1696^j)bs!V literal 0 HcmV?d00001 diff --git a/pict/file_h_gid_cur.jpg b/pict/file_h_gid_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e775b344bdb256afb445770a8a9314b1a48a64f6 GIT binary patch literal 953 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBkeN}Cfk}{&S&;Gn5r$@< z`&bznfzE^hR-oUQ*;&{a8JL(+BtYUUtZV`dj4X`IOstF?%n&V1j6h*Q21Pa@VZ%fv z5q8JG#)(FYl$}MBn^gosidmQ#Sz)F#G6(`qQ8aWE3QSa*xG+dq)Kt{o14_vObx$#wK&SFNOn#}krdyVqYAycdmCc~ zgWpQ53kh`GHq2%&XMO4Xq29MNcgm@Y>9w=nY?KUVbav}X z_g{_pxZ^6*g`KHlqS>Ost$XhsNp#_4;O^V|YgeoJUBlHIjN2>iF6k|t=zV~n^Jnp# zdG}OY9~WGlw0?qc=WR!eM=wq1O_R{v15{NlMS^Z5!04wWu!S%y61rd*+w% zd|fa7L#|WiewROa_4~`y+cnu9@@)Ute_Q>#-0fS>^DA$^eg1cL=JmV(^!`nm`k&!r OefO7FR!jE(zX<@C3Rgw| literal 0 HcmV?d00001 diff --git a/pict/file_h_gid_link.jpg b/pict/file_h_gid_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38833628098e304ee60396383c984734bf865f40 GIT binary patch literal 725 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%ErhM7^2fk}{&S&;Gn5r%pO z1}0`kpeqr8jfs^VD8$TwD$dNp$i&Jfz`)4N#LC3V3e&^H$jlKU}-Cm>*YbNBqHp!jXc;nrcM?PBrmNQ;t67^~6+Ph0XCjF<{lf;IaFYYA<&sIzQ>~5DS zo|asYb?0)+_iB`MR{xo#0!QlrH+$HE5w~4gOOU~UMb#U9| zE7w=Ne0gc-=dz`SYFD1LR&MyTI^1Ay+?x-6FNG&MrfDA){qgbHp(=yf36HfkT_=gU z8<)nPv|9Aze(cs$JC3<$Ha>Iw5`4-?NG0jjG;@)kN-^46_Zm<7J3V<5%P2ol^7zbc zTTZrxi!MxERLFZYUP-rZM#=gmlDXG58CkAnQFExDzUgVo#y|ae53cK}$P{iZdQ#ky z$M2gcnWHYbE;&c!Y*FVozaM9}1#7#`{*)u}qT^VSn$8yatm!}BZ~3k|`%NoM fYyI~ry#KfN{O09vUZfoEoGjSLaiAr^>HkdtCnfAd literal 0 HcmV?d00001 diff --git a/pict/file_h_meta_cur.jpg b/pict/file_h_meta_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62d64d95d7831aaea0fad1291bb29737c1ea4f14 GIT binary patch literal 1080 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBj+s%Afk}{&S&;Gn5rz&1 z1}0`kMxZlcfSHwng^e93geK0w%*X`vfB*v{Gcyw_BReZp0}~@Ni=YrI1Dm3ulCX$l zV4{(eiWvLCgUZIDfbcgkRun&6FZtMC-}r5`WYenh zg$MsMZ&iCzY!E$5SB~*Ow$|q_nbYQ!dN@=sTcNee!SnF-U|pR9o%v-)xHqbN3fuSf z=C+mfd;7ME3WlFfni>~xzdQ8fx;mpDqLvdM3C_OrJM+X*%{^O`yV!cAA1f}+mCwFZH>j z{Ob9#-W*j8FZbKQZx4RcdNM(U?VG=0w6jWdvU%ssZ6{T2#heb#HNBI4Uih79a_*v| zxs5EMube`>s!LYSYK%!yZ*FH=*d89%yV;ZXOGxp5hTd|$Z0_dU7Z)5kp1jb3-NPj&4Kux;tvO``t~{?uIhiP1kW%d49Aadq!-FzKvn`vId{(ZEKbCB#)dG<~KBY zW%6-~eWT2`pYd1I*Jejmg}3chpPM(mbm}9ioqA=`^UHFkNgjKbli+=H)6(0gABXg? z@?3fGU=shKrG91~zP;xAx*}emv%Ek%?#99F_R_bH4os^^YfNg?DiT_qb(QU^R7`8A z%eJZ4%3NMA+&x)1SCuQnX_mmU7X6^D56?RZ?pt?$)?MSBQ>_E|rbNHYwOV~@-rvAj q&E&WKOzz1CK3I1?jlB8hdzRUE&C8{^ODjHI_DgPG`DuI=H%w(=K}(Mey}1a#RK7?>VxzCA7BvVU=U$YXJ!;+U=n0x7G(T?grSRpfr*)s z5$H@fU}t6HVBuuM5NBaxW@Td+U|?inWM*PvWrb=0vDw%e7=?s6l#G-`1r?o)#eQ50Ibc8(5z$364Zx=E8CoorV37Yk&FKVx;tRMUl1_~Eau<|UO3 zys~oYTujMs={JM#&)RU`H}%g}pO=amPS@XGyi=)v`fva3ReM&&zbbyHs&hFuY02y- zZ?ayQT-GfTO*~_qu95OABHb!*CuP=(i}BN&S2|i85l`Kj`$4o%_NK=I!TqMfi_+e4h!)AqmPMs)l`~Pu z_!#0^P|db+$zkJ?p6Zo#@3*{u8n*DxUAgJeF_XE!=rT^Vi_DMcxYYlUBlxVfeeCgN zizN^8zN*~v;PuCQW!CHE+l$uehD9K` z!mk#8e>$<`{DP~iMES0E9GbZLil@kwkAJKD{FYg^&E=HHl4{9g`?I z8&@(M{p6v%K6lrvJE>u(@8?cfS8uzu;lq*hZ?@H^t)2Zh`mf#51y@f;mw$Zce>Z8_ R#f2OfS~8qW6zl)r1ON!uMaTdE literal 0 HcmV?d00001 diff --git a/pict/file_h_mod_cur.jpg b/pict/file_h_mod_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f08924e959bceefca05ed73511f9af94e2dd61b0 GIT binary patch literal 1364 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%ELgqcy0fk}{&S&;Gn5r%%C z`&bznfzE^hR-oUQ+1Octg3OF4GEB^@jBG3d42;ao%#3WzEZh)nOpMGdf~;%|ib5iW zj)6)>!il2nPR7Avg^d#z1|=ywtE9N92?8}Sva>KT!)#(?5M*LjGz?4>5@vB!auR8r zcrZwr_5Upf9-tB?L1sY)dxn?C=OiDT(Wa0ua9<{UW$si~N41M0tJGhHE?9SWclNQW z%eU`*jFxT=o44|<C;Eu`!=oXdMp2V4Zn-q+qTpenK&f@N*DcEM5#aHjGu`EJ^-9CZ z$wkWhRlC=iC%d^s>a(P3r3tBMVdL={FAeP@vI3gHUY zh<-O)GkbA=@Ym@VWA5}RdcN5#nq0o#AnLPlU8PR{++B)&Pj8ueEic<)@s+>xm*!3x zr*xw~zT0jUp1#76`!P7>RIrAck{8#aRdFd!qO!X$$I4W-AB%T2SMG3KbfV=+-PSmv zwuV0C11p@I_Ra}4i~1fMR`?=&w&=;Tt=%^ZC3|jng=93mZ1@yWGf^(kWz~i0r%%mK z|NgqD{u!@X+&+m2zpX6~nuoLu|2c*2kX(t%}0glUJmKpAMR6 zq*9~U{H5+EpIl`2b|Y<};;^E&{2dy?a~fRU9H{OTY!7(2?$wn0hr_Brs0o?(#`Bk7 z>O08LIB8yJQ|e5GI5p?vvo;8CE8V)4QNCxLcgYj8M}n(W-*V@4XCL+0nSb-{QaN9% z9GeRj9SKBHz9^=Yp#rt zvNVTgzYslEe?4SGRb9?tstFsNi`bVZV=0C%OMCo^V#}TJFBKy?Ee`$UhaQZa_>LG ZuYdQ0kAJJ4V;^f;{iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBj+s%Afk}{&S&;Gn5r$@< z`&bznfzE^jMkW?kc4ju9ATuM13?maW&<6qxjLcxb3f0BL$jrjP$|k5NWGF1+sKg$a zXjJHA>>Mm62vo_)&cehDGn$b>kcnB*FfdU_n8mSiqLY%y!Jwr7w-|Vs8G$Zh7G$tz zxZH1XyxEY);hy3?i}RCiYjHLCF4D|W|FPXXmRi5nUouMI^Lg5dd+*|;zTj;gNlpT zE|$3(IbA6Iec|E^ours2OZ+U>`K3v8`)T{dJz(x!wjgMx)BTd0UP}sJ)ouC^lIJck z=UZgg#@*Lv=vH^`ubJk4?_Njp&QjUnkS{A_s@kvo(A+8G++FMY!O_QN}$e3HALzg|WEcyIbLzf-ZP zHpjV=6nhZQBCnk5f9*3Xk3o9TU%o7r z^R>$1*;+IA#?ADn>V82*%n|b^C+zfd*!lvOc3u8>_2jx!0dE)2U8l=o ze9${6wlpf}$>nBdWBUo_(vm=JJ50OI3;#G4{#W<)H#e|latcciZ*u z71>fz9`TO_wRT_U))ib(<}nUymG;y=AG^=u%>12(D!Ki_x_8%a=2bq?z_;35d}fi= z@=24VU)=iSC$%)!f4UFb)z^$AyR7e=nzU3Y?^Qv#d;gQ<2~qD>x0&mycza)ayxm%f zuj%7S_Q3a_uT0?d?)a*IZPVShN#+tWt+#C08SOJi*48LE`9b)#eFjrgEH?IKf4=nS z?$nrg5lPR7`Ul*_zm*+~zMcEp_(bPA)jylRnXT>$x^UWOUDg++jxHsQjzwUq`~OV< DXwIK- literal 0 HcmV?d00001 diff --git a/pict/file_h_nam_cur.jpg b/pict/file_h_nam_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..19c3d43d6307aec2b3699edeec4a9e931e684b72 GIT binary patch literal 1097 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBhnZ23fk}{&S&;Gn5rzf^ z1}0`kMxZm{fQ6Zroed}i6h;weVg|ZjfPs;jnVE@|nH8#@iIJIwL6B8Zh|N&gF;Gc_ z-N;EaaiOxY3eXZJMn-lPX1KwOf=tXpiiVDXjY=$u6P-jB9%TK0i-Cuk5$GIdK?Zw< z+u4U^w;Q+o6z@)3{Pf=Olj`DZer&EyqT-H`u0b30R?VC05^^zYS5d|E#jEOdkF1`y zF1azW|7nEg4Ufo;(|D3MX=n@HROxyDEUALAmy12@$SUPBiNcEJDZ30){>`|MzopW;Vqzi9L z?3P`7x{$xCba{l4?bW(Nuh$#CNekz;GM>EHH!VagH1PQ29ejOHTw`F%JQw^twUSvGL>RkVf3#0DZ#Gna&7Xvy6(0XOOLIK3X>EiLrS{&GhMK zl6FdNlDOyHb%dEwGdAOf6dQCR?9bz4$BPW!dFN z6N8l>)rE`887LjD3ic_|l(aA4KO#P_?}RzsTxAl6`76U)VImi;O4gar4L90U zH9bCe>Fc<=D_&ima84~}MrG&p!0p=t{;?FFzgr)6Ui#j*5BsLR*!RuWSS|ia)n1-A zmi9Uib&PwT+&D13JJoyp^kXX}xFlEJJg6eS)a%yU%jY(HPFhxOvb|g_`*AeiW8oRc zo<7)aE%W0<*YiscerT0Cxn32unYQUu@>ZEhXAMgaMh9SQFa$6<$Sr-pJc?oV-)g(J zTm4=LZ)td&dOvsD*Z8ITqa2SE+PA#j{i8qk);szA>rB6Y`*P{pYxC9iPx;FD JYKHv(n*gt1nvnni literal 0 HcmV?d00001 diff --git a/pict/file_h_nam_link.jpg b/pict/file_h_nam_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..76c9de71e733b887e1b59b6a37c53e08cb10ed3b GIT binary patch literal 834 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBh?!B4fk}{&S&;Gn5r%RG zMn(o^peqr8g_Vt+5hM!42*AY5!pg`dz`(@B$im3N1k=I@5@!$;VpB9!5@ruHa#R)p zn$EnDmneX#lQoUW)fr;WUyy=d+SH!omt0(-}tSc zxqkX=`P3yAZWE0RjHXWIQJ8j=gVqI^30=p1wJIFGbFV|eNtH=!Ql1D$?dn`mJNwpNue!3~pwm2I8J0~E)92eX21}ik|9N-M_4pz&>Ad3~7yYi7c=O$9`Q!IK z6k0OmYV5vJclz`*!`R-3KKZFflZ05dq;@{2UY*#o>ZJ6f{i~{DW2!E!_R21FypfZ#|H9;}k;~Srsx&{ncmAwIrD|A`EdRPq z{pFH*E>{;w$>u-uJaizmd~WojE4%$!w&o>Ei|ZJPK318!bW-Bc`n|VSEs2@^)mr1r npWJovTMo`UT=eiF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBl$lYGfk}{&S&;Gn5r$@< z`&b!)u7m?t24)sEb|yv!CT2zy2_|M1Rz@}f21aHkR%T`vW~dHkMkW?PRt7~OVKzf0 z5ywLIz(gabMo}?AphBQZCU%&~j0}QIibBkWEP;s=g+&}27alZn3Q}hMe~W>K8EBgz zvmk>#!zF!rg~;6PMUgk4qN$uZgS?Zwhb3nlGYwKi(p4LPYD`YZW(@~u;WJCC>< zosNri&|Nj1e^y~;0K280Lmv}=wa@a3BN^Y#N^R0_R|^+!TIaVTGItZxnc7t|Qabrw zZ~M%r^3dk&-U9)>QI`Z&S);DjmMmJgN@?BH<=ZSDKlzh-Vew8mMgJ|aYqrN8Kd{4X znm}5SyEfM~RqZ=#LYH~IZfm<2&Zyw@@Pt&yz9uR5i5$wYzE=cihOSf6_xaD@^;^&U z_-CbL-%#dVnW3E9&&mAAopQ_~w74x`zk1K&qK$7#ZKIwnv-wwJ)Y75tWW?_BPr+|< zUFNYTXPyWx*~J?Z=JWbgbL9E{aPh6Srrn&&Tn z)OOoq{|SRB!RxMlERvqFvb(Z&fE3Dw(15QVV%!wQ@5^^cv!hq$7s%rRMnXO47^QJ8WT@k z`?f6poM!qNeW9Lpul@Ff{CIR|Vbt31D=#Lp=^neO`(5IV<28*b3#>M3T;H(r#*tbp z!DycNI`7eeZdbP*W|V&=q}`IiF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%Ero|#dQfk}{&S&;Gn5r#?z z1}0`kpeqr8jfsVoosof=0aYBRjD?j=fPs+(1esy#nHhn~*%$;Bg@gkOmDml9LsW_Ky5_neZs&aO|V7;{5+R4&uiVtB4P zLAjy%bLo`#&y?MteE3#z{&BVN$q#o={=9U0+X-&NFRKzKsaUVvZg6Cd`poSGBFbS~ zT09-Yw#M%d34Oas>uc=Zt^MaGPmAHQn)sRPNK8{(O7h9hR56!~mA8BvX5=T#>fE(b zbX`bR?s==oq!~Jnr4tQGJZ>&CS4(r$O86*zL!e1o`A%4rYDv3x^dVWB1$QM@ANuom z>;Bu%m>A-2OY8_Z$!;HCIy$h}gW?D{4So~y9O1Sv3 ztM3dK-2NyXbKTTdd~WpDnM3DJTpQlMew9}KTAiCoMV*|s?xq%3;{=sd1m=A`AMVzo>?F95`~OV< DIy>&K literal 0 HcmV?d00001 diff --git a/pict/file_h_uid_cur.jpg b/pict/file_h_uid_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fa1d27ea3187815a95bf7cbdf5203a6098d46cb2 GIT binary patch literal 923 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBkeN}Cfk}{&S&;Gn5r$fz z`&b!)u0#N47FITPCPoG(W=0eVW+oO^Mm7NkMrI~fW)^0c95W*miy$k5qL46~p$NNU zV4|p!vWk%)P#F*)jAmpIWD;U#Q8aW6Y!pr`oVZbm_5Upf9-uKyg3N*p_6*k;Pv)jQ znN;yu=0C&cZrMp^j%F}fWEn-v-DI8!&NY2}6Z#H)R*bZIlNc(3wv zlkUcuTb_h_c1+bae(7J=?PC=Y%=dOd-BFjgPM?RB{cT=doTu*}-+Hphz&uhwwNGmG z+=ccF-M39G3k_YSs>9u|tu0o@{?LQ{vOl79O!_{pDO~K4wpA{CXFcQM{|sj{uZG{2 zl89gmELwekzgM5lrcEEVon*{7@p0uM$?m|JJt6KFt+t*CSB=`&9rAT)%^&6bz)h*$ zhZ4(smS#!_tPszR*W6Mm6|S)@O17re?uLdxgCECJL8oxL)pu-ii(~qHE@pr1{xC;9 z#VKe>r`?giDqcpyE7&iF>&&x#dZGL1(i3f0Rif{ndSArQWqL#A*ec#xbDk}fomW+u z_AGQ~7~?$!{xI*}m2BTtm2)5cbMqJFK7Ri3BStQE7t<@386Nbu8tpxDOKy{8)b*5k zKi<5L{9Kv!=J=uqEiaZ%TbtHv+%I_Mmg%7@1q^u_(K`yo3@&J_6RuY`=*iN59Hm=p znEmtS!H#LOmZnCmV0-BP>2k5B(Sx{(w|g?>F17y4Zd))f?6+W_W4~%zi_g?ox7IIu zICE#%@}KH1NjI05obRnvx>+{+Yw_c0=d0FQOKPlKSv%vY+toTz!P?b5-am>OR!A+r zqAQwr)I^y{u#w|H%YyBzf4z?H@zOuknHLcI>ffpB&spYAVSDHnQ`cQ(ezR=%ughEB em3@5|YV!8=`LI<%Gp1-Kdw&b^|FA{>|4jhjWk)yw literal 0 HcmV?d00001 diff --git a/pict/file_h_uid_link.jpg b/pict/file_h_uid_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..29bab9c18fab59b73c9f4d91010c91cc552aba61 GIT binary patch literal 685 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%Ernwe3Mfk}{&S&;Gn5r#$v z1}0`kpeqr8jhTg=l@TP2BF@6d#LUVjz`)4N#KOYN2~*F^$iyPZ%Am-`ZYU%y>KG`J z*cg;l6s!^=2DF8Vk%^U=6{ZvzW`fL$LWYik!Yqk}jT0AcY!dl@i-8AdKa(J{AcH-_ zHO7^>X;&tdJeK+QT+CW^X4h3Wg^qV&tL&SuW>2#TJamxxliKnWi@Pz;)%2cacDl3~ zSiD#Hxk-29%u7YuOOAL=o%vz;eAZ=V`J6}ZX6QdS)pIJ1vWh23yfbGq@IE6SVCPv?2^Y2&sJ{Gtq1SI!n1tS?G2 zJ8QV(BlEqCSO s{|pNJw^gmf)7PK=Ubm+BKf~hqTmLT3yOVh6(uac_2`vUr_5W`I0P&;P=l}o! literal 0 HcmV?d00001 diff --git a/pict/file_h_wr_cur.jpg b/pict/file_h_wr_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bd9d380ed717fe727c1f550d0058f1c2ea5631b4 GIT binary patch literal 1336 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%ELl9^GEfk}{&S&;Gn5r%%C z`&bznfzE^jW)@a9c19*f1}0`y2_~QnBbxvN6C*P-6VN;C5G{;M%z`Ye3_@&*!iJ6_ z?170!PD(+_qKy+59yC@d5oBNlDrRMZsRjmNaMuBg-$^m4}MH4 zQfB>si-Ct3Xt5x(AcH-_Res&WdfwW7` znC$XY>0r(^nLaPO`*+r97alMC)5iH^vhpU+Vd7{iI%x z&)ge}`BY7sG>XfFys}-qS48gOn%B6e;X>JW_RC-eoR^+`Seu()vXeVGx9pL2V_FBL`{-^ln1~4x9jfwpG|WtRvF&qnlV*AyO{Oq67gwocinp`<}v%w zszZyHPrN>NC$rGe45pX9ZZo9>HrJO{=vCX+_w6_+EV;XPqfF!BRpH_`ohmJP+B+v_ z=Q4km&3Lojph2lJS^mlDd)rc+OKgQC>hp{u{xcLl-5KHZ;kEdD&5o_XqHJ!jG#*Z1 zS)mx9y(y$5?c?Q`yPc8g{|-04kS#LnnEy8Pp6c6p!y}$YR8Abr*C{-czW?~49Y2Ppb+V1Y;+0Xiz{cX76 zp&JE1)|@m8`@XGwPcy&D#0}ebZd*}3J6+dz6I1yDTVIaPQcu2bdy@7iQ%QY>rRa^D z6Y_Sf?bl8%tnHn3>0Ti3;kOmB`zEU7sQ6y_?X9u?bmZ>rEk2@YiHC|Tc|SWlw(pTF z+VbV7y@Th+uknv=K99OKFZAX5@aNG>?f&3hLee+lt3?sTZ^)jxNG+1<4!{N-@f_1?Umm%&s!6!0^TpX zRj2hM`1umQ8IS5y-k$#LzU*x|fBmJhZ{Ibv_iw*ks`+^N&iE_;R`_p~690b_0Hg~b A!~g&Q literal 0 HcmV?d00001 diff --git a/pict/file_h_wr_link.jpg b/pict/file_h_wr_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..709726d663f642f0a364aaea76b3c3fe44b7e3c5 GIT binary patch literal 1014 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 literal 0 HcmV?d00001 diff --git a/pict/hashdb_h_ig.jpg b/pict/hashdb_h_ig.jpg new file mode 100644 index 0000000000000000000000000000000000000000..edf80bbadc96f8b137c461a99b05dbf7beda2f34 GIT binary patch literal 2640 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 I`A%p43$=)d1ONa4 literal 0 HcmV?d00001 diff --git a/pict/hashdb_h_nsrl.jpg b/pict/hashdb_h_nsrl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b333af90c19ac2f680246ead9725025d5702aba7 GIT binary patch literal 1147 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%GBo|#dQfk}{&S&;Gn5rz&1 z1|}wEpex~kg_W6&k%^rV0^q_xe=sq#unI6Ru&^+*F|l((Wk8~WLab~I!Xk!_N=BmW zieiC88SGa^z6pl%o>uon?>eme14inEAXy^R3P+*@`Pqr_~qA2ra#M!9dnk z#BeFoGY%13>1`b>?9y>}cbnSiEBOY#3%z&ovdcPY(XY1bT@zViOp2NxHC{CkGzjw9 zpyFfjNXFhb>d_$&x$i|ApWRx!)qQLD>YYnEi?6s|%50eMfGOCksKs)x#cHRckvk?T zn)JP1S3P&??!xGEYrkJLFt~hfQ|FplO%5GXd^{Z71bFvZOuP7U*3L#{yL;sf(NOtUd~03L z6tVWZ(aqK0KDHKmF(qxCT)1cvf9A&zNl%?RJr))AaH##UaK9;2a=CPq`YV?jVVzq? zDsM$g_FnoM74&M#vt=O{Z#A`a%;~`*4#s3 z??YcNxnL^bzlvw^5jG_*y`bM48hxalr95M8R(D8U&V98sfA92FCchrflIj!{o}1PX zXw;yp;FY;O|5)tR(rY38iea|-KQ*gz#;B4<0U$-S~)UB{#>p*hLY) zYVY_?|5qG(_>JC)-HMgBrigtvt~wjKnRV*wHH$pgEf6@S!=T0>dy&WX-0mpF3eLG@ zv#V~En&rn`ezo?l$#P-S&n@TJlw779oAK<1jEdm#iLW=kEz9!Ez85x;Z~wwciI=lK zCEESjbNAmG&FQxlwANm#s=6ERe|eAb*P@g|3DauM@ntw!f7CWUo*?{dzN7vdD;Bo+ z$%|VKOVmv_srwTj@^gaTwtX{S^FHnCUfa0*`@OdK7aCRThGqm8sCjAJ9HLzHmI3j z(rnAuKP#v4VzK;o>3{pDpP9p>8Rv4z{$;GO`}9Baru$Exs=2Q&o@LY7v%4(LZk}os H{Qo8ZhfuVg literal 0 HcmV?d00001 diff --git a/pict/int_b_calc.jpg b/pict/int_b_calc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..db33eca6ba0396288096a5e37e5b3e872402cb17 GIT binary patch literal 1824 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 literal 0 HcmV?d00001 diff --git a/pict/int_h_data.jpg b/pict/int_h_data.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cf69f3704e4de9f5ba945e4958b33a99463d0271 GIT binary patch literal 2058 zcma)$c{JPk8peNFgc6cisv?YrBB~UvmZ&CbiK0XVQ`=ZNN*bM*)LLCM_8_*ZwwAF= zl`^EE)1es3Owqb_uGUf%nUp6?@`5WfbHXYC#B0T37f zLL>u-*8!C6m0(&d00N)@09Z*Z0iZw(xg2x>2rKRQJ@&}N}185bL3i@mC zZy(}L03`z`11%5`3IL-(5EMw<1Efj%Nr6C;nqLKiK&4<{Y0y9VYD++{BtZfoCcpRw{~p3 zxc~*OuLfMbc$GC9nH!M;!{wc)jXVO9iL~M$M)%Fbrh3H7Zn3F zJT?RSv#5iv5ft(iR`E*jODD(*b&#<;rm5Fkm3vjwiD+H*dn)B_j^}_H-lTbEqQWuH zuU|;%^Ja#1<9r{s;n=uf{)9q=7)aBav6W6JpL*NnpVZQBWOckMd76-SJHD{f zKX7;QY4QTf_MB7syuP_E30&`VJ^a3YV|G&@CXNeN(3 z>3xH-LbthAw&A0N(k6^F#@4@XVSB8!kAbV1$PIsJyvi+3eZlUXe_}E8{ehEwFJG!H z0a0g=%N#d&`855^lVyy3`gdJ?UM85#%Z3==1sx8t)psmC(pmSwH>x?Gl@ajbQvn`70~nLP9AY>ysFckpj?#D`dksq4e{D` z2^tOShItCx-Wyn$eBiAh7soL%ODDMn1*4E#yl2m`$});PE0l`t>2uoNo>-fazOX763%?Z#fF zT;+xC1~(k9Kb^9vZEEGp-h4LCsm0bIloy*$=e8zL-6{;N*gUE0j~D6m({q0|jJGCG z_HLKD5m-*&u%l{=3q;X9_|`nb3Q=iRiuNn}uJYyRT!Zkw*#t}E=#TdXa9_BK$D58M z3YOgQwOekUsCb;IslJw$tdVM?o$xcQ73;EmW9lnrET2I{V!E3}SvJ6KR(VWNfrA;C*({dledrJ~XSFR=-S67sWDI^B%npctR(}WwCq?}# z$^%X)`#@E&Q&T7->;8u8YG<3@AI9NJ2Wa>dA4moRw&Xo{jb@C;X*Vx3*~iC-kn@+%AGM{e*&8@^VWYA9?;+TLb+_QTqOEeV@nGM0LA!>6T;W zO;z|u+j^1LY{n0-Q;RE8Ul*2jlS5%WyLLNsP#w*psaSUmvuo{GMYRVXgZNR^zo_ri z9K1YLVer>XjWsfznB;A8&jG$~)EWCrZMpU7*%9}2!}T3v9-eI3n=BYgoObv`m?}t8 zl6_}&Q)3=`a%JU>icf&Mt{J!TM^M5SL?dj)GXZa89aVDs2SvrtZUr zg|61AtZx@TGEc27ZqY+TF}dHJp{H;#Kahrj0+f%^=IG9BlTMmtzSZO0k;&cf<$L7v zZ~BPznnXoiIHCYvLp{Ia3tzg%y}O#N?h*DdwDwZrz$JcCfggT7QZZuer!BLm5%-JJ zSu1xD16gH>`W3@oa;Cw^Dw7A&9v^0hp1SUP5i-(t^+cfAcHiy45QKR0fBoHgX#fBK literal 0 HcmV?d00001 diff --git a/pict/int_h_img.jpg b/pict/int_h_img.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a22cf45eee60064970f62bbb0512f933eedb798c GIT binary patch literal 2005 zcma)*c|6qlAIHDnIW@*HZf2Nuq;iI6Y1~DlMdX||BZkeDb<5F|ijWaXyPHK(JuoVY zA!pl+apc$(I~q(c%)465?oSX&D)5X&e@d#o@mTL?V%5XfXvzNd+ZYjI7f4!GCQ8 ztpG*@kO5kuAO?V7Kqv+jFo9H|KR5`2LZAN%gu)R>7(_%!|EGVku!0aM3@!;kARr8c zLZJ}kx7jxeV5AVL2GU5Evuf6cG7+vhHtI$ivLeDw5D)@~!oPn5VjxfhDOGEivzK40 zNk`<^7{UAm!vGoz3Qa*VfF&>(vqHOEY&2|X_@B7&r^jpUK-h>Hx|3v zz4*p+)SiLIrMXnuv6U|{gZH#h3!A^XG=6MM5vly`-stmGWBtv=(#?HsRiTbS%<2;p zQ3{PLnU>6F%AKzH7|!)IJ1vLW?(IdpVODv6s)%W`%jS||p<;uW!gP8D5$ka8_N_&0 zWZ#v_9r-z;hM{r;XiM)JdiWeGhO>zXJm_U+fGR+8yRVDV>0u+`h8Vel5DS~bflf(jc%=maQ1l{~7+f*@g7={L-7;%GD%HFv{!3mu&PYq{)0BD7seD+jdxHt2M|M4C`IVlU zaa>~O2vg3`mZ9%>$G?6+St;VRxOeUqUFCU1&maBPmbkHl9 zocgqQ$xUwE;?9PXUcUP@EyL#kj@H-i=LGSF1HK!My?!StCD7rV*R6W-?*F*w)seK_1hW{bO+FRJRUy!6Fs`%Pn~4?N(1MVWOf1L@Cv1ks?&|3>)eS7^gh7ph~Z|GhxA?JzezdUm{WYxb40s$4chPHpsoGoKz2vok9XMCtGyAg zXAL!(F08>ymQGda=`E>r^`lvCp_bvJVGHJofpPEjrgQ~>R!lIv$#EEH(_TZohkbpO z%gB;PmuZ?RlXcxI<=M$54hy$Ory_E@2@y!GbdqZT1-ibci)u-3es+zKcmW;D_T%=) zSaey$7dCZ@TWTS~q2D9gdD%zdU*`ph%@kcCyxjNxX64_`;~Z33@%s#Jwl zzNWEGa`U|q6@Yrw_qZx+P>HzyHduG}Z}Q>%`9FKBTra$sCarsPGSz}g9^|c|tN#KC zrvtR&i?HX)YDg7iD>p0R8_G2A=>=Qp%=s49>5YM)H`nPX`^{X52 zhA?KGGve8_Bl6_7k54BJIQMfEg3Fz+CApxpc#D!8uc6<{1c0*Po9;RviW(!g$zC+O z!++I0MbR(lm-rWLWCUrHw!~yD{~DNAxQi=-&ezuFohPmRE^%+0l^L5bqsQv>#|M+1 zK7Z>Ls_J(ozSY7W@7Us)^z})U36TpN0*l3fbFlLSXWcs9EYUX literal 0 HcmV?d00001 diff --git a/pict/int_h_str.jpg b/pict/int_h_str.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f8b3e8e75183f672994acad1851bcfe21059d957 GIT binary patch literal 1553 zcma)1doqkpL~BK*>lQ87 z`!TO9mXHW@b4i(o+ZdI?$w7}>-QAsA$KUt!J>PS_-_PgsJ>TzFIjWQcC~tQ!cL0O| z0835tvFs0U#WNV36vQ zZxRetv1mXaK~Ud9#JJFYvh~HL=7f<9>KEfo*Qi#h3=s6)tQrB)Fo>{4<g*ZXBl{}yR?oDM@ zS^b%`++<;R_Y{R%;Sggxa{vs=$}>pi(7=$t_un<&s;I6`OlAk;t*$PPHd!C+tz%WT z9MpI2+&s2}W{dY(Ic*m-H|{QQQv!}tAxSs1tAgHza2*|n%QCTNYO->BdT@cpH4XZ@ z@n_agI4-f`^*$Di=^t)|%L=#FW9e}zWj&K+O-If@^^~nY_=pQJXKZeAUz==em_qZ( z+;cBYy6r@iz!Rpo?=A4O27E|-d#~8&@O76jzX_}x?!4H-TbnQ6Y|!~BK`duCZX|lX zruGRPianca>J-O+7ep}nUDh>{Y|1wjv5B?q+uldLYr~y6>+|vC@~|~?q&sg+gzDPo zPdhXowHNKOC$N0MO%fS0f%El6_E0A8GzK7>x`J#6_dm-V-)U1KZ$1?EmfjsvLLmAz ze?dnx8hv`B!7J`JFZ0b`(EKblSJsdx$+L5Rg~6|sa|7}1tk9B%OU~-A+(YyUN`UYw zb8)Ya@3RS*Gzb(pStOF)Wpej8t&O*7Uf~7x=5WoD$ky|IW&y}S=#A4v&fntN#?aRF zq2yf*jjqJppYLC{5S(%>Fs#jHYu`LB9O2qc2dAm<*YMfW_Ue(S!a|#_+n#`)H&Hm9ks997BpA~p>%AJcZ(jLH2v}K}mVk z>HfzhGRfzpMx4;Fmc%BT*K{L$e;B=$QPmS2UdiYqUv+HFE=@_~FBr=L0(N-wnwZD6 z4(F%U6ibWc%)s8N7QYAE$+O<}o>}ovFsmXeSOBMEqh0es3VnyT)61wVCbI6X48v8@?|8gW|bhs{jcqpZ^O& Cb$<5% literal 0 HcmV?d00001 diff --git a/pict/int_h_tl.jpg b/pict/int_h_tl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d1afeed84e02ea11d23704a72ee1c23213c89cb5 GIT binary patch literal 1124 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 SohC&)Pv(ksz7^dg9{n$?X(Ims literal 0 HcmV?d00001 diff --git a/pict/logo.jpg b/pict/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0d9c29c3826757ccb30110bebf418ddc79121a3c GIT binary patch literal 39208 zcmeEv2V4`))9?W*C1Iv7=P!ohT^1NN-A1q)C%r z1*t;l5LzI~cVKz+Y5)K8mhbm{@9X84yW82_+1a_d*}2`D8)6Uf6L8?NoT3~+LP`P@ zf?>`1ex#q| z$ZzzMF#kwD$cwLZlAI>}j+=?$3pzjnJZ{sxb0q%ELxpW9aTcK3>5Hk13P4Jn1E_aW zfW@utn#6wK9zaDwL9v&DYVTeuTFQNtv~)C7R5Wz-hYrylIz&%PwX=Oad`bL%PqLqq zazFL{1Ju+94pUQ8AKu_TNE3d=1c20CvDFG7>g`l$L~ymW22b>^24Q9SIbq zayQA&1`@ozk%0oTYxf>B4*+V0P5v;Zk7NbRm2n#lL;7TO`<1mD43AO%irhj#Pd4mrF{!5hui1%Z?1!_Id? zWwhvEE`p1v_G}YCep={l8%RX*Q43ieVORLbcM|@Z0*>EEAoc-NWIJur0#IPOP4QG> znc~UN%bMUWJkRHa+e}a_?nSw`(3l%%?=&H=tWZOa2q?|!pQ=Po`ePXuLqyh5)G8MbFMGgel_f0BacjfJG23bqa&7hoJhZ1{b?Fp1Ll zYBu&(I?Cj&ZBcNlH_N)OJHM&w}U;rh^0x zJIitQpgnTK$W!kR2B0&US>m?b+r>IKG%aURL^zo%_A>y+8a=}^1=xrNCGW&;@7)I} z6>V?Z`m#P`A5*tJdoomUAINqs;)fruL(??b^jRwWgDp$J3niT=Vn|-2CRfMx!fsEM zRro}(Sev&g9=JB^W9<>^la04>o5$$s+zt+>H+FE>YV?tPlf8Q$nd>(%f4s0`C{@LE zCfx$&7WC9xr(3kSKChy`T~6A*jCvQ7jhoJ)Nqyr|B9QHsh+gKboW@#Mxbi$z<%N`W z%wgZSs6=#4m_|M9);w;x_40B~En)=^UGTr_!V=S7;8QRP?-@k9Z$vIq_p8UCVya&l0?(mfYFGP%$(4^*KpE1GyQ!d)K8vOOUY z>iok1jlzcC1>cB{GkHCN*qg0^j?|g<>vQ(EBoMj&VXO8-!@^$k`N5yj&ed|$K6x6R zuPYk|T$Gr?RwXs%m~3fmr|VJzXbhR!H&wg6`h~qSH-_4?{k=99&$w+c9EK06X{EA2 z`7?Uj!*0V7C6qiZGS~a1juRqly`ndzSg?cHm1U?+CJD;)4y9#rnU8R6ur*Tc6%jD6 zyFQ~W0@i3k(m&QObg*i)2NPono`{cXGmd9kc$D!COQ#BjfG}Jd)tyH<54*V)6Uf` zZuZ`HK6h#hWhFKAmlaERcvtpwVbP;fHkrMfGTB$TUUj#^WTNr!ie@~H=vYCA&)r~- zG2#CZs6tpo=lSwzgk~J5H7#RiA}oa}o~$_qO4V6n>kks8cy6P&Cjok-v9Upxer2zB z&@zq-hJ0&mwSEpQbzraH;V#TZOhj=Ob2Kd7>L_32G_II;cNt!P^Sa22Tv-upz8tM} zx}_D@r8C9FleYpr7%x15H@1F*@#aawn0!=KaTCBsz}vdYEBNQ0M?!n`lEZLD%6`}N zO;f1@SE?{wmL_rzmRGAW47qS2y%57ytw6&-4-dQd%oUu2!>fd+wuF{|tvF61aK8M7 zUDAh7!o6B4G**HOlUfT8gAQ`B#MXpreeTVkVt{H2ctxpJXVUhnJn!9~q1vBWnK73< zxarM^R-0}&_CZbZJhk>Vx6OZHJ$)s6#jYl`D?i%+^7ef?3Q>DgqytCeHnbpw=9&L& zn|;*{;5S+`bw(|IDqL^IMwf&6vgDYoG%EXRzQ@AKnGw*T^jR@QxAdtj1P^QQ^AxzZ8 z{b5(Lb5SZUj5dYw(1Ny>HsdKg=XHW#q)+Ikjd=@@Ksxq5#a;W&YaUCPhTN+ITQ;lZ zT_y5fQMllYfOEw+@OIOSF?hEoE4)inW5tXysjpY?_`}jB$7d%251IZou*pf2eipcH4;$`0>18oXe+P%Cx zOYwejSq?HJx2La=)RfJBod2kzr(-%v1Z1ZAiGVX*JS#7uxHYI7eHLxwO&>TgeQdz) z0aY;}vTgcU&8QnvbKZ2L+so{ng^d!NSvwp>t z2<&R01!PXznnO(K$gU2BjfqBgTf(&-$+#Pbz--bhA)Zt)WV7>XeDl+&yB#hG9hsR- zm^nH+Z&c=iwaR|W08}-M6 z^Q)T@nVIeOSA4=maMyjJutjGr|?k#g5#>M&U=hh#-j>mQ*U^q ztyhE%35RA(N^p?YyD7k6SbMA>84b%~dZYv)tQ)ejoNhS*|IEbcmH=TS0xv$5_AnVb zr1nRIH(s~9E?ew{$c`iee8I9PDR^ma9HxM3%uWcw+v} zkZQlMQ0~xFyDgq8*zoANT!UFQx(Jbv6CsZVPy9+N+UNQaRb;elB}%G+X3Mc}D(RW>;0U)r?6z5y)?Sr0V0| z_lh|zw`(XLHeO0Pa4b^#gKI2=#r*x}HE*LE*NMQJENG@$L+uguZin|%k;S)`K2Z(9 z%3bi0!reGMpQd-nNs|UCqiG`0cJ6~v(CDkyb5Nn<=^v&NL=F8`hcz}OXxLt{ylY#QI3cmGHo%v+! zb*}EnvaTNH&;6xTFH2q;;5+B?a_U#SIY#pzu6RQ}Xym7O365FVW%Kq5tNMrFExmgZ z^vJXN6*9UFW#1;u=8cV9;WM_>=?s?dE?~;|(9fU})ot2~d^W~Yj*BVpv%8v~ipX9; z>sFRHfQOAE+OwI7xHlyNNgD1N-t=$RUYJXC_;Xpx7~f3@bD2Rrd2guF;YRZT7f^$h zG8`=QIs)HFU^>cv=E%4pl<8D%;9w4C(5c{jY5!SluWj$GuvGP)dC1_FqT}n3*5P+9GB?7I6TLckMNc8b6)6A$TJvCtZ>3#VOS7qi5 zoPC{J&j$Uc{H&Mq`{w8pd>YJd*yXYxMWS1a(8)w#4-rsp;8Yk7IWGF3#*}+~AqOxi zF}5Df6KAGTuXyfl@*=9!x(+UU{H>|3(3*Z&^ZZnICo+`?7#KkH1UNCrIq1R@dPT!a zSU8!sxE-E(NucDH6T_ylXr&UXbqVO@5^>Y>)l+3hEGg$38Y^=zHq3KhqjOkMm6jG3 zwHMS}E6PPKqgK$G9~Us-An$ebO2w?c$6T(6S~p*!b!pA4-DtAC&FPS@>y1av#pU zue{4Kr9VHdrPRQuZv9PVb)&)t#CJDny4<(pSd_(GEhj~!T6wL~ zDy%YB28&9@pE4<0r!yG(EP|7O>gnV=S9b87Z&WzwWU;V0M6>Gw6t$xHCK!UN9_2Xv zoRt#`UI?ur(}l#?{*^BjO#skJ?wvbvgzY47h`5P`Wa+A?&O-=IXPL>SGYY-=)V zC1y5Cn+XWpVx-8{N0V0!$CG=mtnp&5C@C)9Jy<%E7ua2yYY}i%ywBx~%i30vvt_sp+PZS;q2e&G_W@7r5K36%gi3RLQNS*ZuwYxL%vKG3REF=g02F zN2i#35Im|nYUhe?7t?ucODcwU|cDy`q2S<142G zv2KBE;gTwzmaFN*AG!t3_#|!aACil6Dz8;|Lj)9wz!@L^jlS+{WzcMTB4E{2R~N^b zJ-g|Ve`|Kew%P-K5p$)jMF%gDY37=kJ>?Za2{OpqK6>rp7KOZ=&5dS=gS4cehVVDLiEXq>YecCcBC-X*TaaMfns!{h# z@5H7;tKO-~$ddL7a*ix~)QpbTnpXSSn(_!Lp7a&e-sW5u30B|23Fz^sFF@gXR(x7lFXtv>C*gNe&`0U_?cMK|e7a&cclNB6dQ~094QAnX zOip4JQdx=mP+3C+40~7Si^g$2S$VvMA-bx%YM6C8u{Em+gT9Y95-0K-7C(j*moF_j zl%X;{A!Vw)Bk-BC42gbDtW)RL`KyjRxYPk#RtD8$@cdZRmh zpL3eZiM=kJ<86$*Qq;R~yAz9kLf_B4>}XXoLoX&G-rwIo?T+1=fMQn(xwp55(hVtU zt1M^=ZZj;7RfqZ7l4=}tY?y+gxtvinYs@uZ8M)n37i%T8A`H1}va^T0Q~LTtbcLlQ zpow+;Rux-x$Yx`>PS#6w4xZ!C!GX9%fu1YmPgOb|2(N_|!n&hm%LF?&yS>1tU-=D` zW@pSw0VgMA+K~5pu4s{lD#t~*Q0d6y2|^rgWmxg(*w786TEP5e&|Eb4j;$~?O~wSX zB!7yJTPT>TZ^4L42ga;YCg`5Ye^VJRX_MEa+N-ym*rK$7N>#(Up-?gOaLjF9QgCL2 zZ>mgY%y*Y}qX!Y_KJcc zc=2c1{q`bM;u-IlnB@DGjW$g_>rWQ=9B1CdOU$iA7zqR!5wOoaUUcc#1yS>ud&&3* zkFOGedfYlxhfo&9$|lLG5tYL3a}0)D3=_$+be+#C(_NuPS*gMLjgMb1CdJvjsO@#Z zU`xF0aWpyE-CjjrgZFbcqx>g#7KIG@I*e7UZwFe_~ zvS6{jIvXV>(t$pKo~Bv)SbbxCDm)90lWs1+C(qoq(M|~mGhKBw=y%TVmCbn;RhdC( z!YT1(r6Sk82`#N&$TAi&Dlwq`-aE&RbDFE`!}RkEpFcfNgb{34Jo&w(3Wvj!Jm6l_ zML6`E>s15&yR&g-gU=>UwO8Coo|0I8Ps{aJIfue-)!7<&`Dm52PqKXG zaga7mHy)a_L$?uuyP0BTA8jrWfw+0kM5crbS;6B*T{mb6xmxjanE_t@c)J-M)QzS2 zXC+s~ii@J9q`P%WZdgB$VTkD7>RvZOwh|&(d>_f2-SzsBADbB8Sk$x2PW8BSwRRTJ z3dW>OD8p%=(hW*Nu_$8abeB~ZPZ&~fD*Ii{tJ3cLiN4w%r7IJ&ZhA0NxY@k@QHPuc zsl)`76?TRQC^QL1P<))KIEi?uW9;`TxAxIeW;wE}GNIkHeTg@JdTKsl<(P);$pat3 z$-Sw*TEhJ}VPmUFDRFc%;gMY8Qxike;1IvH1B=lUouLceea6L&6?x*XyyYr#TzXoH zyyi1IiNM=c$d$~Fut`KBA-;vMC*2LvW7tasM5W(g?4?n&EJ_{y&`)^NuGLH}q*-jn3R8y>Y8o`M? z-D-Hqftp83x8&%qqup2S!>5@D)q&HqsdTez{UIIs_#3u(X}Hhx4xDG4lokw1CD}F`lJhzKY*IdgpldV_s*3K*G{CM+XQ%G&tcK6-FnMP*@`+7)Fc6$Bc}zSeU6LB47@ve zX;W~pe=B;J2#Af%Obr>9``c9&&>T%NAFML&)g2tDcqJ0q?c!uzlQ+APpp=cMjK!md z7l}Z;zPD+L6<)RAm}~r6!BZ;(Z$0>jenOLrK_6b})wyg~R-SKX4K~g+a|)*`faOHD z=O_52j7~MqN+buO6EF^|UdYA7cLVa_qVTtT0V30*cp~s&WV2-o88@PgALOgPiELP7 zrew@AyGtYK8-r%&C8dbhy{kN8dcmV%FjFqSR0!76;rY6IE|??2mzBLWtiB7M*ZjCa^d z#MMjIZy(T(B|m=DF!0_zN@$5@aWt4_6S`&XDHb44F&vBoO@sMFZ?rDqg-|2-Jb7;3 zqN+w-&CHPz)7EV;Ej1K7ooRrFQkcPF1B)#TVNJb9`C=Hs(BjC3%o-Z?xhEVkGyskNyrN7wa;fGZIo_7Z2I*M3{d69AX; zL@z3;?Al&f0|4@4-~u5j_}hV<+JPOAqgr}&x>UFCMLfyV7pafkxAVv_+j+;cC7~Yn zcC6Ro&Mwvn2Prl_9$q$9xC0DfVeMcg#ipYz$1TbRmEI?L;*y$-w!XS7tD~K@iz}ZuH31<|n#9sD(AmReIlENn5z5 zG>GCWGDl}?2Ui|-Gb^|p!r9&oJXKLZI9q!m99+%pG~q6iknQqdwXfCxyuPb7%ogs- z19OI(xgwmu)!8fQ;tHa-`h9aC$llBWY!WQ_wZy)?e~Z}K6>fjQ+1bqVH`Hd^NsutG z;y2R%0>{7Z+%^)BbUSGgeo4sA$u{1(;P7YZ3pY-+baoZy-E}6N)e?)Ep zrlq%+ow<31xp@V&`N8#PL2*G*14+nE*1x3J#TCRLXJ=;hBUbRz!@;W{%_|A{cDln* z$TyBkLcXyXZ0FyVA2sJ~)|k11H^sNczF(q0mA?Ofq~}k%wk;>$n8)`sAAbqZ-v5vQ zX~E3wKppWvO?ZCSt?x<)l$u{U=evISkBN*fI1XBaV)H+6#QKx2eHWcy#Gr;J&D(Y^07^h^D0v*Me1^KYvk7dLb5FIKOk8EA!@T02-GOutw%|K7m$lUaJf z!p6hN&)P%!+Gc3PL;oln*zcal5p*8w%Q!PL%>$jbworoRo2{{k!`Aoypcg+zpZ0{>={fUW*H(cdi6-y8Y=kgtD_{f}lo z$j$F|J|F+KozKfJ&c`RtFYuF{|F<;%nW6uih59>7{|CAMLGXWo{*y}z-Ua_FMECdo z{0rIT<`ex%?7oWhUw}nK{#(2ju3xB5;dAWH-xcNo3`T50#M8tUo|EtvEA0FKQ zv!bQrVD^7!ME`$4#{QPCg`0<*8(ErA9{r@om{(Wcv zLW2Kd6#onG|ER(J{|gCrbhP;2Fu?y+H-8x9m4A)!+e;k(B_sS-`|pCfA~>nCz3BJt zN&mYM#LLUW4?bi4X6gN%9SN?zT?e1{lo2r7-w;`v*}1?W+Y4KNSJl(6Pj~!X8-MKPH^cGwz5F{Yf6__G?|uBcia&PoTf@J%F@Kvw`F$6^ z^-vPBvl=SBZ)a7PY-(p!*JH=^a>p$aT=5+wJx`n?&XMgQ)g-gpeTHlcTms&9q}+C; z1W0>G&+Ir>T7U`Ay_0Om=@dx>&$rzzzi-zl00xrBJ4x2>z(1VqtRBzqfDe3iGu?J^ z-NsC^v+8_$Cy)BKiqKoYm-XoVJFxAQYLA_gUmQQT)66?qmv{2_?(D%G$(LIDcG4iF z+hsTo?4#2H^f%8KE5r_ivCL zYSzIt062nfr+>PUO>SrZX%_K6lefc}ZPeQf`FnR#+t>1o+wacFkGq|GiXF%{XFx8I zp8xXy%5!EA3hcPue&HtLc9Kj5+8D9zAPCB^R*@1`c4(>5WxH(w3sF~Zqz|_}znlM*B zFtzh?gEr{7Y=>~L0@FL2GThSj$Mi*4g#Fj_4jGzO*S_U%leWjj&Kd@H(X~@{0aGMD zwX=IC4+I|s|KvLf#Y;cnCbx1%xHrlyRZDR-5RzVn;-f!mS zijappz@0(mxP99J+Mu@kT6o`=!rPGT97TI8R`BrO-G4GSXFF}#E81XFUzxkj{GTBz zE>`fLAbZU0T(!-teu7cM;9xzthpVECg0_mXIRas~jgaCS_@}~quOXbhF4$RHed83( zm(GJPXnX;KHOVdDmS%2tuHfn3>);~TpA_F-0N4TlT%6L}N(NzvaQ=b0v|sRFl>eRq zRsmEI4%@um>xytxb8~fpe-n)DynS|{ApHSKWsYzK1?mrQO7Ie2`+f19yO4Gp89?$? zYaQN6Z3`~jPA=7Un(2$C0f1Xz0u+1_@R+m>X8`Cy2lihs@4sB$Csu#Cy#I1}|K;-j z%jNx-%lj{v_g^mWzg*sbxxD{!dH?0|{>$b4m&^Mvm-k;T@4sB$f4RK>a(Vyd^8U-^ z{g=!8FPHaUF7Llw-v8&jynk7_J^?P20e}wp2iMpDfCjh#Sb)pZ<^UXE1=PVMYsAiS z_4eZR_M$Za9Qqd}SOF1$2jJaC_@#v}E8^r|K59(@ezNahmVBIO=YAeNYMMa&}6u*$__ighW4@UG<6B=&i3o#;M+y4X5g~Es}zTuo3({FT)+axCuDBM%`a>Y>|_1bZ!<>~l|OIs+ZC|4hk&iJvPyyg6&3MI2$-8a z=(nwSN%{-NED$iTS;uc5J{RW~6yX&S5isKx6A`uCCP0K+jE`4{+d=?lE@){X0Jr1= z{cQe#4D1$Un}t903+(F`7|2$T!I1A4ZJV6`{_R&I|A@!G*!7ED|A+(ssPHf8`o*q) z#DRZQ_?LA3V%I<7z&|SdOS*os>mPC89~J&3UBB4%k2vs;3jdO>U+nrv9Qa3t|D)0c z&hLDi6@oi}Q$gk~HA0w3kyLOY2?jZrb zhAJZ^CHpb==l8ZrNyxTCmF*!X19zk@B&1}tyMWzbtg;Ildk&d_vC0nfhdd>x`w}W_ zSm22H!b#^li>G7+wL+8fVJ>flE^&k<7YHBKws5U#8=*LTcke!WhI`?%a?c8N+jY(` zE{!g4hbx1--H-SZvg|J+mWe7{x#saOI<2&>XL9|ln4-S5=cAbPvijbsjdS9c4Q#yp zVl&F$_hE2fLYtB8-VKIZ+eJY}X1^0=Y&*Kzh20t;#e1A?hwwkmTR8ltb(sAkou;|- zqQFT(nL9^9wN53$^52rXv98(KxNUYL*^VrAD;G4ONOZ_Q3Lvb6`? z`KkSFa?r#Ne@ zeAO=XcWn1bFD2bRY#&>%5M~uu2#{P*vCF1?bR}H7BU_r;v}Fn(gdATS4->PHHDsX{ zajjXYpmcE^*-iVt(86{7a)|-6SVC$8s|YMig(2{jfERSUJDO+3n@s^yZ`)5!tH|zP zOp&EJG(J-wIsR}@?V@-Rg`mEJ_V4(aOKknKzG$O$y0P}GG;Mkz{RQ69^`}~Jc^qe< z!_F5^F6jk%#%Z+A6-{sSHu?)b4|yi1^%@8X;u1TTky{mcn~h7tTN1nAOGPO2_PJLq zTsS7h&}iR(H=hU`Q#-2hZjjH~3Y$o?yiRNGEh~GFa8*M4!Ir9y`ZRs(9Pk*C>)l1uk2_f6`yLBrp4eA5VSs_hQnRj?p1^kYCJbM(?$ZS%2 z%+l%1f=3M6V4PhgQt}n_v+%L?7C}B#eH&x+2ak|re$t7o@Obgt-T3e;PG;xy$Qr0% z*c@dIZrk0ZHf2QM>{P=k7N#4=Oc!b{Ix)#<-Xd5E`b12`;emPrgNzLaYhydbN7IK% zv#gPb^`pua%!=|DzEF--fiY2Jvn~-h?)hHNGbfiV*16M9?;+nq+Un3<>nCK9efS~C z@TEttS0-sReZ!g(9l~;Qrn_fk4+er^1eAU03AR>aa~ zvhwE-*JB<8>dh>!Z;Yq#@#RgqZ8$|M-N)z$yxF;ZzepdF*!~B`U&gd`%^kUeIh?p> zQ={%_2NB4#V-2a-bQudi8#UpYCZ-t<+y(=9(i}ti^I$bujPqLsr5JDcO9^*6L{o5e zng-3L0Kq-+m zF-Cmmoiqn(G**xj>#PHCF8O;$F2~Bpv<;YCnP!{tq%|@0j8L`+X}IHEsEQu5e1YL* zaBN}mW%*n+?R-OI^xq3~-6h zBLd{6_QKLMo5-DO_UCyChUV=JYP0c&n&u zP@QL<`>Ai4Z+wpYix5_g5G)wbg1=i~iIl7A!ct=JQ-KD{fHmhJ{*RYE6{=vhs~Sg# zH~CUdTlf)*WB3%;2EkdzXx$!De*2rz8Svt0H$?+x9?=+abpfg9W@N4|w`ah0QSEtZZ4b zL>D@@>>8%`nWG<_bas6!W)5Fje5T8&y;>aGG#R`=cf)wAc_9zQ?Nz8)E)(=RA) z%*)pl5NvcjNIBe$C!ly9Q!}Vt?q+CxxRzaPUm^1DEX%}rY`{&U^R?5?&vnXGHmuTB ztlW{~hHo!LHn;UXkh+b>KyX7;4TKi)UIkS)*!sr{hpi`LG=CVBz6=VTf66Y2&w=JG zY9Hpf;rQ8!WTt-ozQEqW3sXy}OSLUrwFfU#k|S6*Qe}%&d3 z=q?F;-{4%sAgka&rkjS3Sp^W-G26yLQ*pJ3Y;)_tcaM$2S{$ETPRa1It@e~FJANd$x}@hRmPnn{($4UnT6wfK_|sch7td&D zdt;~mjww_WVBfYg~3kOXu5yP-u(SJC7*>;Xi;Eo?0sIyC`Zo7>fLV1xh}y&-%z zyLUR)!r*=~HP2ZtxAdU%(xNE5Q9zQp^&MEq&!arC>yM1g=sg*9W>EjiNvAu_voH1~ zWz~-Ry=Y>lTjnXf*)1NCUz}YTc*vbX-=ZA3l7PAcswv6$IkXD!nBAUwiS`yt^Rcr< z{j#J?1sMMQx82qq)QLci4yY%Vv}*WAdCvxv!mXp?Q~cK6^BWr`I@Xy*Fl~ia5p0@~ z1tVtZv{1bq>MF69*AKCrYqnaNL!H2|QCJfJI`BK|w$Xi)3lq_VFv~-ZRCqr7ai@81G33nl8fZm|fe-k=tWx zfH~r1(pz_`I6+2kwCauTOg^D)j3QZCgP!guZQK1vhGyNCxcQl47F!%-u*agX(><9H(N&F-qiGH@rI58>j;A%(n^e)ATQk+i_cyj*#! zZ{j`|Z!Twp%e28}KE9L)e13*p*bu$!7Zq->;U~MaGU)3}$-Y}S`=f%Jdmy@=V3gu@ zVN{+AIhKmk?HR|?N4ky4TP-z}LSHPUZMblQ0ShdB3#+Z56J_OyCmiklZ(Jz*2UtV* z$}`ZG>^k;3piw1QIce}boB!UW&R6*#Z3eZ_S|=s@6m){&eVJRiwe1lu?pg7rPM8x@ zVfXJ*M)K#T>ThJ$ce|*hoau0lTz_72`d->lRO)IdoZwM5p~~~2I-CUZ(ZVJ%QDYqA z4_z9Hbw%^_OLobIUPPK01d{Ex{r1{)ffdFHunxUl z=T%BB-S~UlN4eMF5aY#8HWOqzn7b)ierWOz?VyaDDYs$RrWz-tA&O}O2ScSf>8jCq4@Ec`_F1WSBgjaOeERLQ+kxST;1RD%qYqzA z^_*(cAB;y^vCymMAloLLB*!<+r-d%E~{KVqn@TMBFbp z>?ha*MhxOB6fH94QQ>nqH1#G2X3nXex!D5-+{@AT(>Zzcfu+l?`T9POj+;%X{k&N| zX`yN>=FFMiTcTqY*G@{Q=`OkAqGD%?=CkiT=&62B`YiTcH5hSl$jU$d+2#BEI;}5< zsk3tiC#S5q)GRHsW-e&5Bh*F=$XEncdFekC6|po*Sq`Z#jW<<@<83y)>CL4shf3+6 z-AY3(tY76yKkq4KJ)TM3sSCYP>5PAZL_%s8DwJ8ys}}4oyF;*i>tVfic+w&Og(7EJ zEJjo?8a5(z-gE}ZMqO(c#K{IU+O+I~2cv0?I&9dhLS=By&WmvmFL)Lxdh5x?QuuN{ zd>BhIkguBt?N(Kax+bu$e*t>w)giOQV;ahm_dinzWzu6eQ)w})>2DR9Yc5@QcR2!| zf%GbC9lP%!9i_|Qqy0^|!Qi4_6-K&T>V&a`n!IF}yo@|+>tQ0mS-&;3XmoR|;Y2{> zY3(;f2tgaKWbyN&)eM7*XY!sB5Gt6ElBL4IEF!QpAEQyj_Bw7N-E2HtcZGSx5?%t| zos%PTj(2wI^<_0EuKiVZ$(G(7{qq`h#-*={1k7TBfGsjGe*3NOXQ8@q_U_dlYx zp_X!mk}^=kFkw@y#L-&egOk%cWHq`eVod5VJC7@kAWE`2UDo-tyfxjxqigB(EXOM@ zG>nYbuIe$Lc$*ca_p+o-uz%LDO-=KRKOeB?I@6_~(Gf&oKACsuLX(WPw}Og$n!=iR z_{^EHR+#Ke=Bf{*S9X)ZUdbP!3SF};LMl!Xv`nN8+iL@KHhY7d4MsONz<_>zW;jwr zw0)!e@+sS7Ly`Nhw={@Aih~5pW-szB5f~DUML$F8Gd#1^jTD!@YcGn>-8gdQqTj6x z!}ZgI{BbetQle2liz`FaeqtS@OVIXYdYJ5mqdN4(s5Sl_YoV-FGm&BFH4{f@P9dhPeg&mIdNQ(Nz! zu}D7X$r@`WJ|E8!GgyD-cqZZgA#LzUhX)J@8pek#K=wDLnUiGIh39w6bO^~FjpBLS zcmEhi_`*X@WThrFuzSlNai0i$j0zol{&+VnTvyyA;d#qc#@=UvbV+4W$!z&AY1zC@ zT1CAQQG2EIPX_ai3!J{HiAX(3D9k)pQGKy8Io6kawMV$62^q%86*|v9Rdbvqg{CPB z{s0rc@5!Z(_?o+$m5wh_Jd1A=7v4av%wBLpaWEw!UVX`zJ!~IpxZ#1<8~wB`w*dUf{p!;eJE4ox3!`cC zhBkt6l12hHp1s(xZ7k<{U<#S0VmB?Y7xD<%dafo)vqfszbv$#geJFJ5n7*~z#rP=` zWJPg>ibT`(J2loc^ttMqVEjtc>!ur%!7(3r>qPSsMHn^sBnonpk{#X2*?i4&i5=m# z-D`~3!(49IGu8`UxSZMjaP0m4{-7gL)>{5&;JO zM~#Upw>YjByE`jis2|?ZbU=R26>KV-Ewp9rpIj?-_YjInvX_aO5cB$ zq24d&BdmKEztylzz|d^4@SBzEGL5Ih?>6ebw@FgKpS3MA-W8dTtXE)d%&Mr)kU09( zlF3GG0>Rz8;j1QGfV%9_B4HS@sZrmvnYx^#dWi3gnOAVAds)mEujx+*8D!{vNF_K|hZPvKA4 z-}yvpJUV@6U-NNQ?~9*xyBJJxj83_$eH%k-`9RqcMwCNmU(djW#!*MASZsw8chH?~6@Ub!>Ae5P{ z=;N^xRqfAAK7$&4UW&>AFII?vRAk&4=Fp}GpJ+=Z?)FUFZZU^OukDMKJhJsV)Vj)X zPKPdIXhuIwybw@;!RIGHiMaoSksc82^~+>&rn;n1^ORNOWg}Y9HFn zY)}%#8)o0z*(W!tXkp{Ke6@V6ZygUF)+6X+3T&A5 zucSI?_SAI^1Z&CAgkuTM~iWaY1$@PSe+Al1!tn%+ZC+MG6(isOUF7s)n1VH-*KA zc==>yPo)YH0dE2kIOvoe_eRyH%y#$Zu7JAYD2!o8 zjbnY3u2zP#58IZ>Gaio`mS@>5mU}wF`_d*-J67^>u-C!Q+L^5ZxgtkgINpu9jOyu& zZXJt=Fc`-}H6a5vA&Q~egH<{T*^v^r22(dP1a~Kd?<35T*NXIRYRFF!fl5Nn`RXer z(Zg}7ofe5bgazfO$0-ekjg;~xcOwQ^mh||Y63?_76?4rs&r$YY$(e03OOSawF9RBa z;b?fl0YAaM?AykE&jw*jH3<`xu1Yx?Mpat&?#yj+YFmoXy80UJEX9{mpRb`^=vLwv z6Ye+O?viDe6a{CQAC1fJIq2|gK%hAW8X=j@5;Z#k;VbXp>5=+a-*d2N#FPaPJM28mY~G`l9AB|D($$fzZem+r2BC^KEU-*(d8T@^s|BRZXZ_X9pJ83_Ro( zFW;>NZM9CTuH3O%8zy7p!Zi5jl#iXWclE-ZX-(CT6RA|)*B?YTusoEX&qI3RMa4w< zNqA_ninLiJlMt~!8(L~!8-V-$>Z!Q)2=v%MnMu3{PX9dqicj!bK)x40+13j8xxS$$ z=Bpj!on$Ke(?{(o%ri2ZLVRjB&W5&#Sv$UlVH-HQPoAd=lQexBH@HE0A#snPwk;^# z<~o*FX*LvQJS~}}JDLt*@MDJXlt)Zn>f*w$ypwHMp4@!B!bGW*ZzGxz7DwnnY;p~K zBn(>E2)<~dVWQazuc=~|A*&L${xA{Js0igjeh@8@#P=B640Dst-O{*lVDT3tK&tL)_C8-!U0Fik&&;hikvw zh{=hh`5LQQ;&jQUa|Z1Sexr?2?Vu;z`zZ%YUn6XdW&MBe0MRNH^Y(*l`@Pl3pKhmd-(Jp3}(q5 zuSSL-$0lH_kx4T2HEQ!#_-QVBFxWW`d0(%w7F!Z0*mU{;3+9>R=WH^%$n!&(YQ`}^ z)AII~6W}~I)(4ssKbUogeO>$JLn5Hp?Pdr{n7c$rmVI7^gfrQs9m+b0OLR;MG>(Ik zm2EV4CtBWaRw{aRutmSX*7mkMQxz}EK@qSj$3_^xYhR36)B$ja+3(5s$d9v7$@pTs znv(rRCnw2E8I9*`L5&{8N^|0_mZ<7Y^<%VAn?*Gght>J(1al>(4B{9Khcd4;duar( zDGw>hgI^qsb7-uu4pJvr%^y?IzIF#I+2mwO+@5lYm7nl9?>D%>vj}}Q`zaKgyR~{{ zX@*#6O31DV-_UtPGk;2*?o*&Q z-^wG?57?8Vl-}rhJ|HYVZ*yM2)YLbx?F8;sey6wSLpeGOkAr5qz3GN!@d^)eq;6?_ zgv`0iGQ_wissHl4Gvf%YjvH+M^Ov_~*|oxygpfnof-O;eg_R@I>K!d}y$+0`ujC)| z%OAdkk2+8{ptn)hvN<#sL}ed;^>!$w0)@2+hJ?$s+|x|gGkyh2r@~GI0s@-n0}GxE zK%Av0E6?Adz_VBj?3HI(vl~&%I){wFTs^tRW1-i`V$M_+n zhp`v6d{3Kx9*K@R9LtHg*&rS7lbxz^GVB3KN8`YexcsH44ig)+?J661Q+--^Ga15` zxS`h+<&~2y6wq-4p-^wjr=C;2FYErDRu7T%P4r#9rSl|a`TT{O`rU=Ij3;eVxdkf> z`)b6LPO#LW8n)U*UY98xN8XP<^0;K;mq7CUG!91Hr3GZtT>M6I!btg!i1@5d`EQJm%D=+J|`L>(b#G>)mMrMoNhB zkHY>Zv5J@H*zS2}fQAGSfClsOQ6F$o3x`fw%5$C=rzoIrYq->QC-_cVvv{c2`UL9d>_CNk2fC_gliQOS{GM z2FUSC9plM-7*^eR_ElGrr%*Whh7)zF*@BUvjjRE`&MUWd-{q4r^wv(b47JGe`Yj@` z77(P!;DkJEl8}rk#ucOJX2`7$he#v`7yF7C%k4Ffd34=l;v^Tl^8<%!O{i#(iuY6H zVvNDa9{mx@)ePT}QG(tcyOx=mWM(s@GJZe9X!RcB@mJ>iZDotl54V(WpEj932jnLs z^P8}vatXFOQ)sa)>V-#(MUMDpwdSWU*!aw%d(cO!4#{;+tX=eE6oaub`KPTzHbkz^ zPQNK7=qZK?Y?O{#Uhw?9iAaC5LV-8jX!Vw54fne!EvmDddE(j-zLNzU>fM!?VYPc- z^#?@1s(x2sLscFSiklF$22SKy@jH`J;2{qv*s%oBPedRwbV32xAN#0C(L^DX(^9rX zR~J_qL$=#eUBosn_`bRC1|GV>aGI0$W~guEl0s6<;0;6J-Ly%5VrmIjI*MA$Ss~1K4EyOkEwH`*xI&3K-JvRB zC?j_lr%EWa2m?J-+lCLgw**W~32HW2peT<(=LK3O??_A7denukE4&@a_d3k&NF)*4x>3dp-LoS<5jem={I9VT2klV(BJWo{II2&Sg|Edw87x;IJ(#b22OW zh{^dXMsCsZR@Nn+T;aIW+^G!bpID!oZ4K)$%S z*?Kc?yec^>wkwSgo_?t9+%5KCtLqWyp};CIo^JW_L6=u|9Yh`T6cEoUL#G=J?mFG@ zi+(d8Yj+Rll-jzAM)3-1@;|O+0mH4P1l8`k1be5Qb*Rzn{{-O(9{1<(?08sd+xm0L zIXly8s&AELI52HL-(~(}8AQ%|k3jO{{RV*I{Y#q z7*E6gzx%})W;X}a-;s3ti(9+))NQ7ZQEGnrMLbFq@r0A?voqlBJh7Bv!6?fY^HHaX z1laYv^9NJ?#5ygwFLQFsB#O1K5Px>R^U?nR;u!W;9nMqqV_i)4;T+_Ii_IQo(e#^L zJ#Q@ZAYeqtsvcm3Zcd^0{jGC;pYq@gv?5 zQQlfgyrZ~@*Tr2({0>xc$a50^07}S69;rU3=7=pdD;++}CEWK?gp?!K(*>1l@Ymwq zzu+@74v5YYoWFM*asL37jZ@440D8EQ{y~AQ^)E5Q6-A0&C#1cEg;}Pj{3dR(NXrxn z`nVhnf~INz(VS+no3T~}=G#bY8sxOgY_|{fn<-oNXD6GgiZ}bTGku@2E@onthN(o} z$tI0`XFNePxH(>${borCJPBqj^36qgeMk7wBl~~xURuULj%t@P+v)c#Ovu`tv5#8n zeS~oX@PvhTZcqKyykFjbyB`&dZ~CbRCz=(zxL9t(%F{;#iaxVEYhF@MBDeZHQ7`+i z`@9X{P;;3ffM3IBb7MS`R@u~*w}v(xRk!EyN&9@(B*i{z%N($zvAeC!r0PDisVpqy zll|qqGJI&?P^@&5o9^#1_b;F+q~=~l7c>Oe#n{p7M6@ja?P zZh!T@2yjCkZ~ST2>&|aP2Zg1_{oXJ7sFxe<8abJ)9h6uz!P;2cD(4MA1k;B3C zLFt}U@}g<$9rfyerc?J&kSPfN0II+8Z!zaP*f?;7Zhodsb8iLJyq4E7iC~#ZOB-$( zPf&8OX|?5EZt|mO=EqL3y?HEkOOHuyBmlfXGPl7f`%(OPB4RHg9=uU!6C>&V86vfU z?XPIM1)Plqv>;6~#!8Zr*Mc`1d^{p=`5BsRJ$N}YNO8_yhchSF7zS0ErzzF(G#$<= z@+qz^wZAm-N%%bT`fy8HaE_%@kI6Hzj3a|jxcVXM{=2Cp&V1g1XXS4%X)&4PiDYQU zDK4&vYE$<9Ki#MN4s+Qx*|M4k{z>9<=T7jlcOcIHh+?toCAP9+_9Mv29^;60#VIB>=| zG5-Lk$e#cmNo-=VXd5U+&2p;P@9K~0wGa7w4S6~$xwMIM_y_1CtQ?eP5OM1$1y1n5H7?Vs+U{{VHSM9Gg4x(`b7pOi+Q!uwEF`sg3H zfNrpgckI*u0Lj1D%t_An4X}lOS(W8Yj>S@cG5Kdt^98a+bXqCkC9STbGl&Vm7Uxgl!~mszjszDM;<4i{Zz*+G33X=UL1d*$`dh_{YZ&! zzc3>_f5Xbhvm^5#@UmtI?7UyklacwUcOlnH{KwYoZ*d%YMWc=~$Y>a;`&0p?oBjvW z%#3<07|s6xdnUPOoVNN=nvdm1j~-lE*-0r@k-PwNvacVDF}1VsM;17K_Fv_AKf7H`&U-jDDEM8cd1iSvCYe|I?giv7511Vy-)i9mj#i zP&XPLi*##or`yQK_KZo({s<0PAtE}eM}7HwqugBmX4+}(B;&xUu#qWVUt(@dzwmiy zjC%T*9AKq0ept#DV+Np-Ni9feV`M8)MdI;De$V=uF`vnghLx|AywenFvRQhLqKwhY z83d0102873u<^yL;w{DGy?*$$yq4coRsyq3SBT%Yrq9i>@c>xkHqP{4Ea}=u?;{?y z*%UW24~PTRV_)}LuqNO eTidVMjx`FuJ-WB~Sy3eOO1=elD(qF*tN+=iW~@B` literal 0 HcmV?d00001 diff --git a/pict/main_t_dat_cur.jpg b/pict/main_t_dat_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..02bf5442e84a7dec1a0f90f16c75a33c9490666a GIT binary patch literal 2140 zcma)%dpy(oAIHD5*;sQKBbP;D5-G{GTq4B6aGE;{i>6Ful|~m$mdm1yRnpJ=rb0Sr zA(N8Y*%<1$(}?3*aw*9rYQOzX=bXp+^SnNf_v7(?yk3vT`}O=t`XwWPGS#Gyn>LKx83MSy`w&R5}~v zpisFD2snHL9F9;%{2^t8qLQ+bB0^Oag;G^TYinzxb^jI!27@Ue6f~5THMG=_YFd8> z|8|i)2as}rA&>+HApsdA2#f?t_`o$OwhR~ql5+kfuq+4ym4Qh;ssGOaBm;)XLX`m! z7%bgjFxelW3((4S)bknUG*4;0UZ$+T;!}b~+f1T`qJA zH=;iit*#DfFed11AS8sEGF!Q3UL<_LkYAV*k?e@@cP4MNmshB1*D&05I*G^|5>EkPOV$Kzbs(W!_V9HzrHy6&HNH za4LmuWO(O`c*?$Q$MfHY)t&~ci}vNMoj+s-T%bNE85Ex>J&&och%8 z%GxIVqIdU+<;mmYq#dZ0vBlu@##)<@aDtZgOatqEfBBuE57=i<9BGX*6=k;RB<*bs zCfdMt!f{h~cUL>f%;3uvg$_S%p-~#25`aqMtk!))e&igeD^^o|<#IxO7Ebj=Zv2G3 zB*FoBw7|BuXD;?}?ZesQ=T?l*W`vxI33=TLWojfR*~roFH6BSMnDW)S@G&c{O&FoiuP3obBmaH+%V-*88TKfB)TBQA!s)tbI zX=Zi&e~)H09G*hp4&RIYnMdYCfw-URW_dg-fir3wYb;`U>36QPm-%`@i{f6=W~QJ+ z!G~6u5w9Z(5>@?_J?g&0GDY#5iiIaw#Q~)$0mjznj%~Ok?qI(VMwRS?nS0l}8!a8k z&4x>W^5E`%o{d5HH1kQEpy#s*jbrX%80I)J{45qDya511j+WFSKKXY0y5nwez8h=s zwVNB-?}XapqKGEF1cY3NEnBDf1p$AuFAl!|VV_F<-s*w3_2*N9d4|^H$-#cR?6$4z zXI8At4d$&vW3DW7_<E&&nXl}UFRxBl zj?CCb)mU}g2G%NJV0-))j1Qu-#xsc-E5)4NJvzFH5`f|t+PrG$Qp-vbs>5GiHPycx zKnOVe>C*r-aDv-PI!vl|LgM`3C$J0IMZ7R)7-oL5lmh#7kFp1w7LL{TyjDT4Aj>f! z70z62S#@Ks1Sn}G6i$f)xV?=7=hVuskDV_c$Y3^>zl-5V#?NzF_9FcGcT%^S23EyR zMx<4JCF=&wE3aD?Gaos z_h<95>)5V=0w;%C8NF1#qk_fVe~r7bY-!R?L9Ry_x9VAUeiY+Q_eoaquWuAKciP?F zlYGj{>Pv9V0$N>RxPE7xueveP=!y$=3nK*Q2t5>yD_FejRW=yjq_5@@u2a!l{o3=Q z@8*WMw#984Wg7V-P0jlu(MemGfY|KdPT5(tSruh#_CBQ=4)s>!+1f0(_SA)|XPbF|0-ln)dandR*;cuUnQmyszH&33{-QQ-vIGE#qlreYkW7O4Yov&oK z3d<>sA=X6xM#j~xrr+yd*);n%j!!bzQt^F3<5qovSPKVZ&r9O;sB#gbpFi=*)o?ZR zNosx4n_u#3zK&MYNHYO#nlUl%gKbsv%X*WvZ+yWq!lb;dFAc4 bPp+0s{@`SgM|;-n;=V~gCJL_XlMMV1&+MzJ literal 0 HcmV?d00001 diff --git a/pict/main_t_dat_link.jpg b/pict/main_t_dat_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e40990093dfef4c2c9591bc360abf67f1a7a91d0 GIT binary patch literal 1821 zcmc(bdowQnhqYXvqX!awd7ml z-x@^+AYg$BNJ2scfFM9f0;ISO3Y4)CNC;Bq{98yA1fvlcB~$W$HXsBNMxpTlz%UYx zz@m|VPW*uZ0fp8iGRXslqC47Dk_#hzZvn*y!>w2wV60`GXr$bTfDjnv*)V^tfd~jB zLz7H(p%7sbH+-O=;@7nS5s3;Zz#)~92uK2O0t@G8c>{5QC1z$7SGO^w06CpsE@2OH z?WtphE=jWfgU(L(jEWbs*LFC__GrH5uY2fVYRCP2^HPi!P0-0Ppr?PdsTpcDVYk}l z9L~~D5HW@FQopFAh_?EmXnbSB4z{?NRy#Eztrtyt?e3cPJMy`K?>m(8?1=eF;|rdN zvF~!cR+cO~tJ(5)%J_cqB}#JKLZC^EByfQ=L?^6J&%0_i|!gTW3}5Yyzgzu4_6*aRt1{>d?wAGRlH)e-HV8#G6_!r z8HRsZo!YZqucMSGwaH~#)CjlAKD&y1Oz%l8ZpG_1@Z6L7L+$Ctg9!{WMU2gXh_+96 zdBes8KgZLxb&NHuzZ|HjpVBYv45~VkK};NWfL%YNUA1gCoeQ0_Zrv%i&9%=Uih(Te%Tl{|NL&xBMcE=x6*$$3us)YEd9j+ zTixqQ3zm2X%-;A?*FDvBrt3qeXHhCI%F_jvjo!4h zhjw8?$X@(pkzPp0Bej+Ch5atglcdLD+8LXaeUtn7{`zt7$q~ovYmt z8rwL~P;O%X%4hlV3k24^Wx+$%KUQApm-Kx42x{hP2 z-!_ooyJsRBr_!2^)sFu3AgfNb^2LM4``Tx}v~Cjh&rIA3VV>XFJRlP!|lS56K>#@|N^ z5h{xWhE*4H%$QovcDMxGoua#s!{4u4W zaX#gp?Fy5iRkG;3%Y9PSM3WrKE>9EI_!^xy%UlEV;!APK&*$yPPuj}31XD-X1y&Lx zIAqdhBdUm3^JtiqtmWM?(!<(2+(a)6-U#VOK~ih{JAQoTj|Rt|owzT4?{~_kzCL;B ziDg1PwIR+1mQcJ2bCz0nbi~cuqBq`n$Dzg2bl1FQZOd+_q<}~A^b+<+-7&l0_#tVt z(q?Yai|5~+7}2C0*ko3vNm-voI<4VPqQR-YcjU*t@?A&EIMrM8+=?0x+n=>vPsCOu ztRF)7A$BB3aEJHQ>3q*p%X0HA-CmjeSr6gXLz&E&Ex`)FtjHL^w1=5&du`|8p^;=ib$wq0Mtd22Hm^;wbN~#r%)n(KL?Pl|a4W9zE~NDL)K*iOCDv z7TnC+MvD>?#(EBimxvkl1#hhmwK>n-fO4`7VUUGK0B0-&zFM?X&}CR4s_k^D=-vFL zoO@TNQTNh!*;L-OW)BMwPN$N-eo4q>2)WO9El#)RN8H;!oTh(cRDJBf{ph`YI9PIM PC}aFpHkX>qR1EzN#d+|H literal 0 HcmV?d00001 diff --git a/pict/main_t_fil_cur.jpg b/pict/main_t_fil_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..91a4a83e20501b946b05609807e09d7e5908d2be GIT binary patch literal 2312 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 i8@Yht@MXM5_~rSho+C`(=;+H{f8a6yIZP literal 0 HcmV?d00001 diff --git a/pict/main_t_fil_org.jpg b/pict/main_t_fil_org.jpg new file mode 100644 index 0000000000000000000000000000000000000000..150bdb49620d650abb431975e7a90b6de2d89f4c GIT binary patch literal 1416 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%gr14VdY168IxIDw>r9C%GLeL&W-guXD6u>wJKlDRrpVkW&Dm3J!Yxm zS4=@WebP%qLR}}R%!*iP;;}CO;4jJ#aYMtae4R(&s6COlKGRhq$=@3sU^;Qp@oq$*^1dKKG@s-A{Ao+jb?{ z7CutB^)}m~>2hmHtDva(ElbPw(=J{r|0PSBTsl{;pE~XR>~#}n?MhSV z)4l2%x#XzWn^37wX211W_P@}FUo2g%?kgsO1z>c4=+^AnXxiqmPygvg{ERxCVdd(S$8)4P=QjaVBQIFlyhXO)PgV{}EGMJ!em*Y$j`Trhv>5X&&}RD^)jLX^iMzDo{G@=&qu? zPkWShEMvQKrOPXLf702S2VOhB&O2hjaWL@ps#Pa?W-IVd*tI-;%9CBH7Q(Bh{+0Tf z-Ewo6zm&q%+g%mq*MjF<-L1MvRpd#qKz#U_l~O5FV_YL6I@wM|9=mOEJ=;G1w~XnZ zoXWT_Q~?#dP4K75#0S?!hL?UKs#`TRU4J+oJ|=U#knyT``hl2P6wsQSYmG*PZ{ z->>L{iE_B?^sh#ngH*h>3jFQv+xws4OG2!SWbENdvAY)qZoggP-aOCh{A5}7KZ{i| zE0?jdFf<4-F*tBAGAKZq@;0aEeDiL)a`@E6+mi3BmHSWY9DU_8H+h?MN1s+t+>(>m ztP^**i@NCtrM#Bia7VdovG_`((!Lvcf=2_pugtVMo@37OXa!VDOJPXTS2e$lw|Ng) dtTL>ctRC^U?V(Jl#9q(IYswB6kY(Win*i=SEmi;k literal 0 HcmV?d00001 diff --git a/pict/main_t_ftype_cur.jpg b/pict/main_t_ftype_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c72918d7f8ec4f6cdc160c79efc6720535976adc GIT binary patch literal 2081 zcma)&3pCW}8^?ch#h5XMA!f94Ez`1*M7jJ)Vr<0bGD3+)Zo{~hOSEMXnHslL?8Y=k zM9s_&lUsx(Of@Kt86}I7nvjan{O7di^#7kdXV2O1d*1gv=lMME^L*b|_Ea_js1jY= zTmTRl0K()8ki7vg&PkzBDF6t70svquPe}n4$FSI=$AGX7c?KjC16cqZ3WdU;a2O1( z1eb4RML1kh8HqqBBM?YcyG?az!-?Rmzq9QkBW5+sZ{@&&K4epbuKu`#sH+;kQ`$G2jG)GRgbF^obJ_& zGItCVVlp(|zi-oOs2)g;bmcJ8w6UIJB_;1sh>jHg8vPA3VNlnVkr=yMQ^YeJdL=S+ zrZ)PJB7*EFr5Bxny++-f{(5e*pHa0ny&UV~-;S0DT8thmOnC4(1~ts_O%C8)JmkaqNJ-Z5)63)v{Z#7E4QW7CU@6=4 z#*PS!;-I(O={`jvC3!_HFvyfM{6@QQHOslgm$kKs*kHj5&BJ8WxFxPOHJV-u;kh+R z*5(>^jU1tfjJngy_WIf0QI4ct%Zv0u#y@DtzOm1n%1Ro(1Fxzunctn?`f*@^=+sB+ zRVsa6Ja`5kOjD`avXU)0aOH3vY>)Fp0(1OIB4d4(yx++f|7_Jp1krA(Xr0pD1kqnb zgtzi)WQo(W=Om$7Q%(btsLejq$-+fk?^Y~kf6)kdI~q9^+D7y zHWoZTWHpC{^;zX?F8-8sy2h}qcHpFv8s?PyuS!Dy=lBtcd{@#ltJ{9uqao znG8Nra%M)1dqLnonDQOh>{%9|HMhn#UN863*58_~T)HD%x1>r^k}3lpu2cu91m2bu zv8a}ZdHIPg(#^NFdu(h@k}%nr(upgr9r;Aqj8an=?;Nk}9PO}1Ky%;+tzJ)GhG$^f zkv_BSF{2jM5-~n|xTRr(n`StfOL%J$s^}e4)3L+Y(OTT>ittob<%PZTxddZ`*C==0=ayC|CgoiqH8^IhHJAnk=+6cMN7GD zC%XL8@$?o0cT@3FDRX!>)_R3eo$!UfPZ6qAV}`4H$+;b;Uh8`A$F0$2HzV zK%zWgIay3w-gdtER_iB&y7}j)aGgFZ9rMmXyP8~+Ge26%*(8YfIcSzj(Y292T8=U< zeE2sT|LE`kfdTpBbSp~nac|tZF)1^P_&U#eMGg1*i#?n^F+1GVY578WuYUDA81};l z*lZ0%qXP^24;C6fma=TYut?u|-6FRg^wdAf7Ju>8+2NIvP z%_ZC^UiF(W?oIiZHsoyJH_eajj2i9c-M`d0o~NqvrcVao zT2)M5Z}iv8JIbJ0hYEvZ?FrJ6Ck)}_p-2;3kE^lLI+Y39tpMiP&zbC-Jss;E{%RR^ z8t+G=J;c}PzegQBeGLIzLqK%v7Au8>7XHE)+Wd#dX$6+NGU^FkgI2pliAmJ9NvZw5 zlc}?O?_8_?)pk8;B0-MqPTVFuyC zUylsz-sLiLEZXyq%F^Z~BQD9xotC+vfD`6;AkOCOPsObe@RQ}4B@U@Y)TYa`twFtg y@6bUhhkh|7>--h(L<9_4w_Kn<`>vUS{fEbpty}W_mR{zp=QLcU4Lu2$iT(=$Aeg=Y literal 0 HcmV?d00001 diff --git a/pict/main_t_ftype_link.jpg b/pict/main_t_ftype_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9161ec5fdc1ea495905da6173620490adf293c13 GIT binary patch literal 1764 zcmbVGdsNbQ6#xEsr-%?RpJkGoidiV5vCMp-NoqrfP`t9i0%F}9s;|L*K_&%Nh!KA(F&_i9Eo&j6n7>Fo(1 z7ytro0nN{V;PJ(w!|?zD2mpYSR(b(&u7YU35D0E)6-c87DFB5)Admgr!y)bX7Z41NK%(#fAP{gg zghIjpvi^_(0f|~m3^2cUPBujPfab~x&7+{jNp2e*$rb)F+ItWjhC~4L-*FI(z=5x& znA5}vl51!MF)6RH>)uN@zUDE&YM+4--~_M}tTZsP?}@mD*47o>2RV-cd@-l2G(sWX zPMeUA*cT@ftkJ6}F`bKZ`_OUY9@otYKk8TI#fHRE!_I%mmW81tvWRq9ZvBbRi`M{* z3lXcjDma{G*RCjS2ir$%GwRof%CZ3gGXe#S%)%3&_?{*aDD$W>|%Q2>8*t^kLb&V`|{~UPlpp* z5l4n=_Z*#Z?JlyhPZ|t;L#p1Iu9!I&$yI(j=azDyp2BrrP?P!_BmE+qotL;|??z$` z^AiIHK&ch+Yc|x8D$+gjM_U-DQ5 zgRcbacHvt+Lc0U+@t|XQ*k>h9gSX2mfzR4u<#krw2pC_H^+8|4pqXHPzeBC7Y#S?N zp)=#So5O3}lN+x^%R=yJQs;cR(Ae6wh^3znz-qVo8}~Vn>|RG<)|_HX_JRJ<10gIY zuPdeJ<=3w@S#0>aC&>)}$$LUyDX%Ep&n}uBj+<|(I3+&gOK*I_c(7%VY#cP@yl^jM zEKYLYMmQJ~9>t}xl{uDzWsY=KVdI%$+$t=l8h_(m z$&3$3SmkA4-n}~OW3)SWD%H!&6iPu0Cg1%K+d0zzX(o5Nqa$;=Yx8E?t1?Nm+NB|w z3nkmoh)%s_3^`;q{x4{Q- zVJYn4XSwyXD(lrd50!2i&;WZuYV0!Z4o>yzao`7viDkA_q#WVYonh;+_VhYIs2x%jgSwI@hjP- zIyJ24|BZNaP(obn?89T*U1c_nA6-sj=jJ}?%IEe6e9U796o&VDG73*s8qQBXhE|pqcGZA*WTcCTwS*OW$VQ*QuTtVz zW;|uw2@+9$RVMgezZj%%5`MXrkPuoG@6fdVFQaGIE1|$Cs>tb9I=P-m!Ja z>A%HKmwdm+{Kic(xp1D@@|6TrKyrU!!Bwop8}80e!v!Z}JBH4jx_PU+w6pvqU()M> zhXEH11U4Xm@1axL&vPilb-;j{nQ)37@@2t?Sch aU-lgRUxCUfMb>iMz&mYxMh&%0Gx|G}r`GiV literal 0 HcmV?d00001 diff --git a/pict/main_t_ftype_org.jpg b/pict/main_t_ftype_org.jpg new file mode 100644 index 0000000000000000000000000000000000000000..801c1b075a92baeae0b4e1c39f1cd43d09c7ddc2 GIT binary patch literal 1340 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%gJ{=#GTMTxBpT9m^HucK4j2 zT{TnQbj)tP2dROw5X%bf0SG56J(iqJ6I()Z zIKP~eZjL-rzxwq0JO5UHo_gQs`J$k<2iJtd%JjGyrdD69iZk51PVn=MV~h96DGJ~D8zrUK-g{htLE*3R$$9I1 zjW2ggZ#DKW^_?-_;<513HPx$fj{H2Nbgj~I(d-pVbj>z|gfu5LY|s$SaVt4`@#w73 zh5bpdeRjn}y*r_MXe}4JSC3>y-jiDfN4;*8Enquz;q}tYfGF1%#s%{^CW;1&?02!u zFnQ%sXncvQ>$axPnP)2cbsO9^mA?Hu@6^<7yIz?GZJA;cbHrFI&Zi}Ku9nCazm2=n zSKTPk5Q)-KS-><&*CXJ^uLWlVZutuND)a3Qh^tWCy1Q0Goad6Nen?mA;^zX}w@eXl z_DYCaRd`hGSIDbt^P|HZf|l`hUzU#$TetehpSk&9zg_VY+xTwfX5r@?-H}}TQavtf zsUGlI!=#+H;@EAAORK-hzet>)->-d7Xv)9Io2;V#7XF#LVDE3GEd@p=IykVinmKD&*!SQiS^D}(hik~GRvAIyWM@x zw@Vd?88=sXl--ppzU}$2bumqp-`qFn>5GV<(|xDEtqrSda1B{xzi9F5>R%u9mb1OR zW68bgrT; zePz@8oFtYRR`n}aT0K1BEOJag@JYUUj3ozIMjA`(b*=tzTmK2r{)nWR|8D{S DS;!Qg literal 0 HcmV?d00001 diff --git a/pict/main_t_img_cur.jpg b/pict/main_t_img_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5de656e4a65246e1acc8983fa96cc3ff01b100f4 GIT binary patch literal 2353 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 literal 0 HcmV?d00001 diff --git a/pict/main_t_img_link.jpg b/pict/main_t_img_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51c1654dfb95cffed252a2ecfdb1937713f13c62 GIT binary patch literal 2044 zcmcJPXH*kd8isFr2q7d8kflj8BGMvkltBgvMM?x|B1ngTVF@6D2r3BDi$EyST&0J| z3==^@QI@I*I!F^~Gh|Q{DY7(C)J%4F*0Vq7&%XEEbH4Mu-*>*&e+!SriQ~m_SV>7DQBqP~PEJmK|2IKUD3lmhOa_mak(DAy$$m5b zY$50Z1T-LlNEn0wpackv01@;7mM}IH27w53{#S4W1PViI- zaMT~(zc3&mkP?zk$|J1GQL?EDQ5xmoOVvA{kXPZTDs@D-4+?=IAu#B-83GjMAfZfF zk%SXXgf@y$-2{RF31YivI?ozTwLS1gEt5@{+I7|cBM$YZd;ED5w zWIjtP_Eq(%CEUAV7L*)N+%Vrq!zxjC(ukC-DohM+$HimnK3AhYuz9&Q!GSmy%t1v| z!Xvauw2kU|8^7WudjjoZ~HUxDEQ^Rti!O-=` zmGt&!8BX5n@K}QJ&Xibg%Vk`rG2Up{$=(an6+be+R9)UjQq)VgZHB6JS~T!UQ#ukJ z1GSx+Jv{3toPzm~2i=I|9$>~V(nR*F+V~n+bd-=NGb@&Z@3J+bpEcU^%4ZL{9V8Yd zqz7q*{|JDO`jGa8+#6HoV+U5FtTK(PA~{a$r^k#Yn!Sxfy3G}w$~$l8YFT8a&^=6A zlO!Ah2F$P>T;^J~&O_4fu{UDJlr?yWT<;y-tVAx2Ad+^?AZ)HVjy)V_zssA-Zz-+1 zYdbn}sUn}@=)Zh0D@>!pCoI?SG@4UGURngPPXO*nO8Y>) zb~9tNjxlPb)dt3gdd4}NO8xfh` z5h`|6{Yn==ZKI!jwCF&ypPEt5Jdml`%-r*o+#IN5e|X$yZ4ez`Wr|3JCIJZKvueIk zdufoJW>|1g=?4O9yG)j6Q|Ifp`65GUj!d?KUPwv|)V&5j+xNts{=;pxM;;fW7^-i2 zeLNqv%DdFBQCTZnpXmBGnyh??$J<8YJm9*!qvU)CvO;mXVrpAv$oDmr_>#t7KbC)e zxaf)#-OH2MSzGoRX9VUo1r|8}(iyw{^9zl1c1fXb6V*z7Fa)-U766qZtu;T_7!p$? z{PU*jWak{W>n8z#ev-bpJXod1nGlUSTChp^In9?(2se9)zKk%FD%H{9AsMMd{DXKGJ+8)MK4!|P+QWDssffgZg$8DiX z2XoUqR5KNWT?bq*mM%YDt-sH8TL?Z@uBg}X<6oJzI*daj^;<_*gY7)ot5W06Zp85F zJc)8{+HO+sl(ZY!|Cb4#A*t=e5yR+aQY9uVlquU!2p}{(r>!0!*S6n~cOr(SJ3HGK zmj>7$Hy8cMWKgd2=*DM`rx7owrtTB5KXK?*yq|l^Ri><1uU(DPjDEaFgMo%l-@rbV zq6M@}*P$|9VCA5W@1R~NaENifc=vvp3y1$WJI^Sy*ZM+yqU`CYx1-ZulX`*6T&64C zp_)D6S4f<>&T0*xz0+QD$2kcF-wQg_f4eYw&g;@DW0=3L%FWZ_Zk#z)>RGTC`UCU3 zmi{rD{EW1cCmLd`uQvzTJ};5vK_v^r$`YN7NmtjDsxRK%!3*stnTw3ohrGy9?MUZ{ z#O$}((;BlU9gPg45%T6khv{xaj_>+z(*ffo{_Br2@9l6*V>#BRf&P?tv#nRf*@pG{ z){e$$~* zassE7ms(jS#bw{TvfV?vhaLSdp8Q*&wkdrWsupaK>hzV7C&p{UcGhitHrOlN`L7(!PM`Z CO=VF4 literal 0 HcmV?d00001 diff --git a/pict/main_t_img_org.jpg b/pict/main_t_img_org.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bdc0d2935524e5896b803c1a4bc4c788dc86f2d3 GIT binary patch literal 1487 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%g|5nHbGW4E9_snJG|1!lq&D(vq6!-UnznOQP z*F961Y1!tba$MCX$nVes^yi|P63zcU(Sx#?D zSY+b8WK+ZaPm7nFPfC9DY92WGZ@>26 zfWJX=pZKj_sCm}1c(&Th4snGz)yX3 zEk))N@^ia)cHNhHzjaaV4~theA7825n{PHzkmWc_2ZO?&)hG9tEt~oB*6qq*Q_Gf( zz7ywZ-1Xii8dzX5e{SWwqtb7et@EA5#>tnstS`0md!d`OfbAU>&joT97xYg}pL%j# zs=!sRp55C5jS?0)$hp_#7C0t1RxkT^`?7Y2UQThfe&vVMdojkI)A=Q1yqA6BR(fQ% zw|(0h8_qVvmVb_|i_e@;GK${uNkHJp8qtQWUqtu5k9nHzxzzBtc`@InPb(7wR%+{s zI-Op=*;DDz?yTHq?Sg$?Cv|2{JFUFxu#Aw-nx|Jg58hyq`!!>Sme{ELxihj;`ba%<*GuI})zT3IBc(H%_rgbrr>LT}- z{+;Ua%x80|r(18Dr=r#Yh8>5EzW08q)^hI9&fNLK$k}*VT+HS}k}8>chg@ZEa@zg= zowc%~DQ0r!S&pYS9-Ud4c9?5n{9QxivTjxl{am?Q5wntuML++Uy>nmclrAwf2j4A> zQD&)Ww{spxoB!qiVxIo%_wS@1QP+RQyJk-PTl^`P`)&WHDw%&lJnuhuZ+KH`miX<` z@6DAqx660i$h`M`^5b&F^wW_~&EDK~u{EFk*!NMqu2J9FE6$fI?M&{ee!8qN01~c? zU!IHWlRPu&_NUz$zZ+Jqb*bs@Tc>~fPGami8SC9VX5XW>{+4g%`2I%j)&s!+E=C6p zR)z&4Obrkwqx|eQ3;i^wuXz7Q+I!vRD^t5H@GiaX>twdde6Ra~Td^fqlm|r6 V?fZ(2^?bAIfNpW^T{ZvzO#mrcV@Ci0 literal 0 HcmV?d00001 diff --git a/pict/main_t_met_cur.jpg b/pict/main_t_met_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..64016bdeca984d722a58c4321800da4a43b1907b GIT binary patch literal 2151 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 S*G{hv{HzI*qO@|GZTk~D^6g3h literal 0 HcmV?d00001 diff --git a/pict/main_t_met_org.jpg b/pict/main_t_met_org.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e5c014064d8e9c2bc1ced606167c1fa897eaecfa GIT binary patch literal 1399 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%gG*!}An_o#6BLXLDDtyxGq)NorO8#VL({T#EK@coD%a z?%y;wQ1Fc0S^3j7{LakkePN3~Nj;C*cr4%p@6zq+32Ri1 zCr&)i`dwqfzpy!u`+xme|1SNiz;nf;CFU~6I$af1H-)J+=scAd6h7-(@ubw|UfW#X zr8#H)&K(N4yC|n~PA8k<-;-k7pHB2YyFy;eONudL>K0A05cOG!4vw`ayZ5E_o;O~= z+s=_;=F{|d)BHL9rh><67aVvtXU9@+aaYZ$OSz4N&l>Y($)r2Q>CNY~TBJTB{DQ@< z8j)8W#q3KupKHoE&i0g3V5oI*{?)!vRJjm%}$uo9UOF} zMtxEsU-h(rN%1>psU7C5ntSQe%M;tqPBxe-s5DdK{4ufHvaIhC*FEuCuDxj45^)a? z2UAuTPcM%N{#(xcNix~tF*mTd{$QeGP_WOmS7EcS{oU5cc0qFLXThbLWqme9Ukkhl z4i#NhlTBRvQavtfsUGmz#3*nx+i=^d%+L?=FJkA({R`Wps`=AjC3ESo=bv)9Z_7XV zV)~^g>|dcN&uPy|?dQbruHJdJ?|XXE?rkqV&b#LKCVk26$)y5sciE(GoxGb@dEnTB zn`G?wH{76PAw}jyMP~ zF*tBAGAOVxG=Q1R^5LggrYya;c>aT1elyM&UY1y;U)9f?X_dIcO{@Ff;sZd@Ji)F- s-&cGvo4icAC27UpS2ny$Uba1?t-=|5Uunm;>+E~-vh7i_sQ>?)0NoZR@c;k- literal 0 HcmV?d00001 diff --git a/pict/main_t_srch_cur.jpg b/pict/main_t_srch_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9b99415c84b83ea6f473c103c520fa01cee888ae GIT binary patch literal 2497 zcma)2c{J4PAO4Qn%vi^uh-l`@8W+DBCMB}X*bNm)rz9*tI2MWeO0ZQG`$^AA99I9x$qVXLz8R!udO zn&v;k|9g?P04P~tClCz=p#T{a2#f+r+ku?Td{7W*Gv+@4fgw5#Hy;py=V!RQEJ@7-=Q`=GEguW zB>R_Tb5|%C74QyoFAT&Etr|dMTO>RfnEYUW3cAEil)eSz!Jy5IU=&~rd|ZFi8{0Bf z%DKCe6PL+8nVgtMC*gE+tYdA$9xt`F6m0Pcxc<@WcD!4gzU?{K_6Q6`>$mR4M$9`? zo)2Xad${Sb^GeuXL+z*xSCY5O` z^!)g#XVM^pOKb?bA(wZP64a5u%LtpaRYZsSW~p}=`H~9Ooo671>aD^M^oqJJQOrA- z|Mfu`foUe+a%m*=Bt>re$}TUZfp;myb^0r}*^Nw$}^y~NUlKn)IaO@}^K zICLA^`_-6iwHHxQ(;@D0l&GeD z*&FbNj!4{}vY*eZy+Vd?4${X+m0@A={jwvLx!uip+VghYrV# zS+6T2?c5?&OXjTtwCu?HF~pQslFhx!p6jS63p9=W%x&yE9n)KZDSG78WxL(aSEc&$ zZ68)vjj1K$VqY<>Y-VO&xhb-$$)KM z!1_*)_J#@ZT;QGI3Q6^nl&zpaqPy2k$ zzL!SI)r^^t0&>CWqf~goU5EL?J(h?xMyu6*K~Dye*6G-abwYulcNEq9hEKdYp1bH= z=jastGhfFzl$_(y`w%C80!z-=o6*D?Pqnwgh2}=PhNd<(_D+^G7f$jHmVB8lw&7fE zrgzkscmBF^jAJQL-!GXBvCO2L-^LpgVH*sVsZqh5XM#j9eC_gQSn-4^OFXOJ=P=bq zh>GkUVMWh_4daU>(3>e}SMhI6^?{c&xzi@oe4Of(NA`qYWZ#pO!SRKcuoDM2>X=sX#C%t&_mLkezzb1AC zOotd43lQ+QOFpFcsVO`q{J06N4E(4_v`qR?R(8ViPFuw96cd9Zh_!q|r=pk5g2Q3V zJ!;jl;{*x`>FJ*)JXlnl!jJo%YY}9sES3a*C@~h*>2B?u_hBz-WvH96O5Py&#D;OK zTW+8}_rBB3kN_K}x5+yy=ZcHzzNxdW`J#~X!gLpC+SIpb*New$&-cap>3xN7DBk*N z>(3Dkm0k{8dXr0-e_FYk_XA~(C%=~N{%y5FAFIaIU%4}NB>dL9UJKICk!>Fe7nR!X zODGJBm)QBnc+0WLwdhito1v&r?`$;|mcHN*7rNETZcug7e~*dRHuT&{hKQ{MI0ZO= zSwF{znfL>}v}w0GDc2w&)8k?Cvzyu{e%knLSdC0;)3o+9!XUl22&U8UO8Yp3_nZpdP5t7KcGN7I|?Z>#tM?KtWZF=wGE8WTL{`$$a z{vVi=Z}g1+`1w+U((^chtzvfB^<6UiMNIL&aUCYnTX-Wu=kF$^hVOe0T>INKn7tf) z+YgsPX?e*yexXp9tF-1Yl$-=->xDN>t?s$zOdT&kN7@p@{U?Pd$6~pRndIw-k_S-5 zSO@o>GrvxBrwdodGljLHv@VwpuPsc8UwBA#mzs)Pdem2>W5rK;R^L;VTQv$0QwR3+ zs-(3tQdd+wkheBmaU}+cTavmS7*!t?r0w74ME>|;S5&Z=+93kzk4;@sk zWQ7x#-*Ebqn`%*qS7UB;CBt{$?OeX6Xs7L8=L-KM1p<#dwnzb8BbE3sbt`WoJVwtz z-}30GSO=$M7D^N28NN0^EcK1TO95xWzQ_Ghl5ld#J@(r6rB9Many<@e-p9i?d8$)g zCH|34!lDwD!{&u$@SP{(+C+EXhm*P5LgUs9+xLIHnV#B7G)6F(XY~!GK*4FPAS2(A znHQ=noJH_ zgdAz#$Xv9KPo&_k2i1vZeq=?I;f)lmXJ1xj?P%8RT*v(~Gri}dKWDh>i&9J+ed^x> Y{!1GVzGKtpm{;F6TTJZ=CrL;D3*+c+EdT%j literal 0 HcmV?d00001 diff --git a/pict/main_t_srch_link.jpg b/pict/main_t_srch_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8087c4a48bb9a39e1b063f4bca601a0657ad0645 GIT binary patch literal 2184 zcmbV{c~sI_8^?bLVkIW1kh`YIq`4&KQlnPxE9D-fa$M6)LXF%ob5cZ5~Q0Oj6*q%L-d-lNKuzw2<+ba#1-V2kJm6MZ|RaR0`Qdaw0APETxDVUTz94@bj zL?9LaZv4~3&I16k3qS*xz#s%5h5&&Ppq+joUldym3<8OA{znjT5Ev>ZA!7f{MSliE z#Nhx4ECvCKL;oE3Q(_=^@jf7>?F6ocb2g7lV@Q7oyj=4TvLfDo&DP38(Ewa>s>eI!5WQ`0 z%=+USXypbY&}INDCCs1<=&DrX+>zD&-nraPInqt1hjc8j`WL-D2Pw+(Iu`d-cG4TU zf#^41UmC5qz`f(klQBk9=#3-I##SWnWr-uglzSd{xv0U~6YLBF4fSn@>rC^eQ(Cww zs|1HttI$s^e-s)j+!=jQ7}Ab-xUqY{{KLrAw2I_n{VsIIih^kq%C0uS`RNG0)IGln zbpBeI93-Au>(aG2-bgv_V(%SEu6rIZdcB3kAWDW$xVmh0G9A@7O7iLLwDPRF3?Qrv z5t>!1F;`zke8#RwU7ugFoeqlC^IvS}GdFL{8A>4_E)rc{?cXGh6~qj-hxZQ`9`u4- zZfNYuF5!6>HILv^85YUX$}Nve5^wdlBq3XMJ5i1(VGKFKZaI`&Kam@BYcfK=|Hp(l zjzZNIsd$VkALml=M>r(c)t3A<`6x9eGn%JUuit@g4bU}e3!Ld6EWVX_IWjcUBx_zK zvn>z%^S2Cf^=gwWxAmV7)72Z*5L!0Ex{BumA=3jGJ4aKj>=vC+cQk}ifGnPq16=^{9iXx0v?K+biF z4Q*Io+GZLv+IQ9Yiq!pqZddmkHQ9!F3fQ0=vyrQH&1bDfcTMKrsoSS|hP`)1)dCf} zc15yg&E*}|S7Q=U&y3V3=iyzo&)5r_1*p?n$HYwQoKHD~I_ttNVZK-{FWzCmS{5$& zZCG?qvHPMwc!!KNaKcxrzNr+o*w(6SFl1Zf#-E|JUqR-YKk6UV=Bez1(By3(s9dwq z?iK=9x%8v`?GV0k?5mn5t%gpoLXVcE-Hl=g5vSNwCHpSkw^x+2Kk*36F#&0)5SJtvWjR{QgAFUMZ;=_607VdU_IO)1+4 z+KRj{KL~6VxVvM`7HFDD95*xPjqQhr1qbRQR+bX0&nA;tGrBWuQ@I6fq0lQ_(ED+u zVl5Y1nAuM!V0AOoiv*57mK2So$Kt#ZaZg6(7ZCD8}ifw!6MK4!Ph1y?%MaPU{W zu=GifsocDAr@?^5(1VA1c1xU1tgU~7lvOlH%JKG#9F8^mdL@k#KFVZ`;93(JQF1zv zuh;|g)Poh5=d=-C9X|2Cj(D#<*lp)0*3AA)I^_$?7>BmCKh?&V%O%M@s~=7F7zuve@%aYqbGGaD`m=((te1{oXOH^z zFY=73Vw_RZ)=(^!pZ&(3G zmAhgwqo$9_L3^HD?o2wz;VwKHe)%-R!c@9pGmg@UH!pRQsGj{)@m884X4KM1hnjW2 cMJG|}|9aAeIF0YCp%b=5t}+vK$veOQ3(SeVk^lez literal 0 HcmV?d00001 diff --git a/pict/menu_b_add.jpg b/pict/menu_b_add.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9a50a3c0b18105b65b81bd13c62faf37aa0b9288 GIT binary patch literal 2208 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 literal 0 HcmV?d00001 diff --git a/pict/menu_b_analyze.jpg b/pict/menu_b_analyze.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ab8cad740061be354bf0a27cae798a6e5ec391ef GIT binary patch literal 2758 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 R(w)W%!Q_2u+;jZ#e*=jsb!TWhVtd2mlzO z0mAnHCLa$t`Xhh<3IJduvSt9@krC>D2r%x797retY=A+bP-qkejmAh|M3fZAV8kVH zSga%#izDE^f`G$I6QuDtB2iYBNK{c)R#s8_21rayObREZNFXS#lY`~feLH-w5Z(o_ zIFJQbkq`_JFoc95VLQkc#YP~IqL|-+L?ciTMht=gQpEoNLLgCS0str^1|wP$|D4ub z0HbBNUa|}f$s{YAsO3o2kP9pE_lvLf)HFN0K@1kvg+{IM-;W>!T;h+^B*_qEO{gfx z_^jHNIlr)R4O36yFu);2nP4Og?7@XgI!u_s!-b(g?e9xEc8nv4 zky&J0pJkVh6wZdS<{KO*Tnty{@+&K*31&$K-nq3JL2;Z^J8dOE84R&{MYqw(J%C={ z9+WE<-FK7`k>|MQfs(6L|5QZdK4mYyj(&nM5+XY|kTD7&mYM10cSx1nz0a`pTphr`r*pSeoE(RN$A%; zIME4B-%(Xyp{Q2Uh>AAGdJBR=E?EX*b4kpEnuMtCMuVJt)K#~GknU%0&k~isEn~57 zzy__KEc=VwWM&+2(puX1dWTgd-)P77?BAHA7KbTC@?-x?lZE~Ym2Q*)rLt!UQ{rhn zGxu7_L0FjqrDqDt5uN^#N{2SlqkP!NYAw5 z(x!ck&O;m(`;7t%@5T#)ypYA9TMLm(puW=w31Wpv#^x`ZTpWc=^OzUQDhA`pVch7{n6&U_a(d=T z?o_4ATyt>QXzd^M*oA#_O`jTc-j5Y!fP&vQ+B8=AeCbOoG{wifSW)SxPcPXNQ!FJ4CXv$Zd+he1~m6v?l(;?a2SVW zJclcG$*I{o%d1Pr6Nr~aYk>b^7M*??j_u6zPV?7Tp?mzwpVxUQ1c9E*5ydlkiVMac z+CD$j5rlUs(atmuuSUrHWt#V9eMD2R?TJNFb@vzC=~&)-%DOANqO@&AYSRGe=ah^C zyj!>}&WE`HPv2FyNqH*0&0ko(R?|jH{NEojiieHPc=dkSwf9s0q#;0J5=9_jK&+rZ*+W4P$|y@9P1q+(K|&y<1SLw!h?FHDt5=2s zLV^#n1tL^|Ko}`lWR+0@gyB)2nySf6sr<`+J|e_q{&zzT)4-e*oxjY#nR? z5EuZ0B@Ym<0vMZ^pzvz|2!H|ra8`oW0a>fy$iNUFxKlzv;u#wBcxGCq%;zVLZdzkjgpl^%gLg!SR4+ERZ>(`R8sjYkd%~^3`#~Gjh0uyWAF-} z6aT9bcLEp$fCK6wAPfM;fFKxz#M3kHTkAW+Ds6_SmZ zvOtI$@sO??7K)QJ&>QqN5=KmGk9Y9@5?yuh|~WTZebH@dZc!QRt4t3J`a z_O~ealz`gwLOFQ*g0$kVTCr>NDk?)j^C0Kj72GraLU%@oN2HMctf(+e~$wK%TFqUq7@iDQx25>ry~w>OD??`GaOrK}h-GX(-hksev6B@h2HB4_Jc zMcbJSGP;|hV)N7Tc@i_>0vQ+^66V~TypAViig4|;%F$iRg_eO-6T_R^0y?Kr)Td2l zdj=)&6_VcYo@A>n-_uI!Mn)b{S#WJ8o$Z}Zqtg#?AHF`@^P2OKdHm{woN{gU z5V|C0skb>=U9hKS;dbKl%%`(%A#0$@ztL4P!&^2M(2c$UVF^AJ1DL@AW_|blbqARr zDU5FI!~x@zwTGgAxV|!|owofb`1Bt4x$2ED{7|LIM}wR8NXy*(aw5n1GoZkX)DQS| zw7A>jH0K?e&C{2H>ql1`PMoRVQa3eW8%-C{Pxb6yTr`h0df7USif$>$T}Q>IB}J^! zkJ)N!SGY9to^T?;{r$P&Jf0RqB+|bV6{L~(hTv}#i7cEg=F2IRaJ)jJV?%uqom*~9 zZFxcmGE+U%Wv9-cTU4po*8DeyMw@uipU%*=W_K@>7EtT+^A~Gm0}9(RG_7{nza+je z%(xgM2BdG!?9#M+g?A#}sXvx!pjSBf4Yk!aHqr8dzJS)3=0sg-{n5ni;ce7w3r{pG zjPS0}$v*jp)ug3bd7a=Y#F@<6%M2`ji>vKy}@5$0fell+8vtzZ6zNb7M%|IxbAD)^{_aAC`N+MXKQ!5D0mUy)u^;nbdIdzdc*sS@K{p&oqg*C%bi^!fAw+Ej>w>hdQ|sI z9}399os{~Wa`MVEeS9Fk%V-e3!pH3$#E5na6&4YUHzgM2BBNP&xpduP#r4#8HFQdZ zMz8IA?23KWvtm+Yjzx1?#K{l=2s^$vAiTo8LQH|M^ID9-w zDyZ3ZHe(q!ITVo4EUs6bF9mqA?m1%yVL)xEH(?9 wQtBOW-=Q?MI-A8EHf9MII^OgNl?Nw-DhMVYYW$w&$gS;tIAu25@lZVV4|88bbpQYW literal 0 HcmV?d00001 diff --git a/pict/menu_b_close.jpg b/pict/menu_b_close.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ebed7dd19b09858c175852c608d8dcaa91c64ffd GIT binary patch literal 2495 zcmc&yc|6o>7yr#ZQ^w4g!IY3CqDID=B@9MXwlPAYtYrx?L?bWL6rx3_p+pEnvSn$c zJA}%TY}wr@H_}x%i7eqAb>H64{pbDn{XU=1d7kq;=bY!9^F8Z>>jD6Kz{1J`0D%F( zTeyJr831P7dNXP>8Y3zM2J^${?@i>V_D{cG+BzS= zApr@X5CXyhU>pd71Fbg$cZ6w!pb(HS&;I}phQbga2oePX0bqzw{1;F-2m%8mumJEQ zaVQk=^A#kl1;D}J-FQbtiWnhHj-2a2iMxyRkT(^#zpkmMMU{}m33~<+mI{G_AwMDt zqvIgZZZSGcT#js?nn$2`oKC^tmDh-?FjZ)L!@3S%9|lB(sR_++fHAO~Wm;{yT25EB zp_XXcs%RWk7eG`xd|{Zh=+Q^Xl6Q_v9-;0kI7P#ZlURjJ{Rpr$^H=Ed?1m zFEg`ChymAAt+wHnhI$?5z0jdFKLu9bnTw0(ejB{G>F|XYA(a*%9kHPjB?Py=4?gB5 zP=bLDs?PZW7K_Cb0JAoIdesSf`_hhf-Mt(wW?gJ<=e<;wfurV;r<4bGU*^`|!ZXnn zgV2e59@A=PW~pUpZn8fb>28Ow^Pbz$M9tvqUEx5#E6ez+D)lyfuLO;nBp9*HWy3QV zp}rQ=QpRR85v3RV59)nE@x1%1T1$XSHg~=bPJ*X?=tqolyXIs=0F${5Zw4>qX@H2_oxcDdU1n+tp zc^)!2w|U;$@Q77Tb?ZW^3ALMjIh|{uKr8ZOH|L9|?IfBQ@)g9wj&V{*_g)E5t2d6_ zsK`!3a2;i8Yf)7J_69tAmA_)CsT2C!<;xLwj<5<CBs>R)!~}#;JGV!%&XYXUvEN*7CwU#R?N9a_ z@Y!=#NR&h?XM?E94Wi@+d+|b|A~uNfcHQc^L2aA0V#ra(0)HJSwN0$JSWnVQX*^PD zRWmAKwcU4eaf>$E2#!beXlNElw?swI#y1fsGgHs9(3DosT}8CHC1Q>euqFPbqQhj* z6e4a(3op8Tr}h?ycY1})qb662U*@?6X6-96s{<3+;6(F(v7N&Fo0NDiL)FfqJlYb8 zX&#~4_6E;xo&{@dneIRYYsPT;!Lr~F3oQ>maSs>l3egLluVTLntkaZ4 ziv>DLK)T9g91fYB*K1a_O8c6cFMGRA$LpwI>z^#B`N#7~IdY4qWaNUg)B-0BqeFJ& zBU6~um9k&##!B`x0~-<_)dMB{|;^jCcH*hR=P`eT_g_wmL7M^AkHc0H{Ob z%k4uC!lBCp^zR=@Y7LC)6_YjNWSvh({DvIVOwwnsc_5nu=fE3&GyZ&BVX*8 zB5|Coez8mJ4BEPFN@K<>DV9wgz?}FzS}u8P#A%e;|M208+s7n|{LHtQ)JTmJ*1-YY z#f5oQg?j$e{+C2L{K>a(+azEUS!|q2i=9{-Q*r7MqqyvvHN!}($BHvKt_Fptu3nR6 zSjDp?E5!SGkxHI1Zz9?9H*KLEwxfHnY}&LSBXQ-zTkIt_L;R0%#~mzW)w-=% zG~@3J*x;p(Mxq*s>3#DtA67~$Q(AaZJk6or(rTeftZs*?W3t8yqkPRKlMnu@SUj#*#eF9u*|^tUEhuEoPPT}er+aF1tT-IOPZ(c@RP|Blp^}rk z6?DhFU~(RSLTb1nPITt7MHIK#noykMrZHfgXE3?{>t=L+qBjs zhn&-8k3P~{4I}8BJGV;R=T#pQCo7xZZwvUubR@_7SS3#L`ud7Ldu6uc|2CCQS5hwc z(}7mfcqL%BO4`!rwIqyWjq@ zYhZ zT9McMb4@a7rT$<7ohMv*YjAqc=FAvR;k|{(``k9i&xKG8-Blq(;(r}IF!`c)!t^< zJ|9V^qmk;bGqAw;)ibGh$lnhef4tq=Vh DNyahC literal 0 HcmV?d00001 diff --git a/pict/menu_b_cnew.jpg b/pict/menu_b_cnew.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f4fbf24758bef9998596578ee224b2aed0f9706c GIT binary patch literal 1768 zcmc&yeKgZ+9RL0Hsu?yL$<(ebv~;{BmPE_Tyj-Eo2@#9jrO85Ck#fmfFO(TY8nYF# zu)L(wizw19q_z>Q7q0Z?p2<hgj+FA&NmNpuN(ng`s81y$_(7JjUJzX>ohsWb^CIkY(g!ls>5{cA7>lk4$M#ctM z1LGfo|9Vkh2e4WI9=Hevu>b@MLb0H_6DZKghCo43qw{aT;1DPR32L~1@&E{hLEsq8 zp^0l=gZy3uLZC1Jj@3t)R&K&ao7qMco}iI%$Up(v;E>(=jTzG`4Y3-#;7}+O2K}p# zrYBawgpzIbai%bQAcypx7FBqt!S1124xlwj5G)i6xB@eq1G)TL+(scfNV5EWWqlm8 z?m&5?Yfo{;pmR`1$^8E1`Q^P~mHoZimC!! zDX%P0iJV!=OddD)X4&uoR9fX3WsgKJb6VZ<28T|PoXn^Ly2bos48vhc01}n$G`5s& zz9i2r)SZd{P@B{iGu}DjQ8K~q9?@;$Nu5EKZ!p!&68X}i`x)a87aMuH&tAo(;mocX zx{$Qe+H<$t(FHnmYF{ABrn%z=C$$+_Arn2;O zQvQPRXN}UGn>XF@Mp~%wN;pd=6>+c}T+2u|=ue-RqP50_JyiJJvL>rgn27tJ*G@}F zC5-@&9Z!kK7S-Ihk@^ogZ5Xv}UHKNn^xGd7xRqO69^op_I=4&>fEyLRCFHQkGFtP) z2L%@sw@h@62BlaPzwq*Dr0~2VS6G_Z74fzm=OtNfA*~6YqcmI-gnc(yd@npf>`2V0 z_(lA$?q6GEdp!T^N3gC}-Hq3O5Ts8aE6Xc*dVAVF++ZC1Rcb9lS!gD+3BNW3`z+&aLS zZ$+$Tw@|CAqr*%sv_5UDjtma26uf4njPw$LzEv(SlbOAzjlRGMK02{N``P|`PYCTT z*j*x>M>w+dR^4S~nU7HL2zf$K0gqYVQ2)-U@9{fp#bS4KkuBfY;Z0taB&oUm(L#>P z>TH;7o3wUySWn=}CbN%QBL&{Xd;KBA5c13J$nMy*7S8s8NM_2CYw~q!AZ?-Jieb(X zd&WMA?`v(|{ct(F#yzfXXbmK8yI;M>Re$MC0)<;@8jrYnh$v!|u&?XyP%Q2fN$p$N z*lap|Yd~8X|D;i}OE0_DdvbsLg|=`}h+m(+MVlFVmHBW^yxC5(3%B)}+sJTX9hK^g zn|^-GX8x6;#F*G3uBx)i^WbN@H@j9(ef~NDab0;bsdyD3ry|tDq3Bf=2lv`b)L-^( zIPmg--Xq8_UzwY=^(i@bV!YTPL+Pj&yySLsOC#_Gw&R>lNM}LnUDDNKGGQ1XAzw*w z{Mmk^UPV?!Qx?N|=E68yHt*_7R7o7(!P1qg3tXGe43)vc7FF0KPh;Vw*h-dSu1+3R z<9#Mqylb+Bb@;sbKJ)U9nh}w)uyo?op8486B|A?1Z)w+@?=Rtg7bT*7siMxMt7g;u fO;Q_Vp;HOnq7Ghu+qCJl8gR{u4dWMgsAYcwBP91` literal 0 HcmV?d00001 diff --git a/pict/menu_b_copen.jpg b/pict/menu_b_copen.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4df3f4771bf4fc551bae6e2934db4bd4cd8ee28d GIT binary patch literal 1913 zcmc&yX;hPE7XH3$AWKL{QXqr^VJXV0ETu)EXk>{Ahp>YT$W|2y$Os510%Z#zXdp;x zQ8boif*|{@FetmwgAou2P=YK%gE6vM#Y}2vdd~ctfAie)p7WmPx%a-$x%ZX4l>7>y z$PUg900;qqP-y^?-vBfzE+irm009^P07s?NCV;dLjSdb2LVKhPD47K^00ayMgToMT zIN|_8dgNsh2w8arIXQVbIR%u$XP^|2N+>0y0tSP{VlV`Cb#;Q~UjSufWE2$?RZ%Ea zJPwV+|0Vpd7fBC*mIbgt9TY?Z5HtuygOaB}zSK4Z3W8Ff{{ajRfg(T|Dfi#JG!F*C zQ2+>)>ToFh-$f7*3IpJ1WyE0)1{-+whP4l3(&~?hV$#NmZg9yApaA_thoS*H;DeDt*T~v@Bqt|FWv0uZ`qs

(Ijd{jOo)LQ^wPM0wKG-{vF9E!-;Kmex&$RjQfmrG_zQ%X%t&}xy&FfA7(fQ|r`5(Or zj>FYrjoNJLKC8ptZNB??>~ih8S6Yt#avZ%WanEb5@?gK8=}gos%Dtb4a4~`9f%LJ9 ziRaX}_2rP~5bDKNh!!3ua)ICSjxu|LMY!rJ9zSyAJtK6oE@`^hhlx(oF1mVxxpyWKv7J6f8@fE{)rtJ%P&Yx7ME%}3ffs-@e+9|Qy zXQ!7S)>G&m8S6t_ZKN){z~J#gHx(0&TW>OZ`}dF6<;S*?3zUhXvV!&R&#yGFm6J)? zSP$;p9O{e%_xPY;^ygg}-U*I%|LMBux`6c#!ztybWTap#*|%|mp=+JK(p4^3+B+8V zb>O;Ky8E*$cH}RGjstKnB4>{yDD#`5FZODOw)OHLt&WAv7y0o)nV$SYbyTe|<8SaA zd`=s;eO%>D04>(LoTq(u)Zx9%B-3Buek)(BR6{H!U!*;@-~QP>$0hvhLEEO>7( zaIPQfei@QkKS^GSyp3P|!e%4gwDiO;|BShE;RMB*>pbj0{|Su>>$kLflH%U$Wpo>S-AYHm*C4p{9#<2!B^jzS%QRDHjT?+vt7`yZb=E zcOOq>b^NX>T;q&Q_e6Bzjy)uWGdhTiXAIRkZRvGEuz}^%vZ}Fa+5t*1d>q*8ukuad zuQ|EG{?%Qt(VopDXcOVC(NT*6yRdPeEz6yu2eCZntBZKA`4^Q4^IFIw@bzJ_I)v=g zHhf1;HKe4^D#&+pH-3S>be5fBW)~L{dDJ@DcKDf2xUuDfZTQSw#3^B?E9=r!x?WbO z*@of;4@F%}FqNB7;3h5gj5Fr9Ot$k+g}mXm08=E5NVNq#kix7$}VB5!P z_BYxA=R|r=4^-r}S1EjV+DSsMtqsjc_{O(EuvVgxRc2UX?4OXKRkext_8o5Z)hI)_ z&twgc>>`RC2 zNf+map%Un|SEqeXvaD9=%z#m z$D2;RIb!t1lx9B4I4Z2??tzxzNx3#T%+)^8ThT-OYr-`p)42K?vl+Q)OZ8Wpei70|-^NuU1sWNDsLHc!ulrZtR3Y*iK3wubhFfCQ)fw-~6u zC++GwxA?dCQQ}K@qQ+8MM^M9!?&RX6F`P&DdSk6x<9kuP1Q<4`_t|0`{7 x_1WU?$Y)cQN0heJc-bEx`%~NY>qRy3-yY_r#O1Y%wLb-3Z)mI;83~k3{|gp3L~sBA literal 0 HcmV?d00001 diff --git a/pict/menu_b_fs.jpg b/pict/menu_b_fs.jpg new file mode 100644 index 0000000000000000000000000000000000000000..32bcd63ceedf6b8005cc8deaafcb423e9cc9bf07 GIT binary patch literal 1924 zcmd5)X;70168*m1gn)@8hy(-zgb6InfCwxR88DzkgiXRBM3g{~GlsB21&7+S474 zz|y^aya5mb09;J~>bC%nmK+(M3V;9%0D#>ZN(Jb8aQP8Y09U4AK=mk)4Ip4J7#xOx z!x35tO=_bM2$VJkjn+n^F<8tWz+!Z_V7KUE^z`s}Jv}2Lk!WP{1t1cM)WPT&V6g^< z1RTNeOXGhn)G`2v0`Nc`6vP1#90W4s?Mm7isH8Q^d3PNCT1QG-Rs3!jlAOs47 zV*wBffgll3xYnO72ndA%a2&#HYqcJpYiaMn5R+ILMM!}|ggJpz)#SNzZ^7-`&OZSx-TYW7#ABDi^qYtREVzQ5sUVUA|U~LWT zXv|Zk`6-->oA#DNu2#O$54syZ{A2rh$?^h1(MuCQpm~m;=9|V#U^a6-w<+RheAJo9 z81LIx51PAkg%7jHOT6&hfvRm5J@8<7;@=KN_%nq8m@?g&*0;=4@6eK2d0}ty@$tpR z3o)jDweMmrdRZft?o&%mbfVnmG*zi6YNF5bw|jnfm2;G1w6`ai70fnHIKg4O>_xqp zJ4va!*KuiQP^gRD7=-JP-X7;>YaAN_>Cy|ha_=}CLyz~9EQw#Z0 zQ&jy0F}j*;U0?BFSHf{nb~#SM$(-6#qCC4UzaLA@Z>dTVwL6n0SmP%RiW;n{3MRiP zcdXT_ZvF1*oZHL=rm&O0a%fT(3X3E>d(GaF^n`Wo?;VeeMV8f34_HvUopjy(Qh{kb zEiSt}z2fq&zDg&fs*ZXunaX_ue$k$rptIXO*+|}29yOafQgkq5cKf*-a^AGVaO2my zufVLw%dT-b|6F?%_sg?9X%_Uuz69eg-EF1bl{o{^@xrk-AK|KWyz7*|P&}JY5o4aa z+m_OXJx%CU;ZrGOLhtBnouA&-y)tb~iX@xl2fJ){-gV$nskEPkf zlxn5CrcHi&ekj1BPc-DAYQi*61C1QtgO^6;FcZGc0(Gw8D*4 zr)j7FHRf3KQt6i9`)jVOludYlop*HG$$rBzvtTPaTCzCi3~imev$7gev1IvJ%C=RW z|1GVSuk1|F);1dq(eEQZugyKEZ=kC+et5POuLOHy@k=w!1{gN(&29aAP2b;%wz)d8 zU{h+adORs=ACEiAbZuT$AUqZL0>N+pdigPENhN4C;3aN+JGL}e|IIy@a^a?a{^xVi zkly}9(^cmkQ^jQ8=ARZNt0(uop)nlYJQB*2uQ>KBIaV5{ZG?TRVuPOqm5;CIe+s|< zba;Wsj&Phebse?M%ly#}M#^mvS=aG%gk?tBc}7E#hr(|P>n9ZJ0}+ire!pAmgow!! z6{xmUkj|A5@1P1q4KC%@q?$;}*ca1nE#|V*(kQ&VErK+#0`b|M@i8gG*NL^bF*qR6&as`4 eOv8r;mOK62HcRGy7CC(%w`wwQEzodCJ@Rk5O-lv< literal 0 HcmV?d00001 diff --git a/pict/menu_b_hashdb.jpg b/pict/menu_b_hashdb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ffd2a995d08009e54a563bcbe782d6505aa7ffa8 GIT binary patch literal 2257 zcmd6lXH?T^7RLYSQiOzHXkjrx42C8F0V$CdG!T%^P@;gKQY9cD0-|mxBA8IJfFnu^ zksv5Tl;Wz0C?$eYqzH&;f`Y(E5oef<8D`GTeBO`yyyu?#p5OD__q-pjbVB+LK)N_n zodFOS0K&HqAYB4bPD#h3QvnbF1pvTi8?68e_Ti_)B7pGDZ32=`0Zaf6g+gIaI1C1t zfp3@G4mf;=oV={8oUE)oQvOdNiVE^*w6Zc9jn&Z5z-s+15CVbNDZf({iBwhJ zh1#Y5xADJTq@4h22cQh_ARrU~Mu8wGkhB{p1^_Sw1OjdU^DjZbP#6dS-)7s!U+|9( z0z+U>BmjbdAqWr*0fqc&Zc``<1}MRCCe>)=aJ;>zwvION{3yZ2o{EU2!#mf5J(dK~iC67e?kz32BXajET2 zEX_#;lB}A;b-I#FHN_1vcbTiOEkJxV_^n*5P|W4k^kmSQiS%=)221ecvJ@ZWrKsw{M`hg!ROrPJ|7Dn;-%rB~ zBbip$Hak|lFX?I0yvJ(Okn?C||**)A!)j$1$PNc`bWTd7RH?@9${;~6FLL4@(pkvM}D z<-oB(>I91x^#Rmd*zdTew2r^uKcIxUd%OM)m$B#elNj#Sp2NQ~h1vWOzxNYuv>f?= zo0^VVjRXwadSA~gcvP0_SJHHuoEzDF)S>8}`3=fL3%pD2j|rbpW^J#+N5#qs?G{V3 zxj*-&#>LC!D<;iiTwm-`Wk{VJQ?hB>SJcB?a&Y1)=Nc zpDMXe<2`A$8J&vDIYN(9up8@)V!S~2H@*jqFnPtXM3hBcy*8A9?buhsy~k$)CZan! zWtSfMgsei1>cYd!Ef3m+e5Pfk@C(+_zrLrFIDzw@lA@3-}k3f4Ff;gbL~iwI%#S*~@hY7DUs!sW(YoT%ddfYR6yQ7W z?Gbq}Ng9dgXZytchiC*KVa}D_dW@jcj@?W)rpsQZSn<4a5FI8&Cp;lUQnaHO)ZX zrJ&bNmJzhb|E{{m;K>)~b4yLnq8WjsJe$r7OLv?6Dl!=z$M$2-#soH%>Zf7!(?jt* zA0hE<+s62HcOTAf1Ca|c<@j0O8rA2}d0^f=4d&=lrQ4!WYIZ;G(PX2F#FUKPd;jD_ zaD#femn+RR$R#$0tE6ahpa8>(gEquXyT#EDxR_qncJJX;=X#XEbpzfNCca7$X0t}D zybSdARhz=HqAZSjfwefAOu-a!;q?nTmY70bWJ=nurMEfP)=|yB+uCLn`RobPM)*1` zbCbRf?kS1;i0UH=))VK193>i*?--YWRug@tW#aeXs+pg#a1p*0 z2YBAHW286ojb^mdWs={QUUOwuMV~lvhAkL!%7Q`Y zIVbcLD5^!!Y%h9l=|*;e!=T(2aoEhcnLai`rnlJ~5BSip=~2XF%WwLK(6HP436$jz^PcaV8=hOoU&tjRPRDhQ=U%TfQx738!BX$%4b zY|ZxQ2iQoYxasH2FT02j8$r+8pze0tEvrUzH_hystf0 z^a|HITI?}V&z9$^WL!b#q@QfcMi@(LCVsA^0XjRBXOo%qG<)ziI@4M2kAQ~NT{nqp zP0zPr%b3L{7XJs)+SygLM+EEdZqwF`Q^_`o8E1TN_C=GnG8=rGu5kU0jkR;g$0E$f W$CIs0`ifq@P9V$-nv#>GlfMHhILS@` literal 0 HcmV?d00001 diff --git a/pict/menu_b_hcls.jpg b/pict/menu_b_hcls.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6ef9ec634ab402ed689051374a6f6121ce25de60 GIT binary patch literal 1921 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 literal 0 HcmV?d00001 diff --git a/pict/menu_b_hnew.jpg b/pict/menu_b_hnew.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8cf2e8c5ab3ed2176e60049c7f46871968647629 GIT binary patch literal 1745 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%F012dx_1Ct;lvmoRDBMei3 z&Sqj}WCXes2AEhGnOWG_fnuoQ3_xKfRsjYE7G@SsW+rA%hz3R`W)=oPRv{5pHbujU zlNJdFr-(WxDlHTXG-fw)3QB7FG&xjU5Ex*r%*@OzjI2;yKqo9rVpbLsW>GX0aSTi> zY*aG(FmdC>k52z@G4L=0T_wmY$Y9U#TU%}W)PvSxUW~@lw`??4&$_WXF4l1Wk(G>R zq|Ve&_*>#CZmFA}x^$YDzHf7oD*sE4C7(rib5`eH)O+Dl*|}-@w!cE}T5OKo^uAr! zS?(m4l(Y2hewW<~`3=oN#S+i|jMu-SsiW1VrI+n}cZS#j4oS}``xXCQn0eUa=(TlL z4^$U_eYc}n>JsDE*sU_xr)931D%E|>XR2lHM02hs6I(V5Y+)$WIF%@~>GK_>Ym>hP zwVRkaxK=AU1T?QWvPCgt-$S9>>uqP%FA_7UYUMgtc=}7v zzI_QrDz=)t5?0<(2nbFS*O-Jb%Ib$vv9E{bKgY=TV}jT3+iW8G1(* zOg1wMV&+)4)8*xaOMhohS-hkqqcioo#SZ?Tg7&Gb4bD$XYVS_nv%F*f#!vfS|2%Qe z{-|}m$MecxrI}W>50>X{Y;g%&{JdwD`>Kt$L36@aM2X&-d5B>p!{)6yP1&wfwwzIN zJw8!ZP2T0g{emT@EuX5N^SavW+PqwSZi_&yC|@=(lD!fIC$Kzty*{HelletsuWd&d zB$Pv+>1_-8c7IXqh4vY1JJ}v3_pS8OdNN5`VBKSmU0kj! zO#@tV8~FEBx?YT%c9W}o*I6Zn&CE*=zPnJV$AkSKRDU?rnm;s`|dW zT5oeKo3zh+w!ObGThW^9tN7#9yOWt%sXwa^JH&Ucg)(*t_=S_JG~VBB8%9Vt6_@DFk~umfc|f42pZ!@Q~NM9i1IB z*UqWucrvwgx0;p?qeI4g1C_!V9sD~wTB>EzCgw2h=}T_hm3Xs+f8UC|>0B%CcWpD; znty$&{o8)CcSq_EeO*&&@MHB)(bMhUV+`G-mTXO5lnG=S91fXmE9_&x>tUPJl9?}N zCH}q6V{ldFyvt?&cRLc>R;pF0&8ROu%wy_le9`3a?{yN1t32m*E|b4oaF{p9=Zmkw zzt?RNS(B)4Sk=AM_i12*vp4p4Y?Il4_RF*E`CGoY?UputdH-qBlb-^A_Q$uTOHZG+ H|Nl(@jFQrn literal 0 HcmV?d00001 diff --git a/pict/menu_b_ifnew.jpg b/pict/menu_b_ifnew.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ec8355f99bf052a53827ac0f6e2763d5b1d16d72 GIT binary patch literal 3564 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 literal 0 HcmV?d00001 diff --git a/pict/menu_b_int.jpg b/pict/menu_b_int.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5fc0af25213a370f00e24004df8ca07d75d56b0b GIT binary patch literal 2108 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 Lo)68o-5C21OQM|k literal 0 HcmV?d00001 diff --git a/pict/menu_b_menu.jpg b/pict/menu_b_menu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..124a7e098032178d7696048a7a798b9d11a29c06 GIT binary patch literal 1846 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 literal 0 HcmV?d00001 diff --git a/pict/menu_b_ok.jpg b/pict/menu_b_ok.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e682233fb41bf3932041dbbbfcb97a2ea281ad1f GIT binary patch literal 1355 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%F0IWwam1Ct;lvmoRDBMcLO z&Sqj}WCXes23Xk`nV4DFfnuoQKy@sPtO5)SEX=HIEXTr#Ckjmx zW;1jQR7w(MPb_R)xY0STCB{>j2z4`D;Svs7YZdQGYg9-8nQSB0#$B2sATkE z;=}*97hMR#(a9Z3X|< ztg0}8L_uaedjIO)-9gVvChN&x79V}=?g8v{tzkVeABt@hw4*~ zVzv{r^PA!V+6{7W3(SJ5m?iP%3O7%u^E(FqOER0g7qnEJ+@?L{MBuj>2bcoCbQ+)P zS|w25%eV4|W{AU5t#s2S21ZHKJ6p9hSG!Kk(vs9Zc1T);_oIuqMzFE(M(%yqf?l1= zZnWO#=nC;QJEHf)C1_FRHpTKoN>hbF(t;u@X61Ioe&|^0ayiH8eT%DBz7m=%uWDAP#T2<@sebR3Jubj=NkKI3XcH^t; zw}(I5%$F{+II;N8_U_w;>4#J2?jbH~@)C)%UbznNbC9G*NQZ{nSAKAAsPZ#Z1i zR;_08=jx5bUCy?XrRuWY7~EByce2;sv`ivz!ugbA^JnemG51K{ltwoQ78@lC_! z&(JK8;+{cF$ux!>nJ=e+0hJm)#z_j!~Ll}`Yk zLHD5p2n7H~6+k%!5RcsvF)087FaW?&g{FayD`#i;R=~NUB9Kx6vH=!`VGNALV6Ylk zRcfhYvFchlO-(ILO&lKgO?aG+E?!p$r>{>S=oRW z{JrpBAId8LQ3nJdLPH2ZArKmYl%3$1$~J_7R5rg01EJ6`RtEL@pk=8M(h!wn2G`OS7K4iFL5!Z7mzqyHWVp%A`a zxVagc!qkTeuH>1pcwTen)u(Q6?ba)Y0S*nROrjCs0zR%ve3?y?$VqftzxqBJaDMw_ zZG3}w{XlPBMNX3E9S?P2T54V~`Yd&U^aiY8L^%zv?q8f2F4GU#`1V1E5+uOw`eHe zG{2;!rh>HacAj_n=XCrDB{hSvz(pA{QxGn+i*!@qQ=#bmPNLE;AP!1#pR zLC%TwyknP@($j_4c9{SLuy!}y4SDZuFQ?J9*s^829;U6 z&zhuO z?b{MQR@aF$5S(mP7R- zfONONsAmQ=9P_NJ3u+>%Z(FzO2C|aRcvcxo-0tUTMe%RaI*$kWP4iesc;^8Su|{4EcinaBFrxlEfyjl{e|ZXB-^@8t5fj7ejTW&PhQft z-ySgKSjfWxV@L$9s&WF@?#k19ba_P2<0^=t&ce!9fnC=|jIH9N79(#u||%ggqE=xSZ7= zr+vNaqAMp<1H;Cm6oFzCHG^i(PkYn0Mcyy?%r_OyL_T*ZYwCK`-9m5kYOro|<4U9^ z?Fpy3^4br2J~t1TNC>C>0-1Kk`(Hkg+*^8il+v5!Y@Cq%JJ0%I>hgv;L^_pQwRs;J zt10yJsl5N>kY{Q{aY^H#2X{k^AZP^2aqqczEO~d|%H$NOTq4Vlt6yUyjz3iDmY&tHhwn>$x5xry7WOY=EBKc+)B8NjF WC&f;Ncj>1lQgkQoAElpD4*dydDX1I( literal 0 HcmV?d00001 diff --git a/pict/menu_b_rem.jpg b/pict/menu_b_rem.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0a6f73498d1ad3ba02768b161fdda1a745dfe29c GIT binary patch literal 1681 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%F0IWwam1Ct;lvmoRDBMkjO zXEQM~G6LNR11zkJOl-{TKrvKtpr2WoSp^svnVA_lfSzH6XkcPwW?>Ly615*S#5?Q8Tl&Z^pOSF&t1* zf9ZARy+N(m#6*i7zbAfM8hj`C(43gs6TgGzJt|l(E?;DKW%-Udnn#b{>EEjPPMxc; z@VoL`ujf$Odljeg}#|FBkU-t#Rx zoS1huJ$u$RLnqnpd0EV}ClmKsJXf4ys%PiBwBdEyii+3-1MXJ5y8L17#=VE8#2#*v z)OS^X%roQc+a(6eZb|1V#b+c}cl`LdzBT+t31eep@DUM@zaMXIN}e<0r%&<4*@l_N zZ%;VLup``&RYlcBb<<6)V^0qxZoSWCX1*ita`onI3cGU7&F0cR+agn4*bv$~Ua%4_#bk@c>nQvvaU%brFjQSQGxA6O& z`)@e@Ug=Kw(li?!a$55q%@cX__?`Q$Dc^-#At7yhS+F@8y>ple-dT4kV$mi@7|#fvPbB)CKyZCa!h z=KapPLpyYu>w?yaGbMu$9{IXXFxE_To|f5%+N`A6UWI|%n_qh@yEG>x_rb4Anp>8O zN>|uz>B`kS>UNKRt4p`;JX#`Sp6YQmqubQ0rgposI^S@i)dwxcC zZkA2+bJy+bc=E}-CD~rj=Iu@=7uR669f@ocbF&xSTe`1wSp&PrXX5wmJTl z>*c$X^}CFXQ&SAymL0SCsNQ$O>@%Oum)4Tl)c3db&axSrb#X0STKYq^P%b)m3&Y#z zC3So4{$Bkd^LRyD*QWZU@-qKT%TJx!CRBZ1*NXGB*xWvAiy5CqavaXRjdkJpXCGLx zv^0Na=5~h6)@{xASBBbIpDvX@vF`QTGnp1QjFSA0&0!J};w+MDd40)b%DUErW+&86 zKP>$5ueAHjj_U%>+iPBa+8w#=fvG@jJt&U0_Gxd!9c!>?-E;SZOHQcgkq;}nCgx1_ zn<=}`Q;sFJSz}r14<+5W3o4Uu$RB!H+PH?{t4dwS%sF!Bzng78eC|KPrF*8Y;vctv zj`Qz5Et9q4KSS@OUlrYTv!j1spYu*?`nvl`Qg7z}iu&>|J8Us;Q1HCY<^IpMX11+V zt5Tb5KkMo;sUPyWYG>s@!7W&RDH@GtgpN%{K!Hvy^Xl$y%$alM-g_>8ivJ!!+FFyX0T37fXom&x zHvyDoqz^p?00B?{0E`c%EkNuvEtKjD(4HMCApR_n1i+zCC=3dR!Qcq^VG9ew;ex^< zLPEkqLLx|!e}EJb`wjVO@eyD(#7i$WN6lpry#s_-ejTdBf@g8mvOlq!`tqqHER9a|( z$L<-@Gy*=A6}iv#s3}R~Wo+UiRDSn~b*?%=^23l6hPYRk#QRCjba&BFnM{OYNndnD zU)ziL<1k8NWh_e@qis_2Hesd8;KzyT0^+AcJL}3NlEn1Mm!$sDi8*hGlAQFOn3S(N zz5%nspp4cz8!U?SjgFZP=$0FsFR0d!?+Ged6bq4Qe!LSZ!gD{0y>c*h4Z|B}ryNEG zywIBk73gq;gB~a24;wM7@i}oKS9XdF&~rB3jOx;O<*jc{^v4vJC*0Pps8sQc+`7}^ zdL)+EM~`8>vevNPSMxDh*Jo)8nUMBl)dS`XT}rBw>-QSPtB~?m%zc90!0}`afhV~T z3lps|GNOddAj*vw)}y<)mgS~xwNBaXRUbV`)e82`z6uxDjuUyL%&_YLpJuZ1E*B8I zi`K_TJZEd{vfG8l3@+9CI`zt~6Ta_jGOObyX*l_@BqKdcB?~ht{6G)M0wAtO{RHv63+IarsR9Q_-kJ8y(zLTfYn& z7Fmovw(1u)SHJ8}WR5&%4vwfWv}?Bi+I(oa|6Ff{kov_gSzgIbqj#^%zMXGnF-^?-yJ~l0fUla1| zq+AT~3D>Mn*A4b~93PcYZ}nBJ(euoiJ!^v-XbDie-TD$A5KgqEn(jV+#EyHPgMZ&> zIuV5Z@mgRGhRYLb{*X3kLBBAwidC0PP~Yjd&_^iw8&`;!uev5oi2A?}C=?X2zp%!V zrQS-glK=_(jbzk1VdHmhCf8PL3Y$13@QJHBbQ zJ#8v&ANOi@akfe5wM~z~&Z8-gM8Vg&WZ*VIto`Bn!fZu_#gp41Pdz?AqCRiE{jOGb zlSyt=9=w@nVU(JiK^$AJdyUxk*)x6kR7f(ApP-4haJohpU}qT$&7r9FypDuG|imvJRs-OrKj$vTX8<`{n>AzAqX~@GtqP%R@aw` ztuD3jAhgmEG)p~ZOSD6hFsst)Ds$8soZ?U!d^7fG-e(-c*KM4Y-eetu%qU2uVuxMp znUPZlzvZX5F(vcc#zj@d1r^eBMao9H?ktQ&;8J7kuFLM74jYT2i_h5;^t?Rg6S zn%u{iXka&r7IZ_J+hz$lny*&eH=CGxg(pyPO}*)eg$_vbSt~2FRcc3LkIYPfr7fT<%U>umlwf6;G#`ncF$~<800AG z4~9kCzF-xe71m^7Ig)xotG}Uds)*Btx5h~k_Cs!^$4H$IaLPF*?D>stKhfduvaS?F zPn)?1ed{>wF23-MD37}vtUf?B`uO3+m6%+rTIcT*eGVfI)k)NN!+PpF&7f-Y%96z{ zwkmh5Re1CUEbU6}jSSglvJQ`Q2T~GU%Qdg-5Vr}!=M3g$Hp~}O!YYcARB6fz2)gK( zz_?e8Jw=Fu0%1J$)Y?jm#_+5PS#({;m42nUi8WT=tJm$wJE<|`chFur@Ob#{MBTQB zQ$({_dc6JMk5rLG+})a0&h~Ji%lGa#F%uoUyyC#vQz}@{C7k{|duCokdfq&4P@Ga_ zj7z?Xu>#H_jY?D>1&oN9H`?;zO5TiqY<`y#N6k6ya3Q>>! z+m;drt+M(p>){?d#We`|o@pt(FhGy)ZlBxI12YaMZH9b2`i6 zVDZb$g2FN%u)FkpXt8fse_ws8!+l`WxIs=Xvy1e9%7^_D9g7c)CiuYXC^0Ps*T4I} x{mhFrU5XF8c8VQfn*Jb)K)|M#5_*g28(Ej+Gz5gbFTu_kNKmigrZ)J~{{iO-Fcbg) literal 0 HcmV?d00001 diff --git a/pict/menu_b_tl.jpg b/pict/menu_b_tl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..212be616c47567848cfbdabfbcc6990b05874173 GIT binary patch literal 2545 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 UyQt5y|Eap~s(YkKkgsI)FFXQ#SpWb4 literal 0 HcmV?d00001 diff --git a/pict/menu_h_cdet.jpg b/pict/menu_h_cdet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b9bcfa77e405814fabfb2ade971b6ed41d024d0f GIT binary patch literal 1537 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 O@bC&AKi(+%+`j3qTgPBY~HY`6B$^g5M6{ zQGhs*4uN<8h6f=$$nOHK3C@N=AP5Q${R{{R!Vxeblz{w*e`rAlAs7OV13)+kK`=Ok zf<9?55P~D{00F6>Eo4S?P}C9k3RQ|Vcl3@sm@c6&i4tu4*aH1K3BBDX7#_j{6kuz$Mak^8fm373_g}fYKgsjs7W#LlNnOC1+(J4yr}o*3NG|Xs zMv_V45i^!;Y`x(KUae!!<(@Yl`#B;R2vF;&3r+k6nuyrG*W^U135ivX_;6%~_YUnI z5J^y*&iy&GYtnF~O^&+mWBu}>V`{qhn;ed{!BeZc+7x`EOkL=L{yoE$srkXW1W$Ujk%p(TgD8HdnzwH$tcZFan(!#HYdh?NkRrOJILQ9dTQWYqpzv$gE%W+JtxO`1H z`@;yQiMPiBp8ecnSkYxek?ca_4)Z)>6^yIq{OmWC#ome*B(EvIrt~dJU3rx7r|yf9 z-elMDO7za`Ra?on;hdfI{^HS@l61{icgDIaGS%zK$!OV=C2jW><5cJ|49AJY%*CEZ$gH?6QeTq?|;c_zO#ev+deKWM!F`qd5w zPvN4E;pmmzuJ*KUBogLnX=<6IoSfl&x<9!*HXnE{0z8-7%S9NnHg6_(N)Iicc(C9f z1nnw7Y%=lK_`yTxdV-s_IIi0DttHWPSw^A}_4fwpim8eYBTx41!%K3zZo%>5`ufvT z{U_a)%OkmWf3>lT_fNny&rUifO(f)ZI?wlz&3+Slnf}b4Dk*Pk5N8=!#$tCwu8*El zJ*&IOLsgA1DLoI$$lpvhcdK_ORXo|=TByFRHI){u|5zHmtw~kEl8F{Z}-_#ow^nW`jRpWw7w%?0$yaemC;{qcqXBXRGmB|4Ge8RE)k3+`6~^QvYldRgeBQ_qE6w5Y6d|=^pH!9(>@amdS@SSg z_edI*cKh9Cc&$v4OUUKkaOnj#u7|?L$hy$DOQLsrd#ke-AE?uoH-2xZ$uM~#Gdst* zo9(slCg$yj13j0b2u*CSqx69qk#2NC-wCS@g(Z0_CS^C}7|C@g^*F<}P&A8f>u#}3 zB$?|4B(WT-rgL&MT=(f8kg5D`HTZp5N^p9x>-O=4S2EQ3-qM(zdw&ER7<-z_!E4=U zFio}``_+tNcDfMPrg#KJ*w2x_ksV-#dS-0Xo#`>voB?bKakNok! E0U%UtGynhq literal 0 HcmV?d00001 diff --git a/pict/menu_h_hnew.jpg b/pict/menu_h_hnew.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a0293ccd5c62ecc4c48d6238adcb2c631f2e25a9 GIT binary patch literal 1856 zcma)0c{JOJ7XD?Gl0*_w`>0r2QGKXd#?r>v3AF|(O2R>Ei^i*6Ta;9_LKjR8(@v3@ zmNE>jma0~5ErVD>Eum8tv8!SxFEj7V{PX^K-#z!-d%y2H_g?Xscm}{Y+dJ6{+q0M?d8VI@c%aA zb^wb2@IVm+gayD@5CjVncLG-c01N?vK$1WI1{4B=OM$==@=yHDN-78fhQcra2nvEo zIw&0Smj(twpfEUq#c9Y%84^hGns|>8Bl(Mkm9sXX#s?K7w4)01x^A>p6cNiXvfsSCVyP~sLb~Wc8qhI7CF`U{=f%o zll50`9XM807V3`2IYsm4p-g@zQ`2OvDe#r4s#~g^0^N4gXOkavx6a4&`Mm3shIQ&- zea+Y;GClg|iS3D`b++rF3d8h87lj!%yZ_l zX9?#Mj*Y{{c?S{8Dx+$Z`Wy>)tX&zOo4r35H+&59=VT{vUfm1(4QA@QmtU5vy+in9 zdBHidowKLcts(H+e_9jjb{u1ua;iFK7JCQ*|Kq+bmB6rE6vcV(FR1b(wF66 zPAb}V1|Hft2)|0hWBmND<)a`~F+kjqFF!GVTQ~e=`N2UlG!>c%jn(6L+!nLnIMaFSVhL$x)d;D$az)%O>o~Xm?v1+?cPAG`#uNpJa zo^R9b=vp&fHe8Y(-zJ+4WO=vTmVyIp4y&j_ns4tf+M@a<%6v z7{0<$YE~x7Ag7G2QgHB%?cLMK`&)YXH8Ge%_uosimQD%UOP9xc1H{0t7&vEhwuj_- z+L$my$kh`~Q}*8`t%|gwP8J?J6V3bf<#I_wB(^iBy65V(nnN`vV!(R*$oiCB;_!u9 zVTBX?_=34PtZ3kSfe9+#i2;7?lGTM+0ShA{bZlEQMihK^h&9Dp@0Z?ssVxwHy0xOF zOtin9UDp3NQXf_48^Uy3XDi7Pv=-}AP4^p{4sw~h*pj2)z1-efTNJKQEoAh#Ql-w# zMeo`9(D-rHXnX)Ix0Nh0%+=kAQ4(b z>)+K+TquoMy$22&IJu?nJw)YgxmP>z{my^h{~;wh1fkX?{8W~iMTZvPj_Br@wplez zKblCrDsZya&7BL6e}|`E=qj2a=L(7*Baq#WR$VF-T3Y*8LIPF;r?FhW%lfk9B6?{5 z-MW_ij@0#a%kU>S*ACCLPE)6uIvL*y@|PN^U*}27o13G_3~KtM71-{5ir{KrnRZ2E zxVb}~)h*4iK^SjaXuQG1C@|gTDhUN2t@HLzlm~DhJZ0+H7QZ*Bzp~ImL4zM0?S4k{ z>%qjS9Efg`Rfv>1|GQRoYX-{YTzUK+VlFW0-}s-qxr-X@xyRx9t&t4@ab+04e#oUc zqFHrzTf*i(>$QSU^z#=t)4kU0e9F}cU+EQ$8ZreB_1x+@BVHfUVP|-q9mjjc2C{Pc zsp~Ni+dP-jxsvRu5!9(*9^HBP%3NBn2i@Vu7?;RorG(3Lrzz|`8+qm#qYQ&ySDLRE z1n`4st1(sca{QY{CECR-b}!0|@7P&5<}+O*3MLl`+Q`;Xt4^H+5>4Q$Nv!U@`*=_4 zu`r3I=QiS4=OUN370k%%x^YFlTnxOcvS3jBO44t5Uz5FN_#@Y8oWb+h14Sq3bl^51 q^Szy1i&es08~a$p#3HxL7Te5&p@0a;DP>>)o@orK_}?KzJpLc#9TWZl literal 0 HcmV?d00001 diff --git a/pict/menu_h_idet.jpg b/pict/menu_h_idet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dff892fa72ddb121eaf8c230ad3fc93109c6dfa3 GIT binary patch literal 1553 zcma)4c{J2}6#xEyvtTgIV&4iQvLr82N{F$A`RPJQYcH5 zXX~MwrihF!LqxrIQVJpTnm4a^>hJft=bn4-=X1}!_m3+Y7EJ)0v%Ql&fM5WE#0Es~ z0p5;DrJVv0Kmq`EiK$tDwFx>N7z~0Qh#5#U3K9VtiA181XcP)9g%-QCBpNL#ErY>G zV=yu}neV{KVAtW+VP%L!IXNOxO;uG@ZT(L`5)u-!GO|iIoRW$>US8#=@P8B01AvzV za)5(?@Bqd`2s|X}0xSSv7y&`zJAVKLAz=hsLK6B9KWK4;U<3+@0}v8Iz$h4nKz-L> z2!TZ50Re3yp=q;Ui+K2#h)nJtIgj(&9Fn|(nRpotLoia}=O73Vn;^ukwS+y$hy-q* zRv=OI638GR@mUBwumX!?F%H(fYDpC4_SBcr^yxOQExvhg&OQ09x}j-_Lpoo|Sm$smHGyudqs7`i7gt|Cyx`q6j!4{yseLP4T^x(E^s{ z^)O~KQmVUM3viCII*_lg@mcz;$-8-Ti-Mu*kq(1EDZlB;JJzRXGRFIDwkq)Bh64>D z!lXHeasTEDt!(MTWVw^Za5V9PH_vh5qvoTScy(MvpS-tFZUbp?k34^KQ?*$PnOzqh z&^VJV0<|_aOtsuQ>b)zAO~t1yPFKn z>4Z6$2NXHz1wf5~4xiPpFVp(-TE3Ob7L8{VG}#T$Z}XsDdYbX8r)|lyGb1j^kkh$6 z)hOj$SF}I%D?c<|ZdO)zdYa(-_4z=47tJ`7UyF)M00sR-abFXu8&`+!7*_^;Jw?WZ! zF)obTeAZ5QBu_WTRkgu+l1>qN%4elzuGJ;4(qeCohPOrHh0z}#l}BYRYhnsLu$qtY z@?>{yf*N+~(h4oPaeqC#MXotn_|1rSKPgQ@Lz!YWm?i=$ruJNC89Y1oi68y0okn~5 z?P{~?>z}S1o1)srrk_Z-5OUIVwv&5@^|}6H4sdH6W(1?$`^;7p%g!*z;|8*Blq6tB zb9$zt#>(0(?y1z~D`>myEfRXAyE!gtvEg|AP0WtdQ-?yU8aEl+QuJ~)cb=cQ|na$zNx( z->20toBeSKF+LH=P(Q&u$fWR!s`CB&t4Yh1YWXPCL&BFa2VW6T&QU~O>hJG7FtFFl zbVy)wFZgzq?#ovR<_agFFHUV_tjYr^dsf>+x*bknZrns%AiGk91EdyAhW8N9z4!a~ z$%0UXwF>CP?TjiH(jQ;6pjx}dn<8VQja`RbR;Ql+TS2ATqfMt79U(&+KJZDXR2CAA F`~$)keNF%X literal 0 HcmV?d00001 diff --git a/pict/menu_h_inew.jpg b/pict/menu_h_inew.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1671f20cc442b7d4298de592b52262ba5bd13839 GIT binary patch literal 1808 zcma)%c{JOJ7RP_tEkPoL5lczwLD3>2c4mq)YU|kPv9v|Ro~F8~WtvgDhV-;G6KxTU zwT)CunT%0YH1=9zNwrfYmZ4!fkG#A&?{v=l?|tvN=iKx8-gEBvO5R8o0hEX9Nml>_ z27nl80g^QU{S7smoB@CUC;$L#hModsfgqy!|H1#$s66bgkw;V>9n7A|dh z88}=<9w{d$FDHjYA^#Q%si=ffQbb}fDk>O^CJu+w)cGP10)bFKDyXAS>KdwORgEvk z|2s%}0JIFC0^EXt&;S?>f}lZ?UVtvm2Lnk{{v!w!21kJYtADWcWvPP#KoAHR27y4q zkiWhEP&5nEl&n+>OX(pn2n>ZHzFYvI!4PNZuCL2xWELi+ zv{lbM8;Y0A07wW(nhJsj909&X*uVt+4Kt&oY6@S~YgzFi*KnfoS0_|?UCUK(?U21U zThE@jx&F2`eWGTy(5?SXGAE%_=c)09EH4%~aGhcd+^17zs|hBqja;8&^yO}y!Lqs7 zX(U1?T|{a54D#Jk#TPx^6vQ45SY1XMjgb1)Jja95LaI`2hoMJdz{4^nHetNUm|!TY z-^dI-JE~z2dX`|0|0!q9#PrZU@o;H))C4&PY+){c)R++((^2>+xiVtddQXV#Gz`-t!#w~G4i}ILi;)$ z0;p{Sm%XcvyRg+<^Pu52RIB@C5UlSam)Fg^6jk2Zp7Rnn?gb7t$P2c&y46&yFnU`V zW5>MCtJpb7`;hX^Etn$KOxKSM@sc~OgmNB&UuKK{!W>(6{z~KY0XAKkG+^?21@$H-{PV#$@_S2R0rd8^AZmL-jqg%GG z&lm0g2Q#Y1?xM*z)TBIpo=@X}06tF@>`YcBv?Yo(l&#+lOciBl3(bFbqFRN9osUSV zey(cB79ldB9eu1-Vgm;||1&m8vCpUDy&AhU5b{;W5M|c(RC~}#h3d%Nl9_A|pEm!o z+Oe?is?GZK6DKSV<(HqcSpSn#gZ86%>spVG=_*`Sn5_u-_(~4PoKyBb&b#+%=2>ic zMCZPH{8nnv^pT>&5y9Hiw~{VCf4NvwiDX;PWC^VrrfRh^E>Jo%7_VCGj6UhS*b|?p z`xe}nS2Vbyf0g|sFCsjcO3=9o5jC$gpZYfca$^TtuZdon*(;u!R7Fp`ck#c@dRpTX z9FqTio6*Auv|24{@y`Cqs)lGaq~EsS?Y3FtnTO#aDK}gwU1cTHaXlg#CvO$)nAM@u z;FKSVNtOkpShHKp0r@;rQ^wHNoayi&>%ne+v99;!`_*3`++M2cyVphdK>IGvRNFQ8}mFZX>WvnC>Z@Cr*1d|I-TaAR-8#bHmSl+2$zIpSS$M>3d2ch7v+u3ok zS%20Y_sPb5ba|4z+VuEeaa+3b2=#%|8^pqD5A`drJTow(MlPd5J(#^*rz7cZfIpvH z^LhQpm16DdrCA1VFY#JBwFQ{2IbI_1Lp8rAEcUflD?`}eBHXL9Y=luO$|+<=Ct^uK z%c7bD&?0GN;?Gg*jz_jHro0e&B-_-Wgur}zmMSDq)38Cj5je8%bg+FdIO5W9!B@xb zp$h_LTJCzTdqwhvIYs(Cj2mL2cSz}{Npj(qV7nA=d}WWntvU9jA06X4b^i3ICRg^C zMOj=~TX{mQsm7SsWaklj5WI1J;YBz-WrHwtVgJQJpy3*=vR(9i!Swf9oBi?CW;0I4 w7QZd@Q%@C30f>b-X#jlqbxVZe%*|2G(m@={_J6R$KzeoN1o`s^CCT)^0n2U+oB#j- literal 0 HcmV?d00001 diff --git a/pict/menu_t_cg_cur.jpg b/pict/menu_t_cg_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4ace65321d056d8e3adc9e976c57627de4d29d79 GIT binary patch literal 3648 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 B-ZTIJ literal 0 HcmV?d00001 diff --git a/pict/menu_t_cg_org.jpg b/pict/menu_t_cg_org.jpg new file mode 100644 index 0000000000000000000000000000000000000000..152db199670b79cb3b70a533c27f0d74a1973628 GIT binary patch literal 19559 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 Z48nFo{v3<77D>Q=hTmH7VIbtje*o#UH4Oj& literal 0 HcmV?d00001 diff --git a/pict/menu_t_hg_cur.jpg b/pict/menu_t_hg_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..72cb1fbacd8a0a8f1f76c66ee66ae857d9f0e470 GIT binary patch literal 3573 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 literal 0 HcmV?d00001 diff --git a/pict/menu_t_hm_cur.jpg b/pict/menu_t_hm_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..67a9ee4699f6a9990705b25459aafca434c20e85 GIT binary patch literal 3736 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 wOMhc)<3;npP2><{9 literal 0 HcmV?d00001 diff --git a/pict/menu_t_hm_link.jpg b/pict/menu_t_hm_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4e17433ea435378aeb2828ad57d7922fd714a995 GIT binary patch literal 3361 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 Dp(N*( literal 0 HcmV?d00001 diff --git a/pict/menu_t_hm_org.jpg b/pict/menu_t_hm_org.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5fb204ae57489b7bd2e863b671f7c5cf5bb4d913 GIT binary patch literal 2462 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 Iy88bn0Jz>V_5c6? literal 0 HcmV?d00001 diff --git a/pict/sanit_b_san.jpg b/pict/sanit_b_san.jpg new file mode 100644 index 0000000000000000000000000000000000000000..601b8d67c04ef93b1649be0b0bc2451cd64e9e9e GIT binary patch literal 1558 zcma)2dpOez820-?y&CD%@%2G>FnOq`rNlk8D z$YqjCDMP2x&1K>2q$o~DDk|;lob#NX=ls|EJ>T!30007u4sYyW7iN$3G0jy>v11bi9Bmjj#AdmJs|2RN*z7EVhOi^mfPc)WqWzP`aPKLDc9Xbr3e5r-qr*MW8B|5*I& zplAkQRe%6QK_CpMz#s&JihDr1(jO88l{SAs1wtTEAX-U6;QuzD3Ial+Z~zFYKqv^U zg8o+mDg^)%)<%(v@C25LlM#&^$V;OLjeQGSY$A>=(m}(@xF9qH{ijeyr2=b1B(hT> z6K`yUAovERC64fJv`B3zR7F34h5kN(V89Xhyp>0~Ww_MgocuH~DX##Uth$uIu4de( z6%$4>^jpp+&Kcdz|1+2XcR!e>eL8iPZ0m1b@?2NLK07(5^Nb{agpFNXZa%AJWo*OO zUvDPKyPU@t`(7JQJKj1K<`)NXU2nWC(~;Gm^4L3EAExFv8U|;<923_iZW;I8s8p(u z=W2ANWRnfC{S6~^_mV>&ZSyzMO)C91-alV(vPV4?C8OR+=ET18wTnYW4n=J~f6szb z+h4w>-@sb&&bp)y=86f7R_ z8?i&Ekvq($+g36TU3xWy+*t8Z{q*yGLj+PbQMw2TupSWkWb|xf$U5)$fAEF1PfQ#u zs{;|~0?%0gn9I-*o2f-vG*H575V=^?l542FX4*6X4y4mBN`>;q3(jwp2`+P8Y zxzLW)k!!m@ewj!XZ)`3Y7TPX5Nsk{q;_Mh)xs!QYvbyg3sl!rlvMtSfHGI#2vH9~+ zaQ4(OnQ61Xfs0)ody3sQv}LNnI8~BQ$|q8mFe|Yv3ZYyT;LOn7CdU_65Vq;^^;U~s z79EamwLnR{(|LJ&k>G(nES@*NJ(_x^jEZ2<)Q5fWGZ5_sa#3{17BJ z$#TwI4EOPcN>h`9K@wijD!)ZVP^KkO3q*0=?LB(IDQ-7gn>J<5o2e>P^{fxvckr@6 zcYy)2j$$7^MM=M5bY}6R&GDhDGTNo&lxIT`Z?CgWiI%a_{w!fnW=Bq7a^`>~drOpRnwpk- zri8Mc6K3ulfSRjI*rWwAzFp%T)JlwgrjMSi-|x_3C5e|U7iCpd_9u55-!k%w(C?;b zS0rYHGgtJAVjTnl4pH#$j2QoUgEYc1vqZS%Ws}5Hugl}EkSV_$ZP+R+wKDT`)?Qj` z_R6{GVY)sswXvE|h1eUXJC%WLT4^;IQeD%Vz4Ce{YDnr-Fr}LL;m{}cuAtl7Io<+7 zQc`Jaj41JhnS3XiY_U7geYE&c@@&tNAoJt{i&Jfi0uUqDF?|0E9zs#<tSHyfTi@CVwrdPteVx_El z{APf+yza6L!(8i(i&+;*Qsbw3RLTiKkcYKH;J9sdHV+WCL5+ o_c&*tzbmD692d?xjK6*#?vRh#6%$Z1Hr-hgdna;_ZK$H}FIZlNZ2$lO literal 0 HcmV?d00001 diff --git a/pict/sanitized.jpg b/pict/sanitized.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bec0da750b1534fe54a516f8d0e25c13481879aa GIT binary patch literal 18357 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

X)7SUA}pe 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 literal 0 HcmV?d00001 diff --git a/pict/srch_b_lun.jpg b/pict/srch_b_lun.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8a2d2b720e6ecd7a8e1ff14d8e2ad1cb15328b3d GIT binary patch literal 2180 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 A`2YX_ literal 0 HcmV?d00001 diff --git a/pict/srch_b_un.jpg b/pict/srch_b_un.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e1a4b4d2da8b8d38d84f163fd8d406711676cca9 GIT binary patch literal 2445 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 V)o(s>BU*>sa}7i;VI}I}zX5Ux36%f< literal 0 HcmV?d00001 diff --git a/pict/tab_help.jpg b/pict/tab_help.jpg new file mode 100644 index 0000000000000000000000000000000000000000..632e27006b00f6a18c51e5b20f31ed9dede5de0a GIT binary patch literal 1253 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%hKgqcy0fk}{&S&;Gn5r!TH z1}0`kMxZlcfQ6NTnT;JN1QbS=U}9!rU}R+zU|?isVqszAVq=ErU}9uu5oBc$5@u60 zbQB3LoOn^mXwfBQG4{a3g-w%0jh$Tufm)cESXr21)-W;%GARl%E3p_l1}2IWPBao; z_|U28|1Aa{pb{oQW(10N#agu5!<{*i#3a$t<9bjs_DaiCujfUP4;VIv*NDb<(;xVX7)_g?u1)U*Y0z^ ze0Ij!DJ?QTqm@<8zWR8Wb2bz69l5DaEZH|D`Rm_QF1c}d_w6Ox=a!U(uH=!j__Qn~ zL&P(nZ%)y28J0~cGD)@5U6d+YOYc|ZN*niXt=Q?XZP$yHCPMd9n-pCatytWmwK9gs z*soq<@(Xc4i#`>lMR9AzC7g}!Jr;Uo)wR~M&*61S=i#dcE7plmE^y^Y>au8jFs-~N z>$+Czd7r(O2{wzrelLkr*uU8-<@ehr1q%-q8Bx)yWx}&U73D0Z#k~5yNjcu`+1f`> z^mM1_oIR9#P0d#1_k>A#Ypc_v3f-0GR)mWr-;Hd$F*n?veQ~+74qI@M#%b}Q-^uk^ zHaE82con#BS=M`@&F-OzTSbr6pZm2hbX`8_De3s zHkZ$iE?9h%QFcSjq{7wTIo?^Th{$?LAGn4;!r9BY(9Vsd(ey+RiS@-myN2ih`8Nb}I zmwf-ko=-R{f3jXZu&&z7nRIkwsQ`oq%G){YWSNA8|hhH9N#pc8Ytvdg1wg2271qVW} KN=0w_e-i+Z*6qOn literal 0 HcmV?d00001 diff --git a/pict/tl_t_data_cur.jpg b/pict/tl_t_data_cur.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d9d9b10638a30653b203b5f99107d915ca007465 GIT binary patch literal 2906 zcmbW1c{J4PAIHCA7CSS;;38^_CCn{LNM&m*BWsLps2f8_Tr{em?IQb9Mj16kD6(&v zA>n2#+f7V^p)hD6GG(}y{G5A#_nzN>_ji8p=RD^;=lyx!=kt1=KR$codouvs+5&F@ zfcOA_w7-D8WdMOA`&_yXfB*;p04MjY6+q0C6yog*kUIAr&>kDO0l**-2owT?LScfi z{Vgm2g9!+W2nh)b35mc({t#S5OdKvQCL$prDJdZ#FDEA_ulTn>{QUf)BBC;IxQr|c zfs*~Z@V_4RIst?LpaRr@K?r~k0RkgHd)+|JJ~kg11ls5POJFD;1jY~A_xAn&E`a#J z5GV`|fWTlrFcb#nhyD@a1A!p`6ox<^l5o;`FhY?uy?}l##qVf#HZ(3#4geh>`d1OM3w1R(gp$U}}0EmQOZ3CRngarN2I*|TALlYj_#9|{3R0LH-j8&9)m~mv-yD;7&=E4kUg;sRp^V)>KTiPF9s3sJ;iFYTU#5eVMY-*of`IOyUX! zYkQg+ULb;duX8zRzSiyrE%{z`R!W6Nh1k<)%r=pS@=YnHhB2|$q3I_QbtY;Qx`JBQhu@BdLG6yy zmIWAUPo3kO+c8XCrh4(q``OelWdbXbA9FbAQYV|J60Zkz12waJJn5bUXOp1ySLx2q zBkJut`59+!78eGeNEDg+4Vi!`9%gi=V|3qktu{<#%`=Z7G0seBkEYA{2`Ln#ei5|c ztrE=*0f}+fNdH3UWP?xfnypjPY9Q7wBDSg{zC>n4s`<=@uwq}CX@VYxx-gaa`bM`} zmbH!roG=Z_*4}g&aZR*!vF^0;lgq_-;u>g*!)ujatiKs1d_lpk;BDkx#|gGh_eP(? z)XMXvZPl?24i^vnORpyThVMwwQ|esxX}|Es8M=^JdA-_wU)fM|f*`<*$W2SHNhe6# zBbbxT?dR^i|04@)kQfpRR|gS2-cB%PBg@IU*7t;(!u0H+7BYxkkPBs!Jb` zfKLnVd}!$jPt}x1oxkmUH~36+qbJ_S{oT!weD-j2cA56*s)0(EACidODvBauc|7bT zdzA{#!9|bEU%wFwbh4p$!%BGXRi&2guni_1KinO-YN1R-SbNgrdi1UjF*=)w1P8}b z_QdMBTH1N)t>wuxMeFPCQP)3~ee_x|$nwo?gef`9alT-+Qf3>rhZyZ``Cbij-_oB5 z)&2nFPgD8>FxtZrNZE)TzXzs@`p0ExfaX{xoL*0d|?1EJ{_zQyq4!4j5&*-?!>z?uHI{;>h(yijgIYv_}x{@KGe6nt(Wcl8|^$r=0w zxO|GxdnR~*tJoN}99|N?a726RD(Ju^pVHCJw$IyRPS;=yOft*)bzMb&<-8zx_PZ3N zCagMzOS~&3dpLpQ!p60XzMr1u%K9ywnjqSnnVKFJlcDb{JvHY%JX_8K(Y5i$E@nhlUX6T)nC)JewY5GH>@A$@#l`?ji z&2?W#-g~JRT1zxL&!8Hs)6u)bEh>|axGueqiRlVFMeYBn*P zSP%JL(a~}0%{8ce{JN-yeX+qLFICyaNs*s zGlrJ@CUVditL4P?t+RhLyMF(x_<)Vm{J>9zwp~l778P^z%3kLFYV_AN`y6b1w7z)N zMqZ4EccBUqiuQ5o1gRF@DxFmdYJ!}|U}dG2e_yXzQH6Mr-PpsoBcZ5O86pXt4?+`d zA8m{WbS|c-euaNBR7mZ!Lwz9b9zwEg+Fj2zG1BjLXGjr zfT>g)GXnNmWs1RJEATx62JIOu2eu4T7O_j@X*@ZFBUcZ1pIOawW2__r4V~IDaaqE!(03<}+PB`42Dn&xPF`>kzf zD+gIy228aL?w6~?IG0alpE)8;$bw#sb#}1wt8ucRjPx;<3$s%^-A=f;wqt@At{QrQ zWJ0a|tW`;#`127gaZ2t#0)HHOX?TjmvB&)LFEm<)DR>muuf-6?qWrlI%$1J4iGKqn C5it({ literal 0 HcmV?d00001 diff --git a/pict/tl_t_data_link.jpg b/pict/tl_t_data_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe8333bf274b8acf0ad68cea2502698ad53dabcf GIT binary patch literal 2580 zcmc(aXHe7W8pZ!1?n7(jy8%suV?v=p{F^b9d*?{d8yUhkM?6W}bO|Gv}O_KhA##NMP+8 z>;MoL0D=S$;C}#+HgSPrNdO3d0svqpIIRH(t%67a!9dVc!3D&h0@48?C=?2V3c+AP z2ZRJ8Dk3B#B8q^+Md5IS1maIgAP$O4h#y3tP?C};l)RjroV?QC0tpKXiy_2hBqU^x zNFk+;{0;uwh5r;liU8^W0|G({F{e-j8S zKoS550s#v?1BJo~{ zhgW=5udb}dd#Qi1BT~c3v@-qV=z!khg4q=9$9B}dWz29~H{M3*rLRb%t@ELpoj+>5 zm!BNi~6?u)xAcL+_##6S>>2XUcsW#aq)D=&%S3lmi@q=|b!RQ*tyaT!| zH9e{EEdIf*#a5ihOv^{x>UNDi&gVX+DV6ECBdXL}Wp%|!_2zqS#!!0KF*4S`P6Gc1 zl&`<*I!MTH(Jtttcu+@PxxjVO$M+NRh?fbkmc^fX$PTKVh$i~uF)lS{L}aMcC|^Sw zr@*y>VBx`Yld<#3(RsgH<2q6LVHe$TgRYI$xNTSJhCg)@<6A+cu24rjLz*0Y3FVeP zA>Q|{ZfZO9bsulZg=7om$<1zRPMQ$^fZKaV5}#?F_Zlr`e-%}s%c^??_iERZj89B} zl@D0>O@ES9K508yO32d4u#;a`Eed>|#dE`7@X%#7f4eO*JUW%fsudvz_qCZPs1H+BJLW3MTL*df&#)Lv;eDrVT*Idc8VdDUk z5|ql`Dwe}Re^${vV{?9da{p48lS22}RoO@044-Q&w0TL`(}ov@udSpk=ggK4pSPVh zBEOx9RA|@|H>KFul{UMao3NX!e7;QAqHCr}KD2C&)LvWln^cy~&%&HW?T(4L)W~j5 zUHsliEv*kLR<1ib_2E6MPAyAsJgG_nBrKa4g!=gxTBs(x^>9baf?1OPkw3yMKIP)j{Ul~smUh?=A6GXiNuxuC^WG^7(DCpN$KZAk@!X7dC0K3Lj!9h) zmf_=B{Y~nQY=0G2(Ib^RH~S{5n`wWTXYhUGVpmPTamV5flggJ~O)}Csp>((*CD{_Q zycxa5W#iIWx_1k86_ZWU#9FJ61NEbRU7_+msjx~tc_U&{)8Uo=?x~~g_kC&3*ObX~ z!#K@e@wgmRM3b>b)tUaJcm0~0?pH@RN-Uypr%u8-8$VXpZzKJvvpv~YWG2R9ba$Y+ zH_{Uq?^gIDHZnfuGKWd}>xhc5ur$H(`rza{1wrdJPDOy$)oR z(%EJ5-L0xj_@eJ?MU33yQg1pPw^&dZ&j-W_rFL!7Avwec+n-sFFGSAjmpC9Eu?He5 zJ8feNI|Jw&42#LceO8Y-Mr?tt9qKA;iE23>vbpwSm&8IT-x#1T3 zCgC>G~&p(+}X)E!X=$nXq2;t^pk74e1NpxRD-^* zm?tg8egg--kBJ+yI?XVL`VsiRaS|@jJ<7gK3T+n43s0Fh!QvvA?>qOy&a?A%rXy5; zGfAe%qFZ$PQlE3`UXVqLS~<~NXk0D1@C0~x)Rw+iqKQ1bb$OJfmZPd%y5z{VU{nMi z=zh|=7?i^5u1EYlKYUY8t3cvy+C_!~vnU?+1-sZbo|A@a1*IK!?2i3rIMuQiJ(qKT zU#&M2Z2=GHG-=b@S0cvGAnWiNsLX})7?+W}$EMtZ$OH}SiQ|Ujj9I*mi&ke3yX9Du z>7LYjV5BPh^%x%zjasduC5_dD%$@C+V2IEtDE!85X4x_4+>`pbRk+|n`^N-UH&EHr%%CD#i`8cORp`_Xho+6 z>#3-(FMrN_UvaO$_}ZmNrKEM&Zw(De`h(&To$KbyO2x(3)xD4YWji>>u`zEFZ{4A# zdV8DwuMzTOW74VDS!1Z}eDyo_MUBGTzR|qc*&sKwlJ+2(IK;kg>S=>htm04n6AHPX@Bjb+ literal 0 HcmV?d00001 diff --git a/pict/tl_t_notes_link.jpg b/pict/tl_t_notes_link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe01d8c05554a886039c72e519a95283e67279e8 GIT binary patch literal 2216 zcmdT?c{JPU8vbQPq?(AhTC@$ST4gL{h$U6AgxV9Twl-9UE7OUsrBti!WMZub9 zSppz10QiXxAY1^@#4z8#M*tuI3IKqyNLm7<%>1rVuK<3}L<&ea2HXSSP$(1zg~MQQ z3Am^v#o=&qNhAUxi9jGx$S*)4r4FJFN+B^A85s;lL0(>7;piU#iHV6FKpv1oq2vx@ z(b&U(H2z;Ad8ErFqN*-6|@|| ztNS>C6w{5|$f@ee*2y*)y}Nn+08?pha~Z_BhsAQG+=OqkJDa%G zrjwzs>#X-Xt0=*?KfU&JbfS>6y0f*2TNe2KB6{dHrav)&93Z*%Ql|?W86b9QkhZd?#CI~w7Z|@%HxrtO z9Lw1;n}$VJ!{NTGejmku>yV`kK6y1>%PzX-dUN_{mqwJ6x~ETp1taTm?-7}}h$5xt}bfU>1FznLnsJAt_ zdmo(Qj|6%+Mz3(%f1KeX@NPddnE@wK8mhR^MI2wnLZb7^M;%USJ~PurX>oy)lr$7P zbmsl!HsP-BSV@<$iM?UtxqpQ33ffafU&1bb6a6!geuol-C5;niqA#pefG30C6j4$+s^2E!Gb1T zBB$Q;SjKtv9!5V7*Lv++^!4%i?uE`(pX9|g+&9_U#Y;Yo{`zT>bApq>E#vlfY!30H zCc)|Wfnpt+eY&PJwd{NCxTOKTL5I77&E~hwW`mw4(Nf`wR|Z(sGins|=$*8zN3>Ly z;i#`ayibYqOVAk=H9yf(_}^;lP6!QJnh+GS>x^vYJN6HC5KF9%a^Kw2D)4;Uz+2z+ zXR_$8^!vq(E5-2T5<-9+ZlUG+;ASGdqp`+tZ+v$~CVzWqv}$*c6)--6m6ciX0pLQ-za3`_xl5gCidH>)2DN_calA`sx{vsWh)_ZvTktjI+^8 zmy6z;8lQU!YbQ|4$>cRHe@VM6^RrIp+lMn#N0MvQ1Z57vklm#_t3MxC?yZ@dy^w;Rj4C8CR+vb~XkNU#-y#2$61wG>!$w?8 z#;DO@vXyatwtFq_={j+F16-p3w*1$-l%PUl-r;ghpzvs695B)85fMf}L_9=Oxd^2uFSgc#Y#$ literal 0 HcmV?d00001 diff --git a/pict/tl_t_notes_org.jpg b/pict/tl_t_notes_org.jpg new file mode 100644 index 0000000000000000000000000000000000000000..03c643b84cc6f49571ff4f2219c4107ce28e2c45 GIT binary patch literal 1715 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 N1^3cQg@uZdKLJ#KJ~#jX literal 0 HcmV?d00001 diff --git a/xcode/autopsy.xcodeproj/project.pbxproj b/xcode/autopsy.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..16c279b4f5 --- /dev/null +++ b/xcode/autopsy.xcodeproj/project.pbxproj @@ -0,0 +1,136 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXFileReference section */ + 02B041C40E9070E400E46A87 /* .perltidyrc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = .perltidyrc; sourceTree = ""; }; + 02B041C50E9070E400E46A87 /* Appsort.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Appsort.pm; sourceTree = ""; }; + 02B041C60E9070E400E46A87 /* Appview.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Appview.pm; sourceTree = ""; }; + 02B041C70E9070E400E46A87 /* Args.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Args.pm; sourceTree = ""; }; + 02B041C80E9070E400E46A87 /* Caseman.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Caseman.pm; sourceTree = ""; }; + 02B041C90E9070E400E46A87 /* Data.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Data.pm; sourceTree = ""; }; + 02B041CA0E9070E400E46A87 /* define.pl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = define.pl; sourceTree = ""; }; + 02B041CB0E9070E400E46A87 /* Exec.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Exec.pm; sourceTree = ""; }; + 02B041CC0E9070E400E46A87 /* File.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = File.pm; sourceTree = ""; }; + 02B041CD0E9070E400E46A87 /* Filesystem.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Filesystem.pm; sourceTree = ""; }; + 02B041CE0E9070E400E46A87 /* Frame.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Frame.pm; sourceTree = ""; }; + 02B041CF0E9070E400E46A87 /* Fs.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Fs.pm; sourceTree = ""; }; + 02B041D00E9070E400E46A87 /* Hash.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Hash.pm; sourceTree = ""; }; + 02B041D10E9070E400E46A87 /* Kwsrch.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Kwsrch.pm; sourceTree = ""; }; + 02B041D20E9070E400E46A87 /* Main.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Main.pm; sourceTree = ""; }; + 02B041D30E9070E400E46A87 /* Meta.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Meta.pm; sourceTree = ""; }; + 02B041D40E9070E400E46A87 /* Notes.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Notes.pm; sourceTree = ""; }; + 02B041D50E9070E400E46A87 /* Print.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Print.pm; sourceTree = ""; }; + 02B041D60E9070E400E46A87 /* search.pl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = search.pl; sourceTree = ""; }; + 02B041D70E9070E400E46A87 /* Timeline.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Timeline.pm; sourceTree = ""; }; + 02B041D80E9070E400E46A87 /* Vs.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = Vs.pm; sourceTree = ""; }; + 02B041DA0E90710300E46A87 /* .perltidyrc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = .perltidyrc; sourceTree = ""; }; + 02B041DB0E90710300E46A87 /* autopsy.base */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = autopsy.base; sourceTree = ""; }; + 02B041DD0E90710400E46A87 /* make-live-cd.base */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "make-live-cd.base"; sourceTree = ""; }; + 02EF3BBF0860F668001CA8B0 /* global.css */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = global.css; path = ../global.css; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXGroup section */ + 02670C57079A2F7E00BA95F3 = { + isa = PBXGroup; + children = ( + 02B041D90E90710300E46A87 /* base */, + 02B041C30E9070E400E46A87 /* lib */, + 02EF3BBF0860F668001CA8B0 /* global.css */, + ); + sourceTree = ""; + }; + 02B041C30E9070E400E46A87 /* lib */ = { + isa = PBXGroup; + children = ( + 02B041C40E9070E400E46A87 /* .perltidyrc */, + 02B041C50E9070E400E46A87 /* Appsort.pm */, + 02B041C60E9070E400E46A87 /* Appview.pm */, + 02B041C70E9070E400E46A87 /* Args.pm */, + 02B041C80E9070E400E46A87 /* Caseman.pm */, + 02B041C90E9070E400E46A87 /* Data.pm */, + 02B041CA0E9070E400E46A87 /* define.pl */, + 02B041CB0E9070E400E46A87 /* Exec.pm */, + 02B041CC0E9070E400E46A87 /* File.pm */, + 02B041CD0E9070E400E46A87 /* Filesystem.pm */, + 02B041CE0E9070E400E46A87 /* Frame.pm */, + 02B041CF0E9070E400E46A87 /* Fs.pm */, + 02B041D00E9070E400E46A87 /* Hash.pm */, + 02B041D10E9070E400E46A87 /* Kwsrch.pm */, + 02B041D20E9070E400E46A87 /* Main.pm */, + 02B041D30E9070E400E46A87 /* Meta.pm */, + 02B041D40E9070E400E46A87 /* Notes.pm */, + 02B041D50E9070E400E46A87 /* Print.pm */, + 02B041D60E9070E400E46A87 /* search.pl */, + 02B041D70E9070E400E46A87 /* Timeline.pm */, + 02B041D80E9070E400E46A87 /* Vs.pm */, + ); + name = lib; + path = ../lib; + sourceTree = SOURCE_ROOT; + }; + 02B041D90E90710300E46A87 /* base */ = { + isa = PBXGroup; + children = ( + 02B041DA0E90710300E46A87 /* .perltidyrc */, + 02B041DB0E90710300E46A87 /* autopsy.base */, + 02B041DD0E90710400E46A87 /* make-live-cd.base */, + ); + name = base; + path = ../base; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXProject section */ + 02670C5B079A2F7E00BA95F3 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 027355510E7C4D6D002BD6DB /* Build configuration list for PBXProject "autopsy" */; + hasScannedForEncodings = 1; + mainGroup = 02670C57079A2F7E00BA95F3; + projectDirPath = ""; + targets = ( + ); + }; +/* End PBXProject section */ + +/* Begin XCBuildConfiguration section */ + 027355520E7C4D6D002BD6DB /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Development; + }; + 027355530E7C4D6D002BD6DB /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Deployment; + }; + 027355540E7C4D6D002BD6DB /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Default; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 027355510E7C4D6D002BD6DB /* Build configuration list for PBXProject "autopsy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 027355520E7C4D6D002BD6DB /* Development */, + 027355530E7C4D6D002BD6DB /* Deployment */, + 027355540E7C4D6D002BD6DB /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; +/* End XCConfigurationList section */ + }; + rootObject = 02670C5B079A2F7E00BA95F3 /* Project object */; +}