예제 #1
0
	def test_server_config_verification(self):
		config_file = find.find_data_file('server_config.yml')
		verify_config_file = find.find_data_file('server_config_verification.yml')
		self.assertIsNotNone(config_file)
		config = configuration.Configuration(config_file)
		bad_options = config.get_missing(verify_config_file)
		self.assertIsInstance(bad_options, dict)
		incompatible_options = bad_options.get('incompatible')
		self.assertFalse(bool(incompatible_options), msg='an option is of an invalid type in the server config template')
		missing_options = bad_options.get('missing')
		self.assertFalse(bool(missing_options), msg='an option is missing in the server config template')
예제 #2
0
	def test_server_config_verification(self):
		config_file = find.find_data_file('server_config.yml')
		verify_config_file = find.find_data_file('server_config_verification.yml')
		self.assertIsNotNone(config_file)
		config = Configuration(config_file)
		bad_options = config.get_missing(verify_config_file)
		self.assertIsInstance(bad_options, dict)
		incompatible_options = bad_options.get('incompatible')
		self.assertFalse(bool(incompatible_options), msg='an option is of an invalid type in the server config template')
		missing_options = bad_options.get('missing')
		self.assertFalse(bool(missing_options), msg='an option is missing in the server config template')
예제 #3
0
 def _create_ui_manager(self):
     uimanager = Gtk.UIManager()
     with open(find.find_data_file(
             'ui_info/client_window.xml')) as ui_info_file:
         ui_data = ui_info_file.read()
     uimanager.add_ui_from_string(ui_data)
     return uimanager
예제 #4
0
	def __init__(self, *args, **kwargs):
		super(CampaignViewDashboardTab, self).__init__(*args, **kwargs)
		self.graphs = []
		"""The :py:class:`.CampaignGraph` classes represented on the dash board."""

		dash_ports = {
			# dashboard position, (width, height)
			'top_left': (380, 200),
			'top_right': (380, 200),
			'bottom': (760, 200)
		}
		for dash_port, details in dash_ports.items():
			graph_name = self.config['dashboard.' + dash_port]
			cls = graphs.get_graph(graph_name)
			if not cls:
				self.logger.warning('could not get graph: ' + graph_name)
				logo_file_path = find.find_data_file('king-phisher-icon.svg')
				if logo_file_path:
					image = Gtk.Image.new_from_pixbuf(GdkPixbuf.Pixbuf.new_from_file_at_size(logo_file_path, 128, 128))
					image.show()
					self.gobjects['scrolledwindow_' + dash_port].add(image)
				continue
			graph_inst = cls(self.application, details, getattr(self, self.top_gobject).get_style_context())
			self.gobjects['scrolledwindow_' + dash_port].add(graph_inst.canvas)
			self.gobjects['box_' + dash_port].pack_end(graph_inst.navigation_toolbar, False, False, 0)
			self.graphs.append(graph_inst)
		self.logger.debug("dashboard refresh frequency set to {0} seconds".format(self.refresh_frequency))
		GLib.timeout_add_seconds(self.refresh_frequency, self.loader_idle_routine)
예제 #5
0
	def _create_config(self):
		config_dir = os.path.dirname(self.config_file)
		if not os.path.isdir(config_dir):
			self.logger.debug('creating the user configuration directory')
			os.makedirs(config_dir)
		client_template = find.find_data_file('client_config.json')
		shutil.copy(client_template, self.config_file)
예제 #6
0
 def setUp(self):
     find.data_path_append('data/server')
     web_root = os.path.join(os.getcwd(), 'data', 'server', 'king_phisher')
     config = smoke_zephyr.configuration.Configuration(
         find.find_data_file('server_config.yml'))
     config.set('server.address.host', '127.0.0.1')
     config.set('server.address.port', 0)
     config.set('server.addresses', [])
     config.set('server.database', 'sqlite://')
     config.set(
         'server.geoip.database',
         os.environ.get('KING_PHISHER_TEST_GEOIP_DB',
                        './GeoLite2-City.mmdb'))
     config.set('server.web_root', web_root)
     config.set('server.rest_api.enabled', True)
     config.set('server.rest_api.token', rest_api.generate_token())
     self.config = config
     self.plugin_manager = plugins.ServerPluginManager(config)
     self.server = build.server_from_config(
         config,
         handler_klass=KingPhisherRequestHandlerTest,
         plugin_manager=self.plugin_manager)
     config.set('server.address.port',
                self.server.sub_servers[0].server_port)
     self.assertIsInstance(self.server, server.KingPhisherServer)
     self.server_thread = threading.Thread(target=self.server.serve_forever)
     self.server_thread.daemon = True
     self.server_thread.start()
     self.assertTrue(self.server_thread.is_alive())
     self.shutdown_requested = False
     self.rpc = client_rpc.KingPhisherRPCClient(
         ('localhost', self.config.get('server.address.port')))
     self.rpc.login(username='******', password='******')
예제 #7
0
	def do_activate(self):
		Gtk.Application.do_activate(self)
		sys.excepthook = self.exception_hook

		# load a custom css file if one is available
		css_file = find.find_data_file('king-phisher-client.css')
		if css_file:
			self.logger.debug('loading custom css file: ' + css_file)
			css_file = Gio.File.new_for_path(css_file)
			style_provider = Gtk.CssProvider()
			style_provider.connect('parsing-error', self.signal_css_provider_parsing_error)
			try:
				style_provider.load_from_file(css_file)
			except GLib.Error:
				self.logger.error('there was an error parsing the css file, it will not be applied as a style provider')
			else:
				Gtk.StyleContext.add_provider_for_screen(
					Gdk.Screen.get_default(),
					style_provider,
					Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
				)
		else:
			self.logger.debug('no custom css file was found')

		# create and show the main window
		self.main_window = windows.MainApplicationWindow(self.config, self)
		self.main_window.set_position(Gtk.WindowPosition.CENTER)
		self.main_window.show()
예제 #8
0
	def test_server_config(self):
		config_file = find.find_data_file('server_config.yml')
		self.assertIsNotNone(config_file)
		self.assertTrue(os.path.isfile(config_file))
		config = configuration.Configuration(config_file)
		self.assertTrue(config.has_section('server'))
		self.assertTrue(config.has_section('server.address'))
예제 #9
0
 def test_server_config(self):
     config_file = find.find_data_file('server_config.yml')
     self.assertIsNotNone(config_file)
     self.assertTrue(os.path.isfile(config_file))
     config = configuration.Configuration(config_file)
     self.assertTrue(config.has_section('server'))
     self.assertTrue(config.has_section('server.address'))
예제 #10
0
	def __init__(self, config, application):
		"""
		:param dict config: The main King Phisher client configuration.
		:param application: The application instance to which this window belongs.
		:type application: :py:class:`.KingPhisherClientApplication`
		"""
		assert isinstance(application, Gtk.Application)
		super(MainApplicationWindow, self).__init__(application=application)
		self.application = application
		self.logger = logging.getLogger('KingPhisher.Client.MainWindow')
		self.config = config
		"""The main King Phisher client configuration."""
		self.set_property('title', 'King Phisher')
		vbox = Gtk.Box()
		vbox.set_property('orientation', Gtk.Orientation.VERTICAL)
		vbox.show()
		self.add(vbox)
		default_icon_file = find.find_data_file('king-phisher-icon.svg')
		if default_icon_file:
			icon_pixbuf = GdkPixbuf.Pixbuf.new_from_file(default_icon_file)
			self.set_default_icon(icon_pixbuf)
		self.accel_group = Gtk.AccelGroup()
		self.add_accel_group(self.accel_group)
		self.menubar = MainMenuBar(application, self)
		vbox.pack_start(self.menubar.menubar, False, False, 0)

		# create notebook and tabs
		self.notebook = Gtk.Notebook()
		"""The primary :py:class:`Gtk.Notebook` that holds the top level taps of the client GUI."""
		self.notebook.connect('switch-page', self.signal_notebook_switch_page)
		self.notebook.set_scrollable(True)
		vbox.pack_start(self.notebook, True, True, 0)

		self.tabs = {}
		current_page = self.notebook.get_current_page()
		self.last_page_id = current_page

		mailer_tab = MailSenderTab(self, self.application)
		self.tabs['mailer'] = mailer_tab
		self.notebook.insert_page(mailer_tab.box, mailer_tab.label, current_page + 1)
		self.notebook.set_current_page(current_page + 1)

		campaign_tab = CampaignViewTab(self, self.application)
		campaign_tab.box.show()
		self.tabs['campaign'] = campaign_tab
		self.notebook.insert_page(campaign_tab.box, campaign_tab.label, current_page + 2)

		self.set_size_request(800, 600)
		self.connect('delete-event', self.signal_delete_event)
		self.notebook.show()
		self.show()
		self.rpc = None # needs to be initialized last
		"""The :py:class:`.KingPhisherRPCClient` instance."""

		self.application.connect('server-connected', self.signal_kp_server_connected)

		self.login_dialog = dialogs.LoginDialog(self.application)
		self.login_dialog.dialog.connect('response', self.signal_login_dialog_response)
		self.login_dialog.dialog.show()
예제 #11
0
def which_glade():
    """
	Locate the glade data file.

	:return: The path to the glade data file.
	:rtype: str
	"""
    return find.find_data_file(os.environ['KING_PHISHER_GLADE_FILE'])
예제 #12
0
	def __init__(self, *args, **kwargs):
		super(AboutDialog, self).__init__(*args, **kwargs)
		logo_file_path = find.find_data_file('king-phisher-icon.svg')
		if logo_file_path:
			logo_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(logo_file_path, 128, 128)
			self.dialog.set_property('logo', logo_pixbuf)
		self.dialog.set_property('version', version.version)
		self.dialog.connect('activate-link', lambda _, url: utilities.open_uri(url))
	def _create_ui_manager(self):
		uimanager = Gtk.UIManager()
		with open(find.find_data_file('ui_info/rpc_terminal_window.xml')) as ui_info_file:
			ui_data = ui_info_file.read()
		uimanager.add_ui_from_string(ui_data)
		accelgroup = uimanager.get_accel_group()
		self.window.add_accel_group(accelgroup)
		return uimanager
예제 #14
0
	def _create_ui_manager(self):
		uimanager = Gtk.UIManager()
		with open(find.find_data_file('ui_info/rpc_terminal_window.xml')) as ui_info_file:
			ui_data = ui_info_file.read()
		uimanager.add_ui_from_string(ui_data)
		accelgroup = uimanager.get_accel_group()
		self.window.add_accel_group(accelgroup)
		return uimanager
	def test_client_template_config(self):
		find.data_path_append('data/client')
		config_h = open(find.find_data_file('client_config.json'))
		try:
			json.load(config_h)
		except:
			self.fail("failed to parse the client JSON configuration file")
		finally:
			config_h.close()
예제 #16
0
 def test_client_template_config(self):
     find.data_path_append('data/client')
     config_h = open(find.find_data_file('client_config.json'))
     try:
         json.load(config_h)
     except:
         self.fail("failed to parse the client JSON configuration file")
     finally:
         config_h.close()
예제 #17
0
def which_glade():
	"""
	Locate the glade data file which stores the UI information in a Gtk Builder
	format.

	:return: The path to the glade data file.
	:rtype: str
	"""
	return find.find_data_file(os.environ.get('KING_PHISHER_GLADE_FILE', 'king-phisher-client.ui'))
예제 #18
0
def which_glade():
	"""
	Locate the glade data file which stores the UI information in a Gtk Builder
	format.

	:return: The path to the glade data file.
	:rtype: str
	"""
	return find.find_data_file(os.environ.get('KING_PHISHER_GLADE_FILE', 'king-phisher-client.ui'))
	def respond_not_found(self):
		self.send_response(404, 'Resource Not Found')
		self.send_header('Content-Type', 'text/html')
		self.end_headers()
		page_404 = find.find_data_file('error_404.html')
		if page_404:
			shutil.copyfileobj(open(page_404), self.wfile)
		else:
			self.wfile.write('Resource Not Found\n')
		return
예제 #20
0
	def test_server_config(self):
		config_file = find.find_data_file('server_config.yml')
		self.assertIsNotNone(config_file)
		self.assertTrue(os.path.isfile(config_file))
		config = configuration.Configuration(config_file)
		self.assertTrue(config.has_section('server'))
		self.assertTrue(config.has_option('server.addresses'))
		addresses = config.get('server.addresses')
		self.assertIsInstance(addresses, list)
		self.assertGreater(len(addresses), 0)
예제 #21
0
	def do_reload_css_style(self):
		if self.style_provider:
			Gtk.StyleContext.remove_provider_for_screen(
				Gdk.Screen.get_default(),
				self.style_provider
			)
			self.style_provider = None
		css_file = find.find_data_file('king-phisher-client.css')
		if css_file:
			self.style_provider = self.load_style_css(css_file)
예제 #22
0
 def __init__(self, *args, **kwargs):
     super(AboutDialog, self).__init__(*args, **kwargs)
     logo_file_path = find.find_data_file('king-phisher-icon.svg')
     if logo_file_path:
         logo_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
             logo_file_path, 128, 128)
         self.dialog.set_property('logo', logo_pixbuf)
     self.dialog.set_property('version', version.version)
     self.dialog.connect('activate-link',
                         lambda _, url: utilities.open_uri(url))
예제 #23
0
 def test_server_config(self):
     config_file = find.find_data_file('server_config.yml')
     self.assertIsNotNone(config_file)
     self.assertTrue(os.path.isfile(config_file))
     config = configuration.Configuration(config_file)
     self.assertTrue(config.has_section('server'))
     self.assertTrue(config.has_option('server.addresses'))
     addresses = config.get('server.addresses')
     self.assertIsInstance(addresses, list)
     self.assertGreater(len(addresses), 0)
예제 #24
0
 def respond_not_found(self):
     self.send_response(404, 'Resource Not Found')
     self.send_header('Content-Type', 'text/html')
     self.end_headers()
     page_404 = find.find_data_file('error_404.html')
     if page_404:
         with open(page_404, 'rb') as page_404:
             shutil.copyfileobj(page_404, self.wfile)
     else:
         self.wfile.write('Resource Not Found\n')
     return
예제 #25
0
 def respond_not_found(self):
     self.send_response(404, "Resource Not Found")
     self.send_header("Content-Type", "text/html")
     self.end_headers()
     page_404 = find.find_data_file("error_404.html")
     if page_404:
         with open(page_404, "rb") as page_404:
             shutil.copyfileobj(page_404, self.wfile)
     else:
         self.wfile.write("Resource Not Found\n")
     return
예제 #26
0
	def __init__(self):
		super(CustomCompletionProviderBase, self).__init__()
		self.logger = logging.getLogger('KingPhisher.Client.' + self.__class__.__name__)
		if self.data_file is not None:
			completion_data = find.find_data_file(os.path.join('completion', self.data_file))
			if completion_data is None:
				raise RuntimeError("failed to find completion data file '{0}'".format(self.data_file))
			self.logger.debug("loading {0} completion data from: {1}".format(self.name, completion_data))
			with open(completion_data, 'r') as file_h:
				completion_data = json_ex.load(file_h)
			self.load_data(completion_data)
예제 #27
0
 def respond_not_found(self):
     self.send_response(404, 'Not Found')
     self.send_header('Content-Type', 'text/html')
     page_404 = find.find_data_file('error_404.html')
     if page_404:
         with open(page_404, 'rb') as file_h:
             message = file_h.read()
     else:
         message = b'Resource Not Found\n'
     self.send_header('Content-Length', len(message))
     self.end_headers()
     self.wfile.write(message)
     return
예제 #28
0
	def _create_config(self):
		config_dir = os.path.dirname(self.config_file)
		if not os.path.isdir(config_dir):
			self.logger.debug('creating the user configuration directory')
			os.makedirs(config_dir)
		# move the pre 1.0.0 config file if it exists
		old_path = os.path.expanduser('~/.king_phisher.json')
		if os.path.isfile(old_path) and os.access(old_path, os.R_OK):
			self.logger.debug('moving the old config file to the new location')
			os.rename(old_path, self.config_file)
		else:
			client_template = find.find_data_file('client_config.json')
			shutil.copy(client_template, self.config_file)
예제 #29
0
 def _create_config(self):
     config_dir = os.path.dirname(self.config_file)
     if not os.path.isdir(config_dir):
         self.logger.debug('creating the user configuration directory')
         os.makedirs(config_dir)
     # move the pre 1.0.0 config file if it exists
     old_path = os.path.expanduser('~/.king_phisher.json')
     if os.path.isfile(old_path) and os.access(old_path, os.R_OK):
         self.logger.debug('moving the old config file to the new location')
         os.rename(old_path, self.config_file)
     else:
         client_template = find.find_data_file('client_config.json')
         shutil.copy(client_template, self.config_file)
예제 #30
0
	def respond_not_found(self):
		self.send_response(404, 'Not Found')
		self.send_header('Content-Type', 'text/html')
		page_404 = find.find_data_file('error_404.html')
		if page_404:
			with open(page_404, 'rb') as file_h:
				message = file_h.read()
		else:
			message = b'Resource Not Found\n'
		self.send_header('Content-Length', len(message))
		self.end_headers()
		self.wfile.write(message)
		return
	def _create_ui_manager(self):
		uimanager = Gtk.UIManager()
		with open(find.find_data_file('ui_info/client_window.xml')) as ui_info_file:
			ui_data = ui_info_file.read()
		uimanager.add_ui_from_string(ui_data)
		if graphs.has_matplotlib:
			merge_id = uimanager.new_merge_id()
			uimanager.add_ui(merge_id, '/MenuBar/ToolsMenu', 'ToolsGraphMenu', 'ToolsGraphMenu', Gtk.UIManagerItemType.MENU, False)
			for graph_name in graphs.get_graphs():
				action_name = 'ToolsGraph' + graph_name
				uimanager.add_ui(merge_id, '/MenuBar/ToolsMenu/ToolsGraphMenu', action_name, action_name, Gtk.UIManagerItemType.MENUITEM, False)
		accelgroup = uimanager.get_accel_group()
		self.add_accel_group(accelgroup)
		return uimanager
예제 #32
0
	def do_activate(self):
		Gtk.Application.do_activate(self)
		sys.excepthook = self.exception_hook

		# load a custom css file if one is available
		css_file = find.find_data_file('king-phisher-client.css')
		if css_file:
			self.style_provider = self.load_style_css(css_file)
		else:
			self.logger.debug('no custom css file was found')

		# create and show the main window
		self.main_window = windows.MainApplicationWindow(self.config, self)
		self.main_window.set_position(Gtk.WindowPosition.CENTER)
		self.main_window.show()
	def setUp(self):
		find.data_path_append('data/server')
		web_root = os.path.join(os.getcwd(), 'data', 'server', 'king_phisher')
		config = configuration.Configuration(find.find_data_file('server_config.yml'))
		config.set('server.address.port', random.randint(2000, 10000))
		config.set('server.database', ':memory:')
		config.set('server.web_root', web_root)
		self.config = config
		self.server = build_king_phisher_server(config, HandlerClass=KingPhisherRequestHandlerTest)
		self.assertIsInstance(self.server, KingPhisherServer)
		self.server.init_database(config.get('server.database'))
		self.server_thread = threading.Thread(target=self.server.serve_forever)
		self.server_thread.daemon = True
		self.server_thread.start()
		self.assertTrue(self.server_thread.is_alive())
		self.shutdown_requested = False
예제 #34
0
    def do_config_load(self, load_defaults):
        """
		Load the client configuration from disk and set the
		:py:attr:`~.KingPhisherClientApplication.config` attribute.

		:param bool load_defaults: Load missing options from the template configuration file.
		"""
        self.logger.info('loading the config from disk')
        client_template = find.find_data_file('client_config.json')
        config_file = os.path.expanduser(self.config_file)
        with open(config_file, 'r') as tmp_file:
            self.config = json_ex.load(tmp_file)
        if load_defaults:
            with open(client_template, 'r') as tmp_file:
                client_template = json_ex.load(tmp_file)
            for key, value in client_template.items():
                if not key in self.config:
                    self.config[key] = value
예제 #35
0
	def do_config_load(self, load_defaults):
		"""
		Load the client configuration from disk and set the
		:py:attr:`~.KingPhisherClientApplication.config` attribute.

		:param bool load_defaults: Load missing options from the template configuration file.
		"""
		self.logger.info('loading the config from disk')
		client_template = find.find_data_file('client_config.json')
		config_file = os.path.expanduser(self.config_file)
		with open(config_file, 'r') as tmp_file:
			self.config = json_ex.load(tmp_file)
		if load_defaults:
			with open(client_template, 'r') as tmp_file:
				client_template = json_ex.load(tmp_file)
			for key, value in client_template.items():
				if not key in self.config:
					self.config[key] = value
예제 #36
0
    def show_about_dialog(self):
        """
		Display the about dialog showing details about the programs version,
		license etc.
		"""
        license_text = None
        if os.path.splitext(__file__)[1] == '.py':
            source_file_h = open(__file__, 'r')
            source_code = []
            source_code.append(source_file_h.readline())
            while source_code[-1].startswith('#'):
                source_code.append(source_file_h.readline())
            source_code = source_code[5:-1]
            source_code = map(lambda x: x.strip('# '), source_code)
            license_text = ''.join(source_code)
        logo_pixbuf = None
        logo_file_path = find.find_data_file('king-phisher-icon.svg')
        if logo_file_path:
            logo_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                logo_file_path, 128, 128)
        about_dialog = Gtk.AboutDialog()
        about_dialog.set_transient_for(self)
        about_dialog_properties = {
            'authors': ['Spencer McIntyre', 'Jeff McCutchan', 'Brandan Geise'],
            'comments': 'Phishing Campaign Toolkit',
            'copyright': 'Copyright (c) 2013-2015, SecureState LLC',
            'license-type': Gtk.License.BSD,
            'program-name': 'King Phisher',
            'version': version.version,
            'website': 'https://github.com/securestate/king-phisher',
            'website-label': 'GitHub Home Page',
            'wrap-license': False,
        }
        if license_text:
            about_dialog_properties['license'] = license_text
        if logo_pixbuf:
            about_dialog_properties['logo'] = logo_pixbuf
        for property_name, property_value in about_dialog_properties.items():
            about_dialog.set_property(property_name, property_value)
        about_dialog.connect('activate-link',
                             lambda _, url: utilities.open_uri(url))
        about_dialog.show_all()
        about_dialog.run()
        about_dialog.destroy()
	def handle_javascript_hook(self, query):
		kp_hook_js = find.find_data_file('javascript_hook.js')
		if not kp_hook_js:
			self.respond_not_found()
			return
		javascript = open(kp_hook_js).read()
		if self.config.has_option('beef.hook_url'):
			javascript += "\nloadScript('{0}');\n\n".format(self.config.get('beef.hook_url'))
		self.send_response(200)
		self.send_header('Content-Type', 'text/javascript')
		self.send_header('Pragma', 'no-cache')
		self.send_header('Cache-Control', 'no-cache')
		self.send_header('Expires', '0')
		self.send_header('Access-Control-Allow-Origin', '*')
		self.send_header('Access-Control-Allow-Methods', 'POST, GET')
		self.send_header('Content-Length', str(len(javascript)))
		self.end_headers()
		self.wfile.write(javascript)
		return
예제 #38
0
	def setUp(self):
		find.data_path_append('data/server')
		web_root = os.path.join(os.getcwd(), 'data', 'server', 'king_phisher')
		config = smoke_zephyr.configuration.Configuration(find.find_data_file('server_config.yml'))
		config.set('server.address.port', 0)
		config.set('server.database', 'sqlite://')
		config.set('server.geoip.database', os.environ.get('KING_PHISHER_TEST_GEOIP_DB', './GeoLite2-City.mmdb'))
		config.set('server.web_root', web_root)
		config.set('server.rest_api.enabled', True)
		config.set('server.rest_api.token', rest_api.generate_token())
		self.config = config
		self.server = build_king_phisher_server(config, HandlerClass=KingPhisherRequestHandlerTest)
		config.set('server.address.port', self.server.http_server.server_port)
		self.assertIsInstance(self.server, KingPhisherServer)
		self.server_thread = threading.Thread(target=self.server.serve_forever)
		self.server_thread.daemon = True
		self.server_thread.start()
		self.assertTrue(self.server_thread.is_alive())
		self.shutdown_requested = False
		self.rpc = client_rpc.KingPhisherRPCClient(('localhost', self.config.get('server.address.port')), username='******', password='******')
예제 #39
0
	def handle_javascript_hook(self, query):
		kp_hook_js = find.find_data_file('javascript_hook.js')
		if not kp_hook_js:
			self.respond_not_found()
			return
		with open(kp_hook_js, 'r') as kp_hook_js:
			javascript = kp_hook_js.read()
		if self.config.has_option('beef.hook_url'):
			javascript += "\nloadScript('{0}');\n\n".format(self.config.get('beef.hook_url'))
		self.send_response(200)
		self.send_header('Content-Type', 'text/javascript')
		self.send_header('Pragma', 'no-cache')
		self.send_header('Cache-Control', 'no-cache')
		self.send_header('Expires', '0')
		self.send_header('Access-Control-Allow-Origin', '*')
		self.send_header('Access-Control-Allow-Methods', 'POST, GET')
		self.send_header('Content-Length', len(javascript))
		self.end_headers()
		if not isinstance(javascript, bytes):
			javascript = javascript.encode('utf-8')
		self.wfile.write(javascript)
		return
예제 #40
0
 def setUp(self):
     find.data_path_append('data/server')
     web_root = os.path.join(os.getcwd(), 'data', 'server', 'king_phisher')
     config = configuration.Configuration(
         find.find_data_file('server_config.yml'))
     config.set('server.address.port', 0)
     config.set('server.database', 'sqlite://')
     config.set('server.web_root', web_root)
     self.config = config
     self.server = build_king_phisher_server(
         config, HandlerClass=KingPhisherRequestHandlerTest)
     config.set('server.address.port', self.server.http_server.server_port)
     self.assertIsInstance(self.server, KingPhisherServer)
     self.server_thread = threading.Thread(target=self.server.serve_forever)
     self.server_thread.daemon = True
     self.server_thread.start()
     self.assertTrue(self.server_thread.is_alive())
     self.shutdown_requested = False
     self.rpc = client_rpc.KingPhisherRPCClient(
         ('localhost', self.config.get('server.address.port')),
         username='******',
         password='******')
예제 #41
0
 def handle_javascript_hook(self, query):
     kp_hook_js = find.find_data_file("javascript_hook.js")
     if not kp_hook_js:
         self.respond_not_found()
         return
     with open(kp_hook_js, "r") as kp_hook_js:
         javascript = kp_hook_js.read()
     if self.config.has_option("beef.hook_url"):
         javascript += "\nloadScript('{0}');\n\n".format(self.config.get("beef.hook_url"))
     self.send_response(200)
     self.send_header("Content-Type", "text/javascript")
     self.send_header("Pragma", "no-cache")
     self.send_header("Cache-Control", "no-cache")
     self.send_header("Expires", "0")
     self.send_header("Access-Control-Allow-Origin", "*")
     self.send_header("Access-Control-Allow-Methods", "POST, GET")
     self.send_header("Content-Length", str(len(javascript)))
     self.end_headers()
     if not isinstance(javascript, bytes):
         javascript = javascript.encode("utf-8")
     self.wfile.write(javascript)
     return
예제 #42
0
	def theme_file(self):
		return find.find_data_file(os.path.join('style', 'theme.css'))
예제 #43
0
	def setUp(self):
		find.data_path_append('data/client')
		builder_xml = find.find_data_file('king-phisher-client.ui')
		self.xml_tree = ElementTree.parse(builder_xml)
		self.xml_root = self.xml_tree.getroot()
예제 #44
0
    def __init__(self, config_file=None):
        """
		:param str config_file: The path to the configuration file to load.
		"""
        super(KingPhisherClient, self).__init__()
        self.logger = logging.getLogger('KingPhisher.Client')
        # print version information for debugging purposes
        self.logger.debug("gi.repository GLib version: {0}".format('.'.join(
            map(str, GLib.glib_version))))
        self.logger.debug("gi.repository GObject version: {0}".format('.'.join(
            map(str, GObject.pygobject_version))))
        self.logger.debug("gi.repository Gtk version: {0}.{1}.{2}".format(
            Gtk.get_major_version(), Gtk.get_minor_version(),
            Gtk.get_micro_version()))
        if tools.has_vte:
            self.logger.debug("gi.repository VTE version: {0}".format(
                tools.Vte._version))
        if graphs.has_matplotlib:
            self.logger.debug("matplotlib version: {0}".format(
                graphs.matplotlib.__version__))
        self.config_file = (config_file or CONFIG_FILE_PATH)
        """The file containing the King Phisher client configuration."""
        self.ssh_forwarder = None
        """The :py:class:`.SSHTCPForwarder` instance used for tunneling traffic."""
        self.config = None
        """The main King Phisher client configuration."""
        try:
            self.load_config(load_defaults=True)
        except Exception:
            self.logger.critical('failed to load the client configuration')
            raise
        self.set_property('title', 'King Phisher')
        vbox = Gtk.Box()
        vbox.set_property('orientation', Gtk.Orientation.VERTICAL)
        vbox.show()
        self.add(vbox)
        default_icon_file = find.find_data_file('king-phisher-icon.svg')
        if default_icon_file:
            icon_pixbuf = GdkPixbuf.Pixbuf.new_from_file(default_icon_file)
            self.set_default_icon(icon_pixbuf)

        action_group = Gtk.ActionGroup(name="client_window_actions")
        self._add_menu_actions(action_group)
        uimanager = self._create_ui_manager()
        self._add_menu_optional_actions(action_group, uimanager)
        self.add_accel_group(uimanager.get_accel_group())
        uimanager.insert_action_group(action_group)
        self.uimanager = uimanager
        menubar = uimanager.get_widget("/MenuBar")
        vbox.pack_start(menubar, False, False, 0)

        # create notebook and tabs
        self.notebook = Gtk.Notebook()
        """The primary :py:class:`Gtk.Notebook` that holds the top level taps of the client GUI."""
        self.notebook.connect('switch-page', self.signal_notebook_switch_page)
        self.notebook.set_scrollable(True)
        vbox.pack_start(self.notebook, True, True, 0)

        self.tabs = {}
        current_page = self.notebook.get_current_page()
        self.last_page_id = current_page

        mailer_tab = MailSenderTab(self.config, self)
        self.tabs['mailer'] = mailer_tab
        self.notebook.insert_page(mailer_tab.box, mailer_tab.label,
                                  current_page + 1)
        self.notebook.set_current_page(current_page + 1)

        campaign_tab = CampaignViewTab(self.config, self)
        campaign_tab.box.show()
        self.tabs['campaign'] = campaign_tab
        self.notebook.insert_page(campaign_tab.box, campaign_tab.label,
                                  current_page + 2)

        self.set_size_request(800, 600)
        self.connect('delete-event', self.signal_delete_event)
        self.notebook.show()
        self.show()
        self.rpc = None  # needs to be initialized last
        """The :py:class:`.KingPhisherRPCClient` instance."""
def which_glade(glade):
	return find.find_data_file(os.environ['KING_PHISHER_GLADE_FILE'])
예제 #46
0
    def __init__(self, config, application):
        """
		:param dict config: The main King Phisher client configuration.
		:param application: The application instance to which this window belongs.
		:type application: :py:class:`.KingPhisherClientApplication`
		"""
        assert isinstance(application, Gtk.Application)
        super(MainAppWindow, self).__init__(application=application)
        self.application = application
        self.logger = logging.getLogger('KingPhisher.Client.MainWindow')
        self.config = config
        """The main King Phisher client configuration."""
        self.set_property('title', 'King Phisher')
        vbox = Gtk.Box()
        vbox.set_property('orientation', Gtk.Orientation.VERTICAL)
        vbox.show()
        self.add(vbox)

        default_icon_file = find.find_data_file('king-phisher-icon.svg')
        if default_icon_file:
            icon_pixbuf = GdkPixbuf.Pixbuf.new_from_file(default_icon_file)
            self.set_default_icon(icon_pixbuf)
        self.accel_group = Gtk.AccelGroup()
        self.add_accel_group(self.accel_group)

        self.menu_bar = MainMenuBar(application, self)
        vbox.pack_start(self.menu_bar.menubar, False, False, 0)

        # create notebook and tabs
        self.notebook = Gtk.Notebook()
        """The primary :py:class:`Gtk.Notebook` that holds the top level taps of the client GUI."""
        self.notebook.connect('switch-page', self.signal_notebook_switch_page)
        self.notebook.set_scrollable(True)
        vbox.pack_start(self.notebook, True, True, 0)

        self.tabs = {}
        current_page = self.notebook.get_current_page()
        self.last_page_id = current_page

        mailer_tab = MailSenderTab(self, self.application)
        self.tabs['mailer'] = mailer_tab
        self.notebook.insert_page(mailer_tab.box, mailer_tab.label,
                                  current_page + 1)
        self.notebook.set_current_page(current_page + 1)

        campaign_tab = CampaignViewTab(self, self.application)
        campaign_tab.box.show()
        self.tabs['campaign'] = campaign_tab
        self.notebook.insert_page(campaign_tab.box, campaign_tab.label,
                                  current_page + 2)

        self.set_size_request(800, 600)
        self.connect('delete-event', self.signal_delete_event)
        self.notebook.show()

        self.show()
        self.rpc = None  # needs to be initialized last
        """The :py:class:`.KingPhisherRPCClient` instance."""

        self.application.connect('server-connected',
                                 self.signal_kp_server_connected)

        self.login_dialog = dialogs.LoginDialog(self.application)
        self.login_dialog.dialog.connect('response',
                                         self.signal_login_dialog_response)
        self.login_dialog.dialog.show()
예제 #47
0
	def _create_ui_manager(self):
		uimanager = Gtk.UIManager()
		with open(find.find_data_file('ui_info/client_window.xml')) as ui_info_file:
			ui_data = ui_info_file.read()
		uimanager.add_ui_from_string(ui_data)
		return uimanager
예제 #48
0
	def theme_file(self):
		if not self._theme_file:
			return DISABLED
		return find.find_data_file(os.path.join('style', self._theme_file))
	def load_config(self):
		self.logger.info('loading the config from disk')
		config_file = os.path.expanduser(self.config_file)
		if not os.path.isfile(config_file):
			shutil.copy(find.find_data_file('client_config.json'), config_file)
		self.config = json.load(open(config_file, 'rb'))
예제 #50
0
def init_database(connection_url):
    """
	Create and initialize the database engine. This must be done before the
	session object can be used. This will also attempt to perform any updates to
	the database schema if the backend support such operations.

	:param str connection_url: The url for the database connection.
	:return: The initialized database engine.
	"""
    connection_url = normalize_connection_url(connection_url)
    connection_url = sqlalchemy.engine.url.make_url(connection_url)
    logger.info("initializing database connection with driver {0}".format(
        connection_url.drivername))
    if connection_url.drivername == 'sqlite':
        engine = sqlalchemy.create_engine(
            connection_url,
            connect_args={'check_same_thread': False},
            poolclass=sqlalchemy.pool.StaticPool)
        sqlalchemy.event.listens_for(
            engine, 'begin')(lambda conn: conn.execute('BEGIN'))
    elif connection_url.drivername == 'postgresql':
        engine = sqlalchemy.create_engine(connection_url)
    else:
        raise errors.KingPhisherDatabaseError(
            'only sqlite and postgresql database drivers are supported')

    Session.remove()
    Session.configure(bind=engine)
    try:
        models.Base.metadata.create_all(engine)
    except sqlalchemy.exc.SQLAlchemyError as error:
        error_lines = map(lambda line: line.strip(), error.message.split('\n'))
        raise errors.KingPhisherDatabaseError('SQLAlchemyError: ' +
                                              ' '.join(error_lines).strip())

    session = Session()
    set_meta_data('database_driver',
                  connection_url.drivername,
                  session=session)
    schema_version = (get_meta_data('schema_version', session=session)
                      or models.SCHEMA_VERSION)
    session.commit()
    session.close()

    logger.debug("current database schema version: {0} ({1}current)".format(
        schema_version,
        ('' if schema_version == models.SCHEMA_VERSION else 'not ')))
    if schema_version > models.SCHEMA_VERSION:
        raise errors.KingPhisherDatabaseError(
            'the database schema is for a newer version, automatic downgrades are not supported'
        )
    elif schema_version < models.SCHEMA_VERSION:
        alembic_config_file = find.find_data_file('alembic.ini')
        if not alembic_config_file:
            raise errors.KingPhisherDatabaseError(
                'cannot find the alembic.ini configuration file')
        alembic_directory = find.find_data_directory('alembic')
        if not alembic_directory:
            raise errors.KingPhisherDatabaseError(
                'cannot find the alembic data directory')

        config = alembic.config.Config(alembic_config_file)
        config.config_file_name = alembic_config_file
        config.set_main_option('script_location', alembic_directory)
        config.set_main_option('skip_logger_config', 'True')
        config.set_main_option('sqlalchemy.url', str(connection_url))

        logger.warning(
            "automatically updating the database schema to version {0}".format(
                models.SCHEMA_VERSION))
        try:
            alembic.command.upgrade(config, 'head')
        except Exception as error:
            logger.critical(
                "database schema upgrade failed with exception: {0}.{1} {2}".
                format(error.__class__.__module__, error.__class__.__name__,
                       getattr(error, 'message', '')).rstrip())
            raise errors.KingPhisherDatabaseError(
                'failed to upgrade to the latest database schema')
    set_meta_data('schema_version', models.SCHEMA_VERSION)

    logger.debug("connected to {0} database: {1}".format(
        connection_url.drivername, connection_url.database))
    return engine
예제 #51
0
def init_database(connection_url):
	"""
	Create and initialize the database engine. This must be done before the
	session object can be used. This will also attempt to perform any updates to
	the database schema if the backend supports such operations.

	:param str connection_url: The url for the database connection.
	:return: The initialized database engine.
	"""
	connection_url = normalize_connection_url(connection_url)
	connection_url = sqlalchemy.engine.url.make_url(connection_url)
	logger.info("initializing database connection with driver {0}".format(connection_url.drivername))
	if connection_url.drivername == 'sqlite':
		engine = sqlalchemy.create_engine(connection_url, connect_args={'check_same_thread': False}, poolclass=sqlalchemy.pool.StaticPool)
		sqlalchemy.event.listens_for(engine, 'begin')(lambda conn: conn.execute('BEGIN'))
	elif connection_url.drivername == 'postgresql':
		engine = sqlalchemy.create_engine(connection_url)
	else:
		raise errors.KingPhisherDatabaseError('only sqlite and postgresql database drivers are supported')

	Session.remove()
	Session.configure(bind=engine)
	inspector = sqlalchemy.inspect(engine)
	if not 'meta_data' in inspector.get_table_names():
		logger.debug('meta_data table not found, creating all new tables')
		try:
			models.Base.metadata.create_all(engine)
		except sqlalchemy.exc.SQLAlchemyError as error:
			error_lines = (line.strip() for line in error.message.split('\n'))
			raise errors.KingPhisherDatabaseError('SQLAlchemyError: ' + ' '.join(error_lines).strip())

	session = Session()
	set_meta_data('database_driver', connection_url.drivername, session=session)
	schema_version = (get_meta_data('schema_version', session=session) or models.SCHEMA_VERSION)
	session.commit()
	session.close()

	logger.debug("current database schema version: {0} ({1}current)".format(schema_version, ('' if schema_version == models.SCHEMA_VERSION else 'not ')))
	if schema_version > models.SCHEMA_VERSION:
		raise errors.KingPhisherDatabaseError('the database schema is for a newer version, automatic downgrades are not supported')
	elif schema_version < models.SCHEMA_VERSION:
		alembic_config_file = find.find_data_file('alembic.ini')
		if not alembic_config_file:
			raise errors.KingPhisherDatabaseError('cannot find the alembic.ini configuration file')
		alembic_directory = find.find_data_directory('alembic')
		if not alembic_directory:
			raise errors.KingPhisherDatabaseError('cannot find the alembic data directory')

		config = alembic.config.Config(alembic_config_file)
		config.config_file_name = alembic_config_file
		config.set_main_option('script_location', alembic_directory)
		config.set_main_option('skip_logger_config', 'True')
		config.set_main_option('sqlalchemy.url', str(connection_url))

		logger.warning("automatically updating the database schema to version {0}".format(models.SCHEMA_VERSION))
		try:
			alembic.command.upgrade(config, 'head')
		except Exception as error:
			logger.critical("database schema upgrade failed with exception: {0}.{1} {2}".format(error.__class__.__module__, error.__class__.__name__, getattr(error, 'message', '')).rstrip(), exc_info=True)
			raise errors.KingPhisherDatabaseError('failed to upgrade to the latest database schema')
		# reset it because it may have been altered by alembic
		Session.remove()
		Session.configure(bind=engine)
		session = Session()
	set_meta_data('schema_version', models.SCHEMA_VERSION)

	logger.debug("connected to {0} database: {1}".format(connection_url.drivername, connection_url.database))
	return engine
예제 #52
0
 def theme_file(self):
     if not self._theme_file:
         return DISABLED
     return find.find_data_file(os.path.join('style', self._theme_file))