It all sounds Geek to me! [Gautam Arora]

Monday, July 25, 2005

A Simple Port Scanner using Java

This is part 2 of the ‘Make our own simple networking tools using Java’. In part 1, we developed a simple command-line packet sniffer and now, we will make a simple Port Scanner (Note: We will not be using Threads, so this scanner will be a slow one, but in the weeks to come, we will make one of those fast ones too!)

We will divide our work into 2 java files:

1) JPortScanConn – This file will take care of the socket

2) JPortScanner – This file will deal with the actual command-line interface and validating user input

The tutorial is divided into three sections:

1) Definitions

2) Installation

3) Writing a simple port scanner

Definitions:

1) Port: A connection point for different protocols to communicate on different machines

2) Socket: (java.net.Socket class)is an object that represents a network connection between two machines. This means that’s the two machines have information about each other, including network location (IP address) and TCP port.

3) Port Scanner: is a software program that allows you to scan a target machine to provide information about the status of ports.

Installation:

Download and install Javatm2 Platform, Standard Edition (J2SEtm) JRE or SDK.java.sun.com/download

Writing a Simple Port Scanner:

As we have defined the much needed concepts above, the logic we will try to implement is that we would try to connect to port number x of the target machine, if we are successful, we will declare that the port is open else it is closed!

Ø First let’s make the JPortScanConn.java file:

// Import java.net(This is needed to create sockets and fetch the IP Address!)\\

import java.net.*;

// Create a class JPortScanConn \\

class JPortScanConn

{

// Declare a socket called skt that will make all the connections \\

// Declare integer variable startPort and endPort \\

// Declare an interger array openPorts[] which will hold a list

// of the open ports of the target machine

// Note: 65535 is the maximum number of ports on a machine \\

// Declare a string variable host to store the hostname of the target \\

// Declare an instance of type InetAddress that holds the IP address of the target \\

Socket skt;

int startPort, endPort;

int[] openPorts=new int[65535];

String hostName;

InetAddress hostAddress;

// Create a parameterised constructor to be used if user passes

// all 3 values i.e. for start and end port and the host name \\

JPortScanConn(int startPort, int endPort, String hostName)

{

// Initialize the values for the instance members

// with that passed by the user \\

this.startPort=startPort;

this.endPort=endPort;

this.hostName=hostName;

// Declare a flag named 'open' to hold the status

// of the current scanned port \\

boolean open=false;

// Initialize the hostAddress usning the getByName() method

// of the InetAddress class

// p.s. getByName()throws a UnknownHostException

// if the hostName is invalid \\

try

{

hostAddress=InetAddress.getByName(hostName);

}

catch (UnknownHostException ea) {}

// Initialise all values in the openPorts[] array to 0(closed) \\

for(int i=0;i<65535;i++)

openPorts[i]=0;

System.out.println("Scanning "+hostAddress.getHostAddress()+":");

// Scan the reqired ports by tring to create a connection

// p.s. 'currentport' holds the value of the port with which we

// try to establish a connection on the target machine 'hostAddress' \\

for(int currentPort=startPort,i=0;currentPort<=endPort;currentPort++)

{

try

{

skt= new Socket(hostAddress,currentPort);

// SUCCESS! \\

open=true;

}

catch(java.io.IOException eb)

{

// FAILED! \\

open=false;

}

finally

{

try

{

// Close the connection \\

skt.close();

}

catch(java.io.IOException ec){}

catch(NullPointerException ed){}

}

// Add the port number to the openPorts[] array if the

// connection was established \\

if(open==true)

{

openPorts[i]=currentPort;

// Reset the open flag \\

open=false;

// Move to the next port \\

i++;

}

}

}

// Create another constructor if user wishes to pass only the host name

// and we then scann all the ports \\

JPortScanConn(String hostName) throws UnknownHostException

{

this(1,65535,hostName);

}

// Create a constructor if user wants to scan a single port of the target \\

JPortScanConn(int startPort, String hostName) throws UnknownHostException

{

this(startPort,startPort,hostName);

}

}

Ø Now lets move to JPortScanner.java:

// Create a public class JPortScanner

// p.s. 'public' so that it can use the members and methos of JScanConn class

public class JPortScanner

{

// Make an instance of JPortScanConn

static JPortScanConn jpsc=null;

// Create a method to display the valid synatx for using the port scanner

static void usage()

{

System.out.println("Usage:\njava JPortScanner 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 JPortScanner google.com \n java JPortScanner google.com 80\n java JPortScanner google.com 80 90");

System.exit(0);

}

// Now comes the psvm() \\

public static void main(String[] args)

{

// If invalid syntax is used for command, display the Usage

if(args.length==0||args.length>3)

{

usage();

}

try

{

// Call the appropriate constructor for the jpsc instance

if(args.length==3 && Integer.parseInt(args[1])<65535>

jpsc = new JPortScanConn(Integer.parseInt(args[1]),Integer.parseInt(args[2]),args[0]);

else if(args.length==1)

jpsc = new JPortScanConn(args[0]);

else if(args.length==2)

jpsc = new JPortScanConn(Integer.parseInt(args[1]),args[0]);

else

throw new NumberFormatException();

}

catch(java.net.UnknownHostException ea)

{

System.out.println("Address cannot be resolved"+ea);

}

catch(NumberFormatException eb)

{

System.out.println("startport and endport must be numbers less than 65535"+eb);

}

// Display the open ports

System.out.println("Open ports are...");

for(int i=0;i<65535;i++)

{

if(jpsc.openPorts[i]!=0)

System.out.println(""+jpsc.openPorts[i]);

}

}

}

That’s it!

Open the console window, move to the appropriate directory and type the following commands:

#javac JPortScanConn.java

#javac JPortScanner.java

#java JPortScanner localhost 25

Now you can go ahead scanning ports on your machine or on any target machine!

Lets Tweak:

Allowing timeouts:

Add an int variable ‘timeout’ to the JPortScanConn class and initialize it to 4000( in ms).

Now, edit the line in JPortScanConn.java:

skt= new Socket(hostAddress,currentPort);

To:

skt= new Socket();
skt.connect(new InetSocketAddress(hostAddress,currentPort),timeout);

1 comment:

Nadeem Mohsin said...

Couple of minor optimizations you could make - not really necessary, but fun to think of when ur bored - like I am now...
1. Change the openPorts[] array to a Vector/List/Set. Saves you the bother of using a variable to keep track of the next free index. Collections can often clean up Java code unbelievably - and they're kinda intuitively clear. There's a reason they're built into languages like Python/Ruby as fundamental features.
2. If you do want to use an integer array - don't bother to initialize elements to 0 - that's automatic. But if you do wanna init an array, Arrays.fill() is a quicker way...
3. Yet another way that cleans up some code is to use an array of 65536 booleans for openPorts[]. That way you don't need an open flag - just use openPorts[currentPort]. That should really shrink some code up.

I strongly recommend the third option, for clarity and speed. The first option will probably be marginally slower bcoz of the overhead of managing the data structures.