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)
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)
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)
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)
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
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
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)
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)
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
def can_be_nonzero(self): if isinstance(self, Constant): return bl.Constant(self.value != 0) else: return self != Constant(self.size, 0)
def can_be_zero(self): if isinstance(self, Constant): return bl.Constant(self.value == 0) else: return self == Constant(self.size, 0)
def __neg__(self): if isinstance(self, Constant): return bl.Constant(-self.value) else: return UnaryOperation(UnaryOperator.Negate, self)