sl0scan (ambiguous source portscanner)

From: miff (miffat_private)
Date: Tue Feb 09 1999 - 17:53:34 PST

  • Next message: Ambrose Feinstein: "Re: Pine _again_ :)"

    --YiEDa0DAkWCtVeE4
    Content-Type: text/plain; charset=us-ascii
    
    hello all,
    
    I hear that maybe nmap does something similar to this, but I'm posting it anyway to see if there is enough interest for me to continue developing it.  This is based on some code that I have been evolving for a while now.
    
    sl0scan features:
    - you select which ports to scan using comma separated lists and ranges at runtime
    - *identical* scans sent from as many hosts as you like
    - random generation of dummy hosts, or it can read a file of desired fake scanning sources (or both).
    - choose at what sequence to insert the real scan (say, #500 out of 1000 scans)
    - status shown on screen
    
    also:
    - written in easily modifiable perl;  all packet components are in variables
    
    sl0scan drawbacks:
    - you have to sniff the response.  This really isnt so bad;  you just do "tcpdump src <scantarget>" in a seperate window and look for the big "R" or "S" from each port.  (S means the port was open).  If there is interest, I'll fold in the packet capture function in the next release.
    - it can be slow depending on how you use it
    - tcp only at this release
    
    
    
    
    
    
    
    --YiEDa0DAkWCtVeE4
    Content-Type: text/plain; charset=us-ascii
    Content-Disposition: attachment; filename=sl0scan
    
    #!/usr/bin/perl
    #
    #  sl0scan v0.1
    #   perl spoofer/scanner
    #   based on lego
    #
    #  written by miff  Jan 1999
    #
    #  i wrote this in response to all the
    #  email i got from lego saying:
    #  "i'm not getting a response from the
    #  portscan!!&^@#$"
    #
    #  this version requests the following:
    #	- which ports to scan
    #	- how many fake hosts to use
    #	- the "real" ip (any sniffable ip)
    #	- an optional file of "real" fakes
    #	- when to insert the real scan
    #
    #  you are responsible for sniffing the response,
    #  at this point.  maybe that'll be automatic
    #  in the future.
    #
    # shouts:  b_, X, kubiak, shinex, xyg, ReDragon, #9mm
    #  also:  Clovis  (where ya at h0mez?)
    #
    # best musical artist:  mike patton.
    #
    
    use Socket;
    use strict	qw(refs, subs);
    
    my $delay = 1;  # delay in seconds between scans.  its really important
    #		not to end up with a synflood here, that will break the
    #		scan.  use a large real fake file to avoid DoS.
    
    my $input, $dummy;
    print "Welcome to sl0scan, the slowest scanner on the net.\n";
    print "This program sends out a deluge of fake scans, and inserts \n";
    print " a real scan somewhere in between.  In this version, you \n";
    print " must fire up a sniffer and watch for the responses to \n";
    print " the real scan...  Hope you know what to look for \n";
    print "\n";
    print "ready?\n";
    $dummy = <>;
    print "good.  here's where we axe you the 5 imp0tent questi0nz:\n\n";
    print "1.)  what is the IP ADDY or HOSTNAME of the target? \n";
    $input = <>;
    chop $input;
    $target_box = $input;
    print "got $input.\n\n\n";
    print "2.)  what be the true source of the scan? (any sniffable ip will do) \n";
    $input = <>;
    chop $input;
    $true_source = $input;
    print "got $input.\n\n\n";
    print "3.)  how many fakes should we dump on this homies fro? \n";
    print "note:  number of fakes will directly affect the sl0ness of the scan\n";
    print " to the tune of at least 1 second per host.  we don wanna dos here.. \n";
    print " otoh, lots of fakes increase your invisibility \n";
    $input = <>;
    chop $input;
    $num_fakes = $input;
    print "got $input.  <-- hope that was a number...\n\n\n";
    print "4.)  which ports should we check?  (IMPORTANT) \n";
    print " i recommend as few as possible, as this will *really* slow shit down\n";
    print "enter ports in the following format:  COMMA DELIMITED, indicate ranges with dash\n";
    print " example:  i want to scan ports 22 23 25 80 and 130-140.  i say: \n";
    print "22,23,25,80,130-140\n";
    print "avoid spaces and extra shit.  save that for another time. \n";
    $input = <>;
    chop $input;
    $portlist = $input;
    print "got $input. <-- if you screwed that up, bad shit is gonna happen.\n\n\n";
    print "5.)  At what sequence would you like the real scan inserted? \n";
    print "note:  this number must be <= the total number of fakes...\n";
    $input = <>;
    chop $input;
    $real_seq = $input;
    $real_seq--;  #gotta decrement; we start wit 0
    print "got $input.  <-- hope that was a number...\n\n\n";
    print "6.)  ok last one.  Would you like to use a file of desired fakes?\n";
    print "this gives you the advantage of choosing the fake ips, and \n";
    print "avoiding the situation that all of the fake scans came from \n";
    print "non-existent ips.  i'd recommend using a large file here \n\n";
    print "also, if you use all fake ips, even with the one second delay, \n";
    print "you stand a greater chance of DOS'ing the target.  which is bad.\n\n";
    print "fyi, the format for the file is 1 ip or hostname per line, no extra shit. \n\n";
    print " IF YOU WANT TO USE SUCH A FILE, enter the filename here:\n";
    $input = <>;
    chop $input;
    $frofile = $input;
    print "got $input.  <-- hope that was a real file...\n\n\n";
    print "OK FOO, WE READY.  YOU READY?\n";
    $dummy = <>;
    
    my @frobobs;
    my $frocount = -1;
    # ok, first order of bidniss:  lets get that file open if it exists:
    if ($frofile ne '') {
      if (-e $frofile) {
    	#we got a file...
    	open (FROFILE, $frofile) || die "cant open file, kid";
    	while ($input = <FROFILE>) {
    		chop $input;
    		$frocount++;
    		@frobobs[$frocount] = $input;
    	}
    	close (FROFILE);
    	# while we're at it, lets cal the percent of total fakes:
    	$fro_percent = $frocount * 100 / $num_fakes;
      }
    }
    
    my $scancount = 0;
    my $src_box, $src_port;
    srand(time ^ $$);
    
    while ($scancount < $num_fakes) {
    	# main driver routine
    	if ($scancount == $real_seq) {
    		#this is the real deal
    		print "real scan!! (from $true_source) \n\n";
    		$src_box = $true_source;
    	} else {
    		# grab a random number between 0 and $num_fakes
    		if ($randum > $frocount) {
    			#create one
    			my $rand1 = int(rand(230)) + 20;
                            my $rand2 = int(rand(255));
                            my $rand3 = int(rand(255));
                            my $rand4 = int(rand(255));
                            $src_box = $rand1 . "." . $rand2 . "." . $rand3 . "." . $rand4;
                            #for debugging:
    			print "scan from $src_box \n";
    		} else {
    			# use the array
    			$randum = int(rand($num_fakes));
    			$src_box = @frobobs[$randum];
    			print "we gon fro from $src_box \n";
    		}
    	}
    	# now send the scan
    	sc4n($target_box,$portlist,$src_box,$fake_port);
    	
    	# now sleep to avoid DoS:
    	sleep($delay);
    
    	$scancount++;
    }
    
    
    sub sc4n  {
    	my ($dest_host,$dest_ports,$src_host,$src_port) = @_;
    
    	#print "in scan, got $dest_host,$dest_ports,$src_host,$src_port\n\n";
    
    	#set constants:
    	my ($PROTO_RAW) = 255; # from /etc/protocols
    	my ($PROTO_IP) = 0;  #ditto
    	my ($IP_HDRINCL) = 1;  #we set the ip header, thanks
    
    	#look up mah shit...
    	$dest_host = (gethostbyname($dest_host))[4];
    	$src_host = (gethostbyname($src_host))[4];
    
    	#time to open a raw socket....
    	socket(S, AF_INET, SOCK_RAW, $PROTO_RAW) || die $!;
    
    	#raw socket should be open...
    	#now set the bad boy up...
    	setsockopt(S, $PROTO_IP, $IP_HDRINCL, 1);
    
    	# here we need to interpret the port list:
    	my @ports1 = split (",",$dest_ports);
    
    	my $psplit,$rcount,$range_low,$range_hi;
    	my $p2count = 0;
    	my @ports2;
    	my @range;
    
    	foreach $psplit (@ports1) {
    		if ($psplit =~ '-') {
    			# we have a range
    			@range = split("-",$psplit);
    			$range_low = @range[0];
    			$range_hi = @range[1];
    			$rcount = $range_low;
    			while ($rcount <= $range_hi) {
    				@ports2[$p2count] = $rcount;
    				$p2count++;
    				$rcount++;
    			}
    		} else {
    			@ports2[$p2count] = $psplit;
    			$p2count++;
    		}
    	}
    
    	my $port;
    
    	foreach $port (@ports2) {
    		#build a tcp header:
    
    		#vary the ports in here...
    		$src_port = int(rand(60000));
    		
    		my ($packet) = givehead($src_host, $src_port, $dest_host, $port, $data);
    		#bust out the destination...
    		my ($dest) = pack('S n a4 x8', AF_INET, $port, $dest_host);
    		#send a fux0ring packet
    		send (S,$packet,0, $dest);
    	}
    
    }
    
    sub givehead {
    	my ($src_host, $src_port, $dest_host, $dest_port, $data) = @_;
    
    	#HERE WE PLAY WITH THE INSIDES OF THE TCP PIECE
    	#AND CALC THE TCP HDR CHECKSUM.
    	my $hdr_cksum = 0;  # we set it to 0 so we can calculate it
    	my $zero = 0;  #might need a zero from time to time
    	my $proto_tcp = 6;  # the protocol number for tcp
    	my ($tcplength) = 20; # 20 byte tcp hdr; no data
    	# IF YOU ADD DATA, MAKE SURE TO ADD ITS PACKED LENGTH
    	# TO THE TCPLENGTH HERE!!!
    	# all of the source and destination infoz is passed to us
    	# screw wit it in the parent routine...
    	my $syn = 790047533;  # random syn;  try to keep it under 32 bits :)
    	my $ack = 0;  # zero ack;  try to keep it under 32 bits :)
    	my $tcp_4bit_hdrlen = "5"; # 5 * 32bit (4 byte) = 20 bytes
    	my $tcp_4bit_reserved = 0; # reserved for 0
    	my $hdr_n_reserved = $tcp_4bit_hdrlen . $tcp_4bit_reserved;  # pack them together
    	my $tcp_urg_bit = 0;  # URGENT POINTER BIT
    	my $tcp_ack_bit = 0;  # ACKNOWLEDGEMENT FIELD BIT
    	my $tcp_psh_bit = 0;  # PUSH REQUEST BIT
    	my $tcp_rst_bit = 0;  # RST (RESET CONNXION) BIT
    	my $tcp_syn_bit = 1;  # SYN FLAG BIT  #its a syn!!
    	my $tcp_fin_bit = 0;  # FIN FLAG BIT
    	# here we put together 2 reserved fields and the 6 flags to pack as binary.
    	my $tcp_codebits = $zero . $zero . $tcp_urg_bit . $tcp_ack_bit . $tcp_psh_bit .
    		$tcp_rst_bit . $tcp_syn_bit . $tcp_fin_bit;
    	my $tcp_windowsize = 124;  # default window size
    	my $tcp_urgent_pointer = 0;  # urgent pointer
    
    
    	# the following is not a tcp header per se, but a pseudo header
    	# used to calculate the tcp checksum.  yes, its a pain in the ass.
    	my ($pseudo_tcp) = pack ('a4 a4 C C
    				n n n
    				N N
    				H2 B8
    				n v n',
    			$src_host,$dest_host,$zero,$proto_tcp,
    			$tcplength,$src_port,$dest_port,
    			$syn,$ack,
    			$hdr_n_reserved,$tcp_codebits,
    			$tcp_windowsize,$zero,$tcp_urgent_pointer);
    
    	my ($tcp_chksum) = &checkfro($pseudo_tcp);
    
    
    	# PLAY WITH THE INNARDS OF THE IP PIECE HERE!!!
    	my $ip_version = "4";  # (nybble) tcp/ip version number (current is 4)
    	my $ip_hedlen = "5";  # (nybble) number of 32-bit words in ip header
    	my $ver_n_hlen = $ip_version . $ip_hedlen; # we pack 2 nybbles together
    	my $ip_tos = "00";  # (byte) ip type-of-service
    	my ($totlength) = $tcplength + 20; #tcp + 20 byte ip hdr ##
    	## we'll pack totlength into 2 bytes in the packet
    	my $ip_fragment_id = 31337;  # 2 bytes as well.
    	my $ip_3bit_flags = "010"; # ip fragmentation flags (3 bits) (frag, do not frag)
    	my $ip_13bit_fragoffset = "0000000000000";  #fragment offset
    	my $ip_flags_n_frags = $ip_3bit_flags . $ip_13bit_fragoffset;
    	my $ip_ttl = 64;  # 64 seconds / hops
    	# we have proto_tcp from above...  my $proto_tcp = 6;
    	# we have hdr_checksum from above...
    	# all source and destination infoz is passed to us (it
    	#  gets set in parent routine)
    	# change $syn and $ack above in tcp section
    	# in fact, everything else in the packet is set above.
    	
    
    	my ($hdr) = pack ('H2 H2 n n
    		 	   B16 C2
    			   n a4 a4
    			   n n
    			   N N
    			   H2 B8
    			   n v n',
    		$ver_n_hlen, $ip_tos, $totlength, $ip_fragment_id,
    		$ip_flags_n_frags,$ip_ttl, $proto_tcp,
    		$hdr_cksum, $src_host, $dest_host,
    		# end of ip header, begin tcp header
    		$src_port, $dest_port,
    		$syn,$ack,
    		$hdr_n_reserved,$tcp_codebits,
    		$tcp_windowsize,$tcp_chksum,$tcp_urgent_pointer);
    
    	return $hdr;
    }
    
    sub checkfro {
    	#dis sekzhun robbed from someplace else....
        my (
            $msg            # The message to checkfro
            ) = @_;
        my ($len_msg,       # Length of the message
            $num_short,     # The number of short words in the message
            $short,         # One short word
            $chk            # The checkfro
            );
    
        $len_msg = length($msg);
        $num_short = $len_msg / 2;
        $chk = 0;
        foreach $short (unpack("S$num_short", $msg))
        {
            $chk += $short;
        }                                   # Add some lead
        $chk += unpack("C", substr($msg, $len_msg - 1, 1)) if $len_msg % 2;
        $chk = ($chk >> 16) + ($chk & 0xffff);      # bust out mah fro pic
        return(~(($chk >> 16) + $chk) & 0xffff);    # spray some jheri
    }
    
    
    --YiEDa0DAkWCtVeE4--
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:33:41 PDT