Exemple #1
0
def get_constr_glbstate(contract, address):

    mstate = MachineState(gas=10000000)

    minimal_const_byte_len = get_minimal_constructor_param_encoding_len(abi_json_to_abi(contract.abi))

    # better would be to append symbolic params to the bytecode such that the codecopy instruction that copies the
    # params into memory takes care of placing them onto the memory with the respective size.
    for i in range(int(minimal_const_byte_len / 32)):
        mstate.mem_extend(128 + 32 * i, 32)
        mstate.memory.insert(128 + 32 * i, BitVec('calldata_' + contract.name + '[' + str(i * 32)+ "]", 256))


    # Todo Replace pure placement of enough symbolic 32 Byte-words with placement of symbolic variables that contain
    # the name of the solidity variables

    accounts = {address: Account(address, contract.disassembly, contract_name=contract.name)}

    environment = Environment(
        accounts[address],
        BitVec("caller", 256),
        [],
        BitVec("gasprice", 256),
        BitVec("callvalue", 256),
        BitVec("origin", 256),
        calldata_type=CalldataType.SYMBOLIC,
    )

    # Todo find source for account info, maybe the std statespace?

    return GlobalState(accounts, environment, None, mstate)
Exemple #2
0
def test_stack_pop_too_many(initial_size, overflow):
    # Arrange
    machine_state = MachineState(0)
    machine_state.stack = [42] * initial_size

    # Act + Assert
    with pytest.raises(StackUnderflowException):
        machine_state.pop(initial_size + overflow)
Exemple #3
0
def test_stack_single_pop():
    # Arrange
    machine_state = MachineState(0)
    machine_state.stack = [1, 2, 3]

    # Act
    result = machine_state.pop()

    # Assert
    assert isinstance(result, int)
Exemple #4
0
def test_stack_multiple_pop_():
    # Arrange
    machine_state = MachineState(0)
    machine_state.stack = [1, 2, 3]

    # Act
    a, b = machine_state.pop(2)

    # Assert
    assert a == 3
    assert b == 2
Exemple #5
0
def test_memory_write(initial_size, memory_offset, data):
    # Arrange
    machine_state = MachineState(0)
    machine_state.memory = [0]*initial_size

    # Act
    machine_state.memory_write(memory_offset, data)

    # Assert
    assert len(machine_state.memory) == max(initial_size, memory_offset+len(data))
    assert machine_state.memory[memory_offset:memory_offset+len(data)] == data
Exemple #6
0
def test_memory_extension(initial_size, start, extension_size):
    # Arrange
    machine_state = MachineState(0)
    machine_state.memory = [0] * initial_size

    # Act
    machine_state.mem_extend(start, extension_size)

    # Assert
    assert machine_state.memory_size == len(machine_state.memory)
    assert machine_state.memory_size == max(initial_size, start + extension_size)
Exemple #7
0
def test_stack_multiple_pop(initial_stack, amount, expected):
    # Arrange
    machine_state = MachineState(0)
    machine_state.stack = initial_stack[:]

    # Act
    results = machine_state.pop(amount)

    # Assert
    assert results == initial_stack[-amount:][::-1]
    assert results == expected
    assert len(machine_state.stack) == len(initial_stack) - amount
Exemple #8
0
    def callcode_(self, global_state):
        instr = global_state.get_current_instruction()
        environment = global_state.environment

        try:
            callee_address, callee_account, call_data, value, call_data_type, gas, _, _ = get_call_parameters(
                global_state, self.dynamic_loader, True)
        except ValueError as e:
            logging.info(
                "Could not determine required parameters for call, putting fresh symbol on the stack. \n{}"
                .format(e))
            global_state.mstate.stack.append(
                BitVec("retval_" + str(instr['address']), 256))
            return [global_state]

        global_state.call_stack.append(instr['address'])

        environment = deepcopy(environment)

        environment.callvalue = value
        environment.caller = environment.address
        environment.calldata = call_data

        new_global_state = GlobalState(global_state.accounts, environment,
                                       MachineState(gas))
        new_global_state.mstate.depth = global_state.mstate.depth + 1
        new_global_state.mstate.constraints = copy(
            global_state.mstate.constraints)

        return [new_global_state]
Exemple #9
0
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=10000000))
    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=10000000))
    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=10000000))
    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
Exemple #10
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
Exemple #11
0
    def call_(self, global_state):
        instr = global_state.get_current_instruction()
        environment = global_state.environment

        try:
            callee_address, callee_account, call_data, value, call_data_type, gas, memory_out_offset, memory_out_size = get_call_parameters(
                global_state, self.dynamic_loader, True)
        except ValueError as e:
            logging.info(
                "Could not determine required parameters for call, putting fresh symbol on the stack. \n{}"
                .format(e))
            # TODO: decide what to do in this case
            global_state.mstate.stack.append(
                BitVec("retval_" + str(instr['address']), 256))
            return [global_state]

        if 0 < int(callee_address, 16) < 5:
            logging.info("Native contract called: " + callee_address)
            if call_data == [] and call_data_type == CalldataType.SYMBOLIC:
                logging.debug("CALL with symbolic data not supported")
                global_state.mstate.stack.append(
                    BitVec("retval_" + str(instr['address']), 256))
                return [global_state]

            data = natives.native_contracts(int(callee_address, 16), call_data)
            try:
                mem_out_start = helper.get_concrete_int(memory_out_offset)
                mem_out_sz = memory_out_size.as_long()
            except AttributeError:
                logging.debug(
                    "CALL with symbolic start or offset not supported")
                global_state.mstate.stack.append(
                    BitVec("retval_" + str(instr['address']), 256))
                return [global_state]

            global_state.mstate.mem_extend(mem_out_start, mem_out_sz)
            try:
                for i in range(min(len(data), mem_out_sz)
                               ):  # If more data is used then it's chopped off
                    global_state.mstate.memory[mem_out_start + i] = data[i]
            except:
                global_state.mstate.memory[mem_out_start] = BitVec(data, 256)

            # TODO: maybe use BitVec here constrained to 1
            global_state.mstate.stack.append(
                BitVec("retval_" + str(instr['address']), 256))
            return [global_state]

        global_state.call_stack.append(instr['address'])
        callee_environment = Environment(
            callee_account,
            BitVecVal(int(environment.active_account.address, 16), 256),
            call_data,
            environment.gasprice,
            value,
            environment.origin,
            calldata_type=call_data_type)
        new_global_state = GlobalState(global_state.accounts,
                                       callee_environment, MachineState(gas))
        new_global_state.mstate.depth = global_state.mstate.depth + 1
        new_global_state.mstate.constraints = copy(
            global_state.mstate.constraints)
        return [global_state]