Port Scanner
Port Scanner
Port Scanner
INTRODUCTION: A port scanner is a piece of software designed to search a network host for open ports. This is often used by administrators to check the security of their networks and by hackers to compromise it. An online port scanner will scan your computer looking for open ports. Programs use ports (like we use doors) to visit and communicate with the outside world (the net).Viruses now have built in port scanners that scour the internet looking for unsuspecting computers with open ports; when they find them, they cripple your software or worse, stay hidden and report your personal activity and information to another system. To port scan a host is to scan for multiple listening ports on a single target host. This project basically about how to scan the local database of services of any remote system connected to the Server with the help of IP/TCP Address of the system connected to that server. The scanner also includes a module for testing connections (the Connect page) and allows the handling of the local database of services (the Services page). After a hacker runs a port scanner on your system they know what services you have accepting connections. With this information they can begin attempting to exploit those services to obtain unauthorized access to your system.
PROBLEM DEFINITION:
The only way to track open ports is by using a port scanner, and the most accurate port scanner will be an online port scan. Scanning your ports using software like nmap will work fine, but it will not test your firewall's ability to block port activity. You need a port scanner that is not inside your network to verify accuracy. Our free online port scanner will help you do just that, but before we can scan your ports, we'll need you to verify that you are authorized to initiate the security scan.
PROPOSED SYSTEM:
Many Internet service providers deny their customers the ability to perform port scans outside of their home networks. This is usually covered in the Terms of Service or Acceptable Use Policy to which the customer must have already agreed. Other public and private networks may also place such limitations upon their users. Security and stability concerns associated with the program responsible for delivering the service. The application creates threads which attempt to connect to the supplied ip address and using the range of port numbers supplied. In this approach the effects of connection timeouts is minimized and the application can process a range of port.
INDEX
1. INTRODUCTION OBJECTIVE SCOPE EXISTING SYSTEM PROPOSED SYSTEM HARDWARE & SOFTWARE SPECIFICATIONS 2. PROJECTANALYSIS STUDY OF THE SYSTEM PROJECT FEATURES 3. PROJECT DESIGN OUTPUT SCREEN 4. CONCLUSION 5. FEATURE ENHANCEMENT
6. 7.
INTRODUCTION
Objective Scope Existing System Proposed System Software Requirement Specification System Environment
Objective:
There are hundreds of ports and service in which some of them are in common use. An intruder who sets up a backdoor may use an assigned port for an unregistered service and even he can inject a virus or Trojan horse into our system. A port scanner is a software application designed to probe a network host for open ports. This is often used by administrators to verify security policies of their networks and by hackers to identify running services on a host with the view to compromising it.
The main objective of this project is to scan the various ports within a specified range. With help of this administrator can easily identify the open ports and warn the clients.
Scope:
This project aims at the creation of a comprehensive application, which can be used at corporate environments. The application should be as simple as possible so that it can be configured even by a non-technical person.
Existing System:
Scanning entered the world along with the phone systems. Here we have this tremendous global telecommunications network, all reachable through codes on our telephone. Millions of numbers are reachable locally, yet we may only be interested in 0.5% of these numbers, perhaps those that answer with a carrier.
The logical solution to finding those numbers that interest us is to try them all. Thus the field of "war dialing" arose. . The basic idea is
simple. If you dial a number and your modem gives you a CONNECT, you record it. Otherwise the computer hangs up and tirelessly dials the next one.
While war dialing is still useful, we are now finding that many of the computers we wish to communicate with are connected through networks such as the Internet rather than analog phone dialups.
Proposed system:
Over time, a number of techniques have been developed for surveying the protocols and ports on which a target machine is listening. We send a blizzard of packets for various protocols, and we deduce which services are listening from the responses we receive (or don't receive). The application creates threads which attempt to connect to the supplied ip address and using the range of port numbers supplied. In this approach the effects of connection timeouts is minimized and the application can process a range of port.
System Environment:
Client: Hardware Platform: PIII or above with RAM of 128 or above MB And 20GB or above of HD. Software Platform: Java Enabled Browser
Server: Hardware Platform: PIII or above with RAM of 128 or above MB And 20GB or above of HD. Software Platform : JAVA, jdk1.5.0, awt, Swings, applets
PROJECT ANALYSIS
Study of the system:
Port numbers 0 through 1023 are well-known ports that systems administrators usually use for only system processes or for programs that privileged users are running. If attackers exploit a well-known port, they can potentially gain control of server.
In an effort to compromise a network, attackers use several generic schemes to scan ports. The following examples focus on TCP and UDP scanning: TCP connect () scanning is the most basic form of TCP scanning. An attacker's host issues a connect () system call to every interesting port on the target machine. If the port is listening, connect () will succeed; otherwise, the port is unreachable and the service is unavailable. This attack scheme is fast and doesn't require any special privileges; however, port scanner can easily detect and block this attack at the target system.
scanning is one of the few UDP scans. UDP is a connectionless protocol, so it's harder to scan than TCP because UDP ports aren't required to respond to probes. Most implementations generate an ICMP port unreachable error when a user (or intruder) sends a packet to a closed UDP port. Thus, a lack of a response indicates an active port. Unfortunately, UDP port scanning is not as reliable as TCP port scanning.
Project features:
Module: Scanning page
Scanning module:
In this we use the concept called multithreading to scan the multiple ports simultaneously. There are two types of scanning one is TCP scan and other is UDP scan. In TCP scan we send connect () system call to each and every port. If the port is open then connect () will proceed. In UDP scan we send a packet, if the packet is unreachable then we get ICMP port unreachable error. TCP scan is more reliable than UDP scan. In the scan page the admin/clients have to specify the IP address of the target machine, type of scanning and the range of the ports to be scanned.
MAIN SCREEN
In the scan page the admin/clients have to specify the IP address of the target machine, type of scanning and the range of the ports to be scanned.
CONCLUSION:
The technological benefits of PORT SCANNER are monitor and enhance the performance of the system and provide security to the system. Using port scanner we can scan multiple ports simultaneously by using the concept called multi threading, by this time will be saved. Mainly port scanners are used in firewalls to find the open ports, so that the firewall can protect our system from threats which attack through these open ports. We can scan our own system with out any help of a web server and we dont require any additional software to use this.
ADVANTAGES:
We can scan multiple ports simultaneously. Any system in the LAN can be scanned by the authorized users. It is compatible on any operating system. It is mainly used to provide security.
FUTURE ENHANCEMENT:
In future administration will be given rights to close the open ports of the clients. Time limit will be given for each and every open port, if the port is not closed in the specified time it will be closed automatically. It can be extended as ONLINE PORT SCANNER.
public class JMapFE extends JFrame { protected Scan scan; protected Scanning sh;
protected final String version = "version 0.3.1"; protected final int FRAME_WIDTH = 455; protected final int FRAME_HEIGHT = 530;
protected JPanel mainPanel = new JPanel(new BorderLayout()); protected JTextArea resultsText = new JTextArea(); protected JScrollPane resultsScroll = new JScrollPane(resultsText); protected JPanel buttonsPanel = new JPanel(new GridLayout(1,5)); protected JButton scanButton = new JButton("Scan"); protected JButton quitButton = new JButton("Quit"); protected JPanel titlePanel = new JPanel(new GridLayout(8,3)); protected JLabel titleLabel = new JLabel( "JMap"); protected JLabel hostnameLabel = new JLabel("Hostname: "); protected JTextField hostnameInput = new JTextField(); protected JCheckBox subnetOption = new JCheckBox("Subnet Scan"); protected JLabel subnetLabel = new JLabel("Subnet: "); protected JTextField subnetInput = new JTextField("255.255.255.0"); protected JCheckBox scanSubnetForOption = new JCheckBox("Scan Subnet for");
protected JComboBox scanSubnetForCombo = new JComboBox(); protected JCheckBox scanTCPOption = new JCheckBox("TCP", true); protected JCheckBox scanUDPOption = new JCheckBox("UDP", false); protected JCheckBox portsSelected = new JCheckBox(
"Port Range", false); protected JTextField lowestPortInput = new JTextField("1"); protected JLabel portRangeLabel = new JLabel("to"); protected JTextField highestPortInput = new JTextField("1024");
//used in (process bar) dialog box to stop it all protected JButton stopProcessButton;
protected JMenuBar menu = new JMenuBar(); protected JMenu scanMenu = new JMenu("Scan"); protected JMenuItem scanMenuItem = new JMenuItem("Scan");
protected JMenuItem exitMenuItem = new JMenuItem("Exit"); protected JMenu helpMenu = new JMenu("Help"); protected JMenuItem usageMenuItem = new JMenuItem("Usage"); protected JMenuItem aboutMenuItem = new JMenuItem("About"); protected JMenuItem versionMenuItem = new JMenuItem("Version"); protected JMenuItem bugsMenuItem = new JMenuItem("Bugs");
//set frame to this so to referrence in child and inner classes frame = this;
titlePanel.add(new JLabel()); titlePanel.add(hostnameLabel); hostnameLabel.setHorizontalAlignment(JLabel.RIGHT); titlePanel.add(hostnameInput); hostnameInput.setToolTipText("Hostname or IP address of " + "system to scan");
lowestPortInput.setToolTipText("Network Port" + "to start scanning from"); titlePanel.add(portRangeLabel); titlePanel.add(highestPortInput); highestPortInput.setToolTipText("Network Port to scan upto");
buttonsPanel.add(new JLabel()); buttonsPanel.add(scanButton); scanButton.setToolTipText("Start Scanning"); buttonsPanel.add(new JLabel()); buttonsPanel.add(quitButton); quitButton.setToolTipText("Close JMap"); buttonsPanel.add(new JLabel());
resultsText.setText(this.getUsage());
//create stop button for later usage in (process bar) dialog box stopProcessButton = new JButton("Stop");
this.setVisible(true); }
/** *Returns a String containing basic usage of the client */ protected String getUsage(){ return ""; }
menu.add(scanMenu); menu.add(helpMenu);
scanMenu.setMnemonic('s'); helpMenu.setMnemonic('h');
scanMenuItem.setMnemonic('s'); exitMenuItem.setMnemonic('x');
bugsMenuItem.setMnemonic('u');
this.setJMenuBar(menu); }
protected void setupCombo(){ //get list of ports, and services String [] portList = Scan.getPortList();
stopProcessButton.addActionListener(new JMapFEActionListener());
/** *Enables of disables input options *@param boolean true to enable */ protected void enableInputs(boolean enable){ if (portsSelected.isSelected()){ lowestPortInput.setEditable(enable); highestPortInput.setEditable(enable); }
if (scanSubnetForOption.isSelected()){ scanSubnetForCombo.setEnabled(enable);
scanMenuItem.setEnabled(enable);
class Scanning extends Thread implements Observer{ JDialog progressDialog; //dialog to show progress bar JProgressBar progress; JPanel dialogPanel; JLabel portDescription;
//get subnet String subnet; if (subnetOption.isSelected()){ subnet = subnetInput.getText(); } else{ subnet = null; }
if (hostnameInput.getText().length() == 0){
resultsText.setText("You have not entered a hostname\n" + "\n"); enableInputs(true); //reactivate the inputs return; //they havent entered a hostname }
Integer.parseInt(lowestPortInput.getText()),
Integer.parseInt(highestPortInput.getText())); } else if (scanSubnetForOption.isSelected()){ //work out what part number has been selected String selectedPortName =
(String)scanSubnetForCombo.getSelectedItem();
selectedPortName.substring(0,
selectedPortName.indexOf(' '))); scan = new Scan(hostnameInput.getText(), subnet, selectedPortNumber, selectedPortNumber); } else{ scan = new Scan(hostnameInput.getText(), subnet); } } catch(Exception e){ resultsText.setText(e.getMessage()); enableInputs(true);
//setup progress dialog - set non-model progressDialog = new JDialog(frame, "Scanning....", false); progressDialog.addWindowListener(new DialogWindowListener());
dialogPanel = new JPanel(new BorderLayout()); progress = new JProgressBar(0, scan.getNumberPorts()); portDescription = new JLabel( "_____________________PLEASE WAIT_______________________"); //forces a wider progress window
public void update(Observable o, Object arg){ if (arg instanceof Integer){ //we should update our progress by this number progress.setValue( progress.getValue() + ((Integer)arg).intValue() ); return; } else{ //increment the progress bar's value
progress.setValue(progress.getValue()+1);
portDescription.setText((String)arg); } }
// if UDP scanning, warn of length of time if (scanUDPOption.isSelected()){ resultsText.setText( "UDP Scanning takes some time\n" + "go have a coffee :)\n"); }
scanTCPOption.isSelected(),
scanUDPOption.isSelected())); enableInputs(true);
progressDialog.setVisible(false); }
//handles this dialog window closing class DialogWindowListener extends WindowAdapter{ public void windowClosing(WindowEvent e){ scanButton.setText("Halting"); stopProcessButton.setText("Halting"); sh.destroy(); } }
class JMapFEWindowAdapter extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); //kill everything } }
class JMapFEActionListener implements ActionListener{ public void actionPerformed(ActionEvent e){ String action = e.getActionCommand();
lowestPortInput.setEditable(portsSelected.isSelected());
highestPortInput.setEditable(portsSelected.isSelected());
subnetInput.setEditable(subnetOption.isSelected());
scanSubnetForOption.setEnabled(subnetOption.isSelected());
if (!subnetOption.isSelected()){ //if deselecting subnet scanning, disable scan subnet //for server scanSubnetForOption.setSelected(false); scanSubnetForCombo.setEnabled(false); //disable combo } } else if (action.equals(stopProcessButton.getText())){ scanButton.setText("Halting");
class JMapFEKeyAdapter extends KeyAdapter{ public void keyPressed(KeyEvent e){ if (e.getKeyCode() == KeyEvent.VK_ENTER){ sh = new Scanning(); sh.start(); } } }
class JMapFEMenuListener implements ActionListener { public void actionPerformed(ActionEvent e){ String event = e.getActionCommand();
if (event.equals(scanMenuItem.getText())){ sh = new Scanning(); sh.start(); } else if (event.equals(exitMenuItem.getText())){ System.exit(0); } else if (event.equals(usageMenuItem.getText())){ resultsText.setText(getUsage()); } else if (event.equals(aboutMenuItem.getText())){ resultsText.setText("Java Port Scanner\n" + ""); } else if (event.equals(versionMenuItem.getText())){ resultsText.setText("JMap - " + version + "\n"); } else if (event.equals(bugsMenuItem.getText())){ resultsText.setText("JMap\n\n" + ""+ "\n");
JMAP:
import java.io.*;
Scan scan;
try{ if (args.length == 1){ scan = new Scan(args[0]); System.out.println(scan.scan()); } else if (args.length == 4 && args[0].equals("-p")){ scan = new Scan(args[3], Integer.parseInt(args[1]), Integer.parseInt(args[2])); System.out.println(scan.scan()); } else{
System.err.println("USAGE: JMap [-p <start port> <end port>] " + "HOSTNAME"); System.exit(-1); } } catch(Exception e){ System.err.println(e.getMessage()); } } }
public class PortLookup{ protected String defsFile; protected String [] portsList; protected final String JAR_FILE_NAME = "jmap.jar";
/** *Constructs port lookup object, to lookup service usually associated with *a given port number *@param String definitions file, similar in style to the one in * /etc/services *@throws NullPointerException error getting to file */ public PortLookup(String defsFile) throws NullPointerException{ this.defsFile = defsFile;
arch.getInputStream(arch.getEntry(defsFile)))); while(temp != null){ temp = in.readLine(); ports += temp + "\n"; } } catch(Exception e){ System.err.println(e.getMessage()); } portsList = ports.split("\n"); //split line into array }
/**
*Gets the service normally associated with the given port, if known *@param int port to find service name for *@param String protocol, such as tcp or udp *@return String the service name, or Unknown */ public String getService(int port, String protocol){ for (int i=0; i<portsList.length; i++){ if (portsList[i].matches(".*\t" + port + "\\/" + protocol + ".*")){ if (portsList[i].indexOf("\t") > 0){ return portsList[i].substring(0,portsList[i].indexOf("\t")); } } } return "UNKNOWN"; }
/** *Gets all port numbers that are associated with a service *@returns int array the list of ports
*/ public int[] getActivePorts(){ Vector resultStrings = new Vector(); int start, stop;
for (int i=0; i<portsList.length; i++){ if (portsList[i].startsWith("#")){ //comment continue; } start = portsList[i].indexOf("\t"); stop = portsList[i].indexOf("/tcp"); if (start < stop && start > 0){ resultStrings.add(portsList[i].substring(start+1, stop).trim()); } }
int [] results = new int[resultStrings.size()]; for (int i=0; i<resultStrings.size(); i++){ results[i] = Integer.parseInt((String)resultStrings.get(i)); } return results;
public static void main(String [] args){ if (args.length != 1){ System.err.println("USAGE: portLookup <port_number>"); System.exit(0); }
PortLookup p; try{ p = new PortLookup("ports.defs"); System.out.println( p.getService(Integer.parseInt(args[0]), "tcp")); } catch(Exception e){ System.err.println("Couldn't open port definitions file"); System.exit(-1); } } }
Scan: import java.net.*; import java.io.*; import java.util.*; public class Scan extends Observable implements Observer { public static final String PORT_DEFINITIONS = "ports.defs"; protected static int MAX_THREADS = 10; // hosts to scan at once protected static int WINDOWS_MAX_THREADS = 3; //max threads to run under Win
protected InetAddress host; private int [] hostParts = new int[4]; protected InetAddress subnet; private int [] subnetParts = new int[4]; protected int[] portsToScan; private PortLookup portService; private boolean stopped = false; //true to stop scanning
protected String resultsString = new String(); protected String subnetResults; private Vector hostsScanning = new Vector(); //stores handle to threads scanning each host
//for use when only scanning one port on each host private int portsRequired = 0;; private int portsScanned = 0;
/* *Scan specified hostname *This constructor always gets called, by the other constructors *@param String hostname *@throws ScanningException - initialisation error */ public Scan(String hostname) throws ScanningException{ try{ host = InetAddress.getByName(hostname); portService = new PortLookup(PORT_DEFINITIONS);
// check our operating system, if windows then reduce no of threads if (System.getProperty("os.name").startsWith("Windows")){ this.MAX_THREADS = this.WINDOWS_MAX_THREADS; } }
catch(UnknownHostException e){ throw new ScanningException("Host: " + hostname + " unknown :("); } catch(NullPointerException e){ throw new ScanningException("Could not open port services" + " definitions file"); } catch(Exception e){ throw new ScanningException(e.getMessage()); } }
/** *Scan subnet, probing default ports *@param String hostname *@param String subnet, eg 255.255.255.0 */ public Scan(String hostname, String subnet) throws ScanningException{
if (subnetParts.length != 4){ //should be four sectios throw new ScanningException("Subnet invalid:\n" + "should be specified in form:\n" +
"\t255.255.255.0\tor similar"); }
//form the subnetParts array of ints for (int i=0; i<subnetParts.length; i++){
subnetParts[i] = Integer.parseInt(subnetStrings[i]); }
boolean zeroFlag = false; //raised after which bits should be 0 boolean badSubnet = false; //signals a bad subnet
for (int i=0; i<subnetParts.length; i++){ if (zeroFlag){ if (subnetParts[i] != 0){ badSubnet = true; break; } } else{ if (subnetParts[i] < 255){ zeroFlag = true; //remainder should be '0' continue; } else if (subnetParts[i] > 255){
this.subnet = InetAddress.getByName(subnet); } catch(UnknownHostException e){ throw new ScanningException("Subnet: " + subnet + " invalid"); } }
/* *Scan specified ports on given hostname, to scan subnet for just one port, *enter the same values for lowestPort and highestPort *@param String hostname *@param String subnet in form 255.255.255.0 (for example) *@param int lowestPort - port to start scanning from *@param int highestPort - port to scan up to *@throws ScanningException - initialisation error */ public Scan(String hostname, String subnet, int lowestPort, int highestPort) throws ScanningException{ this(hostname, subnet);
if (lowestPort <= highestPort && lowestPort > 0){ portsToScan = new int[highestPort - lowestPort + 1];
portsToScan[i++] = lowestPort++; } } else{ //illegal port range throw new ScanningException("Illegal port range specified"); } }
/* *Scan specified ports on given hostname *@param String hostname *@param int lowestPort - port to start scanning from *@param int highestPort - port to scan up to *@throws ScanningException - initialisation error */ public Scan(String hostname, int lowestPort, int highestPort)
/** *Returns the number of ports which are to be scanned *@return int the total number of ports to scan */ public int getNumberPorts(){ if (subnet == null){ return portsToScan.length; } else{ return portsToScan.length * this.getNumberHosts(); } }
/** * calculates the maximum number of possible hosts on this subnet *@return int the maximum number of hosts on subnet */ protected int getNumberHosts(){ // use exclusive OR bitwise operation on subnet parts int partOne = subnetParts[0] ^ 0xff;
int partTwo = subnetParts[1] ^ 0xff; int partThree = subnetParts[2] ^ 0xff; int partFour = subnetParts[3] ^ 0xff;
// scale the return value appropriatly return partFour + (partThree*0xff) + (partTwo*0xff*0xff) + (partOne*0xff*0xff*0xff) + 1; //add 1 for '0' }
/** *Returns list of services in format: PORT_NUMBER - DEFINITION *@return String array of port data */ public static String [] getPortList(){ PortLookup portsList = new PortLookup(PORT_DEFINITIONS); int [] portNums = portsList.getActivePorts(); String [] retrStr = new String[portNums.length];
/** *Default protocol used for scanning (TCP/IP) *@returns String list of open ports */ public String scan(){ return this.scan(true, false); //tcp scan only }
/** *Scans given host/subnet *@param boolean TCP/IP scanning enabled *@param boolean UDP scanning enabled */ public String scan(boolean tcp, boolean udp){ if (subnet == null){ // if we are only scanning one host
this.scanHost(host.getHostName(), tcp, udp); } else{ int [] subnetHostParts = new int[4]; String subnetHost; subnetResults = new String(); InetAddress returnedHost; InetAddress tmpHost; String displayHost; //to display hostname int port = -1; //used only if there is one port only
//if there is only one port to scan, select it if (portsToScan.length == 1){ port = portsToScan[0]; }
for (int i=0; i<subnetHostParts.length; i++){ // bitwise AND operation to get the starting address subnetHostParts[i] = hostParts[i] & subnetParts[i]; }
for (int i=0; i<this.getNumberHosts(); i++){ if (stopped){ resultsString = "Scanning Aborted, results so far:\n\n" + resultsString; return resultsString; }
//form the host to scan from the individual parts of this //subnet host subnetHost = subnetHostParts[0] + "." + subnetHostParts[1] + "." + subnetHostParts[2] + "." + subnetHostParts[3];
try{ //dont scan network of broadcast address if (subnetHostParts[3] != 0 && subnetHostParts[3] != 0xff){ //retrived less output if only scanning one port if (port > 0){ setChanged(); notifyObservers("Probing: " + subnetHost + " PORT: " + port + " " +
portService.getService(port, "tcp"));
tmpHost = InetAddress.getByName(subnetHost);
if (tcp){ this.scanTCP(tmpHost, port); } if (udp){ this.scanUDP(tmpHost, port); } } else{ scanHost(subnetHost, tcp, udp);
subnetHostParts[0]++; if (subnetHostParts[0] == 0x100){ //you really have gone too far break; } } } } } if (port > 0){ while (this.portsScanned < this.portsRequired && !stopped){ try{ Thread.sleep(1000); } catch(Exception e){ ; }
//wait for all results to come back while(this.hostsScanned < this.hostsToScan && !stopped){ try{ Thread.sleep(1000); } catch(Exception e){ ; } } if (stopped){ resultsString = "Scanning stopped, results so far:\n\n" + resultsString; } stopped = false; //reset switch return resultsString; //this final results
/** *Scans single port using specified TCP hoost/port *@param InetAddress host to probe *@param int port number */ protected void scanTCP(InetAddress IP, int port){ portsRequired++; ScanTCP s = new ScanTCP(IP, port); s.addObserver(this); Thread scanPortThread = new Thread(s); //scanPortThread.setPriority(Thread.MAX_PRIORITY); scanPortThread.start(); }
/** *Scans single UDP port on host/port *@param InetAddress IP address of the victim *@param int port number */ protected void scanUDP(InetAddress IP, int port){
portsRequired++;
ScanUDP s = new ScanUDP(IP, port); s.addObserver(this); Thread scanPortThread = new Thread(s); //scanPortThread.setPriority(Thread.MAX_PRIORITY); scanPortThread.start(); }
/** *Scans a given host, protected so that external classes can only scan *using options set in constructor *@param String victim - the host to scan *@param boolean TCP/IP scanning enabed *@param boolean UDP scanning enabled */ protected void scanHost(String hostname, boolean tcp, boolean udp){ if (hostsToScan - hostsScanned > this.MAX_THREADS){ // we are running too many threads
// wait until half threads have done while (hostsToScan - hostsScanned > this.MAX_THREADS/2){ try{ Thread.sleep(5000); } catch(Exception e){ } } }
//increment counter of number of hosts we're waiting for results from hostsToScan++;
ScanHost s = new ScanHost(hostname, tcp, udp, portsToScan, portService); hostsScanning.add(s); //store reference to this thread s.addObserver(this);
scanThread.setPriority(Thread.MAX_PRIORITY); scanThread.start();
// pause before attempting to start another thread try{ Thread.sleep(2000); } catch(Exception e){ } }
public void update(Observable o, Object arg){ if (o instanceof ScanTCP){ portsScanned++; //responce to only scanning for one port per host if ( ((String)arg).equals("OPEN")){ ScanTCP s = (ScanTCP)o; subnetResults += s.getIP().getHostName() + "\t" + s.getPort() + " tcp " + portService.getService(s.getPort(), "tcp") + "\tOPEN\n"; }
} else if (o instanceof ScanUDP){ portsScanned++; //responce to only scanning for one port per host if ( ((String)arg).equals("OPEN")){ ScanUDP s = (ScanUDP)o; subnetResults += s.getIP().getHostName() + "\t" + s.getPort() + " udp " + portService.getService(s.getPort(), "udp") + "\tOPEN\n"; } } else if (arg instanceof String){ //is a status update, update our observer setChanged(); notifyObservers(arg); } else if (arg instanceof Status){ hostsScanned++;
hostsScanning.remove((ScanHost)o);
try { resultsString += InetAddress.getByName( ((ScanHost)o).getHostname()).getHostName() + "(" + InetAddress.getByName(((ScanHost)o).getHostname()) .getHostAddress() + ")\n"; } catch(UnknownHostException e){ resultsString += ((ScanHost)o).getHostname() + "\n"; } resultsString += ((Status)arg).toString() + "\n\n\n"; } }
/** *Stops the scanning of a host */ public void stop(){ stopped = true;
//call stop for all threads left scanning for (int i=0; i<hostsScanning.size(); i++){ ((ScanHost)hostsScanning.get(i)).stop(); } }
public static void main(String [] args){ if (args.length != 1){ System.out.println("USAGE: scanTCP <hostname>"); System.exit(0); }
ScanHost:
public class ScanHost extends Observable implements Observer, Runnable { protected static int MAX_THREADS = 20; // max threads to run per host on windows protected static int WINDOWS_MAX_THREADS = 12;
private String hostname; private InetAddress victim; private boolean tcp; private boolean udp; private int[] portsToScan; private PortLookup portService;
/** *Constructs thread to Scan an individual host, on set ports and protocol *@param String victim - the host to scan *@param boolean TCP/IP scanning enabed *@param boolean UDP scanning enabled *@param int[] the list of ports to be scanned *@param PortLookup the service defining names for the ports */ public ScanHost(String hostname, boolean tcp, boolean udp, int[] portsToScan, PortLookup portService){ this.hostname = hostname; this.tcp = tcp; this.udp = udp; this.portsToScan = portsToScan; this.portService = portService;
setChanged(); }
if (resultsPending - portsScanned > this.MAX_THREADS){ // we currently have too many threads running
// wait until at least half of the threads have finished while (resultsPending - portsScanned > (this.MAX_THREADS/2)){ try{ Thread.sleep(5000); } catch(Exception e){ } } }
//for updating the progress bar setChanged(); if (i == portsToScan.length-1){ notifyObservers(" } else{ notifyObservers("Probing: " + hostname + " PORT: " + p + " " + portService.getService(p, "tcp")); } Waiting for responces ");
if (stopped){ break; }
if (tcp){ ScanTCP scan = new ScanTCP(victim, p); scan.addObserver(this); Thread scanThread = new Thread(scan); //scanThread.setPriority(Thread.MAX_PRIORITY); scanThread.start();
if (udp){ ScanUDP scan = new ScanUDP(victim, p); scan.addObserver(this); Thread scanThread = new Thread(scan); //scanThread.setPriority(Thread.MAX_PRIORITY); scanThread.start(); //increment the results that we are waiting for resultsPending++; try{ Thread.sleep(1100); //pause before starting next thread }
catch(Exception e){ ; } } }
while (!this.stopped && !statusReg.isUnreachable() && portsScanned < resultsPending){ try{ Thread.sleep(500); //all results havent arrived yet } catch(Exception e){ ; } }
String returnString = new String(); try{ returnString = InetAddress.getByName(hostname).getHostName() + "(" + InetAddress.getByName(hostname).getHostAddress() + ")\n"; }
setChanged(); notifyObservers(statusReg); }
if (result.equals("CLOSED"))
statusReg.addStatus(port, Status.CLOSED, Status.TCP); else if (result.equals("DROPPED")) statusReg.addStatus(port, Status.DROPPED, Status.TCP); else if (result.equals("OPEN")) statusReg.addStatus(port, Status.OPEN, Status.TCP); } else if (o instanceof ScanUDP){ int port = ((ScanUDP)o).getPort(); String result = (String)arg;
/** *Stops the scanning of a host */ public void stop(){ stopped = true;
} }
ScanningException:
public class ScanTCP extends Observable implements Runnable { private InetAddress IP; private int port; private int timesDropped = 0; private int timesClosed = 0; private static int SOCKET_TIMEOUT = 2000; private static int MAX_TIMES_DROPPED = 3; private static int MAX_TIMES_CLOSED = 2;
/* *Constructs new thread to Scan host on TCP port *@param InetAddress the IP address of host to scan *@param int port number to scan */ public ScanTCP(InetAddress IP, int port){ this.IP = IP;
this.port = port;
// if we are running on Windows, increase timeout and no. of retries if (System.getProperty("os.name").startsWith("Windows")){ this.SOCKET_TIMEOUT = 2500; this.MAX_TIMES_DROPPED = 4; this.MAX_TIMES_CLOSED = 3; } }
/** *Returns the IP address being scanned */ public InetAddress getIP(){ return IP; }
return port; }
/** *Scans host/port using the TCP protocol */ public void run() { try{ String portsStatus = this.scanTCP(); setChanged(); notifyObservers(portsStatus); } catch(NoRouteToHostException e){ setChanged(); notifyObservers("null"); //null to signify error contacting host return; } }
/** *Scans single port using specified TCP hoost/port *@return String - either OPEN CLOSED DROPPED
//set the socket to timeout, multiply the timeout by number of retry s.connect(new InetSocketAddress(IP, port), this.SOCKET_TIMEOUT * ((timesDropped | timesClosed)+1)); s.close(); } catch(NoRouteToHostException e){ throw e; //throw to calling } catch(SocketTimeoutException e){ /* * Sometimes a socket times out in error (due to intensive scanning) *check again, to make sure */ if (this.timesDropped < this.MAX_TIMES_DROPPED){
this.timesDropped++; try{ Thread.sleep(2500); // wait before trying again } catch(Exception f){ } // scan again! return this.scanTCP(); } else{ return "DROPPED"; } } catch(IOException e){ if (this.timesClosed < this.MAX_TIMES_CLOSED){ this.timesClosed++; try{ Thread.sleep(2500); } catch(Exception f){ }
return this.scanTCP(); } else{ return "CLOSED"; } } //if got this far, is opem return "OPEN"; }
public class ScanUDP extends Observable implements Runnable { private InetAddress IP; private int port;
/** *Constructs thread to scan a UDP port *@param InetAddress address of host to scan *@param int port number to scan */ public ScanUDP(InetAddress IP, int port){ this.IP = IP; this.port = port; }
/**
*Returns the IP address being scanned */ public InetAddress getIP(){ return IP; }
/** *Return the port being scanned */ public int getPort(){ return port; }
/** *Scans single UDP port on host/port *@return String either OPEN CLOSED
*/ protected String scanUDP(){ DatagramSocket ds; DatagramPacket dp; DatagramChannel dChannel; try{ byte [] bytes = new byte[128]; ds = new DatagramSocket(); dp = new DatagramPacket(bytes, bytes.length, IP, port); dChannel = DatagramChannel.open(); dChannel.connect(new InetSocketAddress(IP, port)); dChannel.configureBlocking(true); ds = dChannel.socket(); ds.setSoTimeout(1000); ds.send(dp); dp = new DatagramPacket(bytes, bytes.length); Thread.sleep(1000); ds.receive(dp);
return "CLOSED"; }
ds.disconnect(); dChannel.disconnect(); dChannel.close(); ds.close(); } catch(PortUnreachableException e){ return "CLOSED"; } catch(InterruptedIOException e){ return "CLOSED"; } catch(IOException e){ return "CLOSED"; } catch(Exception e){ return "CLOSED"; } return "OPEN"; }}
Status:
import java.util.*;
public class Status{ public static final int TCP = 0; public static final int UDP = 1;
public static final int OPEN = 0; public static final int CLOSED = 1; public static final int DROPPED = 2; private static final int INVALID = -1;
private boolean TCPScan; private boolean UDPScan; private int[] portsTCP = new int[0xffff]; //port status, indexed by port no private int[] portsUDP = new int[0xffff]; //port status, indexed by port no
// to keep count
private int open = 0; private int closed = 0; private int dropped = 0; private PortLookup service = new PortLookup(Scan.PORT_DEFINITIONS);
/** *Constructs status for a specified host and protocol *@param boolean true for TCP *@param boolean true for UDP *@param String host to scan */ public Status(boolean TCPScan, boolean UDPScan, String host){ this.TCPScan = TCPScan; this.UDPScan = UDPScan; this.host = host;
// set all ports to invalid status for (int i=0; i<portsTCP.length; i++){ portsTCP[i] = this.INVALID; } for (int i=0; i<portsUDP.length; i++){ portsUDP[i] = this.INVALID; } }
/** *Returns the hostname of system being scanned */ public String getHost(){ return this.host; }
/** *Returns true is host is unreachable */ public boolean isUnreachable(){ return this.isUnreachable; }
/** *Update the status on a specified port *@param int port number which is being reported *@param int status of port, eg. Status.OPEN *@param int the protocol, eg. Status.TCP */ public void addStatus(int port, int status, int proto){ if (proto == this.TCP) this.portsTCP[port] = status; else if (proto == this.UDP) this.portsUDP[port] = status; else return;
/** *Returns full status of ports on this host */ public String toString(){ if (isUnreachable){ return "UNREACHABLE"; }
// check for signs host may be down if (TCPScan && !UDPScan && this.open == 0 && this.closed == 0){ return "Host appears to be down, or ignoring us"; } else if (TCPScan && UDPScan &&
this.open > 10 && this.dropped > 10 && this.closed == 0){ //10 as a rough mark, 10 consecutive ports unlikely to be open return "Host appears to be down, or ignoring us"; } else if (!TCPScan && UDPScan && this.closed == 0 && this.OPEN > 10){ //10 as a rough mark, 10 consecutive ports unlikely to be open return "Host appears to be down, or ignoring us"; }
for (int i=0; i<portsTCP.length; i++){ if (this.portsTCP[i] == this.INVALID && this.portsUDP[i] == this.INVALID){ continue; //this port has not been scanned }
s += "\t" + i + "\ttcp\t" + service.getService(i,"tcp") + "\tOPEN\n"; } else if (this.portsTCP[i] == this.DROPPED){ s += "\t" + i + "\ttcp\t" + service.getService(i,"tcp") + "\tDROPPED\n"; } } if (this.UDPScan){ if (this.portsUDP[i] == this.OPEN){ s += "\t" + i + "\tudp\t" + service.getService(i,"udp") + "\tOPEN\n"; } } }
return s; } }
BIBLIOGRAPHY
References and Web Resources Java at Sun Microsystems., Inc - java.sun.com. Java user site: www.java.com. Java Community Process Program - www.jcp.com. Java Virtual Machine Specifications, 2nd Ed. - Java.Sun.com Java Upgrade Guide: Migrating From the Microsoft VM for Java to the Sun JRE - java.sun.com Java Virtual Machine - Wikipedia Stack - Wikipedia Java Virtual Machine Specifications, 2nd Ed. - Java.Sun.com Java Upgrade Guide: Migrating From the Microsoft VM for Java to the Sun JRE - java.sun.com Java Virtual Machine - Wikipedia Stack - Wikipedia http://java.sun.com/products/jsp/ http://www.coreservlets.com/Apache-Tomcat-Tutorial/