def run(self, dst_addr, src_addr, limit, src_len=None): self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()), 2: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] memcpy = simuvex.SimProcedures['libc.so.6']['memcpy'] src_len = src_len if src_len is not None else self.inline_call( strlen, src_addr) cpy_size = self.state.se.If( self.state.se.ULE(limit, src_len.ret_expr + 1), limit, src_len.ret_expr + 1) #print "===================" #print sorted(self.state.expr_value(src_len.ret_expr).se.any_n(20)) #print self.state.expr_value(limit.expr).se.any_n(20) #print sorted(self.state.expr_value(cpy_size).se.any_n(20)) #print "-------------------" self.inline_call(memcpy, dst_addr, src_addr, cpy_size) return dst_addr
def run(self, scan, fmt): #additional code trace_data = ("__isoc99_sscanf", { "scan": (scan, scan.symbolic), "fmt": (fmt, fmt.symbolic) }) try: self.state.procedure_data.global_variables["trace"].append( trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append( trace_data) #end of additional code #pylint:disable=attribute-defined-outside-init self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()) } self.return_type = SimTypeInt(self.state.arch.bits, True) fmt_str = self._parse(1) _, items = fmt_str.interpret(self.arg(0), 2, self.arg, region=self.state.memory) return items
def run(self, dst, src): #additional code trace_data = ("strcpy", { "dst": (dst, dst.symbolic), "src": (src, src.symbolic) }) try: self.state.procedure_data.global_variables["trace"].append( trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append( trace_data) #end of additional code self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()) } self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] strncpy = simuvex.SimProcedures['libc.so.6']['strncpy'] src_len = self.inline_call(strlen, src) ret_expr = self.inline_call(strncpy, dst, src, src_len.ret_expr + 1, src_len=src_len.ret_expr).ret_expr return ret_expr
def run(self, haystack_addr, needle_addr, haystack_strlen=None, needle_strlen=None): self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString())} self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] strncmp = simuvex.SimProcedures['libc.so.6']['strncmp'] haystack_strlen = self.inline_call(strlen, haystack_addr) if haystack_strlen is None else haystack_strlen needle_strlen = self.inline_call(strlen, needle_addr) if needle_strlen is None else needle_strlen # naive approach haystack_maxlen = haystack_strlen.max_null_index needle_maxlen = needle_strlen.max_null_index l.debug("strstr with size %d haystack and size %d needle...", haystack_maxlen, needle_maxlen) if needle_maxlen == 0: l.debug("... zero-length needle.") return haystack_addr elif haystack_maxlen == 0: l.debug("... zero-length haystack.") return self.state.se.BitVecVal(0, self.state.arch.bits) if self.state.se.symbolic(needle_strlen.ret_expr): cases = [ [ needle_strlen.ret_expr == 0, haystack_addr ] ] exclusions = [ needle_strlen.ret_expr != 0 ] remaining_symbolic = self.state.libc.max_symbolic_strstr for i in range(haystack_maxlen): l.debug("... case %d (%d symbolic checks remaining)", i, remaining_symbolic) # big hack! cmp_res = self.inline_call(strncmp, haystack_addr + i, needle_addr, needle_strlen.ret_expr, a_len=haystack_strlen, b_len=needle_strlen) c = self.state.se.And(*([ self.state.se.UGE(haystack_strlen.ret_expr, needle_strlen.ret_expr), cmp_res.ret_expr == 0 ] + exclusions)) exclusions.append(cmp_res.ret_expr != 0) if self.state.se.symbolic(c): remaining_symbolic -= 1 #print "CASE:", c cases.append([ c, haystack_addr + i ]) haystack_strlen.ret_expr = haystack_strlen.ret_expr - 1 if remaining_symbolic == 0: l.debug("... exhausted remaining symbolic checks.") break cases.append([ self.state.se.And(*exclusions), self.state.se.BVV(0, self.state.arch.bits) ]) l.debug("... created %d cases", len(cases)) r = self.state.se.ite_cases(cases, 0) c = [ self.state.se.Or(*[c for c,_ in cases]) ] else: needle_length = self.state.se.any_int(needle_strlen.ret_expr) needle_str = self.state.memory.load(needle_addr, needle_length) r, c, i = self.state.memory.find(haystack_addr, needle_str, haystack_strlen.max_null_index, max_symbolic_bytes=self.state.libc.max_symbolic_strstr, default=0) self.state.add_constraints(*c) return r
def run(self, dst, src): self.argument_types = {0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString())} self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] strncpy = simuvex.SimProcedures['libc.so.6']['strncpy'] src_len = self.inline_call(strlen, src) ret_expr = self.inline_call(strncpy, dst, src, src_len.ret_expr+1, src_len=src_len.ret_expr).ret_expr return ret_expr
def run(self, scan, fmt): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(self.state.arch.bits, True) fmt_str = self._parse(1) _, items = fmt_str.interpret(self.arg(0), 2, self.arg, region=self.state.memory) return items
def run(self, a_addr, b_addr): self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(32, True) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] a_strlen = self.inline_call(strlen, a_addr) b_strlen = self.inline_call(strlen, b_addr) maxlen = self.state.se.BVV(max(a_strlen.max_null_index, b_strlen.max_null_index), self.state.arch.bits) strncmp = self.inline_call(simuvex.SimProcedures['libc.so.6']['strncmp'], a_addr, b_addr, maxlen, a_len=a_strlen, b_len=b_strlen) return strncmp.ret_expr
def run(self, s): self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] strncpy = simuvex.SimProcedures['libc.so.6']['strncpy'] malloc = simuvex.SimProcedures['libc.so.6']['malloc'] src_len = self.inline_call(strlen, s).ret_expr new_s = self.inline_call(malloc, src_len + 1).ret_expr self.inline_call(strncpy, new_s, s, src_len + 1, src_len=src_len) return new_s
def run(self, fmt): #additional code trace_data = ("__isoc99_scanf", {"fmt": (fmt, fmt.symbolic)}) try: self.state.procedure_data.global_variables["trace"].append(trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append(trace_data) #end of additional code #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(self.state.arch.bits, True) fmt_str = self._parse(0) # we're reading from stdin so the region is the file's content f = self.state.posix.get_file(0) region = f.content start = f.pos (end, items) = fmt_str.interpret(start, 1, self.arg, region=region) # do the read, correcting the internal file position and logging the action self.state.posix.read_from(0, end - start) return items
def run(self, s_addr, c_int, s_strlen=None): c = c_int[7:0] self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: SimTypeInt(32, True) } # ? self.return_type = self.ty_ptr(SimTypeChar()) # ? s_strlen = self.inline_call( simuvex.SimProcedures['libc.so.6']['strlen'], s_addr) if self.state.se.symbolic(s_strlen.ret_expr): l.debug("symbolic strlen") # TODO: more constraints here to make sure we don't search too little max_sym = min(self.state.se.max_int(s_strlen.ret_expr), self.state.libc.max_symbolic_strchr) a, c, i = self.state.memory.find(s_addr, c, s_strlen.max_null_index, max_symbolic_bytes=max_sym, default=0) else: l.debug("concrete strlen") max_search = self.state.se.any_int(s_strlen.ret_expr) a, c, i = self.state.memory.find(s_addr, c, max_search, default=0) if len(i) != 0: a = a.annotate(MultiwriteAnnotation()) self.state.add_constraints(*c) return a
def run(self, string): #additional code trace_data = ("puts", {"string": (string, string.symbolic)}) try: self.state.procedure_data.global_variables["trace"].append( trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append( trace_data) #end of additional code self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(32, True) write = simuvex.SimProcedures['syscalls']['write'] strlen = simuvex.SimProcedures['libc.so.6']['strlen'] length = self.inline_call(strlen, string).ret_expr self.inline_call(write, self.state.se.BVV(1, self.state.arch.bits), string, length) self.state.posix.write(1, self.state.se.BVV(0x0a, 8), 1) # TODO: return values return self.state.se.Unconstrained('puts', self.state.arch.bits)
def run(self, addr_in): #pylint:disable=unused-argument # arg types: struct....... :( self.return_type = self.ty_ptr(SimTypeString()) #TODO: return an IP address string ret_expr = self.state.se.Unconstrained("inet_ntoa_ret", self.state.arch.bits) return ret_expr
def run(self, s): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(self.state.arch, True) strtol = simuvex.SimProcedures['libc.so.6']['strtol'] return strtol.strtol_inner(s, self.state, self.state.memory, 10, True)[1]
def run(self, dst_addr, src_addr, limit, src_len=None): self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()), 2: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] memcpy = simuvex.SimProcedures['libc.so.6']['memcpy'] src_len = src_len if src_len is not None else self.inline_call( strlen, src_addr).ret_expr cpy_size = self.state.se.If(self.state.se.ULE(limit, src_len + 1), limit, src_len + 1) self.inline_call(memcpy, dst_addr, src_addr, cpy_size) return dst_addr
def run(self, p_addr, flags): self.argument_types = {0: self.ty_ptr(SimTypeString()), 1: SimTypeInt(32, True)} self.return_type = SimTypeFd() strlen = simuvex.SimProcedures['libc.so.6']['strlen'] p_strlen = self.inline_call(strlen, p_addr) p_expr = self.state.memory.load(p_addr, p_strlen.max_null_index, endness='Iend_BE') path = self.state.se.any_str(p_expr) fd = self.state.posix.open(path, flags) return fd
def run(self, a_addr, b_addr): #additional code trace_data = ("strcasecmp", { "a_addr": (a_addr, a_addr.symbolic), "b_addr": (b_addr, b_addr.symbolic) }) try: self.state.procedure_data.global_variables["trace"].append( trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append( trace_data) #end of additional code self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()) } self.return_type = SimTypeInt(32, True) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] a_strlen = self.inline_call(strlen, a_addr) b_strlen = self.inline_call(strlen, b_addr) maxlen = self.state.se.BVV( max(a_strlen.max_null_index, b_strlen.max_null_index), self.state.arch.bits) strncmp = self.inline_call( simuvex.SimProcedures['libc.so.6']['strncmp'], a_addr, b_addr, maxlen, a_len=a_strlen, b_len=b_strlen) return strncmp.ret_expr
def run(self, s): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeLength(self.state.arch) max_symbolic_bytes = self.state.libc.buf_symbolic_bytes max_str_len = self.state.libc.max_str_len if self.state.mode == 'static': self.max_null_index = [] # Make sure to convert s to ValueSet s_list = self.state.memory.normalize_address( s, convert_to_valueset=True) length = self.state.se.ESI(self.state.arch.bits) for s_ptr in s_list: r, c, i = self.state.memory.find( s, self.state.se.BVV(0, 8), max_str_len, max_symbolic_bytes=max_symbolic_bytes) self.max_null_index = max(self.max_null_index + i) # Convert r to the same region as s r_list = self.state.memory.normalize_address( r, convert_to_valueset=True, target_region=s_ptr._model_vsa.regions.keys()[0]) for r_ptr in r_list: length = length.union(r_ptr - s_ptr) return length else: r, c, i = self.state.memory.find( s, self.state.se.BVV(0, 8), max_str_len, max_symbolic_bytes=max_symbolic_bytes) self.max_null_index = max(i) self.state.add_constraints(*c) return r - s
def run(self, string): self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(32, True) write = simuvex.SimProcedures['syscalls']['write'] strlen = simuvex.SimProcedures['libc.so.6']['strlen'] length = self.inline_call(strlen, string).ret_expr self.inline_call(write, self.state.se.BVV(1, self.state.arch.bits), string, length) self.state.posix.write(1, self.state.se.BVV(0x0a, 8), 1) # TODO: return values return self.state.se.Unconstrained('puts', self.state.arch.bits)
def run(self, s): #additional code trace_data = ("strdup", {"s": (s, s.symbolic)}) try: self.state.procedure_data.global_variables["trace"].append(trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append(trace_data) #end of additional code self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] strncpy = simuvex.SimProcedures['libc.so.6']['strncpy'] malloc = simuvex.SimProcedures['libc.so.6']['malloc'] src_len = self.inline_call(strlen, s).ret_expr new_s = self.inline_call(malloc, src_len+1).ret_expr self.inline_call(strncpy, new_s, s, src_len+1, src_len=src_len) return new_s
def run(self, dst_addr, src_addr, limit, src_len=None): #additional code trace_data = ("strncpy", {"dist_addr": (dist_addr, dst_addr.symbolic), "src_addr": (src_addr, src_addr.symbolic), "limit": (limit, limit.symbolic), "src_len": (src_len, src_len.symbolic)}) try: self.state.procedure_data.global_variables["trace"].append(trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append(trace_data) #end of additional code self.argument_types = {0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()), 2: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeString()) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] memcpy = simuvex.SimProcedures['libc.so.6']['memcpy'] src_len = src_len if src_len is not None else self.inline_call(strlen, src_addr).ret_expr cpy_size = self.state.se.If(self.state.se.ULE(limit, src_len + 1), limit, src_len + 1) self.inline_call(memcpy, dst_addr, src_addr, cpy_size) return dst_addr
def run(self, s_addr, c_int, s_strlen=None): #additional code trace_data = ("strchr", { "s_addr": (s_addr, s_addr.symbolic), "c_int": (c_int, c_int.symbolic) }) try: self.state.procedure_data.global_variables["trace"].append( trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append( trace_data) #end of additional code c = c_int[7:0] self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: SimTypeInt(32, True) } # ? self.return_type = self.ty_ptr(SimTypeChar()) # ? s_strlen = self.inline_call( simuvex.SimProcedures['libc.so.6']['strlen'], s_addr) if self.state.se.symbolic(s_strlen.ret_expr): l.debug("symbolic strlen") # TODO: more constraints here to make sure we don't search too little max_sym = min(self.state.se.max_int(s_strlen.ret_expr), self.state.libc.max_symbolic_strchr) a, c, i = self.state.memory.find(s_addr, c, s_strlen.max_null_index, max_symbolic_bytes=max_sym, default=0) else: l.debug("concrete strlen") max_search = self.state.se.any_int(s_strlen.ret_expr) a, c, i = self.state.memory.find(s_addr, c, max_search, default=0) if len(i) != 0: a = a.annotate(MultiwriteAnnotation()) self.state.add_constraints(*c) return a
def run(self, addr_in): #pylint:disable=unused-argument #additional code trace_data = ("inet_ntoa", {"addr_in": (addr_in, addr_in.symbolic)}) try: self.state.procedure_data.global_variables["trace"].append(trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append(trace_data) #end of additional code # arg types: struct....... :( self.return_type = self.ty_ptr(SimTypeString()) #TODO: return an IP address string ret_expr = self.state.se.Unconstrained("inet_ntoa_ret", self.state.arch.bits) return ret_expr
def run(self, s): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeLength(self.state.arch) max_symbolic_bytes = self.state.libc.buf_symbolic_bytes max_str_len = self.state.libc.max_str_len if self.state.mode == 'static': self.max_null_index = [ ] # Make sure to convert s to ValueSet s_list = self.state.memory.normalize_address(s, convert_to_valueset=True) length = self.state.se.ESI(self.state.arch.bits) for s_ptr in s_list: r, c, i = self.state.memory.find(s, self.state.se.BVV(0, 8), max_str_len, max_symbolic_bytes=max_symbolic_bytes) self.max_null_index = max(self.max_null_index + i) # Convert r to the same region as s r_list = self.state.memory.normalize_address(r, convert_to_valueset=True, target_region=s_ptr._model_vsa.regions.keys()[0]) for r_ptr in r_list: length = length.union(r_ptr - s_ptr) return length else: search_len = max_str_len r, c, i = self.state.memory.find(s, self.state.se.BVV(0, 8), search_len, max_symbolic_bytes=max_symbolic_bytes) # try doubling the search len and searching again while all(con.is_false() for con in c): search_len *= 2 r, c, i = self.state.memory.find(s, self.state.se.BVV(0, 8), search_len, max_symbolic_bytes=max_symbolic_bytes) # stop searching after some reasonable limit if search_len > 0x10000: raise simuvex.SimMemoryLimitError("strlen hit limit of 0x10000") self.max_null_index = max(i) self.state.add_constraints(*c) return r - s
def run(self, s): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeLength(self.state.arch) max_symbolic_bytes = self.state.libc.buf_symbolic_bytes max_str_len = self.state.libc.max_str_len r, c, i = self.state.memory.find(s, self.state.BVV(0, 8), max_str_len, max_symbolic_bytes=max_symbolic_bytes) self.max_null_index = max(i) self.state.add_constraints(*c) return r - s
def run(self, fmt): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(self.state.arch.bits, True) fmt_str = self._parse(0) # we're reading from stdin so the region is the file's content f = self.state.posix.get_file(0) region = f.content start = f.pos (end, items) = fmt_str.interpret(start, 1, self.arg, region=region) # do the read, correcting the internal file position and logging the action self.state.posix.read_from(0, end - start) return items
def run(self, s): #pylint:disable=attribute-defined-outside-init #additional code trace_data = ("atoi", {"s": (s, s.symbolic)}) try: self.state.procedure_data.global_variables["trace"].append( trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append( trace_data) #end of additional code self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(self.state.arch, True) strtol = simuvex.SimProcedures['libc.so.6']['strtol'] return strtol.strtol_inner(s, self.state, self.state.memory, 10, True)[1]
def run(self, s, special_addrs=None, added_constraints=None): self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeInt(self.state.arch, True) res_symb_var = claripy.BVS('atoi_ret', self.state.arch.bits) # If the argument is a special constrained variable s_val = self.state.se.any_int(s) if s.concrete and s_val in special_addrs: print( "Got a special memory addr: {:X}\n".format(s_val)) # Grab the operator and right operand (op, r_opr) = special_addrs[s_val] # Add the constraint of: (return_val `op` r_opr) print("Adding claripy_op_mapping[{}]({}, {})\n".format( op, res_symb_var, r_opr)) added_constraints.append(claripy_op_mapping[op]( res_symb_var, r_opr)) return res_symb_var
def run(self, a_addr, b_addr, limit, a_len=None, b_len=None): #pylint:disable=arguments-differ # TODO: smarter types here? self.argument_types = {0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()), 2: SimTypeLength(self.state.arch)} self.return_type = SimTypeInt(32, True) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] a_strlen = a_len if a_len is not None else self.inline_call(strlen, a_addr) b_strlen = b_len if b_len is not None else self.inline_call(strlen, b_addr) a_len = a_strlen.ret_expr b_len = b_strlen.ret_expr match_constraints = [ ] variables = a_len.variables | b_len.variables | limit.variables ret_expr = self.state.se.Unconstrained("strncmp_ret", self.state.arch.bits) # determine the maximum number of bytes to compare concrete_run = False #if not self.state.se.symbolic(a_len) and not self.state.se.symbolic(b_len) and not self.state.se.symbolic(limit): if self.state.se.single_valued(a_len) and self.state.se.single_valued(b_len) and self.state.se.single_valued(limit): c_a_len = self.state.se.any_int(a_len) c_b_len = self.state.se.any_int(b_len) c_limit = self.state.se.any_int(limit) l.debug("everything is concrete: a_len %d, b_len %d, limit %d", c_a_len, c_b_len, c_limit) if (c_a_len < c_limit or c_b_len < c_limit) and c_a_len != c_b_len: l.debug("lengths < limit and unmatched") concrete_run = True maxlen = min(c_a_len, c_b_len, c_limit) else: if self.state.se.single_valued(limit): c_limit = self.state.se.any_int(limit) maxlen = min(a_strlen.max_null_index, b_strlen.max_null_index, c_limit) else: maxlen = max(a_strlen.max_null_index, b_strlen.max_null_index) match_constraints.append(self.state.se.Or(a_len == b_len, self.state.se.And(self.state.se.UGE(a_len, limit), self.state.se.UGE(b_len, limit)))) if maxlen == 0: # there is a corner case: if a or b are not both empty string, and limit is greater than 0, we should return # non-equal. Basically we only return equal when limit is 0, or a_len == b_len == 0 if self.state.se.single_valued(limit) and self.state.se.any_int(limit) == 0: # limit is 0 l.debug("returning equal for 0-limit") return self.state.se.BVV(0, self.state.arch.bits, variables=variables) elif self.state.se.single_valued(a_len) and self.state.se.single_valued(b_len) and \ self.state.se.any_int(a_len) == self.state.se.any_int(b_len) == 0: # two empty strings l.debug("returning equal for two empty strings") return self.state.se.BVV(0, self.state.arch.bits, variables=variables) else: # all other cases fall into this branch l.debug("returning non-equal for comparison of an empty string and a non-empty string") if a_strlen.max_null_index == 0: return self.state.se.BVV(-1, self.state.arch.bits, variables=variables) else: return self.state.se.BVV(1, self.state.arch.bits, variables=variables) # the bytes a_bytes = self.state.memory.load(a_addr, maxlen, endness='Iend_BE') b_bytes = self.state.memory.load(b_addr, maxlen, endness='Iend_BE') # TODO: deps # all possible return values in static mode return_values = [ ] for i in range(maxlen): l.debug("Processing byte %d", i) maxbit = (maxlen-i)*8 a_byte = a_bytes[maxbit-1:maxbit-8] b_byte = b_bytes[maxbit-1:maxbit-8] if concrete_run and self.state.se.single_valued(a_byte) and self.state.se.single_valued(b_byte): a_conc = self.state.se.any_int(a_byte) b_conc = self.state.se.any_int(b_byte) variables |= a_byte.variables variables |= b_byte.variables if a_conc != b_conc: l.debug("... found mis-matching concrete bytes 0x%x and 0x%x", a_conc, b_conc) if a_conc < b_conc: return self.state.se.BVV(-1, self.state.arch.bits, variables=variables) else: return self.state.se.BVV(1, self.state.arch.bits, variables=variables) else: if self.state.mode == 'static': return_values.append(a_byte - b_byte) concrete_run = False if self.state.mode != 'static': byte_constraint = self.state.se.Or(a_byte == b_byte, self.state.se.ULT(a_len, i), self.state.se.ULT(limit, i)) match_constraints.append(byte_constraint) if concrete_run: l.debug("concrete run made it to the end!") return self.state.se.BVV(0, self.state.arch.bits, variables=variables) if self.state.mode == 'static': ret_expr = self.state.se.ESI(8) for expr in return_values: ret_expr = ret_expr.union(expr) ret_expr = ret_expr.sign_extend(self.state.arch.bits - 8) else: # make the constraints l.debug("returning symbolic") match_constraint = self.state.se.And(*match_constraints) nomatch_constraint = self.state.se.Not(match_constraint) #l.debug("match constraints: %s", match_constraint) #l.debug("nomatch constraints: %s", nomatch_constraint) match_case = self.state.se.And(limit != 0, match_constraint, ret_expr == 0) nomatch_case = self.state.se.And(limit != 0, nomatch_constraint, ret_expr == 1) l0_case = self.state.se.And(limit == 0, ret_expr == 0) empty_case = self.state.se.And(a_strlen.ret_expr == 0, b_strlen.ret_expr == 0, ret_expr == 0) self.state.add_constraints(self.state.se.Or(match_case, nomatch_case, l0_case, empty_case)) return ret_expr
def run(self, str_ptr, delim_ptr, save_ptr, str_strlen=None, delim_strlen=None): #additional code trace_data = ("strtok_r", { "str_ptr": (str_ptr, str_ptr.symbolic), "delim_ptr": (delim_ptr, delim_ptr.symbolic), "save_ptr": (save_ptr, save_ptr.symbolic), "str_strlen": (str_strlen, str_strlen.symbolic), "delim_strlen": (delim_strlen, delim_strlen.symbolic) }) try: self.state.procedure_data.global_variables["trace"].append( trace_data) except KeyError: self.state.procedure_data.global_variables["trace"] = [] self.state.procedure_data.global_variables["trace"].append( trace_data) #end of additional code self.argument_types = { 0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()), 2: self.ty_ptr(self.ty_ptr(SimTypeString())) } self.return_type = self.ty_ptr(SimTypeString()) if self.state.libc.simple_strtok: malloc = simuvex.SimProcedures['libc.so.6']['malloc'] token_ptr = self.inline_call( malloc, self.state.libc.strtok_token_size).ret_expr r = self.state.se.If( self.state.se.Unconstrained('strtok_case', self.state.arch.bits) == 0, token_ptr, self.state.se.BVV(0, self.state.arch.bits)) self.state.libc.strtok_heap.append(token_ptr) return r else: strstr = simuvex.SimProcedures['libc.so.6']['strstr'] strlen = simuvex.SimProcedures['libc.so.6']['strlen'] l.debug("Doin' a strtok_r!") l.debug("... geting the saved state") saved_str_ptr = self.state.memory.load( save_ptr, self.state.arch.bytes, endness=self.state.arch.memory_endness) start_ptr = self.state.se.If(str_ptr == 0, saved_str_ptr, str_ptr) l.debug("... getting the lengths") str_strlen = self.inline_call( strlen, start_ptr) if str_strlen is None else str_strlen delim_strlen = self.inline_call( strlen, delim_ptr) if delim_strlen is None else delim_strlen l.debug( "... STRTOK SLOW PATH (symbolic-length delimiteter and/or string)" ) l.debug("... calling strstr") where = self.inline_call(strstr, start_ptr, delim_ptr, haystack_strlen=str_strlen, needle_strlen=delim_strlen) write_length = self.state.se.If(where.ret_expr != 0, delim_strlen.ret_expr, 0) write_content = self.state.se.BVV(0, delim_strlen.max_null_index * 8) # do a symbolic write (we increment the limit because of the possibility that the write target is 0, in which case the length will be 0, anyways) l.debug("... doing the symbolic write") self.state.memory.store(where.ret_expr, write_content, size=write_length, strategy=["symbolic_nonzero", "any"], limit=str_strlen.max_null_index + 1) l.debug("... creating the return address") new_start = write_length + where.ret_expr new_state = self.state.se.If(new_start != 0, new_start, start_ptr) l.debug("... saving the state") self.state.memory.store(save_ptr, new_state, endness=self.state.arch.memory_endness) l.debug("... done") return new_start
def run(self, a_addr, b_addr, limit, a_len=None, b_len=None): #pylint:disable=arguments-differ # TODO: smarter types here? self.argument_types = {0: self.ty_ptr(SimTypeString()), 1: self.ty_ptr(SimTypeString()), 2: SimTypeLength(self.state.arch)} self.return_type = SimTypeInt(32, True) strlen = simuvex.SimProcedures['libc.so.6']['strlen'] a_strlen = a_len if a_len is not None else self.inline_call(strlen, a_addr) b_strlen = b_len if b_len is not None else self.inline_call(strlen, b_addr) a_len = a_strlen.ret_expr b_len = b_strlen.ret_expr match_constraints = [ ] variables = a_len.variables | b_len.variables | limit.variables ret_expr = self.state.se.Unconstrained("strncmp_ret", self.state.arch.bits) # determine the maximum number of bytes to compare concrete_run = False if not self.state.se.symbolic(a_len) and not self.state.se.symbolic(b_len) and not self.state.se.symbolic(limit): c_a_len = self.state.se.any_int(a_len) c_b_len = self.state.se.any_int(b_len) c_limit = self.state.se.any_int(limit) l.debug("everything is concrete: a_len %d, b_len %d, limit %d", c_a_len, c_b_len, c_limit) if (c_a_len < c_limit or c_b_len < c_limit) and c_a_len != c_b_len: l.debug("lengths < limit and unmatched") return self.state.se.BVV(1, self.state.arch.bits, variables=variables) concrete_run = True maxlen = min(c_a_len, c_b_len, c_limit) else: if not self.state.se.symbolic(limit): c_limit = self.state.se.any_int(limit) maxlen = min(a_strlen.max_null_index, b_strlen.max_null_index, c_limit) else: maxlen = max(a_strlen.max_null_index, b_strlen.max_null_index) match_constraints.append(self.state.se.Or(a_len == b_len, self.state.se.And(self.state.se.UGE(a_len, limit), self.state.se.UGE(b_len, limit)))) if maxlen == 0: l.debug("returning equal for 0-length maximum strings") return self.state.se.BVV(0, self.state.arch.bits, variables=variables) # the bytes a_bytes = self.state.memory.load(a_addr, maxlen, endness='Iend_BE') b_bytes = self.state.memory.load(b_addr, maxlen, endness='Iend_BE') # TODO: deps for i in range(maxlen): l.debug("Processing byte %d", i) maxbit = (maxlen-i)*8 a_byte = a_bytes[maxbit-1:maxbit-8] b_byte = b_bytes[maxbit-1:maxbit-8] if concrete_run and not self.state.se.symbolic(a_byte) and not self.state.se.symbolic(b_byte): a_conc = self.state.se.any_int(a_byte) b_conc = self.state.se.any_int(b_byte) variables |= a_byte.variables variables |= b_byte.variables if a_conc != b_conc: l.debug("... found mis-matching concrete bytes 0x%x and 0x%x", a_conc, b_conc) return self.state.se.BVV(1, self.state.arch.bits, variables=variables) else: concrete_run = False byte_constraint = self.state.se.Or(a_byte == b_byte, self.state.se.ULT(a_len, i), self.state.se.ULT(limit, i)) match_constraints.append(byte_constraint) if concrete_run: l.debug("concrete run made it to the end!") return self.state.se.BVV(0, self.state.arch.bits, variables=variables) # make the constraints l.debug("returning symbolic") match_constraint = self.state.se.And(*match_constraints) nomatch_constraint = self.state.se.Not(match_constraint) #l.debug("match constraints: %s", match_constraint) #l.debug("nomatch constraints: %s", nomatch_constraint) match_case = self.state.se.And(limit != 0, match_constraint, ret_expr == 0) nomatch_case = self.state.se.And(limit != 0, nomatch_constraint, ret_expr == 1) l0_case = self.state.se.And(limit == 0, ret_expr == 0) empty_case = self.state.se.And(a_strlen.ret_expr == 0, b_strlen.ret_expr == 0, ret_expr == 0) self.state.add_constraints(self.state.se.Or(match_case, nomatch_case, l0_case, empty_case)) return ret_expr