Merge branch 'develop' into feature/ignore-regressions

feature/ignore-regressions
Bernhard Mueller 6 years ago committed by GitHub
commit e56f69bf1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      mythril/analysis/modules/delegatecall.py
  2. 14
      mythril/analysis/modules/ether_thief.py
  3. 11
      mythril/analysis/modules/external_calls.py
  4. 19
      mythril/analysis/modules/suicide.py

@ -6,6 +6,10 @@ from typing import List, cast, Dict
from mythril.analysis import solver from mythril.analysis import solver
from mythril.analysis.swc_data import DELEGATECALL_TO_UNTRUSTED_CONTRACT from mythril.analysis.swc_data import DELEGATECALL_TO_UNTRUSTED_CONTRACT
from mythril.laser.ethereum.transaction.symbolic import ATTACKER_ADDRESS
from mythril.laser.ethereum.transaction.transaction_models import (
ContractCreationTransaction,
)
from mythril.analysis.report import Issue from mythril.analysis.report import Issue
from mythril.analysis.modules.base import DetectionModule from mythril.analysis.modules.base import DetectionModule
from mythril.exceptions import UnsatError from mythril.exceptions import UnsatError
@ -17,16 +21,19 @@ log = logging.getLogger(__name__)
class DelegateCallAnnotation(StateAnnotation): class DelegateCallAnnotation(StateAnnotation):
def __init__(self, call_state: GlobalState) -> None: def __init__(self, call_state: GlobalState, constraints: List) -> None:
""" """
Initialize DelegateCall Annotation Initialize DelegateCall Annotation
:param call_state: Call state :param call_state: Call state
""" """
self.call_state = call_state self.call_state = call_state
self.constraints = constraints
self.return_value = call_state.new_bitvec( self.return_value = call_state.new_bitvec(
"retval_{}".format(call_state.get_current_instruction()["address"]), 256 "retval_{}".format(call_state.get_current_instruction()["address"]), 256
) )
return DelegateCallAnnotation(self.call_state, copy(self.constraints))
def get_issue(self, global_state: GlobalState, transaction_sequence: Dict) -> Issue: def get_issue(self, global_state: GlobalState, transaction_sequence: Dict) -> Issue:
""" """
Returns Issue for the annotation Returns Issue for the annotation
@ -107,26 +114,26 @@ def _analyze_states(state: GlobalState) -> List[Issue]:
gas = state.mstate.stack[-1] gas = state.mstate.stack[-1]
to = state.mstate.stack[-2] to = state.mstate.stack[-2]
constraints = copy(state.mstate.constraints) constraints = [
# Check whether we can also set the callee address to == ATTACKER_ADDRESS,
constraints += [
to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF,
UGT(gas, symbol_factory.BitVecVal(2300, 256)), UGT(gas, symbol_factory.BitVecVal(2300, 256)),
] ]
try:
solver.get_model(constraints)
state.annotate(DelegateCallAnnotation(call_state=state))
except UnsatError: for tx in state.world_state.transaction_sequence:
log.debug("[DELEGATECALL] Annotation skipped.") if not isinstance(tx, ContractCreationTransaction):
constraints.append(tx.caller == ATTACKER_ADDRESS)
state.annotate(DelegateCallAnnotation(state, constraints))
return [] return []
else: else:
for annotation in annotations: for annotation in annotations:
try: try:
transaction_sequence = solver.get_transaction_sequence( transaction_sequence = solver.get_transaction_sequence(
state, state.mstate.constraints + [annotation.return_value == 1] state,
state.mstate.constraints
+ annotation.constraints
+ [annotation.return_value == 1],
) )
issues.append( issues.append(
annotation.get_issue( annotation.get_issue(

@ -8,6 +8,9 @@ from mythril.analysis import solver
from mythril.analysis.modules.base import DetectionModule from mythril.analysis.modules.base import DetectionModule
from mythril.analysis.report import Issue from mythril.analysis.report import Issue
from mythril.laser.ethereum.transaction.symbolic import ATTACKER_ADDRESS from mythril.laser.ethereum.transaction.symbolic import ATTACKER_ADDRESS
from mythril.laser.ethereum.transaction.transaction_models import (
ContractCreationTransaction,
)
from mythril.analysis.swc_data import UNPROTECTED_ETHER_WITHDRAWAL from mythril.analysis.swc_data import UNPROTECTED_ETHER_WITHDRAWAL
from mythril.exceptions import UnsatError from mythril.exceptions import UnsatError
from mythril.laser.ethereum.state.global_state import GlobalState from mythril.laser.ethereum.state.global_state import GlobalState
@ -85,11 +88,10 @@ class EtherThief(DetectionModule):
constraints += [BVAddNoOverflow(eth_sent_total, tx.call_value, False)] constraints += [BVAddNoOverflow(eth_sent_total, tx.call_value, False)]
eth_sent_total = Sum(eth_sent_total, tx.call_value) eth_sent_total = Sum(eth_sent_total, tx.call_value)
constraints += [ if not isinstance(tx, ContractCreationTransaction):
tx.caller == ATTACKER_ADDRESS, constraints.append(tx.caller == ATTACKER_ADDRESS)
UGT(call_value, eth_sent_total),
target == ATTACKER_ADDRESS, constraints += [UGT(call_value, eth_sent_total), target == ATTACKER_ADDRESS]
]
try: try:
@ -114,7 +116,7 @@ class EtherThief(DetectionModule):
log.debug("[ETHER_THIEF] no model found") log.debug("[ETHER_THIEF] no model found")
return [] return []
self._cache_addresses[address] = True # self._cache_addresses[address] = True
return [issue] return [issue]

@ -3,6 +3,10 @@ calls."""
from mythril.analysis import solver from mythril.analysis import solver
from mythril.analysis.swc_data import REENTRANCY from mythril.analysis.swc_data import REENTRANCY
from mythril.laser.ethereum.transaction.symbolic import ATTACKER_ADDRESS
from mythril.laser.ethereum.transaction.transaction_models import (
ContractCreationTransaction,
)
from mythril.analysis.modules.base import DetectionModule from mythril.analysis.modules.base import DetectionModule
from mythril.analysis.report import Issue from mythril.analysis.report import Issue
from mythril.laser.smt import UGT, symbol_factory, Or, BitVec from mythril.laser.smt import UGT, symbol_factory, Or, BitVec
@ -44,7 +48,12 @@ def _analyze_state(state):
# Check whether we can also set the callee address # Check whether we can also set the callee address
try: try:
constraints += [to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF] constraints += [to == ATTACKER_ADDRESS]
for tx in state.world_state.transaction_sequence:
if not isinstance(tx, ContractCreationTransaction):
constraints.append(tx.caller == ATTACKER_ADDRESS)
transaction_sequence = solver.get_transaction_sequence(state, constraints) transaction_sequence = solver.get_transaction_sequence(state, constraints)
description_head = "A call to a user-supplied address is executed." description_head = "A call to a user-supplied address is executed."

@ -5,6 +5,9 @@ from mythril.exceptions import UnsatError
from mythril.analysis.modules.base import DetectionModule from mythril.analysis.modules.base import DetectionModule
from mythril.laser.ethereum.state.global_state import GlobalState from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.transaction.symbolic import ATTACKER_ADDRESS from mythril.laser.ethereum.transaction.symbolic import ATTACKER_ADDRESS
from mythril.laser.ethereum.transaction.transaction_models import (
ContractCreationTransaction,
)
import logging import logging
import json import json
@ -58,16 +61,18 @@ class SuicideModule(DetectionModule):
) )
description_head = "The contract can be killed by anyone." description_head = "The contract can be killed by anyone."
caller = state.current_transaction.caller
constraints = []
for tx in state.world_state.transaction_sequence:
if not isinstance(tx, ContractCreationTransaction):
constraints.append(tx.caller == ATTACKER_ADDRESS)
try: try:
try: try:
transaction_sequence = solver.get_transaction_sequence( transaction_sequence = solver.get_transaction_sequence(
state, state,
state.mstate.constraints state.mstate.constraints + constraints + [to == ATTACKER_ADDRESS],
+ [
to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF,
caller == ATTACKER_ADDRESS,
],
) )
description_tail = ( description_tail = (
"Anyone can kill this contract and withdraw its balance to an arbitrary " "Anyone can kill this contract and withdraw its balance to an arbitrary "
@ -75,7 +80,7 @@ class SuicideModule(DetectionModule):
) )
except UnsatError: except UnsatError:
transaction_sequence = solver.get_transaction_sequence( transaction_sequence = solver.get_transaction_sequence(
state, state.mstate.constraints + [caller == ATTACKER_ADDRESS] state, state.mstate.constraints + constraints
) )
description_tail = "Arbitrary senders can kill this contract." description_tail = "Arbitrary senders can kill this contract."

Loading…
Cancel
Save