Tuesday, 22 April 2014

Multi threaded Port Scanner with Scapy

Writing this tool forced me to learn about queues, threads and thread-locks. As well as introduced a python module called Scapy. After using Scapy it immediately became clear the power this module has. Instead of manually crafting raw packets I can just use Scapy to fill in the packet segments I need and let the default settings do the rest. This module opened up a lot of new doors for me and I can now script tools I previously only dreamed of being able to create. The port scanner does have some bugs but for internal networks it seems to do the job as intended. As this is only a poc I do not see the need in fixing all the bugs and making it absolutely perfect. Other tools like nmap have been created for that. This tool works by grabbing a user supplied port range and adding them into a queue. The queue is then passed into 10 separate threads. If a SynAck is received from the server an RST is sent back and the port marked as open. This adds a little bit of stealth.


#!/usr/bin/python

import Queue
import sys
import threading
from scapy.all import *

class workerThread(threading.Thread):
def __init__(self, queue, destIP, lock):
threading.Thread.__init__(self)
self.queue = queue
self.destIP = destIP
self.lock = lock

def run(self):
while True:
self.lock.acquire()
self.dport = self.queue.get() #Grab the port not from the queue
reply = sr1(IP(dst = self.destIP)/TCP(sport = RandShort(), dport = self.dport), verbose = 0, timeout = 1)
if reply == "<type 'NoneType'>":
print str(sport) + " is filtered"
elif reply.haslayer(TCP) and reply.getlayer(TCP).flags == 0x12:
print "Port open: " + str(reply.sport) + reply.sprintf(" %TCP.sport%")
send_rst = sr(IP(dst = self.destIP)/TCP(dport = reply.sport, sport = RandShort(), flags = "R"), verbose = 0, timeout = 1)
self.queue.task_done()
self.lock.release()

try:
destIP = sys.argv[1]
portRange = sys.argv[2].split("-")
startPort = int(portRange[0])
endPort =  int(portRange[1])

queue = Queue.Queue()

#Fill the queue
for q in range(startPort, endPort+1):
queue.put(q)


#create the threads and pass them the queue
for port in range(10):
lock = threading.Lock()
worker = workerThread(queue, destIP, lock)
worker.setDaemon(True)
print "Creating thread ",port + 1
worker.start()

#Wait for all queues to and threads to finish
queue.join()
print "\nScan complete\n"

except:
print "Usage: synScannerMultiThread <ip-address> <startport-endport>"



Output scanning a range of 1 - 1024:


The scan took around 15 seconds to scan all 1024 ports.

No comments:

Post a Comment