Beispiel #1
0
 def __ne__(self, other):
     if isinstance(self, Constant) and isinstance(other, Constant):
         return bl.Constant(self.value != other.value)
     elif isinstance(self, Constant) and isinstance(other, int):
         return bl.Constant(self.value != other)
     else:
         equal = (self == other)
         return bl.UnaryOperation(UnaryOperator.Not, equal)
Beispiel #2
0
 def __eq__(self, other):
     if isinstance(self, Constant) and isinstance(other, Constant):
         return bl.Constant(self.value == other.value)
     elif isinstance(self, Constant) and isinstance(other, int):
         return bl.Constant(self.value == other)
     elif isinstance(other, int):
         return BooleanBinaryOperation(self, BinaryOperator.Equal,
                                       Constant(self.size, other))
     else:
         return BooleanBinaryOperation(self, BinaryOperator.Equal, other)
Beispiel #3
0
 def __le__(self, other):
     if isinstance(self, Constant) and isinstance(other, Constant):
         return bl.Constant(self.value <= other.value)
     elif isinstance(self, Constant) and isinstance(other, int):
         return bl.Constant(self.value <= other)
     elif isinstance(other, int):
         return BooleanBinaryOperation(
             self, BinaryOperator.UnsignedLessThanOrEqual,
             Constant(self.size, other))
     else:
         return BooleanBinaryOperation(
             self, BinaryOperator.UnsignedLessThanOrEqual, other)
Beispiel #4
0
 def __gt__(self, other):
     if isinstance(self, Constant) and isinstance(other, Constant):
         return bl.Constant(self.value > other.value)
     elif isinstance(self, Constant) and isinstance(other, int):
         return bl.Constant(self.value > other)
     elif isinstance(other, int):
         return BooleanBinaryOperation(self,
                                       BinaryOperator.UnsignedGreaterThan,
                                       Constant(self.size, other))
     else:
         return BooleanBinaryOperation(self,
                                       BinaryOperator.UnsignedGreaterThan,
                                       other)
Beispiel #5
0
    def __iter__(self):
        terminated = False
        index = 0
        constraint = bl.Constant(True)
        while not terminated:
            read_address = self.address + bv.Constant(self.address.size, index)
            byte = self.state.read(read_address, 8)

            if self.state.solver.check(byte.can_be_nonzero()):
                if byte.symbolic:
                    if not constraint.symbolic:
                        constraint = (byte != 0)
                    else:
                        # not sure that I've implemented &= in smt
                        constraint = constraint & (byte != 0)

                    # this might look silly, but it actually makes the
                    # output smt formulae substantially smaller...

                    returned_constraint = bl.Symbol(
                        unique_name('string_length'))
                    self.state.solver.add(returned_constraint == constraint)
                    yield (byte, returned_constraint)
                else:
                    yield (byte, constraint)
            else:
                terminated = True
                yield (bv.Constant(8, 0), constraint)
            index += 1
Beispiel #6
0
    def _parse_model(self, results, expr=None):
        output = dict()

        expressions = list(self.roots())
        if expr is not None:
            self._cache(expr)
            expressions.append(expr)

        symbols = set()
        for e in expressions:

            symbols.update(e.symbols())

        for bl_match in self.bl_re.findall(results):
            name = bl_match[0]
            if bl_match[1] == 'true':
                value = True
            else:
                value = False
            output[name] = bl.Constant(value)

        for bv_match in self.bv_re.findall(results):
            name = bv_match[0]
            size = int(bv_match[1])
            value = int('0x' + bv_match[2], 16)
            output[name] = bv.Constant(size, value)

        for symbol in symbols:
            if symbol.name not in output:
                if isinstance(symbol, bv.Expression):
                    output[symbol.name] = bv.Constant(symbol.size,
                                                      0x2323232323232323)
                else:
                    output[symbol.name] = bl.Constant(True)

        return output
Beispiel #7
0
def strcmp(s, cc):
    f = cc(s)

    str1 = f.params[0]
    str2 = f.params[1]

    s.log.function_call(f, 'strcmp(str1={}, str2={})', str1, str2)

    iter1 = iter(String(s, str1))
    iter2 = iter(String(s, str2))

    first_smaller = bv.Constant(32, -1)
    first_larger = bv.Constant(32, 1)
    zero = bv.Constant(32, 0)

    characters = []
    not_terminated = None
    not_already_terminated = bl.Constant(True)
    while True:
        (char1, constraint1) = next(iter1)
        (char2, constraint2) = next(iter2)

        not_terminated = not_already_terminated & constraint1
        not_terminated = not_terminated & constraint2
        not_terminated = not_terminated & (char1 == char2)

        characters.append((not_already_terminated, char1, char2))

        not_already_terminated = not_terminated

        if ((not char1.symbolic and char1.value == 0)
            or (not char2.symbolic and char2.value == 0)):
            break

    characters.reverse()

    result = None
    prev_result = None
    for (not_already_terminated, char1, char2) in characters:
        if result is None:
            result = bv.if_then_else(
                        char1 == char2,
                        zero,
                        bv.if_then_else(
                            char1 < char2,
                            first_smaller,
                            first_larger))
        else:
            result = bv.if_then_else(
                        not_already_terminated,
                        bv.if_then_else(
                            char1 == char2,
                            prev_result,
                            bv.if_then_else(
                                char1 < char2,
                                first_smaller,
                                first_larger)),
                        prev_result)

        # this reduces the memory footprint_ of the resulting expression
        # significantly
        prev_result = bv.Symbol(32, unique_name('tmp'))
        s.solver.add(prev_result == result)

    if result.symbolic:
        result_symbol = bv.Symbol(32, unique_name('strcmp'))
        s.solver.add(result_symbol == result)
        result = result_symbol

    return f.ret(value=result)
Beispiel #8
0
def memcmp(s, cc):
    f = cc(s)

    ptr1 = f.params[0]
    ptr2 = f.params[1]
    num = f.params[2]

    s.log.function_call(f, 'memcmp(ptr1={}, ptr2={}, num={})', ptr1, ptr2, num)

    count = 0

    first_smaller = bv.Constant(ptr1.size, -1)
    first_larger = bv.Constant(ptr1.size, 1)
    zero = bv.Constant(ptr1.size, 0)

    bytes = []

    not_terminated = None
    not_already_terminated = bl.Constant(True)
    while s.solver.check(num > count):
        byte1 = s.read(ptr1 + bv.Constant(ptr1.size, count), 8)
        byte2 = s.read(ptr2 + bv.Constant(ptr2.size, count), 8)

        not_terminated = not_already_terminated & (byte1 == byte2)

        bytes.append((not_already_terminated, byte1, byte2))

        if not_terminated.symbolic:
            not_already_terminated = bl.Symbol(unique_name('tmp'))
            s.solver.add(not_already_terminated == not_terminated)
        else:
            not_already_terminated = not_terminated

        count += 1

    bytes.reverse()

    result = None
    prev_result = None
    for (not_already_terminated, byte1, byte2) in bytes:
        if result is None:
            result = bv.if_then_else(
                        byte1 == byte2,
                        zero,
                        bv.if_then_else(
                            byte1 < byte2,
                            first_smaller,
                            first_larger))
        else:
            result = bv.if_then_else(
                        not_already_terminated,
                        bv.if_then_else(
                            byte1 == byte2,
                            prev_result,
                            bv.if_then_else(
                                byte1 < byte2,
                                first_smaller,
                                first_larger)),
                        prev_result)

        # this reduces the memory footprint_ of the resulting expression
        # significantly
        prev_result = bv.Symbol(ptr1.size, unique_name('tmp'))
        s.solver.add(prev_result == result)

    if result.symbolic:
        result_symbol = bv.Symbol(result.size, unique_name('memcmp'))
        s.solver.add(result_symbol == result)
        result = result_symbol

    return f.ret(value=result)
Beispiel #9
0
def memchr(s, cc):
    f = cc(s)

    ptr = f.params[0]
    value = f.params[1].resize(8)
    num = f.params[2]

    if num.symbolic:
        num = maximum(s, num)

    s.log.function_call(f, 'memchr(ptr={}, value={}, num={})', ptr, value, num)

    if ptr.symbolic:
        ptrs = concretise(s, ptr)
    else:
        ptrs = [ptr]

    ss = []
    total_ptrs = len(ptrs)
    while len(ptrs) > 0:
        ptr = ptrs.pop()

        if total_ptrs > 1:
            s_ = s.fork()
        else:
            s_ = s

        count = 0
        null = bv.Constant(ptr.size, 0)
        bytes = []

        not_terminated = None
        not_already_terminated = bl.Constant(True)
        while s_.solver.check(num > count):
            byte = s_.read(ptr + bv.Constant(ptr.size, count), 8)

            not_terminated = not_already_terminated & (byte == value)
            bytes.append((not_already_terminated, byte, count))

            if not_terminated.symbolic:
                not_already_terminated = bl.Symbol(unique_name('tmp'))
                s_.solver.add(not_already_terminated == not_terminated)
            else:
                not_already_terminated = not_terminated

            count += 1

        bytes.reverse()

        result = None
        prev_result = None
        for (not_already_terminated, byte, count) in bytes:
            if result is None:
                result = bv.if_then_else(
                            byte == value,
                            ptr + bv.Constant(ptr.size, count),
                            null)
            else:
                result = bv.if_then_else(
                            not_already_terminated,
                            bv.if_then_else(
                                byte == value,
                                ptr + bv.Constant(ptr.size, count),
                                prev_result),
                            prev_result)

            # this reduces the memory footprint_ of the resulting expression
            # significantly
            prev_result = bv.Symbol(ptr.size, unique_name('tmp'))
            s_.solver.add(prev_result == result)

        if result.symbolic:
            result_symbol = bv.Symbol(ptr.size, unique_name('memcmp'))
            s_.solver.add(result_symbol == result)
            result = result_symbol

        f_ = cc(s_)
        ss += f_.ret(value=result)

    return ss
Beispiel #10
0
 def can_be_nonzero(self):
     if isinstance(self, Constant):
         return bl.Constant(self.value != 0)
     else:
         return self != Constant(self.size, 0)
Beispiel #11
0
 def can_be_zero(self):
     if isinstance(self, Constant):
         return bl.Constant(self.value == 0)
     else:
         return self == Constant(self.size, 0)
Beispiel #12
0
 def __neg__(self):
     if isinstance(self, Constant):
         return bl.Constant(-self.value)
     else:
         return UnaryOperation(UnaryOperator.Negate, self)