Example #1
0
def execute_message_call(laser_evm, callee_address: str) -> None:
    """Executes a message call transaction from all open states.

    :param laser_evm:
    :param callee_address:
    """
    # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        if open_world_state[callee_address].deleted:
            log.debug("Can not execute dead contract, skipping.")
            continue

        next_transaction_id = get_next_transaction_id()
        transaction = MessageCallTransaction(
            world_state=open_world_state,
            identifier=next_transaction_id,
            gas_price=symbol_factory.BitVecSym(
                "gas_price{}".format(next_transaction_id), 256),
            gas_limit=8000000,  # block gas limit
            origin=symbol_factory.BitVecSym(
                "origin{}".format(next_transaction_id), 256),
            caller=symbol_factory.BitVecVal(ATTACKER_ADDRESS, 256),
            callee_account=open_world_state[callee_address],
            call_data=SymbolicCalldata(next_transaction_id),
            call_value=symbol_factory.BitVecSym(
                "call_value{}".format(next_transaction_id), 256),
        )
        _setup_global_state_for_execution(laser_evm, transaction)

    laser_evm.exec()
Example #2
0
def execute_message_call(
    laser_evm,
    callee_address,
    caller_address,
    origin_address,
    code,
    data,
    gas,
    gas_price,
    value,
):
    """ Executes a message call transaction from all open states """
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        next_transaction_id = get_next_transaction_id()
        transaction = MessageCallTransaction(
            identifier=next_transaction_id,
            world_state=open_world_state,
            callee_account=open_world_state[callee_address],
            caller=caller_address,
            call_data=Calldata(next_transaction_id, data),
            gas_price=gas_price,
            call_value=value,
            origin=origin_address,
            call_data_type=CalldataType.SYMBOLIC,
            code=Disassembly(code),
        )

        _setup_global_state_for_execution(laser_evm, transaction)

    laser_evm.exec()
Example #3
0
def execute_message_call(laser_evm, callee_address):
    """ Executes a message call transaction from all open states """
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        if open_world_state[callee_address].deleted:
            debug("Can not execute dead contract, skipping.")
            continue

        next_transaction_id = get_next_transaction_id()
        transaction = MessageCallTransaction(
            world_state=open_world_state,
            callee_account=open_world_state[callee_address],
            caller=BitVec("caller{}".format(next_transaction_id), 256),
            identifier=next_transaction_id,
            call_data=Calldata(next_transaction_id),
            gas_price=BitVec("gas_price{}".format(next_transaction_id), 256),
            call_value=BitVec("call_value{}".format(next_transaction_id), 256),
            origin=BitVec("origin{}".format(next_transaction_id), 256),
            call_data_type=CalldataType.SYMBOLIC,
        )
        _setup_global_state_for_execution(laser_evm, transaction)

    laser_evm.exec()
Example #4
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 #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
Example #6
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 #7
0
def execute_message_call(
    laser_evm,
    callee_address,
    caller_address,
    origin_address,
    code,
    data,
    gas_limit,
    gas_price,
    value,
    track_gas=False,
) -> Union[None, List[GlobalState]]:
    """Execute a message call transaction from all open states.

    :param laser_evm:
    :param callee_address:
    :param caller_address:
    :param origin_address:
    :param code:
    :param data:
    :param gas_limit:
    :param gas_price:
    :param value:
    :param track_gas:
    :return:
    """
    # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        next_transaction_id = get_next_transaction_id()
        transaction = MessageCallTransaction(
            world_state=open_world_state,
            identifier=next_transaction_id,
            gas_price=gas_price,
            gas_limit=gas_limit,
            origin=origin_address,
            code=Disassembly(code),
            caller=caller_address,
            callee_account=open_world_state[callee_address],
            call_data=ConcreteCalldata(next_transaction_id, data),
            call_value=value,
        )

        _setup_global_state_for_execution(laser_evm, transaction)

    return laser_evm.exec(track_gas=track_gas)
Example #8
0
def execute_message_call(laser_evm, callee_address):
    """ Executes a message call transaction from all open states """
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        transaction = MessageCallTransaction(
            open_world_state,
            open_world_state[callee_address],
            BitVec("caller", 256),
            [],
            BitVec("gas_price", 256),
            BitVec("call_value", 256),
            BitVec("origin", 256),
            CalldataType.SYMBOLIC,
        )
        _setup_global_state_for_execution(laser_evm, transaction)

    laser_evm.exec()
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 #10
0
def execute_message_call(laser_evm, callee_address):
    """ Executes a message call transaction from all open states """
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        try:
            open_world_state = open_states[0]
            open_world_state.accounts = deepcopy(open_world_state.accounts)
            for address, account in open_world_state.accounts.items():
                account.reset_state()
            if not laser_evm.open_states:
                laser_evm.open_states.append(open_world_state)
            else:
                for address, account in open_world_state.accounts.items():
                    for added_world_state in laser_evm.open_states:
                        if address not in added_world_state.accounts:
                            for address_existing, account_existing in added_world_state.accounts.items(
                            ):
                                if account.code != account_existing.code:
                                    raise FoundDistinctGlobalWorldState()
        except FoundDistinctGlobalWorldState as f:
            laser_evm.open_states.append(open_world_state)

    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        transaction = MessageCallTransaction(
            open_world_state,
            open_world_state[callee_address],
            BitVec("caller", 256),
            [],
            BitVec("gasprice", 256),
            BitVec("callvalue", 256),
            BitVec("origin", 256),
            CalldataType.SYMBOLIC,
        )
        _setup_global_state_for_execution(laser_evm, transaction)

    laser_evm.exec()
Example #11
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 #12
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 #13
0
def execute_message_call(laser_evm,
                         callee_address: str,
                         priority=None) -> None:
    """ Executes a message call transaction from all open states """
    # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here
    # TODO: if the function of openstate.node.funcname is not in priority list, dont add it
    # TODO: This is for deleting repeated variables read
    # copy the open states from last iteration to this iteration
    # The working list is always empty when an iteration is done
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        if open_world_state[callee_address].deleted:
            debug("Can not execute dead contract, skipping.")
            continue

        next_transaction_id = get_next_transaction_id()
        transaction = MessageCallTransaction(
            world_state=open_world_state,
            identifier=next_transaction_id,
            gas_price=BitVec("gas_price{}".format(next_transaction_id), 256),
            gas_limit=8000000,  # block gas limit
            origin=BitVec("origin{}".format(next_transaction_id), 256),
            caller=BitVecVal(ATTACKER_ADDRESS, 256),
            callee_account=open_world_state[callee_address],
            call_data=SymbolicCalldata(next_transaction_id),
            call_data_type=CalldataType.SYMBOLIC,
            call_value=BitVec("call_value{}".format(next_transaction_id), 256),
        )

        # the open states from last iterations are appended to work list here
        _setup_global_state_for_execution(laser_evm, transaction,
                                          open_world_state.node.function_name)

    laser_evm.exec(priority=None)
Example #14
0
def heuristic_message_call_helper(laser_evm,
                                  callee_address: str,
                                  priority=None):
    jump = False

    open_states_copy = copy(laser_evm.open_states)

    for open_state in open_states_copy:
        name = open_state.node.function_name

        for priority_list in priority['RAW']:
            if name == priority_list.first.function_name:
                laser_evm.first_order_work_list.append(open_state)
                laser_evm.open_states.remove(open_state)
                jump = True
                break

        if jump:
            jump = False
            continue

        for priority_list in priority['WAR']:
            if name == priority_list.first.function_name:
                laser_evm.second_order_work_list.append(open_state)
                laser_evm.open_states.remove(open_state)
                jump = True
                break

        if jump:
            jump = False
            continue

        for priority_list in priority['WAW']:
            if name == priority_list.first.function_name:
                laser_evm.third_order_work_list.append(open_state)
                laser_evm.open_states.remove(open_state)
                jump = True
                break

        if jump:
            jump = False
            continue

        for priority_list in priority['RAR']:
            if name == priority_list.first.function_name:
                laser_evm.forth_order_work_list.append(open_state)
                laser_evm.open_states.remove(open_state)
                jump = True
                break
        if jump:
            jump = False
            continue

    laser_evm.ranking.append(laser_evm.first_order_work_list)
    laser_evm.ranking.append(laser_evm.second_order_work_list)
    laser_evm.ranking.append(laser_evm.third_order_work_list)
    laser_evm.ranking.append(laser_evm.forth_order_work_list)

    del laser_evm.open_states[:]

    for items in laser_evm.ranking:
        title = items[0]
        list1 = items[1:]

        for open_world_state in list1:
            if open_world_state[callee_address].deleted:
                debug("Can not execute dead contract, skipping.")
                continue

            last_func_called = open_world_state.node.function_name
            next_transaction_id = get_next_transaction_id()
            transaction = MessageCallTransaction(
                world_state=open_world_state,
                callee_account=open_world_state[callee_address],
                caller=BitVecVal(ATTACKER_ADDRESS, 256),
                identifier=next_transaction_id,
                call_data=SymbolicCalldata(next_transaction_id),
                gas_price=BitVec("gas_price{}".format(next_transaction_id),
                                 256),
                call_value=BitVec("call_value{}".format(next_transaction_id),
                                  256),
                origin=BitVec("origin{}".format(next_transaction_id), 256),
                call_data_type=CalldataType.SYMBOLIC,
                gas_limit=8000000,  # block gas limit
            )

            # the open states from last iterations are appended to work list here
            _setup_global_state_for_execution(laser_evm, transaction,
                                              last_func_called)
        laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm)

        # Execute the new open states added to the work list in Instruction.jumpi_ function

        if title == 'RAW':
            for gs in laser_evm.second_work_list:
                laser_evm.work_list.append(gs)
            laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm)
        elif title == 'WAR':
            for gs in laser_evm.third_work_list:
                laser_evm.work_list.append(gs)
            laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm)
        elif title == 'WAW':
            for gs in laser_evm.forth_work_list:
                laser_evm.work_list.append(gs)
            laser_evm.exec(priority=priority, title=title, laser_obj=laser_evm)
Example #15
0
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


def test_extcodehash_no_code():

    # If account code does not exist, return hash of empty set.