Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
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]
Ejemplo n.º 3
0
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]
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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