Recipe16.9.Use Sockets to Scan the Ports on a Machine


Recipe 16.9. Use Sockets to Scan the Ports on a Machine

Problem

You want to determine the open ports on a machine to see where the security risks are.

Solution

Use the CheapoPortScanner class constructed for your use; its code is shown in Example 16-11. CheapoPortScanner uses the Socket class to attempt to open a socket and connect to an address on a given port. The OpenPortFound event is available for a callback when an open port is found in the range supplied to the CheapoPortScanner constructor or in the default range (1 to 65535). By default, CheapoPortScanner will scan the local machine.

Example 16-11. CheapoPortScanner class

 class CheapoPortScanner {     #region Private consts and members     const int PORT_MIN_VALUE = 1;     const int PORT_MAX_VALUE = 65535;     private int _minPort = PORT_MIN_VALUE;     private int _maxPort = PORT_MAX_VALUE;     private List<int> _openPorts = null;     private List<int> _closedPorts = null;     private string _host = "127.0.0.1"; // localhost     #endregion     #region Event     public class OpenPortEventArgs : EventArgs     {         int _portNum;         public OpenPortEventArgs(int portNum) : base()         {             _portNum = portNum;         }         public int PortNum         {         get { return _portNum; }         }     }     public delegate void OpenPortFoundEventHandler(object sender, OpenPortEventArgs args);     public event OpenPortFoundEventHandler OpenPortFound;     #endregion // Event     #region CTORs & Init code     public CheapoPortScanner()     {         // Defaults are already set for ports and localhost         SetupLists();     }     public CheapoPortScanner(string host, int minPort, int maxPort)     {         if (minPort > maxPort)             throw new               ArgumentException("Min port cannot be greater than max port");         if (minPort < PORT_MIN_VALUE || minPort > PORT_MAX_VALUE)             throw new ArgumentOutOfRangeException("Min port cannot be less than "+                           PORT_MIN_VALUE + " or greater than " + PORT_MAX_VALUE);         if (maxPort < PORT_MIN_VALUE || maxPort > PORT_MAX_VALUE)             throw new ArgumentOutOfRangeException("Max port cannot be less than "+                           PORT_MIN_VALUE + " or greater than " + PORT_MAX_VALUE);         _host = host;         _minPort = minPort;         _maxPort = maxPort;         SetupLists();     }     private void SetupLists()     {         // Set up lists with capacity to hold half of range         // Since we can't know how many ports are going to be open,         // we compromise and allocate enough for half         // rangeCount is max - min + 1         int rangeCount = (_maxPort - _minPort) + 1;         // If there are an odd number, bump by one to get one extra slot.         if (rangeCount % 2 != 0)             rangeCount += 1;         // Reserve half the ports in the range for each         _openPorts = new List<int>(rangeCount / 2);         _closedPorts = new List<int>(rangeCount / 2);     }     #endregion // CTORs & Init code 

There are two properties on CheapoPortScanner that bear mentioning. The OpenPorts and ClosedPorts properties return a ReadOnlyCollection of type int that is a list of the ports that are open and closed, respectively. Their code is shown in Example 16-12.

Example 16-12. OpenPorts and ClosedPorts properties

 #region Properties  public ReadOnlyCollection<int> OpenPorts {     get { return new ReadOnlyCollection<int>(_openPorts); } }  public ReadOnlyCollection<int> ClosedPorts {     get { return new ReadOnlyCollection<int>(_closedPorts); } } #endregion // Properties #region Private Methods private void CheckPort(int port) {     if (IsPortOpen(port))     {         // If we got here it is open         _openPorts.Add(port);         // Notify anyone paying attention         OpenPortFoundEventHandler openPortFound = OpenPortFound;         if (openPortFound != null)          openPortFound(this, new OpenPortEventArgs(port));     }     else     {         // Server doesn't have that port open         _closedPorts.Add(port);     } } private bool IsPortOpen(int port) {     Socket sock = null;     try     {         // Make a TCP-based socket         sock = new Socket(AddressFamily.InterNetwork,                         SocketType.Stream,                         ProtocolType.Tcp);         // Connect         sock.Connect(_host, port);         return true;     }     catch (SocketException se)     {         if (se.SocketErrorCode == SocketError.ConnectionRefused)         {             return false;         }         else         {             // An error occurred when attempting to access the socket             Debug.WriteLine(se.ToString());             Console.WriteLine(se.ToString());         }     }     finally     {         if (sock != null)         {             if (sock.Connected)                 sock.Disconnect(false);             sock.Close();         }     }     return false; } #endregion 

The trigger method for the CheapoPortScanner is Scan. Scan will check all of the ports in the range specified in the constructor. The ReportToConsole method will dump the pertinent information about the last scan to the console output stream:

 #region Public Methods public void Scan() {     for (int port = _minPort; port <= _maxPort; port++)     {         CheckPort(port);     } }  public void ReportToConsole() {     Console.WriteLine("Port Scan for host at {0}:", _host.ToString());     Console.WriteLine("\tStarting Port: {0}; Ending Port: {1}",                       _minPort, _maxPort);     Console.WriteLine("\tOpen ports:");     foreach (int port in _openPorts)     {         Console.WriteLine("\t\tPort {0}", port);     }     Console.WriteLine("\tClosed ports:");     foreach (int port in _closedPorts)     {         Console.WriteLine("\t\tPort {0}", port);     } } #endregion // Public Methods } 

The PortScan method demonstrates how to use CheapoPortScanner by scanning ports 130 on the local machine. It first subscribes to the OpenPortFound event. The handler method for this event, cps_OpenPortFound, writes out the number of any port found open. Next, PortScan calls the Scan method. Finally, it calls ReportToConsole to show the full results of the scan, including the closed ports as well as the open ones.

 public static void PortScan () {     // Do a specific range     Console.WriteLine("Checking ports 1-30 on localhost…");     CheapoPortScanner cps = new CheapoPortScanner("127.0.0.1",1,30);     cps.OpenPortFound +=         new CheapoPortScanner.OpenPortFoundEventHandler(cps_OpenPortFound);     cps.Scan();     Console.WriteLine("Found {0} ports open and {1} ports closed",             cps.OpenPorts.Count, cps.ClosedPorts.Count);     // Do the local machine, whole port range 1-65535     cps = new CheapoPortScanner();     cps.Scan();     cps.ReportToConsole(); } static void cps_OpenPortFound(object sender, CheapoPortScanner.OpenPortEventArgs args) {     Console.WriteLine("OpenPortFound reported port {0} was open",args.PPortNumP); } 

The output for the port scanner as shown appears here:

 Checking ports 1-30 on localhost… OpenPortFound reported port 22 was open OpenPortFound reported port 26 was open Found 2 ports open and 28 ports closed 

Discussion

Open ports on a machine are significant because they indicate the presence of a program listening on those ports. Hackers look for "open" ports as ways to enter your systems without permission. CheapoPortScanner is an admittedly rudimentary mechanism for checking for open ports, but it demonstrates the principle well enough to provide a good starting point.

If you run this on a corporate network, you may quickly get a visit from your network administrator, as you may set off alarms in some intrusion-detection systems. Be judicious in your use of this code.


See Also

See the "Socket Class" and "Sockets" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net