diff --git a/libs/scanner.py b/libs/scanner.py index 16ddece..a81828c 100644 --- a/libs/scanner.py +++ b/libs/scanner.py @@ -7,6 +7,8 @@ import struct import re from threading import Thread +import nmap + import src.utils as utils import libs.scanutils as scanutils @@ -30,17 +32,28 @@ for script in utils.listSubdirs(utils.getRoot("libs/scanners/")): -def getScanner(port: int, protocol: str): +def scan(host:str, port: int, protocol: str): + error = False + results = "" for scanner in portScanners: if str(scanner.__name__) == f'{protocol}{port}.py': - return scanner + scanResults, error = scanner.scan(host, port) + results += f'[{scanner.__name__}, {host}:{port}] {scanResults}' + if not error: + return results + else: + results += " Trying default scanner... " + if protocol == "tcp": - return tcpScanner + scanResults, error = tcpScanner.scan(host, port) + results += f'[{tcpScanner.__name__}, {host}:{port}] {scanResults}' elif protocol == "udp": - return udpScanner + scanResults, error = udpScanner.scan(host, port) + results += f'[{udpScanner.__name__}, {host}:{port}] {scanResults}' else: raise Exception("This should not happen...") + return results def start(settings): @@ -79,7 +92,11 @@ def start(settings): for i in range(0,settings['numJobs']): c = ScanTask(i) - t = Thread(target = c.run, args=(settings['maxPingTimeout'],portString,)) + t = Thread(target = c.run, args=( + settings['maxPingTimeout'], + settings['maxNmapTimeout'], + settings['nmapGroupSize'], + portString,)) t.start() tasks.append(c) @@ -98,26 +115,22 @@ def processStarted(): -def parseNmapResult(result: str, address: str): +def parseNmapResult(result: object, host: str): - ports = scanutils.getPorts(result) - hostname = scanutils.getHostname(result) - resultstr = f'### {address} ({hostname}) {ports}\n' + hostname = result.hostname() + resultstr = f'### {host} ({hostname}) {result.keys()}\n' - # resultstr += f'Location: {scanutils.geolocation(address)}\n' + # resultstr += f'Location: {scanutils.geolocation(host)}\n' - for port in ports: - if port[1] != 'open': - continue - # resultstr += str(port) + '\n' - - portInt = int(port[0].split("/")[0]) - protocol = port[0].split("/")[1] - scanner = getScanner(portInt, protocol) - - resultstr += f'[{scanner.__name__}]\n' - resultstr += scanner.scan(address, portInt) + "\n" - + for protocol in result.all_protocols(): + for portInt in result[protocol].keys(): + port = result[protocol][portInt] + + if port['state'] != 'open': + continue + + resultstr += scan(host, portInt, protocol) + "\n" + print(resultstr) @@ -125,29 +138,38 @@ class ScanTask: def __init__(self, threadid: int): self.threadid = threadid self.running = True + self.nm = nmap.PortScanner() def stop(self): self.running = False - def run(self, maxPingTimeout: int, portString: str): + def run(self, maxPingTimeout: int, maxNmapTimeout: int, nmapGroupSize: int, portString: str): while self.running: - address = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff))) + ipGroup = [] + while len(ipGroup) < nmapGroupSize and self.running: + address = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff))) - pingCommand = f"ping {address} -c 1 -W {maxPingTimeout}" + pingCommand = f"ping {address} -c 1 -W {maxPingTimeout}" - try: - subprocess.check_output(pingCommand.split(" ")) - # print(f"{self.threadid} {address}: FOUND") - except subprocess.CalledProcessError: - # print(f"{self.threadid} {address}: FAIL") - continue + try: + subprocess.check_output(pingCommand.split(" ")) + print(f"{self.threadid} {address}: FOUND {len(ipGroup)+1}/{nmapGroupSize}") + ipGroup.append(address) + except subprocess.CalledProcessError: + # print(f"{self.threadid} {address}: FAIL") + continue + print(f'Scanning: {ipGroup}') + self.nm.scan(hosts=' '.join(ipGroup), ports=portString, arguments="-O --send-eth --privileged -sS --reason -sU") + + for address in self.nm.all_hosts(): + parseNmapResult(self.nm[address], address) - nmapCommand = f"sudo nmap {address} -O --send-eth --privileged -v -sS --reason -sU -p {portString}" + # nmapCommand = f"sudo nmap {address} -O --send-eth --privileged -v -sS --reason -sU -p {portString}" - try: - parseNmapResult(subprocess.check_output(nmapCommand.split(" ")).decode(), address) - except subprocess.CalledProcessError: - continue + # try: + # parseNmapResult(subprocess.check_output(nmapCommand.split(" ")).decode(), address) + # except subprocess.CalledProcessError: + # continue \ No newline at end of file diff --git a/libs/scanners/tcp3128.py b/libs/scanners/tcp3128.py index 086343b..85f689f 100644 --- a/libs/scanners/tcp3128.py +++ b/libs/scanners/tcp3128.py @@ -1,4 +1,4 @@ -import libs.scanners.tcp80 +import libs.scanners.tcp80 as tcp80 def scan(host:str, port:int): return tcp80.scan(host, port) \ No newline at end of file diff --git a/libs/scanners/tcp443.py b/libs/scanners/tcp443.py index 3a656a1..b57d794 100644 --- a/libs/scanners/tcp443.py +++ b/libs/scanners/tcp443.py @@ -88,6 +88,7 @@ def scan(address:str, port:str): ssl_sock = context.wrap_socket(sock, server_hostname=address) returnVal = "" + error = False try: # Connect to the server @@ -96,24 +97,24 @@ def scan(address:str, port:str): ssl_sock.sendall(generate_headers().encode()) cert = ssl_sock.getpeercert(binary_form=True) - # Receive the response - response = b"" + # Receive the response while True: chunk = ssl_sock.recv(64) if not chunk: break - response += chunk - - returnVal = f"Response {response.decode()}" + "\n" + returnVal += chunk.decode() + + returnVal += "\n" returnVal += "SSL Certificate Information:\n" returnVal += get_ssl_cert_info(cert) + "\n" returnVal += "######### \n" - except socket.error as e: - returnVal = f" (possible connection reset) {e}" + except Exception as e: + returnVal += f"" + error = True finally: if ssl_sock: ssl_sock.close() - return returnVal \ No newline at end of file + return returnVal, error \ No newline at end of file diff --git a/libs/scanners/tcp591.py b/libs/scanners/tcp591.py index 086343b..85f689f 100644 --- a/libs/scanners/tcp591.py +++ b/libs/scanners/tcp591.py @@ -1,4 +1,4 @@ -import libs.scanners.tcp80 +import libs.scanners.tcp80 as tcp80 def scan(host:str, port:int): return tcp80.scan(host, port) \ No newline at end of file diff --git a/libs/scanners/tcp80.py b/libs/scanners/tcp80.py index 0fa55f1..8254413 100644 --- a/libs/scanners/tcp80.py +++ b/libs/scanners/tcp80.py @@ -17,6 +17,7 @@ def generate_headers(): def scan(host:str, port:int): returnVal = "" + error = False try: client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((host, port)) @@ -28,21 +29,18 @@ def scan(host:str, port:int): client_socket.send(request.encode()) - response = b"" while True: - chunk = client_socket.recv(64) if not chunk: break - response += chunk + returnVal += chunk.decode() - returnVal = "Response: " + response.decode() - - except: - returnVal = " (possible connection reset)" + except Exception as e: + returnVal += f"" + error = True finally: if client_socket: client_socket.close() - return returnVal \ No newline at end of file + return returnVal, error \ No newline at end of file diff --git a/libs/scanners/tcp8008.py b/libs/scanners/tcp8008.py index 086343b..85f689f 100644 --- a/libs/scanners/tcp8008.py +++ b/libs/scanners/tcp8008.py @@ -1,4 +1,4 @@ -import libs.scanners.tcp80 +import libs.scanners.tcp80 as tcp80 def scan(host:str, port:int): return tcp80.scan(host, port) \ No newline at end of file diff --git a/libs/scanners/tcp8080.py b/libs/scanners/tcp8080.py index 086343b..85f689f 100644 --- a/libs/scanners/tcp8080.py +++ b/libs/scanners/tcp8080.py @@ -1,4 +1,4 @@ -import libs.scanners.tcp80 +import libs.scanners.tcp80 as tcp80 def scan(host:str, port:int): return tcp80.scan(host, port) \ No newline at end of file diff --git a/libs/scanners/tcp8088.py b/libs/scanners/tcp8088.py index 086343b..85f689f 100644 --- a/libs/scanners/tcp8088.py +++ b/libs/scanners/tcp8088.py @@ -1,4 +1,4 @@ -import libs.scanners.tcp80 +import libs.scanners.tcp80 as tcp80 def scan(host:str, port:int): return tcp80.scan(host, port) \ No newline at end of file diff --git a/libs/scanners/tcpScanner.py b/libs/scanners/tcpScanner.py index 2723ef1..d82af7f 100644 --- a/libs/scanners/tcpScanner.py +++ b/libs/scanners/tcpScanner.py @@ -3,6 +3,7 @@ import time def scan(address:str, port:int, timeout:int=5): returnVal = "" + error = False client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -11,24 +12,21 @@ def scan(address:str, port:int, timeout:int=5): client_socket.settimeout(timeout) start_time = time.time() - outBytes = b'' while time.time() - start_time < timeout: try: data = client_socket.recv(64) if not data: break - outBytes += data + returnVal += data.decode() except socket.timeout: break - - returnVal = f'({address}:{port}) Recieved: {outBytes.decode()}' - except socket.error as e: - print(f"Error: {e}") - returnVal = f'({address}:{port}) Recieved: ' + except Exception as e: + returnVal += f'' + error = True finally: client_socket.close() - return returnVal \ No newline at end of file + return returnVal, error \ No newline at end of file diff --git a/libs/scanners/udpScanner.py b/libs/scanners/udpScanner.py index ece49d9..c0e6b94 100644 --- a/libs/scanners/udpScanner.py +++ b/libs/scanners/udpScanner.py @@ -1,2 +1,2 @@ def scan(address:str, port:int): - return f'<{address}:{port}>' \ No newline at end of file + return f'<{address}:{port}>', False \ No newline at end of file diff --git a/modules/scan/main.py b/modules/scan/main.py index f623b3b..431dc36 100755 --- a/modules/scan/main.py +++ b/modules/scan/main.py @@ -27,8 +27,10 @@ def init(moduleMaster): mm.vars['Scanner-Settings'] = { "range": [[0,0,0,0], [255,255,255,255]], - "numJobs": 10, - "maxPingTimeout": 1, + "numJobs": 30, + "maxPingTimeout": 3, + "maxNmapTimeout": 2, + "nmapGroupSize": 3, # Port modes: # -1: Disable @@ -37,16 +39,16 @@ def init(moduleMaster): # 3: Related to word "tcpSettings": { - "mode": 1, - "ports": [631] - # "topCount": 100 - # "relatedString": "http" + "mode": 2, + "ports": [631], + "topCount": 10, + "relatedString": "http" }, "udpSettings": { "mode": -1, - # "ports": [631, 161, 137, 123, 138] - "topCount": 50 - # "relatedString": "telnet" + "ports": [631, 161, 137, 123, 138], + "topCount": 50, + "relatedString": "telnet" }, "runTCP": True, "runUDP": False diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..10b6370 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +flask +geoip2 +faker +python-nmap