mirror of https://github.com/ConsenSys/mythril
commit
08d1d30a91
@ -1,6 +1,6 @@ |
||||
What is Mythril Classic? |
||||
What is Mythril? |
||||
======================== |
||||
|
||||
Mythril Classic is a security analysis tool for Ethereum smart contracts. It was `introduced at HITBSecConf 2018 <https://github.com/b-mueller/smashing-smart-contracts/blob/master/smashing-smart-contracts-1of1.pdf>`_. |
||||
Mythril is a security analysis tool for Ethereum smart contracts. It was `introduced at HITBSecConf 2018 <https://github.com/b-mueller/smashing-smart-contracts/blob/master/smashing-smart-contracts-1of1.pdf>`_. |
||||
|
||||
Mythril Classic detects a range of security issues, including integer underflows, owner-overwrite-to-Ether-withdrawal, and others. Note that Mythril is targeted at finding common vulnerabilities, and is not able to discover issues in the business logic of an application. Furthermore, Mythril and symbolic executors are generally unsound, as they are often unable to explore all possible states of a program. |
||||
Mythril detects a range of security issues, including integer underflows, owner-overwrite-to-Ether-withdrawal, and others. Note that Mythril is targeted at finding common vulnerabilities, and is not able to discover issues in the business logic of an application. Furthermore, Mythril and symbolic executors are generally unsound, as they are often unable to explore all possible states of a program. |
||||
|
@ -1,4 +1,4 @@ |
||||
Creating a Module |
||||
================= |
||||
|
||||
Create a module in the :code:`analysis/modules` directory, and create an instance of a class that inherits :code:`DetectionModule` named :code:`detector`. Take a look at the `suicide module <https://github.com/ConsenSys/mythril-classic/blob/develop/mythril/analysis/modules/suicide.py>`_ as an example. |
||||
Create a module in the :code:`analysis/modules` directory, and create an instance of a class that inherits :code:`DetectionModule` named :code:`detector`. Take a look at the `suicide module <https://github.com/ConsenSys/mythril/blob/develop/mythril/analysis/modules/suicide.py>`_ as an example. |
||||
|
@ -0,0 +1,84 @@ |
||||
from mythril.laser.ethereum.state.global_state import GlobalState |
||||
from mythril.laser.ethereum.strategy.basic import BasicSearchStrategy |
||||
from mythril.laser.ethereum.state.annotation import StateAnnotation |
||||
from mythril.laser.ethereum import util |
||||
from typing import Dict, cast, List |
||||
from copy import copy |
||||
import logging |
||||
|
||||
|
||||
log = logging.getLogger(__name__) |
||||
|
||||
|
||||
class JumpdestCountAnnotation(StateAnnotation): |
||||
"""State annotation that counts the number of jumps per destination.""" |
||||
|
||||
def __init__(self) -> None: |
||||
self._jumpdest_count = {} # type: Dict[int, int] |
||||
|
||||
def __copy__(self): |
||||
result = JumpdestCountAnnotation() |
||||
result._jumpdest_count = copy(self._jumpdest_count) |
||||
return result |
||||
|
||||
|
||||
class BoundedLoopsStrategy(BasicSearchStrategy): |
||||
"""Adds loop pruning to the search strategy. |
||||
Ignores JUMPI instruction if the destination was targeted >JUMPDEST_LIMIT times. |
||||
""" |
||||
|
||||
def __init__(self, super_strategy: BasicSearchStrategy, *args) -> None: |
||||
"""""" |
||||
|
||||
self.super_strategy = super_strategy |
||||
self.jumpdest_limit = args[0][0] |
||||
|
||||
log.info( |
||||
"Loaded search strategy extension: Loop bounds (limit = {})".format( |
||||
self.jumpdest_limit |
||||
) |
||||
) |
||||
|
||||
BasicSearchStrategy.__init__( |
||||
self, super_strategy.work_list, super_strategy.max_depth |
||||
) |
||||
|
||||
def get_strategic_global_state(self) -> GlobalState: |
||||
""" |
||||
:return: |
||||
""" |
||||
|
||||
while True: |
||||
|
||||
state = self.super_strategy.get_strategic_global_state() |
||||
opcode = state.get_current_instruction()["opcode"] |
||||
|
||||
if opcode != "JUMPI": |
||||
return state |
||||
|
||||
annotations = cast( |
||||
List[JumpdestCountAnnotation], |
||||
list(state.get_annotations(JumpdestCountAnnotation)), |
||||
) |
||||
|
||||
if len(annotations) == 0: |
||||
annotation = JumpdestCountAnnotation() |
||||
state.annotate(annotation) |
||||
else: |
||||
annotation = annotations[0] |
||||
|
||||
try: |
||||
target = util.get_concrete_int(state.mstate.stack[-1]) |
||||
except TypeError: |
||||
return state |
||||
|
||||
try: |
||||
annotation._jumpdest_count[target] += 1 |
||||
except KeyError: |
||||
annotation._jumpdest_count[target] = 1 |
||||
|
||||
if annotation._jumpdest_count[target] > self.jumpdest_limit: |
||||
log.debug("JUMPDEST limit reached, skipping JUMPI") |
||||
continue |
||||
|
||||
return state |
Loading…
Reference in new issue