From 27aff199e9c3d3dbd1e5524ffa757bcf0e89dbb0 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:03:21 +0100 Subject: [PATCH 01/11] initialise mythril plugin loader at start --- mythril/__init__.py | 8 ++++++++ mythril/plugin/loader.py | 1 + 2 files changed, 9 insertions(+) diff --git a/mythril/__init__.py b/mythril/__init__.py index 063d3b9b..d1d2caab 100644 --- a/mythril/__init__.py +++ b/mythril/__init__.py @@ -1,6 +1,14 @@ # We use RsT document formatting in docstring. For example :param to mark parameters. # See PEP 287 __docformat__ = "restructuredtext" +import logging # Accept mythril.VERSION to get mythril's current version number from .__version__ import __version__ as VERSION # NOQA +from mythril.plugin.loader import MythrilPluginLoader + +log = logging.getLogger(__name__) + +# Initialise core Mythril Components +log.info("Initializing core Mythril components") +_ = MythrilPluginLoader() diff --git a/mythril/plugin/loader.py b/mythril/plugin/loader.py index 6c75cf4d..b14f6c92 100644 --- a/mythril/plugin/loader.py +++ b/mythril/plugin/loader.py @@ -19,6 +19,7 @@ class MythrilPluginLoader(object, metaclass=Singleton): """ def __init__(self): + log.info("Initializing mythril plugin loader") self.loaded_plugins = [] def load(self, plugin: MythrilPlugin): From 9606bd3d885abbe4accdf523d54e20af8aa64d8e Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:08:56 +0100 Subject: [PATCH 02/11] add helper function to discovery to list plugins --- mythril/plugin/discovery.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/mythril/plugin/discovery.py b/mythril/plugin/discovery.py index 783a3f0b..e9b2aaf5 100644 --- a/mythril/plugin/discovery.py +++ b/mythril/plugin/discovery.py @@ -2,6 +2,8 @@ import pkg_resources from mythril.support.support_utils import Singleton from mythril.plugin.interface import MythrilPlugin +from typing import List + class PluginDiscovery(object, metaclass=Singleton): """PluginDiscovery class @@ -9,7 +11,7 @@ class PluginDiscovery(object, metaclass=Singleton): This plugin implements the logic to discover and build plugins in installed python packages """ - # Installed plugins structure. Retreives all modules that have an entry point for mythril.plugins + # Installed plugins structure. Retrieves all modules that have an entry point for mythril.plugins _installed_plugins = { entry_point.name: entry_point.load() for entry_point in pkg_resources.iter_entry_points("mythril.plugins") @@ -30,3 +32,17 @@ class PluginDiscovery(object, metaclass=Singleton): raise ValueError(f"No valid plugin was found for {plugin_name}") return plugin + + def get_plugins(self, default_enabled=None) -> List[str]: + """ Gets a list of installed mythril plugins + + :param default_enabled: Select plugins that are enabled by default + :return: List of plugin names + """ + if default_enabled is None: + return list(self._installed_plugins.keys()) + + return [ + plugin_name for plugin_name, plugin_class + in self._installed_plugins.items() if plugin_class.default_enabled == default_enabled + ] From 3acc3ef3a6aa87c45155836773f0b553effd823f Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:12:23 +0100 Subject: [PATCH 03/11] load plugins that are enabled by default --- mythril/plugin/loader.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mythril/plugin/loader.py b/mythril/plugin/loader.py index b14f6c92..9930b789 100644 --- a/mythril/plugin/loader.py +++ b/mythril/plugin/loader.py @@ -1,6 +1,7 @@ from mythril.analysis.module import DetectionModule from mythril.plugin.interface import MythrilCLIPlugin, MythrilPlugin +from mythril.plugin.discovery import PluginDiscovery from mythril.support.support_utils import Singleton import logging @@ -21,6 +22,7 @@ class MythrilPluginLoader(object, metaclass=Singleton): def __init__(self): log.info("Initializing mythril plugin loader") self.loaded_plugins = [] + self._load_default_enabled() def load(self, plugin: MythrilPlugin): """Loads the passed plugin""" @@ -38,3 +40,9 @@ class MythrilPluginLoader(object, metaclass=Singleton): def _load_detection_module(self, plugin: DetectionModule): pass + + def _load_default_enabled(self): + logging.info("Loading installed analysis modules that are enabled by default") + for plugin_name in PluginDiscovery().get_plugins(default_enabled=True): + plugin = PluginDiscovery().build_plugin(plugin_name) + self.load(plugin) From d9f6f9b6e65b0e55d1948ae700a87388937338d4 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:13:24 +0100 Subject: [PATCH 04/11] add logging to load function of plugin loader --- mythril/plugin/loader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mythril/plugin/loader.py b/mythril/plugin/loader.py index 9930b789..b76753d9 100644 --- a/mythril/plugin/loader.py +++ b/mythril/plugin/loader.py @@ -26,6 +26,7 @@ class MythrilPluginLoader(object, metaclass=Singleton): def load(self, plugin: MythrilPlugin): """Loads the passed plugin""" + logging.info(f"Loading plugin: {plugin.name}") if not isinstance(plugin, MythrilPlugin): raise ValueError("Passed plugin is not of type MythrilPlugin") @@ -37,6 +38,7 @@ class MythrilPluginLoader(object, metaclass=Singleton): raise UnsupportedPluginType("Passed plugin type is not yet supported") self.loaded_plugins.append(plugin) + logging.info(f"Finished loading plugin: {plugin.name}") def _load_detection_module(self, plugin: DetectionModule): pass From 02fed33ea01e68a4f2a0139ea17f179e20850881 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:23:46 +0100 Subject: [PATCH 05/11] check subclass rather than instance of --- mythril/plugin/discovery.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mythril/plugin/discovery.py b/mythril/plugin/discovery.py index e9b2aaf5..f3bb880b 100644 --- a/mythril/plugin/discovery.py +++ b/mythril/plugin/discovery.py @@ -28,10 +28,10 @@ class PluginDiscovery(object, metaclass=Singleton): plugin = self._installed_plugins.get(plugin_name) - if plugin is None or not isinstance(plugin, MythrilPlugin): + if plugin is None or not issubclass(plugin, MythrilPlugin): raise ValueError(f"No valid plugin was found for {plugin_name}") - return plugin + return plugin() def get_plugins(self, default_enabled=None) -> List[str]: """ Gets a list of installed mythril plugins From f1082e2dd9eccb1472f7fca730fe502948dbcc84 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:25:28 +0100 Subject: [PATCH 06/11] add detection module loading logic --- mythril/plugin/loader.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mythril/plugin/loader.py b/mythril/plugin/loader.py index b76753d9..25302130 100644 --- a/mythril/plugin/loader.py +++ b/mythril/plugin/loader.py @@ -4,6 +4,8 @@ from mythril.plugin.interface import MythrilCLIPlugin, MythrilPlugin from mythril.plugin.discovery import PluginDiscovery from mythril.support.support_utils import Singleton +from mythril.analysis.module.loader import ModuleLoader + import logging log = logging.getLogger(__name__) @@ -38,13 +40,14 @@ class MythrilPluginLoader(object, metaclass=Singleton): raise UnsupportedPluginType("Passed plugin type is not yet supported") self.loaded_plugins.append(plugin) - logging.info(f"Finished loading plugin: {plugin.name}") + log.info(f"Finished loading plugin: {plugin.name}") def _load_detection_module(self, plugin: DetectionModule): - pass + log.info(f"Loading detection module: {plugin.name}") + ModuleLoader().register_module(plugin) def _load_default_enabled(self): - logging.info("Loading installed analysis modules that are enabled by default") + log.info("Loading installed analysis modules that are enabled by default") for plugin_name in PluginDiscovery().get_plugins(default_enabled=True): plugin = PluginDiscovery().build_plugin(plugin_name) self.load(plugin) From 11c2bc3cb8912dd2f3c52e97215797cf12fdf493 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:26:04 +0100 Subject: [PATCH 07/11] make static and add documentation --- mythril/plugin/loader.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mythril/plugin/loader.py b/mythril/plugin/loader.py index 25302130..bcc180a8 100644 --- a/mythril/plugin/loader.py +++ b/mythril/plugin/loader.py @@ -42,7 +42,9 @@ class MythrilPluginLoader(object, metaclass=Singleton): self.loaded_plugins.append(plugin) log.info(f"Finished loading plugin: {plugin.name}") - def _load_detection_module(self, plugin: DetectionModule): + @staticmethod + def _load_detection_module(plugin: DetectionModule): + """Loads the passed detection module""" log.info(f"Loading detection module: {plugin.name}") ModuleLoader().register_module(plugin) From 41b3917379d01305b75d38795ffcc20740ce2563 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:54:08 +0100 Subject: [PATCH 08/11] make variable name explicitly connected to plugins --- mythril/plugin/discovery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mythril/plugin/discovery.py b/mythril/plugin/discovery.py index f3bb880b..4a5fd68c 100644 --- a/mythril/plugin/discovery.py +++ b/mythril/plugin/discovery.py @@ -44,5 +44,5 @@ class PluginDiscovery(object, metaclass=Singleton): return [ plugin_name for plugin_name, plugin_class - in self._installed_plugins.items() if plugin_class.default_enabled == default_enabled + in self._installed_plugins.items() if plugin_class.plugin_default_enabled == default_enabled ] From 0f2d406059abefe82d6432134e00ce9a54f9dcc2 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Thu, 27 Feb 2020 15:57:44 +0100 Subject: [PATCH 09/11] black --- mythril/plugin/discovery.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mythril/plugin/discovery.py b/mythril/plugin/discovery.py index 4a5fd68c..b157dec8 100644 --- a/mythril/plugin/discovery.py +++ b/mythril/plugin/discovery.py @@ -43,6 +43,7 @@ class PluginDiscovery(object, metaclass=Singleton): return list(self._installed_plugins.keys()) return [ - plugin_name for plugin_name, plugin_class - in self._installed_plugins.items() if plugin_class.plugin_default_enabled == default_enabled + plugin_name + for plugin_name, plugin_class in self._installed_plugins.items() + if plugin_class.plugin_default_enabled == default_enabled ] From 1810884b9e76ea525b92b90db8258c76be8607e1 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Mon, 2 Mar 2020 10:32:32 +0100 Subject: [PATCH 10/11] add plugin name parameter --- mythril/plugin/interface.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mythril/plugin/interface.py b/mythril/plugin/interface.py index 34f3625f..ead1a5da 100644 --- a/mythril/plugin/interface.py +++ b/mythril/plugin/interface.py @@ -12,6 +12,7 @@ class MythrilPlugin: """ author = "Default Author" + name = "Plugin Name" plugin_license = "All rights reserved." plugin_type = "Mythril Plugin" plugin_version = "0.0.1 " From 5771158671568e24177b42d64a1cb09110a05588 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Mon, 2 Mar 2020 13:29:59 +0100 Subject: [PATCH 11/11] perform check before log statement --- mythril/plugin/loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mythril/plugin/loader.py b/mythril/plugin/loader.py index bcc180a8..45699d8a 100644 --- a/mythril/plugin/loader.py +++ b/mythril/plugin/loader.py @@ -28,9 +28,9 @@ class MythrilPluginLoader(object, metaclass=Singleton): def load(self, plugin: MythrilPlugin): """Loads the passed plugin""" - logging.info(f"Loading plugin: {plugin.name}") if not isinstance(plugin, MythrilPlugin): raise ValueError("Passed plugin is not of type MythrilPlugin") + logging.info(f"Loading plugin: {plugin.name}") log.info(f"Loading plugin: {str(plugin)}")