📄 find_scanners
字号:
#!/usr/bin/perl -w## Copyright (c) 2001# The Regents of the University of Minnesota. All rights reserved.### This code is inspired and partially derived from the find_random_http# script posted to the flowtools email list on Aug 1, 2001 by Dave Plonka.# I owe him much for making this script possible. -Paul Dokas### Redistribution and use in source and binary forms, with or without# modification, are permitted provided that the following conditions# are met:# 1. Redistributions of source code must retain the above copyright# notice, this list of conditions and the following disclaimer.# 2. Redistributions in binary form must reproduce the above copyright# notice, this list of conditions and the following disclaimer in the# documentation and/or other materials provided with the distribution.# 3. All advertising materials mentioning features or use of this software# must display the following acknowledgement:# This product includes software developed by the University of# Minnesota and its contributors.# 4. Neither the name of the University nor the names of its contributors# may be used to endorse or promote products derived from this software# without specific prior written permission.## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS# OR SERVICES; 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.### $Id: find_scanners,v 1.7 2001/11/28 20:36:40 dokas Exp $############################################################################ This script is meant, more or less as a replacement for the very long# string of piped commands involving flow-cat, flow-stat, awk and sort# that I'd been using to analyze my border flows. I wanted to be able# to see a list of IP addresses sorted by bandwidth, flows or number of# packets and the services that were being used in one relatively small# format.## The following are examples of how I run this script on the flows that# I collect with the OSU flow-tools:## Show the source IP addresses for the top 20 outbound bandwidth# consumers and show the top 7 source and destination ports for the# 10 minute period ending at 08:30 on 11/26/2001:## find_scanners -S -o -b 20 -s 7 -d 7 cf05.2001-11-26.083001 | less### Show the destination IP addresses for the top 10 inbound flow consumers# and show the top 7 source and destination ports for the 10 minute# period ending at 08:30 on 11/26/2001:## find_scanners -D -i -f 20 -s 7 -d 7 cf05.2001-11-26.083001 | less### I find this script particularly helpful when I'm trying to figure out# what created all of those spikes in my FlowScan graphs. DOS attacks# are usually *really* easy to identify with this script.## And finally, be warned that this script can consume a *LOT* of memory.# I collect flows at about 1.1 Mflows/10 minutes or about 1.8Kflows/sec# and this script routinely uses around 500MBytes of memory when chewing# on just 10 minutes worth of flows.############################################################################ To use this script, you'll need to install the following Perl modules:## Net::Patricia# http://net.doit.wisc.edu/~plonka/Net-Patricia/# or as found on CPAN## Cflow# http://net.doit.wisc.edu/~plonka/Cflow/### And, to get the Cflow module working, you'll need to be collecting flows# with one of the following:### CAIDA's cflowd 2.x by Daniel McRobb (with Cisco's NetFlow v5):# http://www.caida.org/tools/measurement/cflowd/# http://net.doit.wisc.edu/~plonka/cflowd/# # flow-tools by Mark Fullmer (with NetFlow v1, v5, v6, or v7):# http://www.splintered.net/sw/flow-tools/## lfapd by Steve Premeau (with Riverstone's LFAPv4):## http://www.nmops.org/############################################################################ Please send all bug fixes or enhancements to dokas@cs.umn.edu##########################################################################use strict;use POSIX;use Getopt::Std;use Cflow qw(:flowvars :tcpflags :icmptypes :icmpcodes 1.028);use Net::Patricia;use IO::File;use Socket; # for inet_ntoa## Initialization## Place your networks here## E.G.# 10.0.0.0/8# 192.168.0.0/16# 172.16.0.0/12my @MY_NETS = qw();## Known services not necessarily in /etc/services.# You can also override /etc/services here.#my %KNOWN_SERVICES = ( kazaa => \&kazaa, gnutella => \&gnutella, hotline => \&hotline, ntp => \&ntp, ftp => \&ftp, http => \&http, dns => \&dns);my $insuspect = new Net::Patricia;die unless ref($insuspect);my $outsuspect = new Net::Patricia;die unless ref($outsuspect);my $net = new Net::Patricia;die unless ref($net);if ($#MY_NETS == -1) { print("You need to put your networks into the @MY_NETS variable.\n"); print("Edit the source and add your networks to the @MY_NETS variable at line 138.\n"); exit(0); }foreach (@MY_NETS) { $net->add_string($_) }## Globals#my $nfiles = 0;my $all_flows = 0;my $all_pkts = 0;my $all_bytes = 0;my %protocol_cache = ( 1 => 'icmp', 6 => 'tcp', 17 => 'udp', 47 => 'gre', 50 => 'esp', 51 => 'ah', );my %service_cache = ( '412/6' => 'NeoModus', '1214/6' => 'KaZaA', '2340/6' => 'CuteMX', '4661/6' => 'eDonkey2000', '4662/6' => 'eDonkey2000', '5190/6' => 'AIM', '5501/6' => 'HotLine', '5502/6' => 'HotLine', '6257/17' => 'WinMX', '6346/6' => 'Gnutella', '6347/6' => 'Gnutella', '6699/6' => 'WinMX', '12345/6' => 'NetBus', '12346/6' => 'NetBus', '27015/17' => 'HalfLife', '27374/6' => 'SubSeven', '31337/6' => 'Elite', );#our $filter_sub = \&kazaa;our $filter_sub = undef;## Global command line arguments#our $opt_h = 0;our $opt_x = 0;our $opt_n = 0;our $opt_S = 0;our $opt_D = 0;our $opt_c = 0;our $opt_f = 0;our $opt_p = 0;our $opt_b = 0;our $opt_o = 0;our $opt_i = 0;our $opt_s = 0;our $opt_d = 0;our $opt_F = "";## Parse command line arguments#if (!getopts('hxnSDc:f:p:b:ios:d:F:') || $opt_h ) { usage("find_scanners"); }## make sure the arguments are sane and set defaults as necessary#$opt_S = 1 if ($opt_S == 0 && $opt_D == 0);usage("find_scanners") if ($opt_S != 0 && $opt_D != 0);$opt_c = 10 if ($opt_c == 0 && $opt_f == 0 && $opt_p == 0 && $opt_b == 0);usage("find_scanners") if (($opt_c != 0) && ($opt_f != 0 || $opt_p != 0 || $opt_b != 0));usage("find_scanners") if (($opt_f != 0) && ($opt_c != 0 || $opt_p != 0 || $opt_b != 0));usage("find_scanners") if (($opt_p != 0) && ($opt_c != 0 || $opt_f != 0 || $opt_b != 0));usage("find_scanners") if (($opt_b != 0) && ($opt_c != 0 || $opt_f != 0 || $opt_p != 0));$opt_i = 1 if ($opt_o == 0 && $opt_i == 0);$opt_d = 10 if ($opt_s == 0 && $opt_d == 0);if ($opt_F ne "") { $filter_sub = eval("sub { if (".$opt_F.") { return 1; } else { return 0; } }") or die("Error compiling filter"); }## actually cut the flows#print("Cutting flows...\n") if ($opt_x);Cflow::verbose(1);Cflow::find(\&do_flow, \&do_file, (-1 != $#ARGV) ? @ARGV : '-');print("Done cutting flows.\n") if ($opt_x);###if ($opt_o) { my @top = (); find_top($insuspect, \@top); if ($opt_c > 0) { print("\n"); print("----------------------------------------\n"); print("Top outbound hosts by hosts counted\n"); print("----------------------------------------\n"); print_top($insuspect, \&ip_by_count, \&port_by_flows, $opt_c, \@top); } if ($opt_f > 0) { print("\n"); print("----------------------------------------\n"); print("Top outbound hosts by flows\n"); print("----------------------------------------\n"); print_top($insuspect, \&ip_by_flows, \&port_by_flows, $opt_f, \@top); } if ($opt_p > 0) { print("\n"); print("----------------------------------------\n"); print("Top outbound hosts by packets\n"); print("----------------------------------------\n"); print_top($insuspect, \&ip_by_pkts, \&port_by_pkts, $opt_p, \@top); } if ($opt_b > 0) { print("\n"); print("----------------------------------------\n"); print("Top outbound hosts by bandwidth\n"); print("----------------------------------------\n"); print_top($insuspect, \&ip_by_bytes, \&port_by_bytes, $opt_b, \@top); } }###if ($opt_i) { my @top = (); find_top($outsuspect, \@top); if ($opt_c > 0) { print("\n"); print("----------------------------------------\n"); print("Top inbound hosts by hosts counted\n"); print("----------------------------------------\n"); print_top($outsuspect, \&ip_by_count, \&port_by_flows, $opt_c, \@top); } if ($opt_f > 0) { print("\n"); print("----------------------------------------\n"); print("Top inbound hosts by flows\n"); print("----------------------------------------\n"); print_top($outsuspect, \&ip_by_flows, \&port_by_flows, $opt_f, \@top); } if ($opt_p > 0) { print("\n"); print("----------------------------------------\n"); print("Top inbound hosts by packets\n"); print("----------------------------------------\n"); print_top($outsuspect, \&ip_by_pkts, \&port_by_pkts, $opt_p, \@top); } if ($opt_b > 0) { print("\n"); print("----------------------------------------\n"); print("Top inbound hosts by bandwidth\n"); print("----------------------------------------\n"); print_top($outsuspect, \&ip_by_bytes, \&port_by_bytes, $opt_b, \@top); } }exit(0);###sub do_file{ my $fname = shift; print(">>> Cutting $fname\n"); $nfiles++;}###sub add_flow{ my $suspectdb = shift; my $addr1 = shift; my $ip1 = inet_ntoa(pack("N", $addr1)); my $port1 = shift; my $addr2 = shift; my $ip2 = inet_ntoa(pack("N", $addr2)); my $port2 = shift; my $scanner; print("$protocol\t$ip1 $port1\t$ip2 $port2\n") if ($opt_x); if ($scanner = $suspectdb->match_integer($addr1)) { my $victim; # # tally protocol/port pairs. # $scanner->{dstprotocolport}->{$protocol."-".$dstport}->{flows}++; $scanner->{dstprotocolport}->{$protocol."-".$dstport}->{pkts} += $pkts; $scanner->{dstprotocolport}->{$protocol."-".$dstport}->{bytes} += $bytes; $srcport = $dstport if ($protocol == 1); $scanner->{srcprotocolport}->{$protocol."-".$srcport}->{flows}++; $scanner->{srcprotocolport}->{$protocol."-".$srcport}->{pkts} += $pkts; $scanner->{srcprotocolport}->{$protocol."-".$srcport}->{bytes} += $bytes; # # Earlier start time? # $scanner->{startime} = $startime if ($scanner->{startime} > $startime); # # Later end time? # $scanner->{endtime} = $endtime if ($scanner->{endtime} < $endtime); # # # $victim = $scanner->{remote}->match_integer($addr2); if (! defined($victim)) { $victim = $scanner->{remote}->add_string($ip2, { flows => 1, pkts => $pkts, bytes => $bytes }); } else { $victim->{flows}++; $victim->{pkts} += $pkts; $victim->{bytes} += $bytes; } } else { $scanner = $suspectdb->add_string($ip1, { startime => $startime, endtime => $endtime, addr => $addr1, remote => new Net::Patricia }); $scanner->{remote}->add_string($ip2, { flows => 1, pkts => $pkts, bytes => $bytes, }); if ($opt_s) { $srcport = $dstport if ($protocol == 1); $scanner->{srcprotocolport}->{$protocol."-".$srcport} = { flows => 1, pkts => $pkts, bytes => $bytes } } if ($opt_d) { $scanner->{dstprotocolport}->{$protocol."-".$dstport} = { flows => 1, pkts => $pkts, bytes => $bytes } } }}###sub do_flow{ my ($addr1, $port1); my ($addr2, $port2); print("do_flow()\n") if ($opt_x); # # # $all_flows++; $all_pkts += $pkts; $all_bytes += $bytes; # # # if ($opt_S) { $addr1 = $srcaddr; $port1 = $srcport; $addr2 = $dstaddr; $port2 = $dstport; } elsif ($opt_D) { $addr1 = $dstaddr; $port1 = $dstport; $addr2 = $srcaddr; $port2 = $srcport; } # # # if (($opt_o) and ($net->match_integer($srcaddr))) { if ($opt_F ne "") { return(0) if (! &$filter_sub()); } add_flow($insuspect, $addr1, $port1, $addr2, $port2); } # # # elsif (($opt_i) and (! $net->match_integer($srcaddr))) { if ($opt_F ne "") { return(0) if (! &$filter_sub()); } add_flow($outsuspect, $addr1, $port1, $addr2, $port2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -