def vte_child_routine(config): """ This is the method which is executed within the child process spawned by VTE. It expects additional values to be set in the *config* object so it can initialize a new :py:class:`.KingPhisherRPCClient` instance. It will then drop into an interpreter where the user may directly interact with the rpc object. :param str config: A JSON encoded client configuration. """ config = json_ex.loads(config) try: import readline import rlcompleter # pylint: disable=unused-variable except ImportError: pass else: readline.parse_and_bind('tab: complete') for plugins_directory in ('rpc_plugins', 'rpc-plugins'): plugins_directory = find.find_data_directory(plugins_directory) if not plugins_directory: continue sys.path.append(plugins_directory) headers = config['rpc_data'].pop('headers') rpc = KingPhisherRPCClient(**config['rpc_data']) if rpc.headers is None: rpc.headers = {} for name, value in headers.items(): rpc.headers[str(name)] = str(value) banner = "Python {0} on {1}".format(sys.version, sys.platform) print(banner) # pylint: disable=superfluous-parens information = "Campaign Name: '{0}' ID: {1}".format( config['campaign_name'], config['campaign_id']) print(information) # pylint: disable=superfluous-parens console_vars = { 'CAMPAIGN_NAME': config['campaign_name'], 'CAMPAIGN_ID': config['campaign_id'], 'os': os, 'rpc': rpc, 'sys': sys } export_to_builtins = ['CAMPAIGN_NAME', 'CAMPAIGN_ID', 'rpc'] console = code.InteractiveConsole(console_vars) for var in export_to_builtins: console.push("__builtins__['{0}'] = {0}".format(var)) console.interact( 'The \'rpc\' object holds the connected KingPhisherRPCClient instance') return
def vte_child_routine(config): """ This is the method which is executed within the child process spawned by VTE. It expects additional values to be set in the *config* object so it can initialize a new :py:class:`.KingPhisherRPCClient` instance. It will then drop into an interpreter where the user may directly interact with the rpc object. :param str config: A JSON encoded client configuration. """ config = json_ex.loads(config) try: import readline import rlcompleter # pylint: disable=unused-variable except ImportError: pass else: readline.parse_and_bind('tab: complete') for plugins_directory in ('rpc_plugins', 'rpc-plugins'): plugins_directory = find.find_data_directory(plugins_directory) if not plugins_directory: continue sys.path.append(plugins_directory) headers = config['rpc_data'].pop('headers') rpc = KingPhisherRPCClient(**config['rpc_data']) if rpc.headers is None: rpc.headers = {} for name, value in headers.items(): rpc.headers[str(name)] = str(value) banner = "Python {0} on {1}".format(sys.version, sys.platform) print(banner) # pylint: disable=superfluous-parens information = "Campaign Name: '{0}' ID: {1}".format(config['campaign_name'], config['campaign_id']) print(information) # pylint: disable=superfluous-parens console_vars = { 'CAMPAIGN_NAME': config['campaign_name'], 'CAMPAIGN_ID': config['campaign_id'], 'os': os, 'rpc': rpc, 'sys': sys } export_to_builtins = ['CAMPAIGN_NAME', 'CAMPAIGN_ID', 'rpc'] console = code.InteractiveConsole(console_vars) for var in export_to_builtins: console.push("__builtins__['{0}'] = {0}".format(var)) console.interact('The \'rpc\' object holds the connected KingPhisherRPCClient instance') return
def __init__(self, file_name, mode, encoding='utf-8'): """ :param str file_name: The path to the file to open as an archive. :param str mode: The mode to open the file such as 'r' or 'w'. :param str encoding: The encoding to use for strings. """ self._mode = mode + ':bz2' self.encoding = encoding self.file_name = file_name epoch = datetime.datetime.utcfromtimestamp(0) self.mtime = (datetime.datetime.utcnow() - epoch).total_seconds() self._tar_h = tarfile.open(file_name, self._mode) if 'r' in mode and self.has_file(self.metadata_file_name): self.metadata = json_ex.loads(self.get_data(self.metadata_file_name).decode(self.encoding)) else: self.metadata = {} if 'w' in mode: self.metadata['timestamp'] = datetime.datetime.utcnow().isoformat() self.metadata['version'] = version.version
def __init__(self, file_name, mode, encoding='utf-8'): """ :param str file_name: The path to the file to open as an archive. :param str mode: The mode to open the file such as 'r' or 'w'. :param str encoding: The encoding to use for strings. """ self._mode = mode + ':bz2' self.encoding = encoding self.file_name = file_name epoch = datetime.datetime.utcfromtimestamp(0) self.mtime = (datetime.datetime.utcnow() - epoch).total_seconds() self._tar_h = tarfile.open(file_name, self._mode) if 'r' in mode and self.has_file(self.metadata_file_name): self.metadata = json_ex.loads( self.get_data(self.metadata_file_name).decode(self.encoding)) else: self.metadata = {} if 'w' in mode: self.metadata['timestamp'] = datetime.datetime.utcnow().isoformat() self.metadata['version'] = version.version
def message_data_from_kpm(target_file, dest_dir): """ Retrieve the stored details describing a message from a previously exported file. :param str target_file: The file to load as a message archive. :param str dest_dir: The directory to extract data and attachment files to. :return: The restored details from the message config. :rtype: dict """ if not archive.is_archive(target_file): logger.warning('the file is not recognized as a valid archive') raise KingPhisherInputValidationError('file is not in the correct format') kpm = archive.ArchiveFile(target_file, 'r') attachment_member_names = [n for n in kpm.file_names if n.startswith('attachments' + os.path.sep)] attachments = [] if not kpm.has_file('message_config.json'): logger.warning('the kpm archive is missing the message_config.json file') raise KingPhisherInputValidationError('data is missing from the message archive') message_config = kpm.get_data('message_config.json') message_config = json_ex.loads(message_config) if attachment_member_names: attachment_dir = os.path.join(dest_dir, 'attachments') if not os.path.isdir(attachment_dir): os.mkdir(attachment_dir) for file_name in attachment_member_names: arcfile_h = kpm.get_file(file_name) file_name = os.path.basename(file_name) file_path = os.path.join(attachment_dir, file_name) with open(file_path, 'wb') as file_h: shutil.copyfileobj(arcfile_h, file_h) attachments.append(file_path) logger.debug("extracted {0} attachment file{1} from the archive".format(len(attachments), 's' if len(attachments) > 1 else '')) for config_name, file_name in KPM_ARCHIVE_FILES.items(): if not file_name in kpm.file_names: if config_name in message_config: logger.warning("the kpm archive is missing the {0} file".format(file_name)) raise KingPhisherInputValidationError('data is missing from the message archive') continue if not message_config.get(config_name): logger.warning("the kpm message configuration is missing the {0} setting".format(config_name)) raise KingPhisherInputValidationError('data is missing from the message archive') arcfile_h = kpm.get_file(file_name) file_path = os.path.join(dest_dir, message_config[config_name]) with open(file_path, 'wb') as file_h: shutil.copyfileobj(arcfile_h, file_h) message_config[config_name] = file_path if 'message_content.html' in kpm.file_names: if not 'html_file' in message_config: logger.warning('the kpm message configuration is missing the html_file setting') raise KingPhisherInputValidationError('data is missing from the message archive') arcfile_h = kpm.get_file('message_content.html') file_path = os.path.join(dest_dir, message_config['html_file']) with open(file_path, 'wb') as file_h: file_h.write(message_template_from_kpm(arcfile_h.read(), attachments)) message_config['html_file'] = file_path elif 'html_file' in message_config: logger.warning('the kpm archive is missing the message_content.html file') raise KingPhisherInputValidationError('data is missing from the message archive') kpm.close() return message_config
def test_json_ex_loads(self): try: json_ex.loads(json_ex.dumps('test')) except ValueError: self.fail('Invalid data type for json_ex.loads()')
def test_json_ex_loads_invalid(self): with self.assertRaises(ValueError): json_ex.loads("'test")