#!/usr/bin/perl -T # $Author: hso $ # $Date: 2001/06/17 06:00:36 $ # $Revision: 1.23 $ # $RCSfile: snifob,v $ # $Name: v0_9_2 $ use vars qw( @default_color_set @mac_addr_color_set @src_ip_color_set @dst_ip_color_set @src_port_color_set @dst_port_color_set @time_color_set @hex_p_color_set @hex_np_color_set @keyword_color_set %foreground %background %intensity $reset $escape $snort_hex_re $snoop_hex_re $hex_X_re $hex_x_re $hex_smb_re $snort_timestamp_re $dt_timestamp_re $tcpdump_epoch_timestamp_re $snoop_dr_timestamp_re $num_ip_addr_re $aip_addr_re $hostname_re $fqdn_re $alphnum_hn_port_re $num_port_re $alphnum_port_re $mac_addr_re $sniffer $sniffer_options $sniffer_dump $sniffer_options_dump $using_snifoutfh $rel_version $opt_Debug $opt_Help $opt_Nocolor $opt_Nodecode $opt_Run $opt_Drun $eol ); use strict; use Getopt::Long; ## begin user configurable # color sets @default_color_set = qw(dark cyan black); @mac_addr_color_set = qw(dark cyan blue); @src_ip_color_set = qw(bright magenta black); @dst_ip_color_set = qw(bright yellow black); @src_port_color_set = qw(dark white blue); @dst_port_color_set = qw(dark black green); @time_color_set = qw(dark green black); @hex_p_color_set = qw(bright green black); @hex_np_color_set = qw(dark blue black); @keyword_color_set = qw(bright cyan blue); $sniffer = "Not configured"; $sniffer_options = "Not configured"; #$sniffer = "/usr/local/bin/sudo /usr/local/bin/snort"; #$sniffer_options = "-A none -axvBi eth0"; #$sniffer = "/usr/local/bin/sudo /usr/local/sbin/tcpdump"; #$sniffer_options = "-vveln"; # the following should include an option or options to dump the # packet payload $sniffer_dump = "Not configured"; $sniffer_options_dump = "Not configured"; #$sniffer_dump = "/usr/local/bin/sudo /usr/local/bin/snort"; #$sniffer_options_dump = "-A none -axvdBi eth0"; #$sniffer_dump = "/usr/local/bin/sudo /usr/local/sbin/tcpdump"; #$sniffer_options_dump = "-Xvvelns 1518"; ## begin potentially evil security hole # # *NOTE*: users could set their environment to anything they # want and this program *will* run that code. This is bad # if you are using sudo with a policy for a user to only # run snifob as root. You could tighten the de-tainting # regex: /(.*)/ to fit what you're trying to accomplish to # help. # #$sniffer = $ENV{sniffer}; #$sniffer_options = $ENV{sniffer_options}; # #if ($sniffer =~ /(.*)/) { # $sniffer = $1; #} #if ($sniffer_options =~ /(.*)/) { # $sniffer_options = $1; #} # ## end potentially evil security hole ## end user configurable ## begin non user configurable ( certainly user hackable, however ;) ) ## use the source l |_| |< 3 !! # clean path for perl -T $ENV{PATH} = ""; $ENV{ENV} = ""; # signal handlers to clean up colorization $SIG{INT} = \&sig_exit_cleanup_handler; $SIG{QUIT} = \&sig_exit_cleanup_handler; $SIG{STOP} = \&sig_stop_cleanup_handler; # colors %foreground = ( black => 30, red => 31, green => 32, yellow => 33, blue => 34, magenta => 35, cyan => 36, white => 37 ); %background = ( black => 40, red => 41, green => 42, yellow => 43, blue => 44, magenta => 45, cyan => 46, white => 47 ); %intensity = ( dark => 0, bright => 1 ); # escape sequences $escape = "\033["; $reset = "00m"; # can all the ( become (?: # patterns $snort_hex_re = '(?:0x[\dA-Fa-f]{4}:\s)?(?:[\dA-F]{2}\s){1,16}\s+.{1,16}'; $snoop_hex_re = '\s{1,11}\d+:\s(?:[\dA-Fa-f]{2,4}\s)+'; $hex_X_re = '0x[\dA-Fa-f]{4}\s+[\dA-Fa-f]+'; $hex_x_re = '\s+([\dA-Fa-f]{2,4} )+'; $hex_smb_re = '\[[A-Fa-f\d]{3}\]( [A-Fa-f\d]{2})+'; $snort_timestamp_re = '\d{2}\/\d{2}-\d{2}:\d{2}:\d{2}\.\d{6}'; $dt_timestamp_re = '(\d{1,2}:){2}\d{1,2}\.\d+'; $tcpdump_epoch_timestamp_re = '\d+\.\d{6}'; $snoop_dr_timestamp_re = '\d+\.\d{5}'; $num_ip_addr_re = '(((2([0-4]\d|5[0-5])|[01]?\d{1,2}))\.){3}((2([0-4]\d|5[0-5])|[01]?\d{1,2}))'; # hostname_re and fqdn_re shouldn't accept (see RFC 1035) '_' (found in \w); Since some people # have used '_' in their labels/hostnames.... $hostname_re = '(([a-zA-z][A-Za-z\d_-]{1,61}[A-Za-z\d])|([a-zA-z][A-Za-z\d])|[a-zA-z])'; $fqdn_re = '((([a-zA-z][A-Za-z\d_-]{1,61}[A-Za-z\d])|([a-zA-z][A-Za-z\d])|[a-zA-z])\.)+(([a-zA-z][A-Za-z\d_-]{1,61}[A-Za-z\d])|([a-zA-z][A-Za-z\d])|[a-zA-z])'; $num_port_re = '\d{1,5}'; $alphnum_port_re = '[\w-]+'; $mac_addr_re = '([\dA-Fa-f]{1,2}:){5}[\dA-Fa-f]{1,2}'; # global variables $eol = $/; $rel_version = "0.9.2"; $using_snifoutfh = 0; # immediately flush output buffer when data is written $| = 1; GetOptions( "debug:i" => \$opt_Debug, "help" => \$opt_Help, "nocolor" => \$opt_Nocolor, "nodecode" => \$opt_Nodecode, "run" => \$opt_Run, "drun" => \$opt_Drun ); #begin "main" { my $fh_to_read = (); &reset_ansi(); if ($opt_Help) { print "\n"; print "Options available for $0 v$rel_version:\n"; print "\n"; print " --help\tshow this information\n"; print " --nocolor\tdo not colorize output\n"; print " --nodecode\tdo not de-hexify tcpdump -x output\n"; print " --debug\tjust like it sounds\n"; print " --run\trun \"$sniffer\" with options \"$sniffer_options\" &\n"; print " \t\tsnag stdout (doesn't dump packet payload)\n"; print " --drun\trun \"$sniffer_dump\" with options \"$sniffer_options_dump\" &\n"; print " \t\tsnag stdout (dumps packet payload)\n"; print "\n"; print " For additional information, run perldoc on $0\n"; print "\n"; exit 1; } if (defined($opt_Debug)) { if ($opt_Debug < 1) { $opt_Debug = 1; } } if ($opt_Run) { if ($sniffer eq "Not configured" || $sniffer_options eq "Not configured") { print "\nEdit $0 and configure \$sniffer and \$sniffer_options\n\n"; exit 1; } else { &debug_msg("Opening |$sniffer $sniffer_options\n") if $opt_Debug; open(SNIFOUTFH, "$sniffer $sniffer_options|") || die "Can't start \"$sniffer $sniffer_options\". error: $?"; $using_snifoutfh = 1; print "$0 v$rel_version processing SNIFOUTFH.\n"; } } elsif ($opt_Drun) { if ($sniffer_dump eq "Not configured" || $sniffer_options_dump eq "Not configured") { print "\nEdit $0 and configure \$sniffer_dump and \$sniffer_options_dump\n\n"; exit 1; } else { &debug_msg("Opening |$sniffer_dump $sniffer_options_dump\n") if $opt_Debug; open(SNIFOUTFH, "$sniffer_dump $sniffer_options_dump|") || die "Can't start \"$sniffer_dump $sniffer_options_dump\". error: $?"; $using_snifoutfh = 1; print "$0 v$rel_version processing SNIFOUTFH.\n"; } } else { print "\n\n$0 v$rel_version processing stdin.\n"; } &colorize(\@default_color_set); ## begin main loop if ($opt_Run || $opt_Drun) { while () { &match_line($_); } } else { while() { &match_line($_); } } ## end main loop if ($opt_Run || $opt_Drun) { close(SNIFOUTFH); } } #end "main" sub match_line () { my $line_matched = 0; my $line = (); $line = &multi_chomp($_[0]); #&debug_msg("Called: match_line (snort)\n") if $opt_Debug; &debug_msg("Called: match_line\n") if $opt_Debug; if (!$line_matched && !$opt_Nodecode && $line =~ /^$hex_x_re/) { &old_hex($line); $line_matched = 1; } if (!$line_matched && $line =~ /^$hex_X_re/) { &new_hex($line); $line_matched = 1; } if (!$line_matched && $line =~ /^$hex_smb_re/) { &smb_hex($line); $line_matched = 1; } if (!$line_matched && $line =~ /^$snoop_hex_re/) { &new_hex($line); $line_matched = 1; } # tcpdump info lines if (!$line_matched && $line =~ /^arp (who-has|reply)/) { &arp_info_line($line); $line_matched = 1; } if ( !$line_matched && ( ($line =~ /^$dt_timestamp_re/) || ($line =~ /^$tcpdump_epoch_timestamp_re/) || ($line =~ /^( )?$snoop_dr_timestamp_re/) ) ) { &time_info_line($line); $line_matched = 1; } if ( !$line_matched && ( ($line =~ /^$num_ip_addr_re\.($num_port_re|$alphnum_port_re) > /) || ($line =~ /^$fqdn_re\.($num_port_re|$alphnum_port_re) > /) || ($line =~ /^$hostname_re\.($num_port_re|$alphnum_port_re) > /) ) ) { if(&addr_port_info_line($line) == 1) { $line_matched = 1; } } if ( !$line_matched && ( ( ($line =~ /^ ?$num_ip_addr_re > /) || ($line =~ /^ ?$fqdn_re > /) || ($line =~ /^ ?$hostname_re > /) ) || ( ( ($line =~ /^ ?$num_ip_addr_re -> /) || ($line =~ /^ ?$fqdn_re -> /) || ($line =~ /^ ?$hostname_re -> /) ) && (index($line, "=") >= 0) ) ) ) { &addr_info_line($line); $line_matched = 1; } if (!$line_matched && $line =~ /^$mac_addr_re/) { &mac_info_line($line); $line_matched = 1; } # snort lines if ( !$line_matched && ( ($line =~/^$snort_timestamp_re/) ) ) { &s_time_info_line($line); $line_matched = 1; } if ( !$line_matched && ( ($line =~/^$snort_hex_re/) ) ) { &s_hex_line($line); $line_matched = 1; } if ( !$line_matched && ( ($line =~/^(?: )?$num_ip_addr_re(?::$num_port_re)? -> $num_ip_addr_re(?::$num_port_re)?/) || ($line =~/^(?: )?$num_ip_addr_re(?::$num_port_re)? -> $num_ip_addr_re(?::$num_port_re)?/) ) ) { &s_ipaddr_line($line); $line_matched = 1; } if ( !$line_matched && ( ($line =~/^(ICMP|TCP|UDP)[^:]/) ) ) { my @tmp_line_array = split(/\ /, $line); &s_process_rest_of_line(\@tmp_line_array); $line_matched = 1; } # snoop -v if ( !$line_matched && ( ($line =~/^[A-Z]+:/) ) ) { my @tmp_line_array = split(/\ /, $line); &snoopv_process_rest_of_line(\@tmp_line_array); $line_matched = 1; } # what if dos/win32, do we need \r\n ? if (! $line_matched) { print ("$line$eol"); } $line_matched = 0; } # snort functions sub s_time_info_line() { my $wrk_line = $_[0]; my @wrk_line_array = (); my $date = (); my $time = (); &debug_msg("Called: s_time_info_line (snort)\n") if $opt_Debug; @wrk_line_array = split("\ ", $wrk_line); ($date, $time) = split(/-/, shift(@wrk_line_array)); &colorize(\@time_color_set); print "$date"; &colorize(\@default_color_set); print "-"; &colorize(\@time_color_set); print "$time"; &colorize(\@default_color_set); &s_process_rest_of_line(\@wrk_line_array); } sub s_ipaddr_line() { my $wrk_line = $_[0]; my @wrk_line_array = (); my $addr = (); my $port = (); &debug_msg("Called: s_ipaddr_line (snort)\n") if $opt_Debug; @wrk_line_array = split("\ ", $wrk_line); $addr = shift(@wrk_line_array); if (index($addr, ":") >= 0) { ($addr, $port) = split (/:/, $addr); &colorize(\@src_ip_color_set); print "$addr"; &colorize(\@default_color_set); print ":"; &colorize(\@src_port_color_set); print "$port"; &colorize(\@default_color_set); } else { &colorize(\@src_ip_color_set); print "$addr"; &colorize(\@default_color_set); } &s_process_rest_of_line(\@wrk_line_array); } sub s_hex_line() { my $wrk_line = $_[0]; my $preamble = (); my $beg_hex_chunk = (); my $end_hex_chunk = (); my @lhs_hex_array = (); my @rhs_hex_array = (); my $l_ele = (); my $r_ele = (); my $index = 0; my $padding = 0; &debug_msg("Called: s_hex_line (snort)\n") if $opt_Debug; if ($wrk_line =~ /(0x[\dA-Fa-f]{4}:\s)?(([A-Fa-f\d]{2} ){1,16})(\s+)(.{1,16})/) { if ($opt_Debug) { if ($opt_Debug == 4) { print "\$&: $&\n"; print "\$`: $`\n"; print "\$': $'\n"; print "\$1: $1\n"; print "\$2: $2\n"; print "\$3: $3\n"; print "\$4: $4\n"; print "\$5: $5\n"; print "\$6: $6\n"; print "\$7: $7\n"; print "\$8: $8\n"; print "\$9: $9\n"; } } $preamble = $1 if defined($1); $beg_hex_chunk = $2; $padding = $4; $end_hex_chunk = $5; } @lhs_hex_array = split(/\ /, $beg_hex_chunk); @rhs_hex_array = split(/ */, $end_hex_chunk); print "$preamble" if defined($1); foreach $l_ele (@lhs_hex_array) { if ($l_ele ge "20" && $l_ele le "7E") { &colorize(\@hex_p_color_set); print "$l_ele"; &colorize(\@default_color_set); if ($index <= $#lhs_hex_array) { print " "; } } else { &colorize(\@hex_np_color_set); print "$l_ele"; $rhs_hex_array[$index] = "\0"; if ($index <= $#lhs_hex_array) { print " "; } } $index++; } print $padding; # fixme: # 0x0000: 00 50 DA 30 97 05 00 50 DA 30 57 FA 08 00 45 10 .P.0...P.0W...E. # 0x0010: 00 D0 DB 8B 40 00 40 06 E3 31 C0 A8 FD 03 C0 A8 ....@.@..1...... # 0x0020: FD 05 07 FA 00 8B AA 81 92 94 00 06 34 96 50 18 ............4.P. # 0x0030: 7D 74 25 B1 00 00 00 00 00 A4 FF 53 4D 42 72 00 }t%........SMBr. # 0x0040: 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 00 ................ # 0x0050: 00 00 00 00 B7 79 00 00 01 00 00 81 00 02 50 43 .....y........PC # 0x0060: 20 4E 45 54 57 4F 52 4B 20 50 52 4F 47 52 41 4D NETWORKPROGRAM # 0x0070: 20 31 2E 30 00 02 4D 49 43 52 4F 53 4F 46 54 20 1.0...ICROSOFT # 0x0080: 4E 45 54 57 4F 52 4B 53 20 31 2E 30 33 00 02 4D NETWORKS1.03... # 0x0090: 49 43 52 4F 53 4F 46 54 20 4E 45 54 57 4F 52 4B ICROSOFTNETWORK # 0x00A0: 53 20 33 2E 30 00 02 4C 41 4E 4D 41 4E 31 2E 30 S3.0...ANMAN1.0 # 0x00B0: 00 02 4C 4D 31 2E 32 58 30 30 32 00 02 53 61 6D ..LM1.2X002..Sam # 0x00C0: 62 61 00 02 4E 54 20 4C 41 4E 4D 41 4E 20 31 2E ba..NTLANMAN1. # 0x00D0: 30 00 02 4E 54 20 4C 4D 20 30 2E 31 32 00 0..NTLM0.12.Use of uninitialized value at /home/hso/proj/snifob/snifob line 530, chunk 782. # .. foreach $r_ele (@rhs_hex_array) { if ($r_ele ge "!" && $r_ele le "~") { &colorize(\@hex_p_color_set); print "$r_ele"; &colorize(\@default_color_set); } else { &colorize(\@hex_np_color_set); print "."; } } &colorize(\@default_color_set); print "\n"; } sub s_process_rest_of_line() { my $wrk_line_array_ref = $_[0]; my $index = 0; my $curr_victim = (); &debug_msg("Called: s_process_rest_of_line (snort)\n") if $opt_Debug; for($index = 0; $index <= $#$wrk_line_array_ref; $index++) { my $did_print = 0; my $look_forward = 0; my $look_backward = 0; my $continue = 0; $curr_victim = $$wrk_line_array_ref[$index]; if ($opt_Debug) { if ($opt_Debug == 3) { &debug_msg("loop pass: $index, \$current_victim: $curr_victim"); } } $look_backward = 1 if ($index > 0); $look_forward = 1 if ($index < $#$wrk_line_array_ref); if ($continue == 0 && $look_backward) { $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "->"); $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "who-has" && $$wrk_line_array_ref[$index + 1] eq "tell"); $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "tell" && $$wrk_line_array_ref[$index - 3] eq "who-has"); $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "reply" && $$wrk_line_array_ref[$index + 1] eq "is-at"); } if ($continue == 0 && $look_forward) { $continue = 1 if ($$wrk_line_array_ref[$index + 1] eq "->"); } if ($did_print == 0) { if ( $continue && ($curr_victim =~ /^$num_ip_addr_re(:$num_port_re)?/)) { print " "; my $addr = (); my $port = (); if (index($curr_victim, ":") >= 0) { ($addr, $port) = split(/:/, $curr_victim); } else { $addr = $curr_victim; } if ( $$wrk_line_array_ref[$index-1] eq "->" || $$wrk_line_array_ref[$index-1] eq "who-has" ) { &colorize(\@dst_ip_color_set); } else { &colorize(\@src_ip_color_set); } print "$addr"; &colorize(\@default_color_set); if (defined($port)) { if ( $$wrk_line_array_ref[$index-1] eq "->" || $$wrk_line_array_ref[$index-1] eq "who-has" ) { print ":"; &colorize(\@dst_port_color_set); print "$port"; } else { print ":"; &colorize(\@src_port_color_set); print "$port"; } } &colorize(\@default_color_set); $did_print = 1; $continue = 0; } } if ($did_print == 0) { if ($curr_victim =~ /$mac_addr_re/) { print " "; &colorize(\@mac_addr_color_set); print "$curr_victim"; &colorize(\@default_color_set); $did_print = 1; } } if ($did_print == 0) { if ( ($curr_victim eq "ARP") || ($curr_victim eq "ICMP") || ($curr_victim eq "TCP" && ($$wrk_line_array_ref[$index + 1] ne "Options")) || ($curr_victim eq "UDP") ) { if ( ($$wrk_line_array_ref[0] ne "ICMP") && ($$wrk_line_array_ref[0] ne "TCP") && ($$wrk_line_array_ref[0] ne "UDP") ) { print " "; } if ($opt_Debug) { if ($opt_Debug == 3) { print &debug_msg("matched snort keyword"); } } &colorize(\@keyword_color_set); print "$curr_victim"; &colorize(\@default_color_set); $did_print = 1; } } if ($did_print == 0) { if ($curr_victim =~ /$mac_addr_re/) { print " "; &colorize(\@mac_addr_color_set); print "$curr_victim"; &colorize(\@default_color_set); $did_print = 1; } } if (!$did_print) { print " $curr_victim"; } else { $did_print = 0; } } print "\n"; } # snoopv functions sub snoopv_process_rest_of_line() { my $wl_ref = $_[0]; my $ele = (); my $index = (); &debug_msg("Called: snoopv_process_rest_of_line"); for ($index = 0; $index <= $#$wl_ref; $index++) { my $found_comma = (); $ele = $$wl_ref[$index]; $found_comma = chop($ele) if ($ele =~ /.*,$/); print " "; if ($#$wl_ref >= 3) { &colorize(\@src_port_color_set) if ($$wl_ref[$index - 2] eq "port" && $$wl_ref[$index - 3] eq "Source"); &colorize(\@dst_port_color_set) if ($$wl_ref[$index - 2] eq "port" && $$wl_ref[$index - 3] eq "Destination"); &colorize(\@src_ip_color_set) if (($$wl_ref[$index - 2] eq "address" && $$wl_ref[$index - 3] eq "Source") && $ele ne "="); &colorize(\@dst_ip_color_set) if (($$wl_ref[$index - 2] eq "address" && $$wl_ref[$index - 3] eq "Destination") && $ele ne "="); } if ($#$wl_ref >= 4) { &colorize(\@src_ip_color_set) if ($$wl_ref[$index - 3] eq "address" && $$wl_ref[$index - 4] eq "Source"); &colorize(\@dst_ip_color_set) if ($$wl_ref[$index - 3] eq "address" && $$wl_ref[$index - 4] eq "Destination"); } &colorize(\@time_color_set) if ($ele =~ /$dt_timestamp_re/); &colorize(\@mac_addr_color_set) if ($ele =~ /$mac_addr_re/); print "$ele"; &colorize(\@default_color_set); print "," if defined($found_comma); } print "\n"; } # tcpdump (works w/ some of snoop too) functions sub new_hex () { my $wrk_line = $_[0]; my $preamble = (); my $lhs_hex_chunk = (); my $rhs_hex_chunk = (); my @lhs_hex_array = (); my @rhs_hex_array = (); my $padding = (); my $index = (); my $wl_re = (); my $l_ele = (); my $r_ele = (); &debug_msg("Called: new_hex (tcpdump/snoop)\n") if $opt_Debug; # fixme: # 0: 00b0 d078 9de8 0800 20f2 8996 0800 4510 ...x............ # 16: 0264 2592 4000 ff06 f934 ac14 014b ac14 .d%.@....4...K.. # 32: 0149 0016 04c6 3dbd 3cdb 5a9f 3db0 8018 .I....=.<.Z.=... # 48: 2798 cc85 0000 0101 080a 0978 0b13 002a '..........x...* # 64: 50b4 0000 0209 5a86 1d43 e8aa 1a91 595b P.....Z..C....Y[ # 80: 0c7b 3fb0 06c5 9694 b6b0 5f11 3353 3e84 .{?......._.3S>. # 96: a0d8 f207 1333 bb2f 61b6 7757 9583 430e .....3./a.wW..C. # 112: ad95 88ed b0bc 39f6 28a6 fde2 66fe ecfe ......9.(...f... # 128: cf35 9e21 cbaa b4d7 9656 12f4 8278 a91c .5.!.....V...x.. # 144: 59ff 2b44 3217 0b23 7a9d 336e 7b33 625a Y.+D2..#z.3n{3bZ # 160: 0f23 370c 835b 29c4 dddc f44a 8829 f8c0 .#7..[)....J.).. # 176: 2beb 4ec8 b357 4f78 17d7 97d8 9401 c415 +.N..WOx........ # 192: 7823 e194 68a6 c187 c8be e4d6 e552 10bc x#..h........R.. # 208: b7d1 7d09 6a6c b081 b4e0 f66e 41b9 76c6 ..}.jl.....nA.v. # 224: f1b3 572a 6683 8a85 574c ead7 da0a eb37 ..W*f...WL.....7 # 240: 124e 1b43 84e1 c9fa a30a 461f f359 b61e .N.C......F..Y.. # 256: ff9a 060a 20ee ef41 251e 7451 153e 292b .......%..Q..)+ # 272: 2b20 30fa fcee 3428 4369 395a d51c 4b27 +0....(Ci9Z...' # 288: c5ba 6124 ded6 8620 b515 f1ad 63f2 209d ..a$..........Use of uninitialized value in string ge at ./snifob line 848, line 2632. #.. # 304: 7559 7a44 94b3 3a67 6c5d 7074 5554 cbea uYzD..:gl]ptUT.. # 320: 3f90 1704 a3bc 62c5 7455 edb5 fcfc 3e38 ?.....b.tU....>8 # 336: 1979 187b 76a1 1916 26fa 3387 dac7 1153 .y.{v...&.3....S # 352: 1447 f447 4d34 a3f1 14ed 39cf 43e8 36ec .G.GM4....9.C.6. # 368: 7e4f 9761 83a9 e707 9d7a f3fc 8697 7b31 ~O.a.....z....{1 # 384: 60b2 1137 88ad d3bb a1fb 39c1 d960 4ccc `..7......9..`L. # 400: c39a dce0 39fd 7f18 8feb f2fa b0d3 b348 ....9..........H # 416: 5d17 e412 316a 514c 522c 4eff ea0b 44af ]...1jQLR,N...D. # 432: 51f8 8aca 2b73 2c03 8dd3 12cd bcb1 2f8b Q...+s,......./. # 448: 597e 6a29 ccbb 3991 e30a ffa8 f33f 0310 Y~j)..9......?.. # 464: 0bb8 3153 5752 2220 b612 7574 b278 3c9c ..1SWR"...t..<.. # 480: 0159 bdf6 d9f4 592d b544 aabf eccf 1dc3 .Y....Y-.D...... # 496: ff9c 839e 3806 6282 5603 3541 78c2 5fc7 ....8.b.V.5Ax._. # 512: 0faf bfad 7146 b9cd e5fd 4815 fa03 562d ....qF....H...V- # 528: 1a6d 75e5 e248 20a6 7a1f 7c96 8094 4175 .mu..H........u # 544: a4dc 4fb7 94db ab8c bcd7 7929 885d d8ba ..O.......y).].. # 560: 97ea 962e 3385 db9f 3327 e541 2293 df64 ....3...3'.A"..d # 576: 3e89 c064 59c5 ad28 9e41 c935 6fee df80 >..dY..(.A.5o... # 592: f8b5 6a53 8375 0000 0012 525e c73c 75d7 ..jS.u....R^. 31) && ($byte < 127)){ &colorize(\@hex_p_color_set); print chr($byte); &colorize(\@default_color_set); } else { # note that '.' is == to 2e in hex, so if you # see a '.' with a 2e below it really is '.' &colorize(\@hex_np_color_set); print "."; &colorize(\@default_color_set); } } else { print chr($byte); } print " "; if ($space == 2) { $space = 0; print " "; } $space++; } } print "\n$wrk_line\n"; } sub smb_hex () { my $wrk_line = $_[0]; my $preamble = (); my $lhs_hex_chunk = (); my $rhs_hex_chunk = (); my @lhs_hex_array = (); my @rhs_hex_array = (); my $padding = (); my $index = (); my $wl_re = (); my $l_ele = (); my $r_ele = (); &debug_msg("Called: smb_hex (tcpdump)\n") if $opt_Debug; $wl_re = '^(\[[\dA-Fa-f]+\]\s)((([A-Fa-f\d]{2}\s{1,2}){1,15})?([A-Fa-f\d]{2}))(\s{1,48})(.{1,8}(\s.{1,8})?)'; if ($wrk_line =~ /$wl_re/) { $preamble = $1; $lhs_hex_chunk = $2; $rhs_hex_chunk = $7; $padding = $6; } $lhs_hex_chunk =~ s/ / /; @lhs_hex_array = split(/\ /, $lhs_hex_chunk); @rhs_hex_array = split(/ */, $rhs_hex_chunk); print "$preamble"; $index = 0; foreach $l_ele (@lhs_hex_array) { if ( uc($l_ele) ge "20" && uc($l_ele) le "7E") { &colorize(\@hex_p_color_set); print "$l_ele"; &colorize(\@default_color_set); } else { &colorize(\@hex_np_color_set); print "$l_ele"; $rhs_hex_array[$index] = "\0"; } if ($index < $#lhs_hex_array) { print " "; if (($index + 1) % 8 == 0) { print " "; } } $index++; } print $padding; $index = 0; foreach $r_ele (@rhs_hex_array) { if ( $r_ele ge " " && $r_ele le "~") { &colorize(\@hex_p_color_set); print "$r_ele"; &colorize(\@default_color_set); } else { &colorize(\@hex_np_color_set); print "."; } print " " if ($index == 7); $index++; } &colorize(\@default_color_set); print "\n"; } sub time_info_line() { my $wrk_line = $_[0]; my @wrk_line_array = (); my $time = (); &debug_msg("Called: time_info_line (tcpdump)\n") if $opt_Debug; @wrk_line_array = split("\ ", $wrk_line); $time = shift(@wrk_line_array); &colorize(\@time_color_set); print "$time"; &colorize(\@default_color_set); &process_rest_of_line(\@wrk_line_array); } sub addr_info_line() { my $wrk_line = $_[0]; my @wrk_line_array = (); my $addr = (); my $colon_found = (); &debug_msg("Called: addr_info_line (tcpdump)\n") if $opt_Debug; @wrk_line_array = split("\ ", $wrk_line); $addr = shift(@wrk_line_array); &colorize(\@src_ip_color_set); print "$addr"; &colorize(\@default_color_set); &process_rest_of_line(\@wrk_line_array); } sub addr_port_info_line() { my $wrk_line = $_[0]; my @wrk_line_array = (); my $addr_port = (); my $addr = (); my $port = (); my $colon_found = (); &debug_msg("Called: addr_port_info_line (tcpdump)\n") if $opt_Debug; @wrk_line_array = split("\ ", $wrk_line); $addr_port = shift(@wrk_line_array); ($addr, $port) = &proc_addr_port(\$addr_port); if (!defined($addr) && !defined($port)) { return (0); } &colorize(\@src_ip_color_set); print "$addr"; &colorize(\@default_color_set); print "."; &colorize(\@src_port_color_set); print "$port"; &colorize(\@default_color_set); &process_rest_of_line(\@wrk_line_array); return(1); } sub arp_info_line() { my $wrk_line = $_[0]; my @wrk_line_array = (); my $first_arp_ele = (); &debug_msg("Called: arp_info_line (tcpdump)\n") if $opt_Debug; @wrk_line_array = split("\ ", $wrk_line); $first_arp_ele = shift(@wrk_line_array); print "$first_arp_ele"; &process_rest_of_line(\@wrk_line_array); } sub mac_info_line() { my $wrk_line = $_[0]; my @wrk_line_array = (); my $mac_addr = (); &debug_msg("Called: mac_info_line (tcpdump)\n") if $opt_Debug; @wrk_line_array = split("\ ", $wrk_line); $mac_addr = shift(@wrk_line_array); &colorize(\@mac_addr_color_set); print "$mac_addr"; &colorize(\@default_color_set); &process_rest_of_line(\@wrk_line_array); } sub proc_addr_port() { my $addr_port_ref = $_[0]; my @addr_port_rev = (); my $lport = (); my $laddr = (); &debug_msg("Called: proc_addr_port\n") if $opt_Debug; @addr_port_rev = split(/\./, reverse($$addr_port_ref)); $lport = reverse(shift (@addr_port_rev)); $laddr = reverse(join('.', @addr_port_rev)); if ($lport =~ /[A-Za-z_-]+/) { if ( ! defined(getservbyname("$lport", "tcp")) && ! defined(getservbyname("$lport", "udp")) ) { $lport = (); $laddr = (); } } return ($laddr, $lport); } sub process_rest_of_line() { my $wrk_line_array_ref = $_[0]; my $index = 0; my $curr_victim = (); &debug_msg("Called: process_rest_of_line (tcpdump)\n") if $opt_Debug; for($index = 0; $index <= $#$wrk_line_array_ref; $index++) { my $did_print = 0; my $look_forward = 0; my $look_backward = 0; my $continue = 0; $curr_victim = $$wrk_line_array_ref[$index]; # addrs w/ ports $look_backward = 1 if ($index > 0); $look_forward = 1 if ($index < $#$wrk_line_array_ref); # fixme: # think about look forward/backward issue #one.area.com > home3: icmp: echo replyUse of uninitialized value at ./snifob line 1046, chunk 85. # (DF) #crux.domain > home3.1024: 18535* 1/2/2 (164) #home3 > one.area.com icmp: echo request #one.area.com > home3: icmp: echo replyUse of uninitialized value at ./snifob line 1046, chunk 88. # (DF) #home3 > one.area.com icmp: echo request #one.area.com > home3: icmp: echo replyUse of uninitialized value at ./snifob line 1046, chunk 90. # (DF) # $look_forward = 0 if ($index == $#$wrk_line_array_ref); if ($continue == 0 && $look_backward) { $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq ">"); $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "->"); $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "who-has" && ( $$wrk_line_array_ref[$index + 1] eq "tell" || $$wrk_line_array_ref[$index + 2] eq "tell" ) ); $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "tell" && ( $$wrk_line_array_ref[$index - 3] eq "who-has" || $$wrk_line_array_ref[$index - 4] eq "who-has" ) ); $continue = 1 if ($$wrk_line_array_ref[$index - 1] eq "reply" && $$wrk_line_array_ref[$index + 1] eq "is-at"); } if ($continue == 0 && $look_forward) { $continue = 1 if ($$wrk_line_array_ref[$index + 1] eq ">"); $continue = 1 if ($$wrk_line_array_ref[$index + 1] eq "->"); } if ($did_print == 0) { if ( $continue && ( ($curr_victim =~ /$num_ip_addr_re\.($num_port_re|$alphnum_port_re):?$/) || ($curr_victim =~ /$fqdn_re\.($num_port_re|$alphnum_port_re):?$/) || ($curr_victim =~ /$hostname_re\.($num_port_re|$alphnum_port_re):?$/) ) ) { my $colon_found = (); my $addr = (); my $port = (); ($curr_victim, $colon_found) = &was_there_colon($curr_victim); ($addr, $port) = &proc_addr_port(\$curr_victim); if (defined($addr) && defined($port)) { if ( $$wrk_line_array_ref[$index-1] eq ">" || $$wrk_line_array_ref[$index-1] eq "->" ) { &colorize(\@dst_ip_color_set); print " $addr"; &colorize(\@default_color_set); print "."; &colorize(\@dst_port_color_set); print "$port"; } else { &colorize(\@src_ip_color_set); print " $addr"; &colorize(\@default_color_set); print "."; &colorize(\@src_port_color_set); print "$port"; } &colorize(\@default_color_set); if ($colon_found) { print ":"; $colon_found = 0; } $did_print = 1; $continue = 0; } } } # addrs w/o ports if ($did_print == 0) { if ( $continue && ( ($curr_victim =~ /^$num_ip_addr_re:?$/) || ($curr_victim =~ /^$fqdn_re:?$/) || ($curr_victim =~ /$hostname_re:?$/) ) ) { my $colon_found = (); ($curr_victim, $colon_found) = &was_there_colon($curr_victim); if ( $$wrk_line_array_ref[$index-1] eq "->" || $$wrk_line_array_ref[$index-1] eq ">" || $$wrk_line_array_ref[$index-1] eq "who-has" ) { &colorize(\@dst_ip_color_set); } else { &colorize(\@src_ip_color_set); } print " $curr_victim"; &colorize(\@default_color_set); if ($colon_found) { print ":"; $colon_found = 0; } $did_print = 1; $continue = 0; } } # ports, snoop style if ($did_print == 0) { if ($curr_victim =~ /(D|S|port)=($num_port_re)/ && ( ($$wrk_line_array_ref[$index-1] eq "TCP" || $$wrk_line_array_ref[$index-2] eq "TCP" ) || ($$wrk_line_array_ref[$index-1] eq "UDP" || $$wrk_line_array_ref[$index-2] eq "UDP" ) ) ) { print " $1="; &colorize(\@dst_ip_color_set) if ($1 eq "D"); &colorize(\@src_ip_color_set) if ($1 eq "S" || $1 eq "port"); print "$2"; &colorize(\@default_color_set); $did_print = 1; } } # mac addrs if ($did_print == 0) { if ($curr_victim =~ /$mac_addr_re/) { print " "; &colorize(\@mac_addr_color_set); print "$curr_victim"; &colorize(\@default_color_set); $did_print = 1; } } if (! $did_print) { print " $curr_victim"; } else { $did_print = 0; } } print "\n"; } sub was_there_colon() { my $dotted_tuple = $_[0]; &debug_msg("Called: was_there_colon\n") if $opt_Debug; if ($dotted_tuple =~ /.*:$/) { chop($dotted_tuple); return ($dotted_tuple, 1); } else { return ($dotted_tuple, 0); } } # support functions sub sig_exit_cleanup_handler() { $SIG{INT} = \&sig_exit_cleanup_handler; $SIG{QUIT} = \&sig_exit_cleanup_handler; &reset_ansi(); if ($using_snifoutfh) { close(SNIFOUTFH); } exit; } sub sig_stop_cleanup_handler() { $SIG{STOP} = \&sig_stop_cleanup_handler; &reset_ansi; } sub multi_chomp () { my $temp_line = $_[0]; &debug_msg("Called: multichomp\n") if $opt_Debug; $temp_line =~ s/$eol$//; return $temp_line; } sub colorize() { my $color_set_ref = $_[0]; my $setInt = $$color_set_ref[0]; my $setFg = $$color_set_ref[1]; my $setBg = $$color_set_ref[2]; &debug_msg("Called: colorize with colors @$color_set_ref\n") if (defined($opt_Debug) && $opt_Debug == 5); if (! $opt_Nocolor) { printf ("%s%d;%d;%dm", $escape, $intensity{$setInt}, $foreground{$setFg}, $background{$setBg}); } } sub reset_ansi() { &debug_msg("Called: reset_ansi\n") if $opt_Debug; print $escape . $reset; } sub debug_msg() { my $message = $_[0]; print "\nd: $opt_Debug -- $message\n"; } __END__ =head1 NAME snifob - sniffer output beautifier =head1 SYNOPSIS snifob [OPTION] =head1 DESCRIPTION snifob colorizes snort and tcpdump output to make the output easier to read. It will also de-hexify tcpdump -x output. --help show help output --nocolor do not colorize output --nodecode do not de-hexify tcpdump -x output --run run "$sniffer" with options "$sniffer_options" and markup stdout (doesn't dump packet payload) --drun run "$sniffer_dump" with options "$sniffer_options_dump" and markup stdout (dumps packet payload) --debug outputs debugging info, can range from 1-5 where 5 is very verbose The user can change the execution of snifob by setting the following variables inside the section marked: ## begin user configurable $sniffer - sets the sniffer that the --run option uses $sniffer_options - sets the options for the sniffer used by --run # the following should include an option or options to dump # the packet payload $sniffer_dump - sets the sniffer that the --drun option uses $sniffer_options _dump - sets the options for the sniffer used by --drun @default_color_set - the default color set that is used when snifob isn't highlighting output There are other color sets available for configuration in this section as well. the syntax for a color set is: @default_color_set = (, , ); the supported intensities are: bright dark the supported background and foreground colors are: black red green yellow blue magenta cyan white To use snort with snifob, you need to patch snort with the diff found at: http://www.nosneros.net/hso/programs/snifob/download/snort-1.7.line.buffered.patch After applying the patch snort 1.7, run ./configure with what ever options you deem appropriate and then make && make install. You might need to delete config.cache and config.status before running ./configure. =head1 AUTHOR snifob was written by Holt Sorenson =head1 BUGS/ISSUES/Reasons snifob needs a therapist -C is not supported when using snort This probably won't change any time soon because I have been unable to figure out a way to match the lines which are basically arbitrary text that can be up to 64 characters long, and include spaces (If spaces weren't included I could conceivably do something like [^ ] && (ch > "!" && ch <= "~"). -V is not supported with snoop because I have not finished it tcpdump (and possibly others) display . instead of a space, so if you seen a bright green (default printable ascii color) you should check to see if the . corresponds to 2e which is actually a period. I might add a switch to allow users to toggle this behavior. =head1 SEE ALSO snort(8), tcpdump(1), perl(1p) http://www.snort.org http://www.tcpdump.org A word about Snort -- I don't mean to imply that Snort is just a sniffer, per say. It has the ability to display information about packets near real time from the command line. However, Snort is a [free] "lightweight network intrusion detection system, capable of performing real-time traffic analysis and packet logging on IP networks. It can perform protocol analysis, content searching/matching and can be used to detect a variety of attacks and probes, such as buffer overflows, stealth port scans, CGI attacks, SMB probes, OS fingerprinting attempts, and much more." If you're interested in using Snort, go to the URL above, it comes with many recommendations. If you're developing in perl, I highly recommend using the Devel-ptkdb module authored by Andrew E. Page You can acquire it at: http://www.cpan.org/modules/by-category/03_Development_Support/Devel/ =head1 ACKNOWLEDGEMENTS gnash for the idea, amholder for the query "why are you using tcpdump? snort has better payload display.", dR. drewenstein for harrassing me about the multiple possibilities of tcpdump output that I wasn't accounting for, and especially to family for putting up with the hands that are seemingly welded to computers. =head1 COPYRIGHT Copyright 2000, Holt Sorenson , All Rights Reserved. This program is licensed under the provisions of the Artistic license as enumerated at: http://www.nosneros.net/hso/programs/licenses/artistic-license.html There are a couple additional quid pro quos: -By downloading or otherwise acquiring snifob you agree to the terms of the license and these quid pro quos. -Any legal or arbitration issues are settled in the current physical locale of the author. -The author retains the right to change the license snifob is made available under. If the author does change the license, the change will apply to that version, and versions later released under the same license. The author commits to keeping the license liberal and available to use for netizens. This is not a requirement, but if snifob is helpful and you use it often, I would like to here from you. If you use it outside of your personal life, I'd like to know where you use it. I ask this out of curiousity, not to track usage for compensation, or some other strange reason. The most current version of snifob can be found at: http://www.nosneros.net/hso/programs/snifob/