Example #1
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 #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 __init__(
     self,
     world_state,
     callee_account,
     caller,
     call_data=None,
     identifier=None,
     gas_price=None,
     call_value=None,
     origin=None,
     call_data_type=None,
     code=None,
 ):
     assert isinstance(world_state, WorldState)
     self.id = identifier or get_next_transaction_id()
     self.world_state = world_state
     self.callee_account = callee_account
     self.caller = caller
     self.call_data = (Calldata(self.id, call_data) if
                       not isinstance(call_data, Calldata) else call_data)
     self.gas_price = (BitVec("gasprice{}".format(identifier), 256)
                       if gas_price is None else gas_price)
     self.call_value = (BitVec("callvalue{}".format(identifier), 256)
                        if call_value is None else call_value)
     self.origin = (BitVec("origin{}".format(identifier), 256)
                    if origin is None else origin)
     self.call_data_type = (BitVec("call_data_type{}".format(identifier),
                                   256)
                            if call_data_type is None else call_data_type)
     self.code = code
     self.return_data = None
Example #4
0
def test_concrete_calldata_uninitialized_index(starting_calldata):
    # Arrange
    calldata = Calldata(0, starting_calldata)
    solver = Solver()

    # Act
    value = calldata[100]
    value2 = calldata.get_word_at(200)

    solver.add(calldata.constraints)
    solver.check()
    model = solver.model()

    value = model.eval(value)
    value2 = model.eval(value2)

    # Assert
    assert value == 0
    assert value2 == 0
Example #5
0
def get_call_data(
    global_state: GlobalState,
    memory_start: Union[int, ExprRef],
    memory_size: Union[int, ExprRef],
):
    """
    Gets call_data from the global_state
    :param global_state: state to look in
    :param memory_start: Start index
    :param memory_size: Size
    :return: Tuple containing: call_data array from memory or empty array if symbolic, type found
    """
    state = global_state.mstate
    transaction_id = "{}_internalcall".format(global_state.current_transaction.id)
    try:
        # TODO: This only allows for either fully concrete or fully symbolic calldata.
        # Improve management of memory and callata to support a mix between both types.
        calldata_from_mem = state.memory[
            util.get_concrete_int(memory_start) : util.get_concrete_int(
                memory_start + memory_size
            )
        ]
        i = 0
        starting_calldata = []
        while i < len(calldata_from_mem):
            elem = calldata_from_mem[i]
            if isinstance(elem, int):
                starting_calldata.append(elem)
                i += 1
            else:  # BitVec
                for j in range(0, elem.size(), 8):
                    starting_calldata.append(Extract(j + 7, j, elem))
                    i += 1

        call_data = Calldata(transaction_id, starting_calldata)
        call_data_type = CalldataType.CONCRETE
        logging.debug("Calldata: " + str(call_data))
    except TypeError:
        logging.debug("Unsupported symbolic calldata offset")
        call_data_type = CalldataType.SYMBOLIC
        call_data = Calldata("{}_internalcall".format(transaction_id))

    return call_data, call_data_type
Example #6
0
    def __init__(
        self,
        world_state,
        caller,
        identifier=None,
        callee_account=None,
        code=None,
        call_data=None,
        gas_price=None,
        call_value=None,
        origin=None,
        call_data_type=None,
    ):
        assert isinstance(world_state, WorldState)
        self.id = identifier or get_next_transaction_id()
        self.world_state = world_state
        # TODO: set correct balance for new account
        self.callee_account = (
            callee_account
            if callee_account
            else world_state.create_account(0, concrete_storage=True)
        )

        self.caller = caller

        self.gas_price = (
            BitVec("gasprice{}".format(identifier), 256)
            if gas_price is None
            else gas_price
        )
        self.call_value = (
            BitVec("callvalue{}".format(identifier), 256)
            if call_value is None
            else call_value
        )
        self.origin = (
            BitVec("origin{}".format(identifier), 256) if origin is None else origin
        )
        self.call_data_type = (
            BitVec("call_data_type{}".format(identifier), 256)
            if call_data_type is None
            else call_data_type
        )

        self.call_data = (
            Calldata(self.id, call_data)
            if not isinstance(call_data, Calldata)
            else call_data
        )
        self.origin = origin
        self.code = code
        self.return_data = None
Example #7
0
def test_concrete_calldata_constrain_index():
    # Arrange
    calldata = Calldata(0, [1, 4, 7, 3, 7, 2, 9])
    solver = Solver()

    # Act
    constraint = calldata[2] == 3

    solver.add(calldata.constraints + [constraint])
    result = solver.check()

    # Assert
    assert str(result) == "unsat"
Example #8
0
def test_concrete_calldata_calldatasize():
    # Arrange
    calldata = Calldata(0, [1, 4, 7, 3, 7, 2, 9])
    solver = Solver()

    # Act
    solver.check()
    model = solver.model()

    result = model.eval(calldata.calldatasize)

    # Assert
    assert result == 7
Example #9
0
def test_concrete_calldata_constrain_index():
    # Arrange
    calldata = Calldata(0, [1, 4, 7, 3, 7, 2, 9])
    solver = Solver()

    # Act
    value, calldata_constraints = calldata[2]
    constraint = value == 3

    solver.add([constraint] + calldata_constraints)
    result = solver.check()

    # Assert
    assert str(result) == "unsat"
Example #10
0
def test_concrete_calldata_constrain_index():
    # Arrange
    calldata = Calldata(0)
    solver = Solver()

    # Act
    constraints = []
    constraints.append(calldata[51] == 1)
    constraints.append(calldata.calldatasize == 50)

    solver.add(calldata.constraints + constraints)
    result = solver.check()

    # Assert
    assert str(result) == "unsat"
Example #11
0
def test_concrete_calldata_constrain_index():
    # Arrange
    calldata = Calldata(0)
    mstate = MagicMock()
    mstate.constraints = []
    solver = Solver()

    # Act
    constraints = []
    value, calldata_constraints = calldata[51]
    constraints.append(value == 1)
    constraints.append(calldata.calldatasize == 50)

    solver.add(constraints + calldata_constraints)

    result = solver.check()

    # Assert
    assert str(result) == "unsat"
Example #12
0
def test_symbolic_calldata_constrain_index():
    # Arrange
    calldata = Calldata(0)
    solver = Solver()

    # Act
    constraint = calldata[100] == 50

    value = calldata[100]

    solver.add(calldata.constraints + [constraint])
    solver.check()
    model = solver.model()

    value = model.eval(value)
    calldatasize = model.eval(calldata.calldatasize)

    # Assert
    assert value == 50
    assert simplify(calldatasize >= 100)