in , , ,

Building a Port Scanner in Groovy, Python & Ruby

My scripts are hard coded to localhost. If you scan a remote host, make sure you have permission to scan it (i.e. your test environment, your client who requests some security testing, etc) and consider any legal issues in your region.

I’m language agnostic.  I love the Watir framework in Ruby for web automation (due to the community behind it), and I love Groovy/Grails for the web development community behind it.  Python has some great security tools out there, and I decided to try and build a simple security tool (Port Scanner) in all three languages and see how they differ.

Groovy

Code

import groovy.time.*
ports = 1..1090
def startTime = new Date()
ports.each { port ->
    try {
        Socket socket = new Socket("127.0.0.1",port)
        print "Port ${port}: OPEN \n"
    }catch (e){
 
    }
}
def endTime = new Date()
TimeDuration duration = TimeCategory.minus(endTime, startTime)
println "It took ${duration} to run this port scan..."

Results:
Port 22: OPEN
Port 106: OPEN
Port 389: OPEN
Port 625: OPEN
Port 631: OPEN
Port 636: OPEN
Port 749: OPEN
It took 7.616 seconds to run this port scan…

Process finished with exit code 0

Python

Code

import socket
import datetime
 
socket.setdefaulttimeout(2)
hostname = "127.0.0.1"
start_time = datetime.datetime.now()
try:
    for port in range(1, 1090):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        connect = sock.connect_ex((hostname, port))
        if connect == 0:
            print("Port " + repr(port) + " : OPEN")
        sock.close()
except socket.gaierror:
    print("Hostname could not be resolved")
 
except socket.error:
    print("Can't connect")
end_time = datetime.datetime.now()
 
print(end_time-start_time)

Results:
Port 22 : OPEN
Port 106 : OPEN
Port 389 : OPEN
Port 625 : OPEN
Port 631 : OPEN
Port 636 : OPEN
Port 749 : OPEN
0:00:08.000313

Process finished with exit code 0

Ruby

Code

require 'socket'
require 'time'
class PortScanner
  hostname = "localhost"
  ports = 1..1090
  time_start = Time.now
    ports.each { |port|
      begin
        timeout(2) do
             s = TCPSocket.open(hostname, port)
        end
        puts "port #{port} is open and accepting connections..."
      rescue Errno::EISCONN
        puts port ":" + s.gets()
      rescue
        # puts "port #{port} is refused"
      end
    }
  time_end = Time.now
  difference = time_end - time_start
  puts "#{difference}"
end

Results:
port 22 is open and accepting connections…
port 88 is open and accepting connections…
port 106 is open and accepting connections…
port 389 is open and accepting connections…
port 464 is open and accepting connections…
port 625 is open and accepting connections…
port 631 is open and accepting connections…
port 636 is open and accepting connections…
port 749 is open and accepting connections…
23.91197 seconds

Process finished with exit code 0

Final Results

Ruby took nearly 3x as long to run the same task (24 seconds vs 7 (Groovy) and 8 (Python.)   Ruby also reported several ports open that I know are not (88 and 464.)   I’m not sure why Ruby reported it as open.  To double check, I ran a built in port scanner against 127.0.0.1 and I got the same results as the Groovy and Python script.  So Ruby was inadvertently reporting 88 and 464 as available, when they weren’t.

While I prefer Ruby in web automation testing, I found better results in Groovy and Python.

I’m still wondering why I keep getting those false positives on Ruby.

References   [ + ]

1. hostname, port

What do you think?

0 points
Upvote Downvote

Total votes: 0

Upvotes: 0

Upvotes percentage: 0.000000%

Downvotes: 0

Downvotes percentage: 0.000000%

Written by Admin

I work for a Telecom company writing and testing software. My passion for writing code is expressed through this blog. It's my hope that it gives hope to any and all who are self-taught.

Comments

One Ping

  1. Pingback:

Leave a Reply

Loading…

Updating MD5 Tool To use SHA 256/512 Hash

OSX: Geolocating Laptop History based on SSID