WRITING
A PORT SCANNER IN JAVA
With all the people writing port scanners of late, I thought I'd hop on
to the bandwagon. I selected Java as my platform because that's the
language I know best. I ran into a couple of problems straight off, as
Java doesn't support Raw Sockets (so no SYN scans) and ICMP (so no
ping) off the bat. However, once I decided to write a simple TCP
connect scanner, it was easy. Anyway, I'll be taking you through the
scanner, how it works and detailing every line of code. This tutorial
is geared towards people who already know Java, so people who don't
won't get too much out of it except some background information.
First, the concept behind the scanner. Java uses sockets to make TCP
connections. Whenever a new socket is created, java first tries to make
the connection. If the connection fails, it throws an IOException. This
is the concept behind the main program loop. The port scanner is
divided into 2 files, one that does the actual work, called
JPortScanCore.java, and another that provides the user interface,
called JPortScanCLI.java. I could have done it in a single file but
that'd have made it harder to provide a GUI.
Anyway, here goes. First, I'll discuss the main file, JPortScanCore.java
The code starts with declaration of variables.
Code:
import java.net.*;
class JPortScanCore
{
Socket worker; //makes all the connections
int startPort, endPort; //what port to start at and
what port to end at
int[] openPorts=new int[65535]; //this holds all the
ports that are open. It's so big because it might need to accomodate
65535 ports in the unlikely event that all 65535 ports are open
String host; //stores the hostname/address of
the target
InetAddress hostAddress; //stores the IP
address of the target
....
Now that we've declared the variables, let's get dirty.
Code:
this.startPort=startPort;
this.endPort=endPort;
this.host=host;
boolean
b=false;
hostAddress=InetAddress.getByName(host); //gets the IP of the target
for(int
i=0;i<65535;i++)
openPorts[i]=0; //tags each element as 0 (closed) by default.
System.out.println("Scanning
"+hostAddress.getHostAddress()+":");
...
Now to the meat of the program.
Code:
for(int
currentPort=startPort,i=0;currentPort<=endPort;currentPort++)
{
try
{
worker= new
Socket(hostAddress,currentPort);
b=true;
}
catch(java.io.IOException e)
{
b=false;
}
finally
{
try
{
worker.close();
}
catch(java.io.IOException e){}
catch(NullPointerException e){}
}
if(b==true)
{
openPorts[i]=currentPort;
b=false;
i++;
}
}
}
...
The first line is a for loop that starts at startPort and ends at
endPort. The first try... catch... finally block does the actual work.
It creates a socket that tries to create a connection to the target. If
it's possible, it sets the boolean variable b to true. If it isn't, b
is set to false inside the catch block. The finally block closes the
socket that frees it up for reuse. IOException is thrown by
Socket.close() and must be caught. If the connection fails, worker is
null, therefore, a NullPointerException must be caught too. Later on,
the if block adds open ports to the openPorts[] array and increments
the counter.
The next block of code is just a couple of alternative constructors.
The first one scans all ports (1-65535) on the target. The second scans
a single port.
Code:
JPortScanCore(String host) throws UnknownHostException
{
this(1,65535,host);
}
JPortScanCore(int startPort, String host) throws
UnknownHostException
{
this(startPort,startPort,host);
}
}
Now that we're done with the main class, let's look at the
implementation of a command line interface (CLI) for it. The file is
called JPortScanCLI.java and it goes like this:
Code:
public class JPortScanCLI
{
static JPortScanCore jpsc=null; //make an instance
of JPortScanCore for use in the class
public static void main(String[] args)
{
if(args.length==0||args.length>3)
{
usage(); //if the arguments are not ok, prints a usage message
and exits
}
...
The next bit of code does the actual initialization and calls the
constructor.
Code:
try
{
//decide
which constructor to call
if(args.length==3 && Integer.parseInt(args[1])<65535
&&Integer.parseInt(args[2])<65535)
jpsc = new
JPortScanCore(Integer.parseInt(args[1]),Integer.parseInt(args[2]),args[0]);
else
if(args.length==1)
jpsc = new JPortScanCore(args[0]);
else
if(args.length==2)
jpsc = new JPortScanCore(Integer.parseInt(args[1]),args[0]);
else
throw new NumberFormatException(); //validate input
}
catch(java.net.UnknownHostException e)
{
System.out.println("Address cannot be resolved"+e); //make sure the
hostname is valid
}
catch(NumberFormatException
e)
{
System.out.println("startport and endport must be numbers less than
65535"+e);
}
System.out.println("Open
ports are...");
for(int
i=0;i<65535;i++)
{
if(jpsc.openPorts[i]!=0)
System.out.println(""+jpsc.openPorts[i]); //output open ports
}
}
...
A couple of things need to be explained here. First, the
Integer.parseInt(int) throws a NumberFormatException that needs to be
caught. This prevents text from being entered when ports are expected.
Second, InetAddress.getByName(host) throws a UnknownHostException when
the host IP cannot be resolved. I've caught it here since I've handled
all errors/exceptions in the interface rather than the core file. This
allows me to make modifications to the interface (like adding a GUI)
without changing the core code.
One last bit of code...
Code:
static void usage()
{
System.out.println("Usage:\njava JPortScanCLI host [startport]
[endport]");
System.out.println("If only
startport is specified, the portscanner scans only that port.");
System.out.println("If
neither is specified, the portscanner scans all ports from 1-65535");
System.out.println("Examples:\n java JPortScanCLI google.com \n java
JPortScanCLI google.com 80\n java JPortScanCLI google.com 80 90");
System.exit(0);
}
}
This method prints the usage notes and exits. Nothing new here. If
there is, you should be learning Java .
That's it for the code. There are a few things worth mentioning before
I sign off. First, Java isn't exactly the ideal language to write a
port scanner in, I just wanted to see if I could do it. Second, while
raw sockets and ICMP aren't available in Java natively, an
implementation of libpcap for Java, jpcap, allows you to do those
things. jpcap can be found at http://jpcap.sourceforge.net. Third, the
port scanner is really slow, one thing worth adding might be parallel
scanning using threads. I might just do that later.
That's all for now. As usual, any comments, criticisms, flames and
questions are welcome.
Cheers,
cgkanchi
PS: If you guys want, I can download the source code off AO and upload
it somewhere. Shipp, we really need an attachment feature!!!
Original Tutorial
by cgkanchi for TheTAZZone-TAZForum
Originally posted on April 19th, 2007 here
Do not use, republish, in whole or in part, without the consent of
the Author. TheTAZZone policy is that Authors retain the rights to the
work they submit and/or post...we do not sell, publish, transmit, or
have the right to give permission for such...TheTAZZone merely retains
the right to use, retain, and publish submitted work within it's
Network.

