Exemple #1
0
 def SHA3(self, gstate, index, length):
     if svm_utils.is_bv_concrete(index) and svm_utils.is_bv_concrete(length):
         index = svm_utils.get_concrete_int(index)
         length = svm_utils.get_concrete_int(length)
         if length == 0:
             gstate.mstate.stack.append(z3.BitVecVal(SHA_EMPTY_ARGS_VALUE, 256))
             return
         data = z3.simplify(svm_utils.get_memory_data(gstate.mstate.memory, index, length))
         sha_constraints, hash_vector = svm_utils.symbolic_keccak(self, data)
         gstate.wstate.constraints.extend(sha_constraints)
         gstate.mstate.stack.append(hash_vector)
         return
     hash_vector = self.svm.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.SHA3,
                                                            gstate.wstate.gen,
                                                            unique=True)
     logging.debug('SHA index or len not resolved. Using the symbolic vector')
     gstate.mstate.stack.append(hash_vector)
     return
Exemple #2
0
    def BALANCE(self, gstate, address):
        if svm_utils.is_bv_concrete(address) and svm_utils.get_concrete_int(address) in gstate.wstate.address_to_account:
            balance = gstate.wstate.address_to_account[svm_utils.get_concrete_int(address)].balance
            gstate.mstate.stack.append(balance)
            return

        address = str(z3.simplify(address)).replace(' ', '_')
        gstate.mstate.stack.append(self.svm.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.BALANCE,
                                                                            gstate.wstate.gen,
                                                                            unique=True))
Exemple #3
0
    def CREATE(self, gstate, balance, offset, length):
        new_gstates = []

        active_address = gstate.environment.active_address
        active_account = gstate.wstate.address_to_account[active_address]

        if gstate.wstate.gen != 0:
            raise SVMRuntimeError('Dynamic contract creation is not supported')

        offset = svm_utils.get_concrete_int(offset)
        length = svm_utils.get_concrete_int(length)
        create_contract_bytes = []
        concrete_prefix_bytes = []
        concrete_prefix_stop = False
        for index in range(0, length):
            memory_byte = gstate.mstate.memory_dict[index+offset]
            memory_byte = svm_utils.get_concrete_int(memory_byte) if svm_utils.is_bv_concrete(memory_byte) else memory_byte
            create_contract_bytes.append(memory_byte)
            concrete_prefix_stop = concrete_prefix_stop or not isinstance(memory_byte, int)
            if not concrete_prefix_stop: concrete_prefix_bytes.append(memory_byte)
        found_swarmhashes = asm.find_swarmhashes(bytes(concrete_prefix_bytes))
        if not len(found_swarmhashes):
            raise SVMRuntimeError('CREATE found no swarmhashes in bytecode')
        create_contract = self.svm.swarm_hash_tuple_to_contract[tuple(found_swarmhashes)]
        create_address = utils.get_next_contract_address()
        create_account = Account(create_address, create_contract, balance=balance)
        logging.debug(f'CREATE created contract {create_account.contract.name}')
        create_enviroment = Environment(active_address=create_address,
                                        sender=z3.BitVecVal(active_account.address, 256),
                                        calldata=[],
                                        gasprice=gstate.environment.gasprice,
                                        callvalue=balance,
                                        origin=gstate.environment.origin,
                                        calldata_type=CalldataType.UNDEFINED,
                                        disassembly=create_account.contract.creation_disassembly,
                                        runtime_bytecode_bytes=create_contract_bytes,
                                        timestamp=gstate.environment.timestamp)
        child_wstate = copy(gstate.wstate)
        child_wstate.address_to_account[create_address] = create_account
        create_gstate = GlobalState(child_wstate, create_enviroment)
        create_gstate.has_storage_changed = True
        intermediate_gstates = self.execute_gstate(create_gstate)
        if len(intermediate_gstates) == 0:
            raise SVMRuntimeError('CREATE has no feasible blocks')
        for new_gstate in intermediate_gstates:
            new_gstate.mstate = deepcopy(gstate.mstate)
            new_gstate.mstate.stack.append(z3.BitVecVal(create_address, 256))
            new_gstate.pc_addr_to_depth = copy(gstate.pc_addr_to_depth)
            new_gstate.mstate.pc += 1
            new_gstate.halt = False
            new_gstate.environment = gstate.environment
            new_gstates.extend(self.execute_gstate(new_gstate))
        logging.debug(f'returning FROM CREATE contract {create_account.contract.name}')
        gstate.halt = True
        return new_gstates
Exemple #4
0
 def abstract(self, label_suffix):
     old_storage = self.storage
     self.storage = AbstractStorage(f'abstract_storage{label_suffix}')
     for map_id in self.mapping_id_to_sum:
         if svm_utils.is_bv_concrete(map_id):
             map_id_string = svm_utils.get_concrete_int(map_id)
         else:
             map_id_string = str(z3.simplify(map_id))
             raise Exception("pdb")
         label = f'abstract_sum_{map_id_string}{label_suffix}'
         self.mapping_id_to_sum[map_id] = z3.BitVec(label, 256)
     self.balance = z3.BitVec(f'gstate_balance{label_suffix}', 256)
Exemple #5
0
 def RETURN(self, gstate, offset, length):
     if not svm_utils.is_bv_concrete(length):
         # raise SVMRuntimeError('Non concrete return length')
         length = 32
     length = svm_utils.get_concrete_int(length)
     return_data_bytes = [z3.Select(gstate.mstate.memory, i+offset) for i in range(length)]
     return_data = z3.Concat(return_data_bytes)
     assert return_data.size() == length*8
     gstate.return_data = return_data
     gstate.exit_code = 1
     gstate.halt = True
     return [gstate]
Exemple #6
0
 def JUMP(self, gstate, jump_addr):
     if not svm_utils.is_bv_concrete(jump_addr):
         if svm_utils.check_wstate_reachable(gstate.wstate, 100):
             logging.warning('JUMP to invalid address')
         return
     # if gstate.pc_addr_to_depth.setdefault((gstate.mstate.pc, jump_addr), 0) < self.svm.max_jump_depth:
     jump_addr = svm_utils.get_concrete_int(jump_addr)
     instr_idx = svm_utils.get_instruction_index(gstate.environment.disassembly.instruction_list, jump_addr)
     if instr_idx is None:
         raise SVMRuntimeError('JUMP to invalid address')
     dest_opcode = gstate.environment.disassembly.instruction_list[instr_idx]['opcode']
     if dest_opcode != 'JUMPDEST':
         raise SVMRuntimeError('JUMP to invalid address')
     gstate.mstate.pc = instr_idx
     return self.execute_gstate(gstate)
Exemple #7
0
    def CODECOPY(self, gstate, dest_offset, offset, length):
        active_address = gstate.environment.active_address
        active_account = gstate.wstate.address_to_account[active_address]

        offset = svm_utils.get_concrete_int(offset)
        if svm_utils.is_bv_concrete(length):
            length = svm_utils.get_concrete_int(length)
        else:
            length = 0
        assert isinstance(gstate.environment.runtime_bytecode_bytes, list)
        bytecode_bytes = gstate.environment.runtime_bytecode_bytes
        for i in range(length):
            if offset + i < len(bytecode_bytes):
                data_byte = bytecode_bytes[offset+i]
            else:
                data_byte = z3.BitVecVal(0, 8)
            gstate.mstate.memory = z3.Store(gstate.mstate.memory, dest_offset+i, data_byte)
            gstate.mstate.memory_dict[svm_utils.get_concrete_int(dest_offset+i)] = data_byte
Exemple #8
0
def extract_index_features(index):
    current_index = index
    features = []
    if current_index.decl().name() == 'bvadd':
        current_index = current_index.arg(0)
    if current_index.decl().name().startswith('sha'):
        current_index = current_index.arg(0)
        features.append(current_index.size())
    else:
        return features
    if current_index.decl().name() == 'concat':
        args = [current_index.arg(i) for i in range(current_index.num_args())]
        if svm_utils.is_bv_concrete(args[-1]):
            features.append(args[-1])
            current_index = z3.Concat(args[0:-1]) if len(args) > 2 else args[0]
        else:
            return features
    elif is_bv_concrete(current_index):
        if current_index.size() > 256:
            prefix, suffix = split_bv(current_index, 256)
            suffix = z3.simplify(suffix)
            features.append(suffix)
            current_index = z3.simplify(prefix)
        elif current_index.size() == 256:
            features.append(current_index)
            return features
        else:
            features.append(current_index)
            return features
    else:
        return features
    if current_index.decl().name().startswith('sha'):
        print(current_index)
        current_index = current_index.arg(0)
        features.append(current_index.size())
    else:
        return features
    return features
Exemple #9
0
def symbolic_keccak(svm, data):
    sha_constraints = []
    sha_func, sha_func_inv = constraints.get_sha_functions(data.size())
    hash_vector = sha_func(data)

    sha_constraints.append(sha_func_inv(sha_func(data)) == data)
    hash_vector_features = extract_index_features(hash_vector)
    data_concrete = svm_utils.is_bv_concrete(data)
    if data_concrete:
        concrete_data = svm_utils.get_concrete_int(data)
        data_bytes = ethereum.utils.zpad(
            ethereum.utils.int_to_bytes(concrete_data),
            data.size() // 8)
        hash_value = int.from_bytes(ethereum.utils.sha3_256(data_bytes), 'big')

    SIZE_PER_SHA_LEN = 2**100

    limit_left = 1024 + SIZE_PER_SHA_LEN * data.size()
    limit_right = limit_left + SIZE_PER_SHA_LEN

    if not data_concrete:
        sha_constraints.append(z3.ULT(limit_left, hash_vector))
        sha_constraints.append(z3.ULT(hash_vector, limit_right))
        # last 4 bits are 0 => hashes are 16 words between each other
        sha_constraints.append(z3.Extract(3, 0, hash_vector) == 0)
    elif data_concrete:
        storage_range = limit_right - limit_left
        scaled_hash_value = limit_left + int(
            (hash_value / svm_utils.TT256M1) * storage_range)
        scaled_hash_value = scaled_hash_value // 16 * 16
        sha_constraints.append(
            hash_vector == z3.BitVecVal(scaled_hash_value, VECTOR_LEN))
    # elif storage_node == svm.storage_root and data_concrete:
    # hash_value = hash_value // 16 * 16
    # sha_constraints.append(hash_vector == z3.BitVecVal(hash_value, VECTOR_LEN))
    return sha_constraints, hash_vector
Exemple #10
0
    def _CALL(self, gstate, gas, to, value, meminstart, meminsize, outmemstart, memoutsize):
        new_gstates = []

        active_account = gstate.wstate.address_to_account[gstate.environment.active_address]
        environment = gstate.environment
        mstate = gstate.mstate
        wstate = gstate.wstate

        active_account.balance -= value

        if z3.is_true(z3.simplify(to == 0x0)):
            mstate.stack.append(z3.BitVecVal(0, 256))
        elif z3.is_true(z3.simplify(to == 0x1)):
           raise Exception('not implemented')
        elif z3.is_true(z3.simplify(to == 0x2)):
           raise Exception('not implemented')
        elif svm_utils.is_bv_concrete(meminsize):
            meminsize = svm_utils.get_concrete_int(meminsize)
            gstate.return_data = None
            callee_calldata = None
            in_data_bytes = [z3.Select(mstate.memory, meminstart+i) for i in range(meminsize)] if meminsize else []
            if meminsize != 0:
                callee_calldata = z3.Concat(in_data_bytes) if len(in_data_bytes) > 1 else in_data_bytes[0]
            for callee_address, callee_account in wstate.address_to_account.items():
                callee_constraint = z3.simplify(to == callee_address)
                if z3.is_false(callee_constraint):
                    continue
                if callee_address == active_account.address:
                    if svm_utils.is_bv_concrete(gstate.environment.sender) and\
                             svm_utils.get_concrete_int(gstate.environment.sender) == callee_address:
                        gstate.halt = True
                        return []
                callee_environment = Environment(active_address=callee_address,
                                                 sender=z3.BitVecVal(active_account.address, 256),
                                                 calldata=callee_calldata,
                                                 gasprice=environment.gasprice,
                                                 callvalue=value,
                                                 origin=environment.origin,
                                                 calldata_type=CalldataType.DEFINED,
                                                 disassembly=callee_account.contract.disassembly,
                                                 runtime_bytecode_bytes=list(callee_account.contract.disassembly.bytecode),
                                                 timestamp=environment.timestamp)
                child_wstate = copy(wstate)
                child_wstate.constraints.append(to == callee_address)
                if not svm_utils.check_wstate_reachable(child_wstate, 100):
                    continue

                child_gstate = GlobalState(child_wstate, callee_environment)
                intermediate_gstates = self.execute_gstate(child_gstate)
                for new_gstate in intermediate_gstates:
                    new_gstate.mstate = deepcopy(gstate.mstate)
                    new_gstate.mstate.stack.append(new_gstate.exit_code)
                    new_gstate.exit_code = None
                    new_gstate.pc_addr_to_depth = copy(gstate.pc_addr_to_depth)
                    new_gstate.mstate.pc += 1
                    new_gstate.halt = False
                    new_gstate.environment = gstate.environment
                    new_gstate.has_storage_changed |= gstate.has_storage_changed
                    if new_gstate.return_data is not None:
                        return_data = new_gstate.return_data
                        memoutsize = svm_utils.get_concrete_int(memoutsize)
                        outmemstart = svm_utils.get_concrete_int(outmemstart)
                        return_data_bytes = svm_utils.split_bv_into_bytes(return_data)
                        for i in range(min(return_data.size()//8, memoutsize)):
                            return_byte = return_data_bytes[i]
                            new_gstate.mstate.memory = z3.Store(new_gstate.mstate.memory, i + outmemstart, return_byte)
                    new_gstates.extend(self.execute_gstate(new_gstate))
        ret = self.svm.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.RETURN_VALUE,
                                                       wstate.gen,
                                                       unique=True,
                                                       acc=active_account.id)
        gstate.return_data = None
        to_constraint = z3.Or([to == p for p in self.svm.possible_caller_addresses])
        wstate.constraints.append(to_constraint)
        wstate.has_symbolic_calls = True
        return_data = self.svm.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.RETURNDATA,
                                                               wstate.gen,
                                                               unique=True,
                                                               bv_size=SYMBOLIC_CALL_RETURNDATA_SIZE_BYTES*8,
                                                               acc=active_account.id)

        gstate.return_data = return_data
        concrete_memoutsize = svm_utils.get_concrete_int(memoutsize)
        if concrete_memoutsize != 0:
            return_data_bytes = svm_utils.split_bv_into_bytes(return_data)
            memoutsize = svm_utils.get_concrete_int(memoutsize)
            for i in range(min(return_data.size()//8, memoutsize)):
                return_byte = return_data_bytes[i]
                mstate.memory = z3.Store(mstate.memory, i+outmemstart, return_byte)
        gstate.has_storage_changed = True
        mstate.stack.append(ret)
        return new_gstates
Exemple #11
0
 def MSTORE8(self, gstate, index, value):
     data = z3.Extract(7, 0, value)
     if svm_utils.is_bv_concrete(index):
         gstate.mstate.memory_dict[svm_utils.get_concrete_int(index)] = data
     gstate.mstate.memory = z3.Store(gstate.mstate.memory, index, data)