Beispiel #1
0
class Calldata:
    """
    Calldata class representing the calldata of a transaction
    """
    def __init__(self, tx_id, starting_calldata=None):
        """
        Constructor for Calldata
        :param tx_id: unique value representing the transaction the calldata is for
        :param starting_calldata: byte array representing the concrete calldata of a transaction
        """
        self.tx_id = tx_id
        if starting_calldata is not None:
            self._calldata = []
            self.calldatasize = BitVecVal(len(starting_calldata), 256)
            self.concrete = True
        else:
            self._calldata = Array("{}_calldata".format(self.tx_id),
                                   BitVecSort(256), BitVecSort(8))
            self.calldatasize = BitVec("{}_calldatasize".format(self.tx_id),
                                       256)
            self.concrete = False

        if self.concrete:
            for calldata_byte in starting_calldata:
                if type(calldata_byte) == int:
                    self._calldata.append(BitVecVal(calldata_byte, 8))
                else:
                    self._calldata.append(calldata_byte)

    def concretized(self, model):
        result = []
        for i in range(
                get_concrete_int(
                    model.eval(self.calldatasize, model_completion=True))):
            result.append(
                get_concrete_int(
                    model.eval(self._calldata[i], model_completion=True)))

        return result

    def get_word_at(self, index: int):
        return self[index:index + 32]

    def __getitem__(self, item: Union[int, slice]) -> Any:
        if isinstance(item, slice):
            start, step, stop = item.start, item.step, item.stop
            try:
                if start is None:
                    start = 0
                if step is None:
                    step = 1
                if stop is None:
                    stop = self.calldatasize
                current_index = (start if isinstance(start, BitVecRef) else
                                 BitVecVal(start, 256))
                dataparts = []
                while simplify(current_index != stop):
                    dataparts.append(self[current_index])
                    current_index = simplify(current_index + step)
            except Z3Exception:
                raise IndexError("Invalid Calldata Slice")

            values, constraints = zip(*dataparts)
            result_constraints = []
            for c in constraints:
                result_constraints.extend(c)
            return simplify(Concat(values)), result_constraints

        if self.concrete:
            try:
                return self._calldata[get_concrete_int(item)], ()
            except IndexError:
                return BitVecVal(0, 8), ()
        else:
            constraints = [
                Implies(self._calldata[item] != 0, UGT(self.calldatasize,
                                                       item))
            ]

            return self._calldata[item], constraints
Beispiel #2
0
class Calldata:
    """
    Calldata class representing the calldata of a transaction
    """
    def __init__(self, tx_id, starting_calldata=None):
        """
        Constructor for Calldata
        :param tx_id: unique value representing the transaction the calldata is for
        :param starting_calldata: byte array representing the concrete calldata of a transaction
        """
        self.tx_id = tx_id
        if starting_calldata:
            self._calldata = []
            self.calldatasize = BitVecVal(len(starting_calldata), 256)
            self.concrete = True
        else:
            self._calldata = Array("{}_calldata".format(self.tx_id),
                                   BitVecSort(256), BitVecSort(8))
            self.calldatasize = BitVec("{}_calldatasize".format(self.tx_id),
                                       256)
            self.concrete = False

        self.starting_calldata = starting_calldata or []

    @property
    def constraints(self):
        constraints = []

        if self.concrete:
            for calldata_byte in self.starting_calldata:
                if type(calldata_byte) == int:
                    self._calldata.append(BitVecVal(calldata_byte, 8))
                else:
                    self._calldata.append(calldata_byte)
            constraints.append(
                self.calldatasize == len(self.starting_calldata))
        else:
            x = BitVec("x", 256)
            constraints.append(
                ForAll(x, Implies(self[x] != 0, UGT(self.calldatasize, x))))

        return constraints

    def concretized(self, model):
        result = []
        for i in range(
                get_concrete_int(
                    model.eval(self.calldatasize, model_completion=True))):
            result.append(
                get_concrete_int(model.eval(self[i], model_completion=True)))

        return result

    def get_word_at(self, index: int):
        return self[index:index + 32]

    def __getitem__(self, item):
        if isinstance(item, slice):
            try:
                current_index = (item.start if isinstance(
                    item.start, BitVecRef) else BitVecVal(item.start, 256))
                dataparts = []
                while simplify(current_index != item.stop):
                    dataparts.append(self[current_index])
                    current_index = simplify(current_index + 1)
            except Z3Exception:
                raise IndexError("Invalid Calldata Slice")

            return simplify(Concat(dataparts))

        if self.concrete:
            try:
                return self._calldata[get_concrete_int(item)]
            except IndexError:
                return BitVecVal(0, 8)
        else:
            return self._calldata[item]