Writing a port scanner in Java
Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Writing a port scanner in Java

  1. #1
    Antionline Herpetologist
    Join Date
    Aug 2001
    Posts
    1,165

    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
    Buy the Snakes of India book, support research and education (sorry the website has been discontinued)
    My blog: http://biology000.blogspot.com

  2. #2
    Want a GUI?


  3. #3
    Senior Member
    Join Date
    Nov 2002
    Posts
    186
    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

  4. #4
    Elite Hacker
    Join Date
    Mar 2003
    Posts
    1,407
    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

  5. #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-

  6. #6
    Antionline Herpetologist
    Join Date
    Aug 2001
    Posts
    1,165
    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.

    Want a GUI?
    Sure, if you don't mind rewriting it everytime I change the portscanner

    Cheers,
    cgkanchi
    Buy the Snakes of India book, support research and education (sorry the website has been discontinued)
    My blog: http://biology000.blogspot.com

  7. #7
    Antionline Herpetologist
    Join Date
    Aug 2001
    Posts
    1,165
    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
    Buy the Snakes of India book, support research and education (sorry the website has been discontinued)
    My blog: http://biology000.blogspot.com

  8. #8
    Junior Member
    Join Date
    Sep 2002
    Posts
    14
    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.

  9. #9
    Senior Member
    Join Date
    Oct 2002
    Posts
    181
    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?\"

  10. #10
    Antionline Herpetologist
    Join Date
    Aug 2001
    Posts
    1,165
    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
    Buy the Snakes of India book, support research and education (sorry the website has been discontinued)
    My blog: http://biology000.blogspot.com

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

 Security News

     Patches

       Security Trends

         How-To

           Buying Guides