#!/usr/bin/wish
# ForensiX - a Forensic analysis program for uniX
# Copyright (c), 1999, Fred Cohen

# use our file selection box

source tkfbox.tcl

proc timestamp {} {
	set seconds [clock seconds]
	set localtime [clock format $seconds -format "%Y/%m/%d-%H:%M:%S"]
	set user [exec /usr/bin/id -nu]
	set md5 [exec /ForensiX/bin/md5 -n log]
	return "$localtime $user $md5"
}

set filehandle [open "/ForensiX/log" a+]
set logstring [timestamp]
puts $filehandle "$logstring # Enter ForensiX !"
close $filehandle


# Set window title

wm title . "ForensiX 1.3 Copyright (c) Fred Cohen & Associates, 1985-2000"

# Initialize data values
set machinetype mac
set filetype text
set fstype hfs
set minsize 1
set device /dev/fd0
set cddevice "0,1,0"
set speed 4
set tapedevice /dev/st0
set tarroot /ForensiX
set loopdev ""
set location /mnt
set verbose verbose
set searchfor ""
set searchconnect near
set searchfor2 ""
set sensitive "insensitive"
set sortby "9"
set readonly ro
set traceroptions -changes
set ethernet eth0
set tcplooptime 60
set tcploops 2
# set tcplocation /ForensiX/IP/

# appearance variables
set mybuttonwidth 0
set smallbuttonwidth 0
set sidemenuwidth 0
set sidemenubuttonwidth 0
set relief flat
set anchor n
set padx 8
set pady 0

#installed in
set installdir /ForensiX/

#   Type names		Extension(s)	Mac File Type(s)
#
#---------------------------------------------------------
set types {
	{"All files"		*}
	{"Text files"		{.txt .doc}	}
	{"Graphics Files"	{.gif .jpeg .jpg}}
    }

proc getfile {default start} {
	global thing types
	set thing [tk_getOpenFile -filetypes $types -initialdir $start -parent .top]
	if {$thing == ""} {return $default}
	return $thing
}

set itypes {
	{"Images"		{.image}}
	{"All files"		*}
    }

proc getifile {default start} {
	global thing itypes
	set thing [tk_getOpenFile -filetypes $itypes -initialdir $start -parent .top]
	if {$thing == ""} {return $default}
	return $thing
}

# Create a frame for buttons and entry.
frame .top -borderwidth 1 -relief raised
frame .top2 -borderwidth 1 -relief raised
frame .top3 -borderwidth 1 -relief raised
pack .top .top3 .top2 -side top -fill x
# frame .side -borderwidth 1
# pack .side -side left -fill x

# Top menu buttons
set but [button .top.run -text "Go!" -command Run  -width $sidemenuwidth -anchor $anchor]
menubutton .top.collect -text "Image" -menu .top.collect.menu  -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
menubutton .top.mount -text "Mount" -menu .top.mount.menu -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
menubutton .top.ls -text "List" -menu .top.ls.menu  -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
menubutton .top.search -text "Search" -menu .top.search.menu  -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
menubutton .top.dump -text "Dump" -menu .top.dump.menu  -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
menubutton .top.tracer -text "Tracer"  -menu .top.tracer.opt -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
menubutton .top.jdlr -text "JDLR"  -menu .top.jdlr.opt -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
menubutton .top.doc -text "Document"  -menu .top.doc.menu -relief $relief -width $sidemenubuttonwidth -anchor $anchor -padx $padx -pady $pady
# tk_optionMenu .top.options verbose verbose quiet
pack .top.run .top.collect .top.mount .top.ls .top.search .top.dump \
	.top.tracer .top.jdlr .top.doc -side left

set m [menu .top.doc.menu -tearoff 0]
$m add command -label "Comment" -command document
#$m add command -label "New Case" -command newcase
#$m add command -label "Edit Case" -command edcase
#$m add command -label "Find Case" -command findcase
#$m add command -label "Work On" -command workon

source collect.tcl
source mount.tcl

set m [menu .top.ls.menu -tearoff 0]
$m add radio -label quiet -variable verbose -command {
	set command "/ForensiX/ForensiX.listfiles $location $verbose +$sortby"}
$m add radio -label verbose -variable verbose -command {
	set command "/ForensiX/ForensiX.listfiles $location $verbose +$sortby"}
$m add sep
$m add cascade -label "Sort Column" -menu $m.sortby

set m [menu .top.ls.menu.sortby -tearoff 0]
foreach i {none 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14} {
$m add radio -label $i -variable sortby -command {
	set command "/ForensiX/ForensiX.listfiles $location $verbose +$sortby"}
	}

source search.tcl
source dump.tcl

set m [menu .top.tracer.opt -tearoff 0]
foreach i {-changes -setuids -rhosts -passwd -rcfiles -passguess -somefile -writeables -chkexploit} {
	$m add radio -label $i -variable traceroptions -command {
	set command "/ForensiX/ForensiX.tracer $traceroptions"}
	}
$m add radio -label WebTrace -variable traceroptions -command { set command "/ForensiX/ForensiX.tracer $traceroptions $searchfor"}

set m [menu .top.jdlr.opt -tearoff 0]
$m add command -label "Just Doesn't Look Right!"
$m add sep
foreach i {what-does-it-look-like what-looks-wrong block-by-block} {
	$m add radio -label $i -variable traceroptions -command {
	set command "/ForensiX/ForensiX.jdlr $traceroptions /mnt"}
	}

# command area
label .top3.l -text Command:
entry .top3.cmd -width 80 -relief sunken -textvariable command
# logo, quit, and help
# image create photo logo -file /ForensiX/ForensiX.gif
# label .top.logo -image logo -bd 1 -relief sunken -padx $padx -anchor center
button .top.quit -text Quit -command bye -width $sidemenuwidth -relief $relief -padx $padx -pady $pady
button .top.help -text Help! -command help -width $sidemenuwidth -relief $relief -padx $padx -pady $pady

# searchterm area
label .top2.s -text "Search for:" -padx 0
entry .top2.search -width 12 -relief sunken -textvariable searchfor
tk_optionMenu .top2.s2 searchconnect near not
entry .top2.search2 -width 12 -relief sunken -textvariable searchfor2
tk_optionMenu .top2.sense sensitive "insensitive" "sensitive"
button .top2.invoke -text "Update Search" -width $sidemenuwidth -relief raised -padx $padx -pady $pady -anchor $anchor -command {
	set command "/ForensiX/ForensiX.searchfor $filetype $location $verbose $minsize \"$searchfor\" $searchconnect \"$searchfor2\" $sensitive" }

# pack top menus
# pack .top.help .top.logo .top.quit -side left
pack .top.quit .top.help -side right
pack .top3.l .top3.cmd -side left
# -fill x -expand true
pack .top2.s .top2.search .top2.s2 .top2.search2 .top2.sense .top2.invoke -side left

frame .t
set log [text .t.log -width 80 -height 24 -borderwidth 2 -relief raised -setgrid true -yscrollcommand {.t.scroll set}]
scrollbar .t.scroll -command {.t.log yview}
pack .t.scroll -side right -fill y
pack .t.log -side left -fill both -expand true
pack .t -side top -fill both -expand true

proc Run {} {
	global command input log but
	set filehandle [open "/ForensiX/log" a+]
	set logstring [timestamp]
	puts $filehandle "$logstring $command !"
	close $filehandle
	set filehandle [open "/ForensiX/output" a+]
	set logstring [timestamp]
	puts $filehandle "$logstring $command !"
	close $filehandle
	if [catch {open "|$command |& /usr/bin/tee -ai /ForensiX/output"} input] {
		$log insert end $input\n
	} else {
		fileevent $input readable Log
		$log insert end $command\n
		$but config -text Stop -command Stop
	}
}

proc bye {} {
	set filehandle [open "/ForensiX/log" a+]
	set logstring [timestamp]
	puts $filehandle "$logstring # Exit ForensiX !"
	close $filehandle
	exit
	}

proc mount {} {
	global command device fstype location readonly
	set command "ForensiX.mount $device $location -t$fstype -o $readonly -o loop"
	}

proc collect {} {
	global command machinetype location device
	set command "/bin/dd if=$device of=$location/incoming"
	}

proc tracer {} {
	global command traceroptions
	set command "/ForensiX/ForensiX.tracer $traceroptions"
	}

proc df {} {
	global command
	set command "/ForensiX/ForensiX.docommands /bin/df /bin/mount"
	}

proc newcase {} {
	edcase
	}

proc edcase {} {
	global f1 f2 f3 f4 f5
	set w .form
	catch {destroy $w}
	toplevel $w
	wm title $w "ForensiX Case Data Form"
	wm iconname $w "form"
	label $w.msg -wraplength 4i -justify left -text "Please update the entries for this case."
	pack $w.msg -side top

	frame $w.buttons
	pack $w.buttons -side bottom -fill x -pady 2m
	button $w.buttons.dismiss -text OK -command "destroy $w"
	pack $w.buttons.dismiss -side left -expand 1
	
	foreach i {f1 f2 f3 f4 f5} {
	    frame $w.$i -bd 2
	    entry $w.$i.entry -relief sunken -width 40 -textvariable $i
	    label $w.$i.label
	    pack $w.$i.entry -side right
	    pack $w.$i.label -side left
	}
	$w.f1.label config -text "Case Name:"
	$w.f2.label config -text "Case Identifier:"
	$w.f3.label config -text "Organization:"
	$w.f4.label config -text "Address:"
	$w.f5.label config -text "Phone:"
	pack $w.msg $w.f1 $w.f2 $w.f3 $w.f4 $w.f5 -side top -fill x
	bind $w <Return> "destroy $w"
	focus $w.f1.entry
	}

proc findcase {} {
	global command
	}

proc workon {} {
	global command
	}

proc myappend data {
	set filehandle [open "/ForensiX/log" a+]
	set logstring [timestamp]
	puts $filehandle "$logstring # Document $data !"
	close $filehandle
	}

proc document {} {
	global comment
	set comment ""
	set w .form
	catch {destroy $w}
	toplevel $w
	wm title $w "Document Situation and Actions"
	wm iconname $w "form"
	label $w.msg -wraplength 4i -justify left -text "Please provide the desired documentation:"
	pack $w.msg -side top
	frame $w.buttons
	pack $w.buttons -side bottom -fill x -pady 2m
	button $w.buttons.dismiss -text Done -command {myappend "$comment" ; destroy .form}
	pack $w.buttons.dismiss -side left -expand 1
	entry $w.doc -relief sunken -width 70 -textvariable comment
	pack $w.doc -side right
	bind .form <Return> {myappend "$comment" ; destroy .form}
	focus $w.doc
	}

source help.tcl

# tk_messageBox -icon info -type ok -title "About ForensiX" -message "ForensiX is Copyright (c) 1999, Fred Cohen & Associates - ALL RIGHTS RESERVED"

# Log output
proc Log {} {
        global input log
        if [eof $input] {
                Stop
        } else {
                gets $input line
                $log insert end $line\n
                $log see end
        }

# Stop the program and fix up the button
proc Stop {} {
        global input but
        catch {close $input}
        $but config -text "Go" -command Run
}}
