/-----------------------------\ | Xine - issue #2 - Phile 019 | \-----------------------------/ TUPoSca - TCP/UDP Port Scanner 0.1b by b0z0/iKx 1. Introduction --------------- TUPoSca is a quite powerfull TCP/UDP scanner that may give you a quite detailed list of the TCP and/or UDP services active on a host. It has many features to improve TCP/UDP scanning such as heavy (this is logging also the response) and selective logging, time-distribuited scanning (to prevent Courtney and such like tools to issue an alert) and customizable strings to send as the request to the server. And this last feature is the one that makes TUPoSca also a generic packet sender. Infact you can define what must TUPoSca send to one or more of the connected ports and then you can log any response from them. 2. System Requirements ---------------------- TUPoSca is written in Perl and has been fully tested with Perl 5.003 under Linux. It requires the Perl modules Socket and getopt.pl that are shipped usually in the Perl package. To improve the logging facility of the scanner you will need two lists of service, one for tcp services (named tcp.services in the current directory) and the other for udp services (named udp.services in the current directory). You can very easily create those two files from your /etc/services file simply doing: $ sort +1 -n /etc/services | grep tcp > tcp.services $ sort +1 -n /etc/services | grep udp > udp.services The program in these two files basically pretends that the first column contains the service name and the second contains the port before a slash, as in the normal /etc/services. Then you could put comments or anything you like. Finally to get all the power of TUPoSca you will also need (also this isn't mandatory) the program fping (written by Roland J. Schemers III, and maintained by Bob Morgan). So if fping is present TUPoSca will try to determinate with fping if the server we are going to scan seems alive. Howerver fping must be run as root (or must be setuid root), so if you can't have this permissions just turn off the ping option. 3. How it works --------------- TUPoSca scanning concept is very simple, but must be divided into two parts: - TCP scanning. TUPoSca simply connects to the host desired port. If the connections is unsucesfull it will tell you that the TCP service on that port isn't avaiable. If the connection is succesfull it will display that something answered on that port. If heavy logging is enabled it will also send the desired string and one newline ("\n") to the server. Then it will wait for a determinate time (selectable via parameters) and log everything (well, you can set a limit of log lines) that comes back from the server. - UDP scanning. To check if a UDP service is enabled TUPoSca will send a packet and check if an error (an ICMP Dest Unreachable) occours. If it doesn't it will assume that something is connected, if the ICMP packet occours then the UDP service isn't avaiable. Then it will try to send the defined string and wait to see if something on the other side is responding. 4. How to use it ---------------- TUPoSca is very simple to use. First of all you must set the right path to Perl on the first line of the Perl script. Then just run it with the right parameters and enjoy :) 4.1 Command line switches ------------------------- TUPoSca command line parameters: -H [hostname] : specifies the name of the host to scan. Of course it can be a fully qualified domain name or a IP. This is the only mandatory command line parameter. -l [fromport] : specifies the port from which we will start the scan. Default is 7. -h [toport] : specifies the highest port that TUPoSca will connect to. Default is 25. -f [filename] : specifies the filename where the scanning log will be written. By default TUPoSca will write the results on user screen. -u 1 : if "-u 1" is specified then we will scan UDP ports. If you omit this parameter TUPoSca will scan TCP ports. -c [secs] : specifies the timeout (in seconds) to wait during the connection phase. -p [msecs] : specifies the timeout (in miliseconds) to wait when trying to determinate if a host is alive using fping. -n 1 : disables use of fping. -b [secs] : specifies the number of seconds to wait between each connection. Default is 0. -a 1 : will send another newline one second after sending our string. This may be useful for talking with things like www servers, but may cause a 'broken pipe' error with some services that closes the connection just after our first sended packet. -o 1 : enables long and detailed output. By default TUPoSca will only tell you if a service is present. -s [string] : specifies which string to send. -L [number lines] : specifies the maximum number of lines to log when long output is enabled. Default is 8. -t [secs] : specifies the number of seconds to wait when receiving output of the other service (this is when we are using the long output option). 4.2 A few examples ------------------ To scan dear.hell.com with default options just do: $ ./tuposca -H dear.hell.com To scan hell.pit.org from port 5 to 35, log everything to urlog and without using fping: $ ./tuposca -H hell.pit.org -l 5 -h 35 -f urlog -n 1 Scan TCP ports of paradise.pit.gov from 1 to 60, make a detailed log to the file pitt and while scanning send always the string 'Hi', logging 20 lines for each port. $ ./tuposca -H paradise.pit.gov -l 1 -h 60 -f pitt -o 1 -s 'Hi' -L 20 Make an UDP scan of the default ports of the site pippo.pluto.com $ ./tuposca -H pippo.pluto.com -u 1 And finally an example of the "-a 1" option. Here we get the server informations of the www server of the ret.org. $ ./tuposca -H ret.org -l 80 -h 80 -o 1 -s 'GET / HTTP/1.0' -a 1 Without the "-a 1" option it won't work, because the server will wait for another newline that evidently noone would make. In this last example you can evidently see how you can make a normal connection to a port sending a string without the need of a telnet client. 5.The program ------------- ------------------>8------->8---[cut]---8<-------8<------------------ #!/usr/bin/perl # TUPoSca - TCP/UDP Port Scanner v0.1b # 1997 b0z0/iKx # a TCP/UDP scanner in Perl. # Tested with Perl 5.003 under Linux # Thanx to Kernel Panic for his help! require Socket; require "getopt.pl"; $|=1; $AF_INET=2; $SOCK_STREAM=1; $scantype='tcp'; $servicefile='./tcp.services'; $out=0; $lockfile="/tmp/scan.udp.lockfile"; &Getopt('HLabcfhlnopstu'); # Get command line options $host=$opt_H; $hport=$opt_h; $recvto=$opt_c; $outfile=$opt_f; $lport=$opt_l; $out=$opt_o; $char_send=$opt_s; $linout=$opt_L; $timeout=$opt_t; $udpscan=$opt_u; $pingto=$opt_p; $noping=$opt_n; $sleeptime=$opt_b; $addenter=$opt_a; $sleeptime=0 if ($sleeptime eq ''); $addenter=0 if ($addenter eq ''); $lport=7 if ($lport eq ''); $hport=25 if ($hport eq ''); $linout=8 if ($linout eq ''); $timeout=3 if ($timeout eq ''); $pingto=10000 if (($pingto eq '') || ($pingto <= 250)); $recvto=5 if ($recvto eq ''); if ($udpscan == 1) { $servicefile='./udp.services'; $scantype='udp'; $SOCK_STREAM=2; $out=1; # UDP must send/receive to test } else { $udpscan == 0; } if ($outfile eq '') { $outfile=STDOUT; } else { open(OUTING,">$outfile"); $outfile=OUTING; } select($outfile); print "\nTUPoSca v0.1b - by b0z0/iKx\n\n\n"; if ($host eq '') { print "usage: tuposca\n"; print " -H [name] => hostname\n"; print " -l [num] => from port\n"; print " -h [num] => to port\n"; print " -f [filename] => output file\n"; print " -u 1 => UDP port scan\n"; print " -c [secs] => connection timeout\n"; print " -p [msecs] => ping timeout\n"; print " -n 1 => don't ping\n"; print " -a 1 => send another enter after 1 sec\n"; print " -b [secs] => pause between each connection\n"; print " -o 1 => long output\n"; print " -s [string] => string to send\n"; print " -L [n.lines] => output lines\n"; print " -t [secs] => recv timeout\n"; exit(); } open(SERVFILE,$servicefile); if ($noping==1) { print "Assuming server is ok...\n"; } else { print "Looking if server seems reachable....\n"; $pinging=`fping -a -t $pingto $host`; chop($pinging); if ($pinging eq '') { print "Host seems unreachable\n"; exit; } } print "Well, it seems that it is reachable\n"; $porton=0; while (($lport > $porton) && ($serventry=)) { ($servicename,$otherstuff)=split(' ',$serventry); ($porton,$istype)=split('/',$otherstuff); } for ($port=$lport;$port<=$hport;$port++) { if ($port==$porton) { $name=$servicename; $serventry=; ($servicename,$otherstuff)=split(' ',$serventry); ($porton)=split('/',$otherstuff); } else { $name='Unknown'; } printf("Service %s at port %s ",$name,$port); connect_and_send(); # connect/send/receive sleep($sleeptime); # sleep a little if requested } close($outfile); close(SERVFILE); # End of the main program sub connect_and_send { $sockaddr='S n a4 x8'; chop($hostname=`hostname`); ($name,$aliases,$proto)=getprotobyname($scantype); ($name,$aliases,$port)=getservbyname($port,$scantype) unless $port=~/^\d+$/;; ($name,$aliases,$type,$len,$thisaddr)= gethostbyname($hostname); $!=0; ($name,$aliases,$type,$len,$thataddr)= gethostbyname($host); if ($! != 0) { print "Resolving error: $!\n"; exit(); } $this=pack($sockaddr,$AF_INET,0,$thisaddr); $that=pack($sockaddr,$AF_INET,$port,$thataddr); if (!socket(S,$AF_INET,$SOCK_STREAM,$proto)) { die "Can't open socket!"; } if (!bind(S,$this)) { die "Can't bind socket!"; } $|=1; select(S); $|=1; select($outfile); unlink($lockfile); $isconn=2; $SIG{'ALRM'}= sub { die }; alarm($recvto); eval <<'EOT' ; $isconn=connect(S,$that); EOT alarm(0); if ($isconn==2) { print ("Timeout time expired during connect!\n") ; } elsif ($isconn) { if ($udpscan == 0) # UDP is connectionless, so we must do { # a full test to see if it is active printf("present! \n"); } if ($out == 1) { if ($pid = fork) { select(S); print $char_send, "\n"; if ($addenter==1) { sleep 1; print "\n"; } sleep $timeout; kill 9,$pid; } else { select($outfile); $ii=$wr=0; $!=0; while (($_=) && ($ii<$linout) && ($! == 0)) { if (($wr==0) && ($udpscan==1)) { $wr++; print "responding: \n"; open(TMPU,">$lockfile"); print TMPU "1\n"; close(TMPU); } print $_; $ii++; } if ((($! != 0)) && ($udpscan==1)) { printf("not connected! error: %s",$!); open(TMPU,">$lockfile"); print TMPU "1\n"; close(TMPU); } exit; } select($outfile); if ((!(open(IMET,"<$lockfile"))) && ($udpscan==1)) { print "connected! "; } close(IMET); print "\n"; } } else { printf "not present! \n"; } } ------------------>8------->8---[cut]---8<-------8<------------------ 6. Final words -------------- If you would like to send me a bug report, an improvement report or something else please contact in some way :) If you make changes and improvements to this program i'll really appreciate if you send me a copy of the changes you made.