Ejemplo n.º 1
0
def test_bitvecfunc_ext_unequal_nested_comparison_f():
    # Arrange
    s = Solver()

    input1 = symbol_factory.BitVecSym("input1", 256)
    input2 = symbol_factory.BitVecSym("input2", 256)
    input3 = symbol_factory.BitVecSym("input3", 256)
    input4 = symbol_factory.BitVecSym("input4", 256)

    bvf1 = symbol_factory.BitVecFuncSym("bvf1", "sha3", 256, input_=input1)
    bvf2 = symbol_factory.BitVecFuncSym("bvf2",
                                        "sha3",
                                        256,
                                        input_=bvf1 + input3)

    bvf3 = symbol_factory.BitVecFuncSym("bvf3", "sha3", 256, input_=input2)
    bvf4 = symbol_factory.BitVecFuncSym("bvf4",
                                        "sha3",
                                        256,
                                        input_=bvf3 + input4)

    # Act
    s.add(input1 != input2)
    s.add(input3 == input4)
    s.add(bvf2 == bvf4)

    # Assert
    assert s.check() == z3.unsat
Ejemplo n.º 2
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()
Ejemplo n.º 3
0
def test_bitvecfunc_bitvecfunc_comparison(operation, expected):
    # Arrange
    s = Solver()

    input1 = symbol_factory.BitVecSym("input1", 256)
    input2 = symbol_factory.BitVecSym("input2", 256)
    bvf1 = symbol_factory.BitVecFuncSym("bvf1", "sha3", 256, input_=input1)
    bvf2 = symbol_factory.BitVecFuncSym("bvf2", "sha3", 256, input_=input2)

    # Act
    s.add(operation(bvf1, bvf2))
    s.add(input1 == input2)

    # Assert
    assert s.check() == expected
Ejemplo n.º 4
0
    def __getitem__(self, item: Union[str, int]) -> Any:
        try:
            return self._storage[item]
        except KeyError:
            if (self.address and self.address.value != 0
                    and (self.dynld and self.dynld.storage_loading)):
                try:
                    self._storage[item] = symbol_factory.BitVecVal(
                        int(
                            self.dynld.read_storage(
                                contract_address=hex(self.address.value),
                                index=int(item),
                            ),
                            16,
                        ),
                        256,
                    )
                    return self._storage[item]
                except ValueError:
                    pass

        if self.concrete:
            return symbol_factory.BitVecVal(0, 256)

        self._storage[item] = symbol_factory.BitVecSym(
            "storage_{}_{}".format(str(item), str(self.address)), 256)
        return self._storage[item]
Ejemplo n.º 5
0
def test_symbolic_calldata_equal_indices():
    calldata = SymbolicCalldata(0)

    index_a = symbol_factory.BitVecSym("index_a", 256)
    index_b = symbol_factory.BitVecSym("index_b", 256)

    # Act
    a = calldata[index_a]
    b = calldata[index_b]

    s = Solver()
    s.append(index_a == index_b)
    s.append(a != b)

    # Assert
    assert unsat == s.check()
Ejemplo n.º 6
0
    def __init__(
        self,
        address: str,
        code=None,
        contract_name="unknown",
        balance=None,
        concrete_storage=False,
        dynamic_loader=None,
    ) -> None:
        """Constructor for account.

        :param address: Address of the account
        :param code: The contract code of the account
        :param contract_name: The name associated with the account
        :param balance: The balance for the account
        :param concrete_storage: Interpret storage as concrete
        """
        self.nonce = 0
        self.code = code or Disassembly("")
        self.balance = (balance if balance else symbol_factory.BitVecSym(
            "{}_balance".format(address), 256))
        self.storage = Storage(concrete_storage,
                               address=address,
                               dynamic_loader=dynamic_loader)
        # Metadata
        self.address = address
        self.contract_name = contract_name

        self.deleted = False
Ejemplo n.º 7
0
def test_bitvecfunc_arithmetic(operation, expected):
    # Arrange
    s = Solver()

    input_ = symbol_factory.BitVecVal(1, 8)
    bvf = symbol_factory.BitVecFuncSym("bvf", "sha3", 256, input_=input_)

    x = symbol_factory.BitVecSym("x", 256)
    y = symbol_factory.BitVecSym("y", 256)

    # Act
    s.add(x != y)
    s.add(operation(bvf, x) == operation(y, bvf))

    # Assert
    assert s.check() == expected
Ejemplo n.º 8
0
def test_bitvecfunc_find_input():
    # Arrange
    s = Solver()

    input1 = symbol_factory.BitVecSym("input1", 256)
    input2 = symbol_factory.BitVecSym("input2", 256)

    bvf1 = symbol_factory.BitVecFuncSym("bvf1", "sha3", 256, input_=input1)
    bvf2 = symbol_factory.BitVecFuncSym("bvf3", "sha3", 256, input_=input2)

    # Act
    s.add(input1 == symbol_factory.BitVecVal(1, 256))
    s.add(bvf1 == bvf2)

    # Assert
    assert s.check() == z3.sat
    assert s.model()[input2.raw] == 1
Ejemplo n.º 9
0
    def __init__(self, tx_id: str) -> None:
        """Initializes the SymbolicCalldata object.

        :param tx_id: Id of the transaction that the calldata is for.
        """
        self._size = symbol_factory.BitVecSym(str(tx_id) + "_calldatasize", 256)
        self._calldata = Array("{}_calldata".format(tx_id), 256, 8)
        super().__init__(tx_id)
Ejemplo n.º 10
0
    def __init__(self, tx_id: str) -> None:
        """Initializes the SymbolicCalldata object.

        :param tx_id: Id of the transaction that the calldata is for.
        """
        self._reads = []  # type: List[Tuple[Union[int, BitVec], BitVec]]
        self._size = symbol_factory.BitVecSym(str(tx_id) + "_calldatasize", 256)
        super().__init__(tx_id)
def test_Independence_solver_unsat():
    # Arrange
    x = symbol_factory.BitVecSym("x", 256)
    y = symbol_factory.BitVecSym("y", 256)
    z = symbol_factory.BitVecSym("z", 256)
    a = symbol_factory.BitVecSym("a", 256)
    b = symbol_factory.BitVecSym("b", 256)

    conditions = [x > y, y == z, y != z, a == b]

    solver = IndependenceSolver()

    # Act
    solver.add(*conditions)
    result = solver.check()

    # Assert
    assert z3.unsat == result
Ejemplo n.º 12
0
def execute_contract_creation(
    laser_evm, contract_initialization_code, contract_name=None, world_state=None
) -> Account:
    """Executes a contract creation transaction from all open states.

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

    world_state = world_state or WorldState()
    open_states = [world_state]
    new_account = None
    for open_world_state in open_states:
        next_transaction_id = get_next_transaction_id()
        # call_data "should" be '[]', but it is easier to model the calldata symbolically
        # and add logic in codecopy/codesize/calldatacopy/calldatasize than to model code "correctly"
        transaction = ContractCreationTransaction(
            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
            ),
            code=Disassembly(contract_initialization_code),
            caller=symbol_factory.BitVecVal(CREATOR_ADDRESS, 256),
            contract_name=contract_name,
            call_data=None,
            call_value=symbol_factory.BitVecSym(
                "call_value{}".format(next_transaction_id), 256
            ),
        )
        _setup_global_state_for_execution(laser_evm, transaction)
        new_account = new_account or transaction.callee_account
    laser_evm.exec(True)

    return new_account
Ejemplo n.º 13
0
    def new_bitvec(self, name: str, size=256) -> BitVec:
        """

        :param name:
        :param size:
        :return:
        """
        transaction_id = self.current_transaction.id
        return symbol_factory.BitVecSym("{}_{}".format(transaction_id, name),
                                        size)
Ejemplo n.º 14
0
def test_bitvecfunc_nested_comparison():
    # arrange
    s = Solver()

    input1 = symbol_factory.BitVecSym("input1", 256)
    input2 = symbol_factory.BitVecSym("input2", 256)

    bvf1 = symbol_factory.BitVecFuncSym("bvf1", "sha3", 256, input_=input1)
    bvf2 = symbol_factory.BitVecFuncSym("bvf2", "sha3", 256, input_=bvf1)

    bvf3 = symbol_factory.BitVecFuncSym("bvf3", "sha3", 256, input_=input2)
    bvf4 = symbol_factory.BitVecFuncSym("bvf4", "sha3", 256, input_=bvf3)

    # Act
    s.add(input1 == input2)
    s.add(bvf2 == bvf4)

    # Assert
    assert s.check() == z3.sat
Ejemplo n.º 15
0
def execute_contract_creation(laser_evm,
                              contract_initialization_code,
                              contract_name=None) -> Account:
    """Executes a contract creation transaction from all open states.

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

    new_account = laser_evm.world_state.create_account(0,
                                                       concrete_storage=True,
                                                       dynamic_loader=None,
                                                       creator=CREATOR_ADDRESS)
    if contract_name:
        new_account.contract_name = contract_name

    for open_world_state in open_states:
        next_transaction_id = get_next_transaction_id()
        transaction = ContractCreationTransaction(
            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),
            code=Disassembly(contract_initialization_code),
            caller=symbol_factory.BitVecVal(CREATOR_ADDRESS, 256),
            callee_account=new_account,
            call_data=[],
            call_value=symbol_factory.BitVecSym(
                "call_value{}".format(next_transaction_id), 256),
        )
        _setup_global_state_for_execution(laser_evm, transaction)
    laser_evm.exec(True)

    return new_account
Ejemplo n.º 16
0
    def __init__(
        self,
        world_state: WorldState,
        callee_account: Account = None,
        caller: ExprRef = None,
        call_data=None,
        identifier: Optional[str] = None,
        gas_price=None,
        gas_limit=None,
        origin=None,
        code=None,
        call_value=None,
        init_call_data=True,
        static=False,
    ) -> None:
        assert isinstance(world_state, WorldState)
        self.world_state = world_state
        self.id = identifier or get_next_transaction_id()

        self.gas_price = (gas_price if gas_price is not None else
                          symbol_factory.BitVecSym(
                              "gasprice{}".format(identifier), 256))
        self.gas_limit = gas_limit

        self.origin = (origin
                       if origin is not None else symbol_factory.BitVecSym(
                           "origin{}".format(identifier), 256))
        self.code = code

        self.caller = caller
        self.callee_account = callee_account
        if call_data is None and init_call_data:
            self.call_data = SymbolicCalldata(self.id)  # type: BaseCalldata
        else:
            self.call_data = (call_data if isinstance(call_data, BaseCalldata)
                              else ConcreteCalldata(self.id, []))

        self.call_value = (call_value if call_value is not None else
                           symbol_factory.BitVecSym(
                               "callvalue{}".format(identifier), 256))
        self.static = static
        self.return_data = None  # type: str
Ejemplo n.º 17
0
def test_memory_write():
    # Arrange
    mem = Memory()
    mem.extend(200 + 32)

    a = symbol_factory.BitVecSym("a", 256)
    b = symbol_factory.BitVecSym("b", 8)

    # Act
    mem[11] = 10
    mem[12] = b
    mem.write_word_at(200, 0x12345)
    mem.write_word_at(100, a)

    # Assert
    assert mem[0] == 0
    assert mem[11] == 10
    assert mem[200 + 31] == 0x45
    assert mem.get_word_at(200) == 0x12345
    assert simplify(a == mem.get_word_at(100))
    assert simplify(b == mem[12])
Ejemplo n.º 18
0
def test_decls():
    # Arrange
    solver = Solver()
    x = symbol_factory.BitVecSym("x", 256)
    expression = x == symbol_factory.BitVecVal(2, 256)

    # Act
    solver.add(expression)
    result = solver.check()
    model = solver.model()

    decls = model.decls()

    # Assert
    assert z3.sat == result
    assert x.raw.decl() in decls
Ejemplo n.º 19
0
def test_as_long():
    # Arrange
    solver = Solver()
    x = symbol_factory.BitVecSym("x", 256)
    expression = x == symbol_factory.BitVecVal(2, 256)

    # Act
    solver.add(expression)
    result = solver.check()
    model = solver.model()

    x_concrete = model.eval(x.raw).as_long()

    # Assert
    assert z3.sat == result
    assert 2 == x_concrete
Ejemplo n.º 20
0
def test_get_item():
    # Arrange
    solver = Solver()
    x = symbol_factory.BitVecSym("x", 256)
    expression = x == symbol_factory.BitVecVal(2, 256)

    # Act
    solver.add(expression)
    result = solver.check()
    model = solver.model()

    x_concrete = model[x.raw.decl()]

    # Assert
    assert z3.sat == result
    assert 2 == x_concrete
Ejemplo n.º 21
0
    def _load(self, item: Union[int, BitVec], clean=False) -> Any:
        expr_item = (symbol_factory.BitVecVal(item, 256) if isinstance(
            item, int) else item)  # type: BitVec

        symbolic_base_value = If(
            expr_item >= self._size,
            symbol_factory.BitVecVal(0, 8),
            BitVec(
                symbol_factory.BitVecSym(
                    "{}_calldata_{}".format(self.tx_id, str(item)), 8)),
        )
        return_value = symbolic_base_value
        for r_index, r_value in self._reads:
            return_value = If(r_index == expr_item, r_value, return_value)
        if not clean:
            self._reads.append((expr_item, symbolic_base_value))
        return simplify(return_value)
Ejemplo n.º 22
0
def test_staticness_call_symbolic(f1):
    # Arrange
    state = get_global_state()
    state.environment.static = True
    state.mstate.stack = []
    call_value = symbol_factory.BitVecSym("x", 256)
    code = Disassembly(code="616263")
    f1.return_value = ("0", Account(code=code,
                                    address="0x19"), 0, call_value, 0, 0, 0)
    instruction = Instruction("call", dynamic_loader=None)

    # Act and Assert
    with pytest.raises(TransactionStartSignal) as ts:
        instruction.evaluate(state)

    assert ts.value.transaction.static
    assert ts.value.global_state.mstate.constraints[-1] == (call_value == 0)
Ejemplo n.º 23
0
def test_bitvecfunc_bitvecfuncval_comparison():
    # Arrange
    s = Solver()

    input1 = symbol_factory.BitVecSym("input1", 256)
    input2 = symbol_factory.BitVecVal(1337, 256)
    bvf1 = symbol_factory.BitVecFuncSym("bvf1", "sha3", 256, input_=input1)
    bvf2 = symbol_factory.BitVecFuncVal(12345678910,
                                        "sha3",
                                        256,
                                        input_=input2)

    # Act
    s.add(bvf1 == bvf2)

    # Assert
    assert s.check() == z3.sat
    assert s.model().eval(input2.raw) == 1337
Ejemplo n.º 24
0
    def __init__(
        self,
        active_account: Account,
        sender: ExprRef,
        calldata: BaseCalldata,
        gasprice: ExprRef,
        callvalue: ExprRef,
        origin: ExprRef,
        code=None,
        static=False,
    ) -> None:
        """

        :param active_account:
        :param sender:
        :param calldata:
        :param gasprice:
        :param callvalue:
        :param origin:
        :param code:
        :param static: Makes the environment static.
        """
        # Metadata

        self.active_account = active_account
        self.active_function_name = ""

        self.address = active_account.address
        self.block_number = symbol_factory.BitVecSym("block_number", 256)

        # Ib
        self.code = active_account.code if code is None else code

        self.sender = sender
        self.calldata = calldata
        self.gasprice = gasprice
        self.origin = origin
        self.callvalue = callvalue
        self.static = static
Ejemplo n.º 25
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