| skipped 26 lines |
27 | 27 | | ############################################################################################################### |
28 | 28 | | |
29 | 29 | | try: |
30 | | - | from exploitdb import exploitdb |
31 | | - | except: |
32 | | - | import os |
33 | | - | print("-"*80) |
34 | | - | print('Submodule not found. Setting up...') |
35 | | - | os.system('cd exploitdb; git submodule init; git submodule update') |
36 | | - | print("-"*80) |
37 | | - | print("Please run again for full functionality.") |
38 | | - | exit() |
39 | | - | import socketserver |
| 30 | + | import socketserver |
| 31 | + | from os.path import isfile |
| 32 | + | import argparse |
| 33 | + | import multiprocessing |
| 34 | + | from csv import DictReader |
| 35 | + | except Exception as e: |
| 36 | + | print("Caught exception: {}\nAre you running with python3?".format(e)) |
| 37 | + | exit(1) |
| 38 | + | |
40 | 39 | | |
41 | 40 | | _PORT_ = 4521 |
42 | 41 | | _IP_ = '0.0.0.0' |
| 42 | + | _SEARCHSPLOIT_ = "/usr/share/exploitdb/files_exploits.csv" |
43 | 43 | | |
44 | 44 | | class SearchHandler(socketserver.StreamRequestHandler): |
45 | 45 | | def handle(self): |
46 | | - | print('[+] Connection from '+ self.client_address[0]) |
47 | | - | data = self.rfile.readline().decode().strip() |
48 | | - | while not data == '': |
49 | | - | print('[ ] Searching for: ' + data) |
50 | | - | output = [ ] |
51 | | - | results = self.server.search(data) |
52 | | - | for exploits in results: |
53 | | - | output.append(exploits[0]['description'] + ' id: ' + exploits[0]['id']) |
54 | | - | if len(output) > 0: |
55 | | - | print(''.join(output)) |
56 | | - | self.wfile.write('\n'.join(output).encode() + b'\n') |
57 | | - | data = self.rfile.readline().decode().strip() |
58 | | - | print('[-] Closing connection from ' + self.client_address[0]) |
| 46 | + | try: |
| 47 | + | print('[+] Connection from '+ self.client_address[0]) |
| 48 | + | self.pool = multiprocessing.Pool(10) |
| 49 | + | for output in self.pool.imap(SearchHandler.search, iter(self.rfile.readline, b'\n')): |
| 50 | + | if output: |
| 51 | + | print(output) |
| 52 | + | self.wfile.write(output.encode() + b'\n') |
59 | 53 | | |
| 54 | + | self.pool.close() |
| 55 | + | print('[$] Closing connection from {}\n'.format(self.client_address[0])) |
| 56 | + | self.pool.join() |
| 57 | + | except Exception as e: |
| 58 | + | self.pool.terminate() |
| 59 | + | self.wfile.write('[-] Exception Caught: {}'.format(e).encode()) |
| 60 | + | print("[-] Exception Caught: {}".format(e)) |
| 61 | + | self.pool.join() |
60 | 62 | | |
61 | | - | |
62 | | - | class ExploitServer(exploitdb.ExploitSearch, socketserver.ThreadingMixIn, socketserver.TCPServer): |
63 | | - | def __init__(self, connectionInfo, handler): |
64 | | - | exploitdb.ExploitSearch.__init__(self) |
65 | | - | socketserver.TCPServer.__init__(self, connectionInfo, handler) |
66 | | - | socketserver.ThreadingMixIn.__init__(self) |
| 63 | + | @classmethod |
| 64 | + | def search(cls, data): |
| 65 | + | query = data.decode().strip().split(" ") |
| 66 | + | query[-1] = query[-1][:3] #cut down on the last item which should be the version number |
| 67 | + | output = [] |
| 68 | + | for rows in ExploitServer.exploitDatabase: |
| 69 | + | if all([term in rows["description"] for term in query]): |
| 70 | + | output.append('\t'.join((rows["description"], rows["file"]))) |
| 71 | + | if output: |
| 72 | + | return "[ ] " + "\n".join([' '.join(query), *output]) |
67 | 73 | | |
68 | 74 | | |
69 | 75 | | |
| 76 | + | class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): |
| 77 | + | exploitDatabase = [] |
70 | 78 | | |
71 | 79 | | |
72 | 80 | | def main(): |
| skipped 7 lines |
80 | 88 | | exploit.server_close() |
81 | 89 | | |
82 | 90 | | if __name__ == "__main__": |
| 91 | + | #parse the args |
| 92 | + | parser = argparse.ArgumentParser() |
| 93 | + | parser.add_argument("-i", "--ip", help="Ip to listen on") |
| 94 | + | parser.add_argument("-p", "--port", help="Port to listen on") |
| 95 | + | parser.add_argument("-f", "--file", help="The exploit csv to use") |
| 96 | + | args = parser.parse_args() |
| 97 | + | if args.ip: |
| 98 | + | _IP_ = args.ip |
| 99 | + | if args.port: |
| 100 | + | _PORT_ = args.port |
| 101 | + | if args.file: |
| 102 | + | _SEARCHSPLOIT_ = args.file |
| 103 | + | |
| 104 | + | if not isfile(_SEARCHSPLOIT_): |
| 105 | + | print("[-] Cannot find csv databse: {}\nFor more details visit: https://github.com/offensive-security/exploit-database".format(_SEARCHSPLOIT_)) |
| 106 | + | exit(2) |
| 107 | + | |
| 108 | + | #parse the exploit database and collect all the results |
| 109 | + | try: |
| 110 | + | with open(_SEARCHSPLOIT_) as Fin: |
| 111 | + | reader = DictReader(Fin) |
| 112 | + | for lines in reader: |
| 113 | + | #add the database to the exploit server for non global persistance... or maybe it is technically still global? |
| 114 | + | ExploitServer.exploitDatabase.append(lines) |
| 115 | + | except Exception as e: |
| 116 | + | print("[-] Exception caught while attempting to parse database file. {}".format(e)) |
| 117 | + | exit(3) |
| 118 | + | |
| 119 | + | print("[ ] Starting up") |
83 | 120 | | main() |