def test_execute_node(mocker):
    record = TaintRecord()
    record.stack = [True, True, False, False]

    state_1 = GlobalState(None, None, None)
    state_1.mstate.stack = [1, 2, 3, 1]
    state_1.mstate.pc = 1
    mocker.patch.object(state_1, "get_current_instruction")
    state_1.get_current_instruction.return_value = {"opcode": "SWAP1"}

    state_2 = GlobalState(None, 1, None)
    state_2.mstate.stack = [1, 2, 4, 1]
    mocker.patch.object(state_2, "get_current_instruction")
    state_2.get_current_instruction.return_value = {"opcode": "ADD"}

    node = Node("Test contract")
    node.states = [state_1, state_2]

    # Act
    records = TaintRunner.execute_node(node, record)

    # Assert
    assert len(records) == 2

    assert records[0].stack == [True, True, False, False]
    assert records[1].stack == [True, True, False]

    assert state_2 in records[0].states
    assert state_1 in record.states
Example #2
0
def execute_create():
    global last_state
    global created_contract_account
    if not last_state and not created_contract_account:
        code_raw = []
        for i in range(len(contract_init_code) // 2):
            code_raw.append(int(contract_init_code[2 * i:2 * (i + 1)], 16))
        calldata = ConcreteCalldata(0, code_raw)

        world_state = WorldState()
        account = world_state.create_account(balance=1000000, address=101)
        account.code = Disassembly("60a760006000f000")
        environment = Environment(account, None, calldata, None, None, None)
        og_state = GlobalState(world_state, environment, None,
                               MachineState(gas_limit=8000000))
        og_state.transaction_stack.append(
            (MessageCallTransaction(world_state=WorldState(),
                                    gas_limit=8000000), None))

        laser = LaserEVM()
        states = [og_state]
        last_state = og_state
        for state in states:
            new_states, op_code = laser.execute_state(state)
            last_state = state
            if op_code == "STOP":
                break
            states.extend(new_states)

        created_contract_address = last_state.mstate.stack[-1].value
        created_contract_account = last_state.world_state.accounts[
            created_contract_address]

    return last_state, created_contract_account
Example #3
0
def test_concrete_call_symbolic_to():
    # arrange
    address = "0x10"

    active_account = Account(address)
    active_account.code = Disassembly("00")
    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment, None)
    state.mstate.memory = ["placeholder", "calldata_bling_0"]

    node = Node("example")
    node.contract_name = "the contract name"
    node.function_name = "the function name"

    to = Variable("calldata_3", VarType.SYMBOLIC)
    meminstart = Variable(1, VarType.CONCRETE)
    call = Call(node, state, None, None, to, None)

    # act
    issues = _concrete_call(call, state, address, meminstart)

    # assert
    issue = issues[0]
    assert issue.address == address
    assert issue.contract == node.contract_name
    assert issue.function == node.function_name
    assert issue.title == "Call data forwarded with delegatecall()"
    assert issue.type == "Informational"
    assert (
        issue.description
        == "This contract forwards its call data via DELEGATECALL in its fallback function."
        " This means that any function in the called contract can be executed."
        " Note that the callee contract will have access to the storage of the "
        "calling contract.\n DELEGATECALL target: calldata_3"
    )
Example #4
0
def test_delegate_call(sym_mock, concrete_mock, curr_instruction):
    # arrange
    # sym_mock = mocker.patch.object(delegatecall, "_symbolic_call")
    # concrete_mock = mocker.patch.object(delegatecall, "_concrete_call")
    sym_mock.return_value = []
    concrete_mock.return_value = []
    curr_instruction.return_value = {"address": "0x10"}

    active_account = Account("0x10")
    active_account.code = Disassembly("00")

    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment, Node)
    state.mstate.memory = ["placeholder", "calldata_bling_0"]
    state.mstate.stack = [1, 2, 3]
    assert state.get_current_instruction() == {"address": "0x10"}

    node = Node("example")
    node.contract_name = "the contract name"
    node.function_name = "fallback"

    to = Variable("storage_1", VarType.SYMBOLIC)
    call = Call(node, state, None, "DELEGATECALL", to, None)

    statespace = MagicMock()
    statespace.calls = [call]

    # act
    execute(statespace)

    # assert
    assert concrete_mock.call_count == 1
    assert sym_mock.call_count == 1
Example #5
0
def get_state():
    active_account = Account("0x0", code=Disassembly("60606040"))
    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment, None, MachineState(gas_limit=8000000))
    state.transaction_stack.append(
        (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
    )
    return state
def _get_global_state():
    active_account = Account("0x0", code=Disassembly("60606040"))
    passive_account = Account("0x325345346564645654645",
                              code=Disassembly("6060604061626364"))
    environment = Environment(active_account, None, None, None, None, None)
    world_state = WorldState()
    world_state.put_account(active_account)
    world_state.put_account(passive_account)
    return GlobalState(world_state, environment, None,
                       MachineState(gas_limit=8000000))
def test_execute(mocker):
    active_account = Account("0x00")
    environment = Environment(active_account, None, None, None, None, None)
    state_1 = GlobalState(None, environment, None,
                          MachineState(gas_limit=8000000))
    state_1.mstate.stack = [1, 2]
    mocker.patch.object(state_1, "get_current_instruction")
    state_1.get_current_instruction.return_value = {"opcode": "PUSH"}

    state_2 = GlobalState(None, environment, None,
                          MachineState(gas_limit=8000000))
    state_2.mstate.stack = [1, 2, 3]
    mocker.patch.object(state_2, "get_current_instruction")
    state_2.get_current_instruction.return_value = {"opcode": "ADD"}

    node_1 = Node("Test contract")
    node_1.states = [state_1, state_2]

    state_3 = GlobalState(None, environment, None,
                          MachineState(gas_limit=8000000))
    state_3.mstate.stack = [1, 2]
    mocker.patch.object(state_3, "get_current_instruction")
    state_3.get_current_instruction.return_value = {"opcode": "ADD"}

    node_2 = Node("Test contract")
    node_2.states = [state_3]

    edge = Edge(node_1.uid, node_2.uid)

    statespace = LaserEVM(None)
    statespace.edges = [edge]
    statespace.nodes[node_1.uid] = node_1
    statespace.nodes[node_2.uid] = node_2

    # Act
    result = TaintRunner.execute(statespace, node_1, state_1, [True, True])

    # Assert
    print(result)
    assert len(result.records) == 3
    assert result.records[2].states == []
    assert state_3 in result.records[1].states
Example #8
0
def get_state():
    world_state = WorldState()
    account = world_state.create_account(balance=10, address=101)
    account.code = Disassembly("60606040")
    environment = Environment(account, None, None, None, None, None)
    state = GlobalState(world_state, environment, None,
                        MachineState(gas_limit=8000000))
    state.transaction_stack.append(
        (MessageCallTransaction(world_state=WorldState(),
                                gas_limit=8000000), None))
    return state
Example #9
0
def test_concrete_call_not_calldata():
    # arrange
    state = GlobalState(None, None, None)
    state.mstate.memory = ["placeholder", "not_calldata"]
    meminstart = Variable(1, VarType.CONCRETE)

    # act
    issues = _concrete_call(None, state, None, meminstart)

    # assert
    assert issues == []
Example #10
0
 def initial_global_state_from_environment(self,
                                           environment,
                                           active_function,
                                           last_function_called=None):
     # Initialize the execution environment
     global_state = GlobalState(self.world_state,
                                environment,
                                None,
                                last_function_called=last_function_called)
     global_state.environment.active_function_name = active_function
     return global_state
Example #11
0
    def initial_global_state_from_environment(self, environment,
                                              active_function):
        """

        :param environment:
        :param active_function:
        :return:
        """
        # Initialize the execution environment
        global_state = GlobalState(self.world_state, environment, None)
        global_state.environment.active_function_name = active_function
        return global_state
Example #12
0
def test_result_no_state():
    # arrange
    taint_result = TaintResult()
    record = TaintRecord()
    state = GlobalState(2, None, None)
    state.mstate.stack = [1, 2, 3]

    # act
    taint_result.add_records([record])
    tainted = taint_result.check(state, 2)

    # assert
    assert tainted is None
    assert record in taint_result.records
Example #13
0
def test_codecopy_concrete():
    # Arrange
    active_account = Account("0x0", code=Disassembly("60606040"))
    environment = Environment(active_account, None, None, None, None, None)
    og_state = GlobalState(None, environment, None, MachineState(gas=10000000))

    og_state.mstate.stack = [2, 2, 2]
    instruction = Instruction("codecopy", dynamic_loader=None)

    # Act
    new_state = instruction.evaluate(og_state)[0]

    # Assert
    assert new_state.mstate.memory[2] == 96
    assert new_state.mstate.memory[3] == 64
def test_execute_state(mocker):
    record = TaintRecord()
    record.stack = [True, False, True]

    state = GlobalState(None, None, None)
    state.mstate.stack = [1, 2, 3]
    mocker.patch.object(state, "get_current_instruction")
    state.get_current_instruction.return_value = {"opcode": "ADD"}

    # Act
    new_record = TaintRunner.execute_state(record, state)

    # Assert
    assert new_record.stack == [True, True]
    assert record.stack == [True, False, True]
Example #15
0
    def initial_global_state(self) -> GlobalState:
        """Initialize the execution environment"""
        environment = Environment(
            self.callee_account,
            self.caller,
            self.call_data,
            self.gas_price,
            self.call_value,
            self.origin,
            code=self.code or self.callee_account.code,
            calldata_type=self.call_data_type,
        )

        global_state = GlobalState(self.world_state, environment, None)
        global_state.environment.active_function_name = "fallback"

        return global_state
def test_codecopy_concrete():
    # Arrange
    active_account = Account("0x0", code=Disassembly("60606040"))
    environment = Environment(active_account, None, None, None, None, None)
    og_state = GlobalState(None, environment, None,
                           MachineState(gas_limit=8000000))
    og_state.transaction_stack.append(
        (MessageCallTransaction(world_state=WorldState(),
                                gas_limit=8000000), None))

    og_state.mstate.stack = [2, 2, 2]
    instruction = Instruction("codecopy", dynamic_loader=None)

    # Act
    new_state = instruction.evaluate(og_state)[0]

    # Assert
    assert new_state.mstate.memory[2] == 96
    assert new_state.mstate.memory[3] == 64
Example #17
0
    def initial_global_state_from_environment(self, environment,
                                              active_function):
        """

        :param environment:
        :param active_function:
        :return:
        """
        # Initialize the execution environment
        global_state = GlobalState(self.world_state, environment, None)
        global_state.environment.active_function_name = active_function

        sender = environment.sender
        receiver = environment.active_account.address
        value = environment.callvalue

        global_state.world_state.balances[sender] -= value
        global_state.world_state.balances[receiver] += value

        return global_state
Example #18
0
def test_extcodecopy_fail():
    # Arrange
    new_world_state = WorldState()
    new_account = new_world_state.create_account(balance=10, address=101)
    new_account.code = Disassembly("60616240")
    new_environment = Environment(new_account, None, None, None, None, None)
    state = GlobalState(
        new_world_state, new_environment, None, MachineState(gas_limit=8000000)
    )
    state.transaction_stack.append(
        (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
    )

    state.mstate.stack = [2, 2, 2, symbol_factory.BitVecSym("FAIL", 256)]
    instruction = Instruction("extcodecopy", dynamic_loader=None)

    # Act
    new_state = instruction.evaluate(state)[0]

    # Assert
    assert new_state.mstate.stack == []
    assert new_state.mstate.memory._memory == state.mstate.memory._memory
Example #19
0
def test_symbolic_call_storage_to(mocker):
    # arrange
    address = "0x10"

    active_account = Account(address)
    active_account.code = Disassembly("00")
    environment = Environment(active_account, None, None, None, None, None)
    state = GlobalState(None, environment, None)
    state.mstate.memory = ["placeholder", "calldata_bling_0"]

    node = Node("example")
    node.contract_name = "the contract name"
    node.function_name = "the function name"

    to = Variable("storage_1", VarType.SYMBOLIC)
    call = Call(node, state, None, "Type: ", to, None)

    mocker.patch.object(SymExecWrapper, "__init__", lambda x, y: None)
    statespace = SymExecWrapper(1)

    mocker.patch.object(statespace, "find_storage_write")
    statespace.find_storage_write.return_value = "Function name"

    # act
    issues = _symbolic_call(call, state, address, statespace)

    # assert
    issue = issues[0]
    assert issue.address == address
    assert issue.contract == node.contract_name
    assert issue.function == node.function_name
    assert issue.title == "Type:  to a user-supplied address"
    assert issue.type == "Informational"
    assert (
        issue.description
        == "This contract delegates execution to a contract address in storage slot 1."
        " This storage slot can be written to by calling the function `Function name`. "
        "Be aware that the called contract gets unrestricted access to this contract's state."
    )
Example #20
0
def test_extcodecopy():
    # Arrange
    new_world_state = WorldState()
    new_account = new_world_state.create_account(balance=10, address=101)
    new_account.code = Disassembly("60616240")
    ext_account = new_world_state.create_account(balance=1000, address=121)
    ext_account.code = Disassembly("6040404040")

    new_environment = Environment(new_account, None, None, None, None, None)
    state = GlobalState(
        new_world_state, new_environment, None, MachineState(gas_limit=8000000)
    )
    state.transaction_stack.append(
        (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
    )

    state.mstate.stack = [3, 0, 0, 121]
    instruction = Instruction("extcodecopy", dynamic_loader=None)

    # Act
    new_state = instruction.evaluate(state)[0]
    # Assert
    assert new_state.mstate.memory[0:3] == [96, 64, 64]
Example #21
0
    def initial_global_state_from_environment(self, environment,
                                              active_function):
        """

        :param environment:
        :param active_function:
        :return:
        """
        # Initialize the execution environment
        global_state = GlobalState(self.world_state, environment, None)
        global_state.environment.active_function_name = active_function

        sender = environment.sender
        receiver = environment.active_account.address
        value = (environment.callvalue if isinstance(
            environment.callvalue, BitVec) else symbol_factory.BitVecVal(
                environment.callvalue, 256))

        global_state.mstate.constraints.append(
            UGE(global_state.world_state.balances[sender], value))
        global_state.world_state.balances[receiver] += value
        global_state.world_state.balances[sender] -= value

        return global_state
Example #22
0
import pytest
import random
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.strategy.basic import ReturnWeightedRandomStrategy
from mythril.laser.ethereum.strategy.graph import SimpleGraph

test_worklist_input = [([
    GlobalState(None, None, None, machine_state=MachineState(gas=100,
                                                             depth=2)),
    GlobalState(None,
                None,
                None,
                machine_state=MachineState(gas=100, depth=10)),
    GlobalState(None,
                None,
                None,
                machine_state=MachineState(gas=100, depth=20)),
])]


@pytest.mark.parametrize("work_list", test_worklist_input)
def test_random_weighted_strategy(work_list):
    strategy = ReturnWeightedRandomStrategy(SimpleGraph(), max_depth=30)
    strategy.graph.work_list = work_list
    counter = {}
    iterations = 10000
    eps = 1e-2
    random.seed(1)
    total_sum = sum(
        [1 / (1 + global_state.mstate.depth) for global_state in work_list])
Example #23
0
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction

from mythril.support.support_utils import get_code_hash

from mythril.laser.smt import symbol_factory

# Arrange
world_state = WorldState()
account = world_state.create_account(balance=10, address=101)
account.code = Disassembly("60606040")
world_state.create_account(balance=10, address=1000)
environment = Environment(account, None, None, None, None, None)
og_state = GlobalState(world_state, environment, None,
                       MachineState(gas_limit=8000000))
og_state.transaction_stack.append(
    (MessageCallTransaction(world_state=WorldState(),
                            gas_limit=8000000), None))

instruction = Instruction("extcodehash", dynamic_loader=None)


def test_extcodehash_no_account():

    # If account does not exist, return 0
    og_state.mstate.stack = [symbol_factory.BitVecVal(1, 256)]
    new_state = instruction.evaluate(og_state)[0]
    assert new_state.mstate.stack[-1] == 0

Example #24
0
import pytest
from mythril.laser.ethereum.strategy.graph import SimpleGraph
from mythril.laser.ethereum.state.global_state import GlobalState

add_vertex_test_data = [GlobalState(None, None, None)]


@pytest.mark.parametrize("vertex", add_vertex_test_data)
def test_add_vertex(vertex):
    graph = SimpleGraph()
    graph.add_vertex(vertex)
    assert graph.work_list[-1] == vertex


add_edge_test_data = [
    (
        GlobalState(None, None, None),
        [GlobalState(None, None, None), GlobalState(None, None, None)],
    )
]


@pytest.mark.parametrize("vertex_from, vertices_to", add_edge_test_data)
def test_add_edges(vertex_from, vertices_to):
    graph = SimpleGraph()
    graph.add_edges(vertex_from, vertices_to)

    assert graph.work_list == vertices_to
Example #25
0
import pytest
from mythril.laser.ethereum.strategy.graph import Graph
from mythril.laser.ethereum.state.global_state import GlobalState

add_vertex_test_data = [GlobalState(None, None, None)]


@pytest.mark.parametrize("vertex", add_vertex_test_data)
def test_add_vertex(vertex):
    graph = Graph()
    graph.add_vertex(vertex)
    assert vertex in graph.adjacency_list


add_edge_test_data = [
    (
        GlobalState(None, None, None),
        [GlobalState(None, None, None), GlobalState(None, None, None)],
    )
]


@pytest.mark.parametrize("vertex_from, vertices_to", add_edge_test_data)
def test_add_edges(vertex_from, vertices_to):
    graph = Graph()
    graph.add_vertex(vertex_from)
    graph.add_edges(vertex_from, vertices_to)

    assert graph.adjacency_list[vertex_from] == vertices_to