def run(self, file_ptr, offset, whence): # TODO: Support symbolic file_ptr, offset, and whence # Make sure whence can only be one of the three values: SEEK_SET(0), SEEK_CUR(1), and SEEK_END(2) if self.state.se.symbolic(whence) and len( self.state.se.any_n_int(whence, 2)) > 1: raise angr.SimProcedureError( 'multi-valued "whence" is not supported in fseek.') else: # Get all possible values all_whence = self.state.se.any_n_int(whence, 2) if not all_whence: raise angr.SimProcedureError( '"whence" has no satisfiable value.') # There is only one value left whence_int = all_whence[0] if whence_int not in (0, 1, 2): return 22 # EINVAL fd_offset = io_file_data_for_arch(self.state.arch)['fd'] fd = self.state.mem[file_ptr + fd_offset:].int.resolved r = self.state.posix.seek(fd, offset, whence_int) return r
def mode_to_flag(mode): # TODO improve this: handle mode = strings if mode[-1] == ord('b'): # lol who uses windows mode = mode[:-1] elif mode[-1] == ord( 't'): # Rarely modes rt or wt are used, but identical to r and w mode = mode[:-1] mode = mode.replace(b'c', b'').replace(b'e', b'') all_modes = { b"r": angr.storage.file.Flags.O_RDONLY, b"r+": angr.storage.file.Flags.O_RDWR, b"w": angr.storage.file.Flags.O_WRONLY | angr.storage.file.Flags.O_CREAT, b"w+": angr.storage.file.Flags.O_RDWR | angr.storage.file.Flags.O_CREAT, b"a": angr.storage.file.Flags.O_WRONLY | angr.storage.file.Flags.O_CREAT | angr.storage.file.Flags.O_APPEND, b"a+": angr.storage.file.Flags.O_RDWR | angr.storage.file.Flags.O_CREAT | angr.storage.file.Flags.O_APPEND } if mode not in all_modes: raise angr.SimProcedureError('unsupported file open mode %s' % mode) return all_modes[mode]
def mode_to_flag(mode): # TODO improve this: handle mode = strings if mode[-1] == 'b': # lol who uses windows mode = mode[:-1] all_modes = { "r" : angr.storage.file.Flags.O_RDONLY, "r+" : angr.storage.file.Flags.O_RDWR, "w" : angr.storage.file.Flags.O_WRTONLY | angr.storage.file.Flags.O_CREAT, "w+" : angr.storage.file.Flags.O_RDWR | angr.storage.file.Flags.O_CREAT, "a" : angr.storage.file.Flags.O_WRTONLY | angr.storage.file.Flags.O_CREAT | angr.storage.file.Flags.O_APPEND, "a+" : angr.storage.file.Flags.O_RDWR | angr.storage.file.Flags.O_CREAT | angr.storage.file.Flags.O_APPEND } if mode not in all_modes: raise angr.SimProcedureError('unsupported file open mode %s' % mode) return all_modes[mode]
def run(self, file_ptr, offset, whence): # TODO: Support symbolic file_ptr, offset, and whence # Make sure whence can only be one of the three values: SEEK_SET(0), SEEK_CUR(1), and SEEK_END(2) try: whence = self.state.solver.eval_one(whence) except SimSolverError: raise angr.SimProcedureError('multi-valued "whence" is not supported in fseek.') try: whence = {0: 'start', 1: 'current', 2: 'end'}[whence] except KeyError: return -1 # EINVAL 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 return self.state.solver.If(simfd.seek(offset, whence), self.state.solver.BVV(0, self.state.arch.bits), -1)
def run(self, line_ptrptr, len_ptr, delim, file_ptr): # let's get the memory back for the file we're interested in and find the delimiter 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 # symbolic delimiters will make this tricky if delim.symbolic: raise angr.SimProcedureError( "I don't know how to handle a symbolic delimiter") # case 1: the data is concrete. we should read it a byte at a time since we can't seek for # the newline and we don't have any notion of buffering in-memory if simfd.read_storage.concrete: realloc = angr.SIM_PROCEDURES['libc']['realloc'] # #dereference the destination buffer line_ptr = self.state.memory.load(line_ptrptr, 8) size = 120 # im just always going to realloc and restart at size = 120, regardless of if a proper size buffer exists. # this doesn't match the exact behavior of get delim, but is the easiest way to ignore symbolic sizes. dst = self.inline_call(realloc, line_ptr, size).ret_expr count = 0 while True: data, real_size = simfd.read_data(1) if self.state.solver.is_true(real_size == 0): break self.state.memory.store(dst + count, data) count += 1 if count == size: size = count + size + 1 dst = self.inline_call(realloc, dst, size).ret_expr if self.state.solver.is_true(data == delim): break self.state.memory.store(dst + count, b'\0') self.state.memory.store(len_ptr, count) self.state.memory.store(line_ptrptr, dst) return count # case 2: the data is symbolic, the delimiter could be anywhere. Read some maximum number of bytes # and add a constraint to assert the delimiter nonsense. # caveat: there could also be no delimiter and the file could EOF. else: # Just a guess as to a good value for a max size size = 1024 data, real_size = simfd.read_data(size - 1) delim_byte = chr(self.state.solver.eval(delim)) for i, byte in enumerate(data.chop(8)): self.state.add_constraints( self.state.solver.If( i + 1 != real_size, byte != delim_byte, # 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 simfd.eof(), # - the file is at EOF, or byte == delim_byte # - it is a newline ))) malloc = angr.SIM_PROCEDURES['libc']['malloc'] dst = self.inline_call(malloc, real_size) self.state.memory.store(dst, data, size=real_size) self.state.memory.store(dst + real_size, b'\0') self.state.memory.store(len_ptr, real_size) self.state.memory.store(line_ptrptr, dst).ret_expr return real_size