def open(self, staged=False): """ opens the server part and listens for connections :param staged: should we stage first? :return: True if successfull """ if not self.validate_options(): return False self.conn = None self.socket = None self.staged = staged lparams = (self.options['LHOST']['Value'], int(self.options['LPORT']['Value'])) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.socket.bind(lparams) except PermissionError as e: print_error("Could not open TCP server on {}:{}: {}".format( lparams[0], lparams[1], str(e))) return False self.socket.listen(1) print_message("TCP transport listening on {}:{}".format( lparams[0], lparams[1])) self.conn, addr = self.socket.accept() print_message("Connection from {}:{}".format(addr[0], addr[1])) return True
def create_signature(pkey, data, digest='sha512'): try: sig = OpenSSL.crypto.sign(pkey, data, digest) return sig except Exception as e: print_error("Signature creation failed: {}".format(e)) return None
def verify_signature(cert, signature, data, digest='sha512'): try: OpenSSL.crypto.verify(cert, signature, data, digest) return True except Exception as e: print_error("Signature verification failed: {}".format(e)) return False
def write(self, data): """ writes data to this channel :param data: data to write to the channel :return: None """ if not self.isOpen(): print_error("cannot write to non-open channel") return return self.sendqueue.write(data)
def dnsip4encode(data): """ encodes the data as a single IPv4 address :param data: data to encode :return: encoded form """ if len(data) > 4 or len(data) < 4: print_error("dnsip4encode: data ({}) is more or less than 4 bytes, cannot encode".format(data)) return None return '{}.{}.{}.{}'.format(*data).encode("utf-8")
def send(self, data): """ send data to the connected host :param data: data to send :return: None """ if not self.conn: print_error("Connection not open") return self.conn.send(data)
def load_certificate(filename): cert = None f = None try: f = open(filename, 'rb') cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read()) except Exception as e: print_error("Loading certificate file failed: {}".format(e)) finally: if f: f.close() return cert
def _validate_port(name, port): """ checks whether the port value is plausible :param name: name of the option, to use in messages :param port: port number to check :return: True iff plausible """ if not isportnumber(port): print_error( str(name) + " is invalid, should be 1 <= port <= 65535") return False else: return True
def do_upload(self, line): """upload LOCALFILE REMOTETARGETFILE :: upload the LOCALFILE from here to the agent file system as """\ """REMOTETARGETFILE""" v = line.split(" ") if len(v) != 2: print_error( "upload: expected LOCALFILE and REMOTETARGETFILE, e.g. upload " "/tmp/input.txt C:\\output.txt") return self.msgqueue.put(["upload", v[0], v[1]]) self.msgqueue.join()
def do_download(self, line): """download REMOTEFILE LOCALTARGETFILE :: download the REMOTEFILE in the agents file system to """\ """LOCALTARGETFILE here""" v = line.split(" ") if len(v) != 2: print_error( "download: expected REMOTEFILE and LOCALTARGETFILE, e.g. download " "C:\\input.txt /tmp/output.txt") return self.msgqueue.put(["download", v[0], v[1]]) self.msgqueue.join()
def writeFromSend(self, data): """ writes data to the receivequeue of this channel, to be used from connection only :param data: data to write to the channel :return: None """ if not self.isOpen(): print_error("cannot write to non-open channel") return # TODO: remove the message here print_debug(DEBUG_MODULE, "received data in channel: {}".format(data)) self.receivequeue.write(data)
def dnsip6encode(data): """ encodes the data as a single IPv6 address :param data: data to encode :return: encoded form """ if len(data) != 16: print_error("dnsip6encode: data is more or less than 16 bytes, cannot encode") return None res = b'' reslen = 0 for i in range(len(data)): res += base64.b16encode(data[i:i+1]) reslen += 1 if reslen % 2 == 0: res += b':' return res[:-1]
def receive(self, leng=1024): """ receive data from connected host :param leng: length of data to collect :return: data (or None if connection closed) """ if not self.conn: print_error("Connection not open") return None try: data = self.conn.recv(leng) except ConnectionResetError: data = None print_debug(DEBUG_MODULE, "received data: {}".format(data)) if not data: print_error("Connection closed by peer") self.close() return data
def validate_options(self): """ Validate all currently set module options. Can be overwritten and expanded by modules. """ valid = True # check for each option for option, values in self.options.items(): # make sure all options are set if values['Required'] and not (values['Value']) or (values['Value'] == ''): print_error(str(option) + " must be set") valid = False # make sure all options with listed alternatives are correct if 'Options' in values and values['Options'] and not ( values['Value'] in values['Options']): print_error( str(option) + " must be one of " + (", ".join(values['Options']))) valid = False return valid
def setoption(self, name, value): """ Sets option <name> to value <value> if possible. Can be overwritten and expanded by modules. """ # name and value must be set and must be string if not name or not isinstance(name, str): print_error("Option name not understood") return False if not value or not isinstance(value, str): print_error("Option value not understood") return False # check whether there is an option of that name if name and isinstance(name, str) and name.upper() in self.options: values = self.options[name.upper()] # if it is an option with fixed values, check whether the value matches if 'Options' in values and values['Options'] and not ( value.upper() in values['Options']): print_error( str(name.upper()) + " must be one of " + (", ".join(values['Options']))) return True # ok, strange, but True only means we found it, even if setting failed elif 'Options' in values and values['Options']: # and if so, set the value to upper case value = value.upper() # finally set the value self.options[name.upper()]['Value'] = value return True else: # no option of that name here # no error now, module should catch that return False