def run(self, sim_nmemb, sim_size): self.argument_types = { 0: SimTypeLength(self.state.arch), 1: SimTypeLength(self.state.arch) } plugin = self.state.get_plugin('libc') self.return_type = self.ty_ptr( SimTypeArray(SimTypeTop(sim_size), sim_nmemb)) if self.state.solver.symbolic(sim_nmemb): # TODO: find a better way nmemb = self.state.solver.max_int(sim_nmemb) else: nmemb = self.state.solver.eval(sim_nmemb) if self.state.solver.symbolic(sim_size): # TODO: find a better way size = self.state.solver.max_int(sim_size) else: size = self.state.solver.eval(sim_size) final_size = size * nmemb if final_size > plugin.max_variable_size: final_size = plugin.max_variable_size addr = plugin.heap_location plugin.heap_location += final_size v = self.state.solver.BVV(0, final_size * 8) self.state.memory.store(addr, v) return addr
def run(self, sim_nmemb, sim_size): self.argument_types = { 0: SimTypeLength(self.state.arch), 1: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr( SimTypeArray(SimTypeTop(sim_size), sim_nmemb)) return self.state.heap._calloc(sim_nmemb, sim_size)
def run(self, sim_nmemb, sim_size): self.argument_types = { 0: SimTypeLength(self.state.arch), 1: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeArray(SimTypeTop(sim_size), sim_nmemb)) actual_val = self.state.heap._conc_alloc_size(sim_nmemb * sim_size) if actual_val > self.state.globals[NO_OOM_MEMSIZE]: return 0 self.state.globals[NO_OOM_MEMSIZE] -= actual_val return self.state.heap._calloc(sim_nmemb, sim_size)
def run(self, fd, dst, length): self.argument_types = {0: SimTypeFd(), 1: self.ty_ptr(SimTypeArray(SimTypeChar(), length)), 2: SimTypeLength(self.state.arch)} self.return_type = SimTypeLength(self.state.arch) simfd = self.state.posix.get_fd(fd) if simfd is None: return -1 return simfd.read(dst, length)
def run(self, fd, dst, length): self.argument_types = { 0: SimTypeFd(), 1: self.ty_ptr(SimTypeArray(SimTypeChar(), length)), 2: SimTypeLength(self.state.arch) } self.return_type = SimTypeLength(self.state.arch) # TODO handle errors length = self.state.posix.read(fd, dst, length) return length
def run(self, s, wchar=False): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: self.ty_ptr(SimTypeString())} self.return_type = SimTypeLength(self.state.arch) if wchar: null_seq = self.state.se.BVV(0, 16) step = 2 else: null_seq = self.state.se.BVV(0, 8) step = 1 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 = 0 # 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, null_seq, max_str_len, max_symbolic_bytes=max_symbolic_bytes, step=step) 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, null_seq, search_len, max_symbolic_bytes=max_symbolic_bytes, step=step) # try doubling the search len and searching again s_new = s while all(con.is_false() for con in c): s_new += search_len search_len *= 2 r, c, i = self.state.memory.find(s_new, null_seq, search_len, max_symbolic_bytes=max_symbolic_bytes, step=step) # stop searching after some reasonable limit if search_len > 0x10000: raise angr.SimMemoryLimitError("strlen hit limit of 0x10000") self.max_null_index = max(i) self.state.add_constraints(*c) result = r - s if result.depth > 3: rresult = claripy.BVS('strlen', len(result)) self.state.solver.add(result == rresult) result = rresult return result
def run(self, ptr, size): self.argument_types = { 0: self.ty_ptr(SimTypeTop()), 1: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr(SimTypeTop(size)) return self.state.heap._realloc(ptr, size)
def run(self, ptr, size): if not self.state.se.symbolic(ptr) and \ self.state.se.eval(ptr) == 0: return self.inline_call(malloc, size).ret_expr try: self.state.add_constraints( size <= self.state.libc.max_variable_size) size_int = self.state.se.max_int(size) l.debug("Size: %d", size_int) self.state.add_constraints(size_int == size) except angr.SimUnsatError: size_int = self.state.libc.max_variable_size self.argument_types = { 0: self.ty_ptr(SimTypeTop()), 1: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr(SimTypeTop(size)) addr = self.state.libc.heap_location v = self.state.memory.load(ptr, size_int) self.state.memory.store(addr, v) self.state.libc.heap_location += size_int return addr
def run(self, fd, dst, length): self.argument_types = { 0: SimTypeFd(), 1: self.ty_ptr(SimTypeArray(SimTypeChar(), length)), 2: SimTypeLength(self.state.arch) } self.return_type = SimTypeLength(self.state.arch) try: simfd = self.state.posix.get_fd(fd) if simfd is None: return -1 return simfd.read(dst, length) except angr.SimUnsatError: return self.state.se.Unconstrained('read', 32, uninitialized=False)
def run(self, dst_addr, src_addr, limit): # TODO: look into smarter types here self.argument_types = {0: self.ty_ptr(SimTypeTop()), 1: self.ty_ptr(SimTypeTop()), 2: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeTop()) if not self.state.solver.symbolic(limit): # not symbolic so we just take the value conditional_size = self.state.solver.eval(limit) else: # constraints on the limit are added during the store max_memcpy_size = self.state.libc.max_memcpy_size max_limit = self.state.solver.max_int(limit) conditional_size = max(self.state.solver.min_int(limit), min(max_limit, max_memcpy_size)) if max_limit > max_memcpy_size and conditional_size < max_limit: l.warning("memcpy upper bound of %#x outside limit, limiting to %#x instead", max_limit, conditional_size) l.debug("Memcpy running with conditional_size %#x", conditional_size) if conditional_size > 0: src_mem = self.state.memory.load(src_addr, conditional_size, endness='Iend_BE') if ABSTRACT_MEMORY in self.state.options: self.state.memory.store(dst_addr, src_mem, size=conditional_size, endness='Iend_BE') else: self.state.memory.store(dst_addr, src_mem, size=limit, endness='Iend_BE') return dst_addr
def run(self, fd): #pylint:disable=attribute-defined-outside-init self.argument_types = {0: SimTypeFd()} self.return_type = SimTypeLength(self.state.arch) return self.state.se.BVV(0, self.state.arch.bits)
def run(self, dst_addr, char, num): char = char[7:0] self.argument_types = {0: self.ty_ptr(SimTypeTop()), 1: SimTypeInt(32, True), # ? 2: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeTop()) if self.state.se.symbolic(num): l.debug("symbolic length") max_size = self.state.se.min_int(num) + self.state.libc.max_buffer_size write_bytes = self.state.se.Concat(*([ char ] * max_size)) self.state.memory.store(dst_addr, write_bytes, size=num) else: max_size = self.state.se.any_int(num) if max_size == 0: return dst_addr if self.state.se.symbolic(char): l.debug("symbolic char") write_bytes = self.state.se.Concat(*([char] * max_size)) else: # Concatenating many bytes is slow, so some sort of optimization is required if char._model_concrete.value == 0: write_bytes = self.state.se.BVV(0, max_size * 8) else: rb = memset._repeat_bytes(char._model_concrete.value, max_size) write_bytes = self.state.se.BVV(rb, max_size * 8) self.state.memory.store(dst_addr, write_bytes) l.debug("memset writing %d bytes", max_size) return dst_addr
def run(self, dst, size, file_ptr): self.argument_types = { 2: SimTypeFd(), 0: self.ty_ptr(SimTypeArray(SimTypeChar(), size)), 1: SimTypeLength(self.state.arch) } self.return_type = self.argument_types[0] # let's get the memory back for the file we're interested in and find the newline fd_offset = io_file_data_for_arch(self.state.arch)['fd'] fd = self.state.mem[file_ptr + fd_offset:].int.resolved simfd = self.state.posix.get_fd(fd) if simfd is None: return -1 data, real_size = simfd.read_data(size - 1) for i, byte in enumerate(data.chop(8)): self.state.solver.add( self.state.solver.If( i + 1 != real_size, byte != '\n', # if not last byte returned, not newline self.state.solver. Or( # otherwise one of the following must be true i + 2 == size, # we ran out of space, or byte == '\n' # it is a newline ))) self.state.memory.store(dst, data, size=real_size) self.state.memory.store(dst + real_size, '\0') return real_size
def run(self, s1_addr, s2_addr, n): # TODO: look into smarter types here self.argument_types = {0: self.ty_ptr(SimTypeTop()), 1: self.ty_ptr(SimTypeTop()), 2: SimTypeLength(self.state.arch)} self.return_type = SimTypeInt(32, True) try: max_memcmp_size = self.state.libc.max_buffer_size definite_size = self.state.se.min_int(n) conditional_s1_start = s1_addr + definite_size conditional_s2_start = s2_addr + definite_size if self.state.se.symbolic(n): conditional_size = int(max(max_memcmp_size - definite_size, 0)) else: conditional_size = 0 l.debug("Definite size %s and conditional size: %s", definite_size, conditional_size) if definite_size > 0: s1_part = self.state.memory.load(s1_addr, definite_size, endness='Iend_BE') s2_part = self.state.memory.load(s2_addr, definite_size, endness='Iend_BE') cases = [ [s1_part == s2_part, self.state.se.BVV(0, self.state.arch.bits)], [self.state.se.ULT(s1_part, s2_part), self.state.se.BVV(-1, self.state.arch.bits)], [self.state.se.UGT(s1_part, s2_part), self.state.se.BVV(1, self.state.arch.bits) ] ] definite_answer = self.state.se.ite_cases(cases, 2) constraint = self.state.se.Or(*[c for c,_ in cases]) self.state.add_constraints(constraint) l.debug("Created definite answer: %s", definite_answer) l.debug("Created constraint: %s", constraint) l.debug("... crom cases: %s", cases) else: definite_answer = self.state.se.BVV(0, self.state.arch.bits) if not self.state.se.symbolic(definite_answer) and self.state.se.eval(definite_answer) != 0: return definite_answer if conditional_size > 0: s1_all = self.state.memory.load(conditional_s1_start, conditional_size, endness='Iend_BE') s2_all = self.state.memory.load(conditional_s2_start, conditional_size, endness='Iend_BE') conditional_rets = { 0: definite_answer } for byte, bit in zip(range(conditional_size), range(conditional_size*8, 0, -8)): s1_part = s1_all[conditional_size*8-1 : bit-8] s2_part = s2_all[conditional_size*8-1 : bit-8] cases = [ [s1_part == s2_part, self.state.se.BVV(0, self.state.arch.bits)], [self.state.se.ULT(s1_part, s2_part), self.state.se.BVV(-1, self.state.arch.bits)], [self.state.se.UGT(s1_part, s2_part), self.state.se.BVV(1, self.state.arch.bits) ] ] conditional_rets[byte+1] = self.state.se.ite_cases(cases, 0) self.state.add_constraints(self.state.se.Or(*[c for c,_ in cases])) ret_expr = self.state.solver.If(definite_answer == 0, self.state.se.ite_dict(n - definite_size, conditional_rets, 2), definite_answer) self.state.add_constraints(self.state.se.Or(*[n-definite_size == c for c in conditional_rets.keys()])) return ret_expr else: return definite_answer except angr.SimUnsatError: return self.state.se.Unconstrained('memcmp', 32, uninitialized=False)
def run(self, sim_size): self.argument_types = {0: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeTop(sim_size)) # this function contains logic errors, including not confirming the resulting # size is a valid one, but it's not likely to fail either # misbehave in the general sense actual_val = self.state.heap._conc_alloc_size(sim_size) if actual_val > self.state.globals[NO_OOM_MEMSIZE]: return 0 self.state.globals[NO_OOM_MEMSIZE] -= actual_val return self.state.heap._malloc(actual_val)
def run(self, fd, dst, length): self.argument_types = { 0: SimTypeFd(), 1: self.ty_ptr(SimTypeArray(SimTypeChar(), length)), 2: SimTypeLength(self.state.arch) } self.return_type = SimTypeLength(self.state.arch) # TODO handle errors length = self.state.posix.read(fd, dst, length) filename = self.state.posix.get_file(fd) #filter read passwd file if (filename.name.find('passwd') != -1 or 1): print filename.name + ' !!!' #print "test!!!!" fff = open('/data/find_read.flag', 'w') fff.close() write_file('read file name: ' + filename.name + '\n') return length
def run(self, ptr, size): self.argument_types = { 0: self.ty_ptr(SimTypeTop()), 1: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr(SimTypeTop(size)) minus = 0 chunk = self.state.heap.chunk_from_mem(ptr) if chunk is not None: minus = chunk.get_size() actual_val = self.state.heap._conc_alloc_size(size) if (actual_val - minus) > self.state.globals[NO_OOM_MEMSIZE]: return 0 self.state.globals[NO_OOM_MEMSIZE] -= (actual_val - minus) return self.state.heap._realloc(ptr, size)
def run(self, sim_size): self.argument_types = {0: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeTop(sim_size)) if self.state.se.symbolic(sim_size): size = self.state.se.max_int(sim_size) if size > self.state.libc.max_variable_size: size = self.state.libc.max_variable_size else: size = self.state.se.any_int(sim_size) addr = self.state.libc.heap_location self.state.libc.heap_location += size return addr
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 = angr.SIM_PROCEDURES['libc']['strlen'] memcpy = angr.SIM_PROCEDURES['libc']['memcpy'] src_len = src_len if src_len is not None else self.inline_call(strlen, src_addr).ret_expr cpy_size = self.state.solver.If(self.state.solver.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, dst_addr, char, num): char = char[7:0] self.argument_types = { 0: self.ty_ptr(SimTypeTop()), 1: SimTypeInt(32, True), # ? 2: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr(SimTypeTop()) if self.state.solver.symbolic(num): l.debug("symbolic length") try: max_size = self.state.solver.min_int( num) + self.state.libc.max_buffer_size except angr.SimUnsatError: max_size = self.state.libc.max_buffer_size write_bytes = self.state.solver.Concat(*([char] * max_size)) self.state.memory.store(dst_addr, write_bytes, size=num) else: max_size = self.state.solver.eval(num) # angr doesn't check max length here. max_size = min(max_size, self.state.libc.max_buffer_size) l.warning("memset writing %d bytes", max_size) offset = 0 while offset < max_size: chunksize = min(max_size - offset, 0x1000) if self.state.solver.symbolic(char): l.debug("symbolic char") write_bytes = self.state.solver.Concat(*([char] * chunksize)) else: # Concatenating many bytes is slow, so some sort of optimization is required if char._model_concrete.value == 0: write_bytes = self.state.solver.BVV(0, chunksize * 8) else: rb = memset._repeat_bytes(char._model_concrete.value, chunksize) write_bytes = self.state.solver.BVV(rb, chunksize * 8) self.state.memory.store(dst_addr + offset, write_bytes) offset += chunksize return dst_addr
def run(self, sim_size): self.argument_types = {0: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeTop(sim_size)) addr = self.state.heap._malloc(sim_size) size = self.state.solver.eval(sim_size) # print("size:",size,"addr:",addr) if "has_malloc" in self.state.globals: malloc_dir = self.state.globals["has_malloc"] else: self.state.globals["has_malloc"] = {} malloc_dir = self.state.globals["has_malloc"] malloc_dir[addr] = size # print(self.state.globals["has_malloc"]) return addr
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 # stop searching after some reasonable limit if search_len > 0x10000: raise angr.SimMemoryLimitError("strlen hit limit of 0x10000") r, c, i = self.state.memory.find(s, self.state.se.BVV(0, 8), search_len, max_symbolic_bytes=max_symbolic_bytes) self.max_null_index = max(i) self.state.add_constraints(*c) return r - s
def run(self, ptr, size): self.state.add_constraints(size <= self.state.libc.max_variable_size) size_int = self.state.se.max_int(size) l.debug("Size: %d", size_int) self.state.add_constraints(size_int == size) self.argument_types = { 0: self.ty_ptr(SimTypeTop()), 1: SimTypeLength(self.state.arch) } self.return_type = self.ty_ptr(SimTypeTop(size)) addr = self.state.libc.heap_location v = self.state.memory.load(ptr, size_int) self.state.memory.store(addr, v) self.state.libc.heap_location += size_int return addr
def run(self, dst, size, file_ptr): self.argument_types = { 2: SimTypeFd(), 0: self.ty_ptr(SimTypeArray(SimTypeChar(), size)), 1: SimTypeLength(self.state.arch) } self.return_type = self.argument_types[0] # some sensible limits for the new line search max_symbolic_bytes = self.state.libc.buf_symbolic_bytes max_str_len = self.state.libc.max_str_len # let's get the memory back for the file we're interested in and find the newline fd_offset = io_file_data_for_arch(self.state.arch)['fd'] fd = self.state.mem[file_ptr + fd_offset:].int.resolved fp = self.state.posix.get_file(fd) pos = fp.pos mem = fp.content # if there exists a limit on the file size, let's respect that, the limit cannot be symbolic limit = max_str_len if fp.size is None else self.state.se.max_int( fp.size - pos) # limit will always be concrete, if it's zero we EOF'd if limit != 0: # XXX max_str_len is small, might not be suitable for tracing! # measure up to the newline of size - 1 r, c, i = mem.find(pos, self.state.se.BVV('\n'), limit, max_symbolic_bytes=max_symbolic_bytes) else: r = 0 c = [] # XXX: this is a HACK to determine if r is 0 because there is a newline at the first index or # if r is 0 because there cannot be any newline errored = False if not self.state.se.satisfiable(extra_constraints=(r > 0, )): errored = True if self.state.se.solution(mem.load(0, 1), self.state.se.BVV('\n')): errored = False # make sure we only read up to size - 1 read_size = self.state.se.If(size == 0, 0, size - 1) # if file can EOF (ie not completely symbolic) if fp.size is not None: read_size = self.state.se.If(limit < read_size, limit, read_size) # now if find errored then there cannot exist a newline in the file, otherwise this logic checks out if not errored: newline_d = self.state.se.If(r == 0, r, r - pos + 1) distance = self.state.se.If(read_size < newline_d, read_size, newline_d) else: distance = read_size # read in up to the newline ret = self.inline_call(angr.SIM_PROCEDURES['posix']['read'], fd, dst, distance).ret_expr # in case there's no newline c = self.state.se.Or(ret == read_size, *c) self.state.add_constraints(c) # otherwise we take care of the newline case # now write the terminating null byte, should be placed after the newline which is also stored self.state.memory.store(dst + distance, self.state.se.BVV(0, 8)) inner_case = self.state.se.If(self.state.se.And(fp.pos == 0, ret == 0), 0, dst) return self.state.se.If(size == 0, 0, inner_case)
def run(self, a_addr, b_addr, limit, a_len=None, b_len=None, wchar=False, ignore_case=False): #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 = angr.SIM_PROCEDURES['libc']['strlen'] a_strlen = a_len if a_len is not None else self.inline_call( strlen, a_addr, wchar=wchar) b_strlen = b_len if b_len is not None else self.inline_call( strlen, b_addr, wchar=wchar) 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, key=('api', 'strncmp')) # 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.eval(a_len) c_b_len = self.state.se.eval(b_len) c_limit = self.state.se.eval(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.eval(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.eval( 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.eval(a_len) == self.state.se.eval(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.eval(a_byte) b_conc = self.state.se.eval(b_byte) variables |= a_byte.variables variables |= b_byte.variables if ignore_case: # convert both to lowercase if ord('a') <= a_conc <= ord('z'): a_conc -= ord(' ') if ord('a') <= b_conc <= ord('z'): b_conc -= ord(' ') 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': if ignore_case: byte_constraint = self.state.se.Or( self.state.se.Or( a_byte == b_byte, self.state.se.And( ord('A') <= a_byte, a_byte <= ord('Z'), ord('a') <= b_byte, b_byte <= ord('z'), b_byte - ord(' ') == a_byte, ), self.state.se.And( ord('A') <= b_byte, b_byte <= ord('Z'), ord('a') <= a_byte, a_byte <= ord('z'), a_byte - ord(' ') == b_byte, ), ), self.state.se.ULT(a_len, i), self.state.se.ULT(limit, i)) else: 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, sim_size): self.argument_types = {0: SimTypeLength(self.state.arch)} self.return_type = self.ty_ptr(SimTypeTop(sim_size)) return self.state.heap._malloc(sim_size)