Fix hosts ranges scan

This commit is contained in:
Oleksii Shevchuk 2017-03-05 15:44:52 +02:00
parent 08fc22a932
commit 41932c6362
2 changed files with 79 additions and 42 deletions

View File

@ -25,11 +25,14 @@ class PortScan(PupyModule):
self.arg_parser.add_argument('target', metavar="ip/range", help='IP/range')
def run(self, args):
if "/" in args.target[0]:
hosts = IPNetwork(args.target[0])
scan_range = False
if '/' in args.target:
hosts = [ str(x) for x in IPNetwork(args.target) ]
scan_range = True
self.log('Scanning range {}: {} hosts'.format(args.target, len(hosts)))
else:
hosts = list()
hosts.append(args.target)
hosts = [ args.target ]
ports = [
p for prange in args.ports.split(',') for p in (
@ -44,30 +47,36 @@ class PortScan(PupyModule):
ports = list(set(ports))
random.shuffle(ports)
for host in hosts:
scanner = self.client.conn.modules['network.lib.scan']
scanner = self.client.conn.modules['network.lib.scan']
def set_connectable(ports):
self.connectable = ports
self.terminated.set()
def set_connectable(addrs):
self.connectable = addrs
self.terminated.set()
self.abort = scanner.scanthread(
str(host), ports, set_connectable, timeout=args.timeout, portion=args.portion
)
self.connectable = []
self.terminated.wait()
self.abort = scanner.scanthread(
hosts, ports, set_connectable, timeout=args.timeout, portion=args.portion
)
ports = sorted(self.connectable)
self.terminated.wait()
if ports:
self.log('{}: {}'.format(host, ', '.join([str(x) for x in ports])))
else:
self.log('{}: closed'.format(host))
if self.connectable:
connectable = {}
for host, port in self.connectable:
if host in connectable:
connectable[host].add(port)
else:
connectable[host] = set([port])
if self.abort.is_set():
break
for host in sorted(connectable.keys()):
ports = ', '.join([str(port) for port in sorted(list(connectable[host]))])
self.log('{}: {}'.format(host, ports))
self.abort = None
elif not scan_range:
self.log('{}: closed'.format(args.target))
self.abort = None
def interrupt(self):
if self.abort:

View File

@ -6,20 +6,33 @@ import errno
import time
import threading
import rpyc
import logging
def chunks(l, n):
for i in xrange(0, len(l), n):
yield l[i:i + n]
chunk = []
for i in l:
if len(chunk) == n:
yield chunk
chunk = []
else:
chunk.append(i)
if chunk:
yield chunk
def create_socket(host, port):
sock = socket.socket()
sock.setblocking(0)
r = sock.connect_ex((host, port))
try:
r = sock.connect_ex((host, port))
except Exception, e:
return None, None
return sock, r
def scan(host, ports, abort=None, timeout=10, portion=32, on_complete=None):
def scan(hosts, ports, abort=None, timeout=10, portion=32, on_complete=None, on_open_port=None):
connectable=[]
for portion in chunks(list(ports), portion):
for portion in chunks(((x, y) for x in hosts for y in ports), portion):
if not portion:
continue
@ -27,29 +40,44 @@ def scan(host, ports, abort=None, timeout=10, portion=32, on_complete=None):
break
sockets = {}
for port in portion:
for host, port in portion:
sock, r = create_socket(host, port)
if sock is None:
continue
if r:
if r in (errno.EAGAIN, errno.EINPROGRESS):
sockets[sock] = port
sockets[sock] = (host, port)
else:
sock.close()
continue
else:
connectable.append(port)
if on_open_port:
on_open_port((host, port))
connectable.append((host, port))
sock.close()
start = time.time()
while sockets and time.time() - start < timeout:
socks = list(sockets.iterkeys())
_, w, _ = select.select([], socks, [], timeout - (time.time() - start))
if sockets:
start = time.time()
while sockets and time.time() - start < timeout:
socks = list(sockets.iterkeys())
_, w, _ = select.select([], socks, [], timeout - (time.time() - start))
for sock in w:
errcode = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
if errcode == 0:
connectable.append(sockets[sock])
sock.close()
del sockets[sock]
for sock in w:
try:
errcode = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
if errcode == 0:
if on_open_port:
on_open_port(sockets[sock])
connectable.append(sockets[sock])
except:
pass
finally:
sock.close()
del sockets[sock]
if on_complete:
if abort and not abort.is_set():
@ -57,8 +85,8 @@ def scan(host, ports, abort=None, timeout=10, portion=32, on_complete=None):
else:
return connectable
def scanthread(host, ports, on_complete, **kwargs):
host = str(host)
def scanthread(hosts, ports, on_complete, **kwargs):
hosts = [ x for x in hosts ]
ports = [ x for x in ports ]
abort = threading.Event()
connectable = []
@ -66,7 +94,7 @@ def scanthread(host, ports, on_complete, **kwargs):
'abort': abort,
'on_complete': rpyc.async(on_complete)
})
scanner = threading.Thread(target=scan, args=(host, ports), kwargs=kwargs)
scanner = threading.Thread(target=scan, args=(hosts, ports), kwargs=kwargs)
scanner.daemon = True
scanner.start()