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.

Source code is attached.
Cheers,
cgkanchi