Refactor detection module whitelist feature

pull/1340/head
Bernhard Mueller 5 years ago
parent 47824a725d
commit 34212e4fe0
  1. 31
      mythril/analysis/module/loader.py
  2. 4
      mythril/analysis/module/modules/exceptions.py
  3. 7
      mythril/exceptions.py
  4. 12
      mythril/interfaces/cli.py
  5. 2
      mythril/laser/ethereum/keccak_function_manager.py
  6. 4
      mythril/mythril/mythril_analyzer.py

@ -9,17 +9,21 @@ from mythril.analysis.module.modules.dependence_on_predictable_vars import (
) )
from mythril.analysis.module.modules.deprecated_ops import DeprecatedOperations from mythril.analysis.module.modules.deprecated_ops import DeprecatedOperations
from mythril.analysis.module.modules.ether_thief import EtherThief from mythril.analysis.module.modules.ether_thief import EtherThief
from mythril.analysis.module.modules.exceptions import ReachableExceptions from mythril.analysis.module.modules.exceptions import Exceptions
from mythril.analysis.module.modules.external_calls import ExternalCalls from mythril.analysis.module.modules.external_calls import ExternalCalls
from mythril.analysis.module.modules.integer import IntegerArithmetics from mythril.analysis.module.modules.integer import IntegerArithmetics
from mythril.analysis.module.modules.multiple_sends import MultipleSends from mythril.analysis.module.modules.multiple_sends import MultipleSends
from mythril.analysis.module.modules.state_change_external_calls import StateChangeAfterCall from mythril.analysis.module.modules.state_change_external_calls import (
StateChangeAfterCall,
)
from mythril.analysis.module.modules.suicide import AccidentallyKillable from mythril.analysis.module.modules.suicide import AccidentallyKillable
from mythril.analysis.module.modules.unchecked_retval import UncheckedRetval from mythril.analysis.module.modules.unchecked_retval import UncheckedRetval
from mythril.analysis.module.modules.user_assertions import UserAssertions from mythril.analysis.module.modules.user_assertions import UserAssertions
from mythril.analysis.module.base import EntryPoint from mythril.analysis.module.base import EntryPoint
from mythril.exceptions import DetectorNotFoundError
from typing import Optional, List from typing import Optional, List
@ -53,11 +57,28 @@ class ModuleLoader(object, metaclass=Singleton):
:param white_list: If specified: only return whitelisted detection modules :param white_list: If specified: only return whitelisted detection modules
:return: The selected detection modules :return: The selected detection modules
""" """
result = self._modules[:] result = self._modules[:]
if white_list:
# Sanity check
available_names = [type(module).__name__ for module in result]
for name in white_list:
if name not in available_names:
raise DetectorNotFoundError(
"Invalid detection module: {}".format(name)
)
result = [
module for module in result if type(module).__name__ in white_list
]
if entry_point: if entry_point:
result = [module for module in result if module.entry_point == entry_point] result = [module for module in result if module.entry_point == entry_point]
if white_list:
result = [module for module in result if module.name in white_list]
return result return result
def _register_mythril_modules(self): def _register_mythril_modules(self):
@ -69,7 +90,7 @@ class ModuleLoader(object, metaclass=Singleton):
PredictableVariables(), PredictableVariables(),
DeprecatedOperations(), DeprecatedOperations(),
EtherThief(), EtherThief(),
ReachableExceptions(), Exceptions(),
ExternalCalls(), ExternalCalls(),
IntegerArithmetics(), IntegerArithmetics(),
MultipleSends(), MultipleSends(),

@ -11,7 +11,7 @@ from mythril.laser.ethereum.state.global_state import GlobalState
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class ReachableExceptions(DetectionModule): class Exceptions(DetectionModule):
"""""" """"""
name = "Reachable Exceptions" name = "Reachable Exceptions"
@ -76,4 +76,4 @@ class ReachableExceptions(DetectionModule):
return [] return []
detector = ReachableExceptions() detector = Exceptions()

@ -39,3 +39,10 @@ class AddressNotFoundError(MythrilBaseException):
found.""" found."""
pass pass
class DetectorNotFoundError(MythrilBaseException):
"""A Mythril exception denoting attempted usage of a non-existant
detection module."""
pass

@ -17,7 +17,11 @@ import traceback
import mythril.support.signatures as sigs import mythril.support.signatures as sigs
from argparse import ArgumentParser, Namespace, RawTextHelpFormatter from argparse import ArgumentParser, Namespace, RawTextHelpFormatter
from mythril import mythx from mythril import mythx
from mythril.exceptions import AddressNotFoundError, CriticalError from mythril.exceptions import (
AddressNotFoundError,
DetectorNotFoundError,
CriticalError,
)
from mythril.laser.ethereum.transaction.symbolic import ACTORS from mythril.laser.ethereum.transaction.symbolic import ACTORS
from mythril.mythril import ( from mythril.mythril import (
MythrilAnalyzer, MythrilAnalyzer,
@ -729,9 +733,11 @@ def execute_command(
"markdown": report.as_markdown(), "markdown": report.as_markdown(),
} }
print(outputs[args.outform]) print(outputs[args.outform])
except ModuleNotFoundError as e: except DetectorNotFoundError as e:
exit_with_error(args.outform, format(e))
except CriticalError as e:
exit_with_error( exit_with_error(
args.outform, "Error loading analysis modules: " + format(e) args.outform, "Analysis error encountered: " + format(e)
) )
else: else:

@ -141,7 +141,7 @@ class KeccakFunctionManager:
) )
concrete_cond = symbol_factory.Bool(False) concrete_cond = symbol_factory.Bool(False)
for key, keccak in self.concrete_hashes.items(): for key, keccak in self.concrete_hashes.items():
hash_eq = And(func(func_input) == keccak, key == func_input,) hash_eq = And(func(func_input) == keccak, key == func_input)
concrete_cond = Or(concrete_cond, hash_eq) concrete_cond = Or(concrete_cond, hash_eq)
return And(inv(func(func_input)) == func_input, Or(cond, concrete_cond)) return And(inv(func(func_input)) == func_input, Or(cond, concrete_cond))

@ -18,6 +18,7 @@ from mythril.analysis.report import Report, Issue
from mythril.ethereum.evmcontract import EVMContract from mythril.ethereum.evmcontract import EVMContract
from mythril.laser.smt import SolverStatistics from mythril.laser.smt import SolverStatistics
from mythril.support.start_time import StartTime from mythril.support.start_time import StartTime
from mythril.exceptions import DetectorNotFoundError
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -172,6 +173,9 @@ class MythrilAnalyzer:
custom_modules_directory=self.custom_modules_directory, custom_modules_directory=self.custom_modules_directory,
) )
issues = fire_lasers(sym, modules) issues = fire_lasers(sym, modules)
except DetectorNotFoundError as e:
# Bubble up
raise e
except KeyboardInterrupt: except KeyboardInterrupt:
log.critical("Keyboard Interrupt") log.critical("Keyboard Interrupt")
if self.iprof is not None: if self.iprof is not None:

Loading…
Cancel
Save