-
May 24th, 2004, 08:56 PM
#1
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.
Source code is attached.
Cheers,
cgkanchi
-
May 24th, 2004, 09:33 PM
#2
Want a GUI?
-
May 24th, 2004, 09:42 PM
#3
Good work!
As I was reading through your tutorial I thought of two things:
1. There is probably some third party libraries to create raw/ICMP sockets
2. Threads would make this A LOT faster
Fortunately you picked up on these things as well.
With the threads how would you implement it? I doubt creating 65535 threads is a good idea. I would think maybe 65 threads that scan 1000 ports each might not be a bad idea. Any other thoughts?
\"When you say best friends, it means friends forever\" Brand New
\"Best friends means I pulled the trigger
Best friends means you get what you deserve\" Taking Back Sunday
Visit alastairgrant.ca
-
May 25th, 2004, 01:50 AM
#4
PM8228 aka silver-bullets and I were working on a java port scanner. We found a
problem where if the port was closed it took an insane amount of time to move on to
the next port. I don't know if this program has that problem but we solved it by putting
a timer on it. We had it going fairly fast in the end, and we were working on some
stuff to make it faster, but I guess we sort of got side tracked. It used threads. I'll
have to give this one a try and see how it performs. Soda, screw your GUI . j/k
-
May 25th, 2004, 03:08 AM
#5
Yah dude. ZC you were good with that timer thingy. I took me a bit to figure it out. Java needs to be able to send SYN and ICMP packets!
-Cheers-
-
May 25th, 2004, 08:25 AM
#6
With the threads how would you implement it? I doubt creating 65535 threads is a good idea. I would think maybe 65 threads that scan 1000 ports each might not be a bad idea.
I doubt whether 65 threads is a good idea either. I wouldn't like to use over 10 threads ever, but I guess you could let the user specify how many threads to use.
We found a problem where if the port was closed it took an insane amount of time to move on to
the next port.
It takes about 4 or 5 seconds I think, maybe a bit more. That's the default timeout value. Unfortunately, while Socket.connect() has a timeout value in one of the methods, the Socket() constructors don't. I'm looking at getting around that problem. Will let you know when I do.
Sure, if you don't mind rewriting it everytime I change the portscanner 
Cheers,
cgkanchi
-
May 25th, 2004, 08:41 AM
#7
Solved the timeout problem quite simply. Aaaargh! I should have seen this last night before I posted this, but it was 3 am. Anyway I just changed this:
Code:
worker= new Socket(hostAddress,currentPort);
To this:
Code:
worker= new Socket();
worker.connect(new InetSocketAddress(hostAddress,currentPort),timeout);
timeout is an integer variable that I have set to 4000. That's the value that's worked the best for me so far.
Cheers,
cgkanchi
-
May 25th, 2004, 12:29 PM
#8
Junior Member
I've written a program that takes a list of ip's and port numbers and creates an ftp connection to them using threads. The main part of this program creates a thread for a new connection, and does this until there are either 5 threads or no ip's left. The program actually creates about 120 threads through the program.
If people are interested, I can dig out the code for the guts of the program.
-
May 25th, 2004, 12:54 PM
#9
Actually java can handle raw socket requests, there are a couple of projects out there that plug into libpcap and libnet, useing a java native interface.
Have a look at http://jpcap.sourceforge.net/ for the libpcap stuff.
I can find the link for the stuff for libnet, ill post the link when I find it
SittingDuck
I\'m a SittingDuck, but the question is \"Is your web app a Sitting Duck?\"
-
May 25th, 2004, 03:14 PM
#10
Actually java can handle raw socket requests, there are a couple of projects out there that plug into libpcap and libnet, useing a java native interface.
Have a look at http://jpcap.sourceforge.net/ for the libpcap stuff.
I can find the link for the stuff for libnet, ill post the link when I find it
SittingDuck
I know that, that's why the last paragraph of my tut says this: 
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.
Sorry, just had to point out that I hadn't left anything out.
Cheers,
cgkanchi
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
|