Esempio n. 1
0
    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.se.symbolic(sim_nmemb):
            # TODO: find a better way
            nmemb = self.state.se.max_int(sim_nmemb)
        else:
            nmemb = self.state.se.any_int(sim_nmemb)

        if self.state.se.symbolic(sim_size):
            # TODO: find a better way
            size = self.state.se.max_int(sim_size)
        else:
            size = self.state.se.any_int(sim_size)

        final_size = size * nmemb * 8
        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.se.BVV(0, final_size)
        self.state.memory.store(addr, v)

        return addr
Esempio n. 2
0
    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
        self.state.posix.read(fd, length, dst_addr=dst)
        return length
Esempio n. 3
0
    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:
                self.ret(dst_addr)
                return

            # 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 * 8)
                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
Esempio n. 4
0
    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
Esempio n. 5
0
    def run(self, dst_addr, src_addr, limit):

        #additional code
        trace_data = ("memmove", {
            "dst_addr": (dst_addr, dst_addr.symbolic),
            "src_addr": (src_addr, src_addr.symbolic),
            "limit": (limit, limit.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

        # 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())

        memcpy = simuvex.SimProcedures['libc.so.6']['memcpy']

        self.inline_call(memcpy, dst_addr, src_addr, limit)
        return dst_addr
Esempio n. 6
0
    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)
Esempio n. 7
0
    def run(self, ptr, size):

        #additional code
        trace_data = ("realloc", {
            "ptr": (ptr, ptr.symbolic),
            "size": (size, size.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.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
Esempio n. 8
0
    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:
                self.ret(dst_addr)
                return

            write_bytes = self.state.se.Concat(*([ char ] * max_size))
            self.state.memory.store(dst_addr, write_bytes)

            l.debug("memset writing %d bytes", max_size)

        return dst_addr
Esempio n. 9
0
    def run(self, sim_nmemb, sim_size):

        #additional code
        trace_data = ("calloc", {
            "sim_nmemb": (sim_nmemb, sim_nmemb.symbolic),
            "sim_size": (sim_size, sim_size.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: 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.se.symbolic(sim_nmemb):
            # TODO: find a better way
            nmemb = self.state.se.max_int(sim_nmemb)
        else:
            nmemb = self.state.se.any_int(sim_nmemb)

        if self.state.se.symbolic(sim_size):
            # TODO: find a better way
            size = self.state.se.max_int(sim_size)
        else:
            size = self.state.se.any_int(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.se.BVV(0, final_size * 8)
        self.state.memory.store(addr, v)

        return addr
Esempio n. 10
0
    def run(self, dst_addr, src_addr, limit):

        #additional code
        trace_data = ("self", {
            "dst_addr": (dst_addr, dst_addr.symbolic),
            "src_addr": (src_addr, src_addr.symbolic),
            "limit": (limit, limit.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

        # 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.se.symbolic(limit):
            # not symbolic so we just take the value
            conditional_size = self.state.se.any_int(limit)
        else:
            # constraints on the limit are added during the store
            max_memcpy_size = self.state.libc.max_memcpy_size
            max_limit = self.state.se.max_int(limit)
            conditional_size = max(self.state.se.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
Esempio n. 11
0
    def run(self, dst_addr, src_addr, limit):
        # TODO: some way to say that type(0) == type(1) ?
        self.argument_types = {
            0: self.ty_ptr(SimTypeTop()),
            1: self.ty_ptr(SimTypeTop()),
            2: SimTypeLength(self.state.arch)
        }

        return self.inline_call(simuvex.SimProcedures['libc.so.6']['memcpy'],
                                dst_addr, src_addr, limit).ret_expr
Esempio n. 12
0
    def run(self, fd, dst, length):

    	#additional code
        trace_data = ("read", {"fd": (fd, fd.symbolic), "dst": (dst, dst.symbolic), "length": (length, length.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: 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
Esempio n. 13
0
    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())

        memcpy = simuvex.SimProcedures['libc.so.6']['memcpy']

        self.inline_call(memcpy, dst_addr, src_addr, limit)
        return dst_addr
Esempio n. 14
0
    def run(self, dst, size, fd):
        self.argument_types = {2: SimTypeFd(),
                               0: self.ty_ptr(SimTypeArray(SimTypeChar(), size)),
                               1: SimTypeLength(self.state.arch)}
        self.return_type = self.argument_types[0]

        f = self.state.posix.get_file(fd)
        old_pos = self.state.posix.pos(fd)

        self.state.memory.copy_contents(dst, old_pos, size, src_memory=f.content)
        f.seek(old_pos + size)

        return dst
Esempio n. 15
0
    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
Esempio n. 16
0
    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) * 8

        addr = self.state.libc.heap_location
        self.state.libc.heap_location += size
        return addr
Esempio n. 17
0
    def run(self, dst_addr, src_addr, limit):
        # TODO: some way to say that type(0) == type(1) ?
        self.argument_types = {0: self.ty_ptr(SimTypeTop()),
                               1: self.ty_ptr(SimTypeTop()),
                               2: SimTypeLength(self.state.arch)}

        #additional code
        trace_data = ("bcopy", {"dst_addr": (dst_addr, dst_addr.symbolic), "src_addr": (src_addr, src_addr.symbolic), "limit": (limit, limit.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


        return self.inline_call(simuvex.SimProcedures['libc.so.6']['memcpy'], dst_addr, src_addr, limit).ret_expr
Esempio n. 18
0
    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
Esempio n. 19
0
    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
Esempio n. 20
0
    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
Esempio n. 21
0
    def run(self, fd):
        #pylint:disable=attribute-defined-outside-init

        #additional code
        trace_data = ("fflush", {"fd": (fd, fd.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: SimTypeFd()}
        self.return_type = SimTypeLength(self.state.arch)

        return self.state.se.BVV(0, self.state.arch.bits)
Esempio n. 22
0
    def run(self, dst_addr, char, num):

        #additional code
        trace_data = ("memset", {"dst_addr": (dst_addr, dst_addr.symbolic), "char": (char, char.symbolic), "num": (num, num.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

        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
Esempio n. 23
0
    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
Esempio n. 24
0
    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.se.symbolic(limit):
            # not symbolic so we just take the value
            conditional_size = self.state.se.any_int(limit)
        else:
            # constraints on the limit are added during the store
            max_memcpy_size = self.state.libc.max_memcpy_size
            max_limit = self.state.se.max_int(limit)
            conditional_size = max(self.state.se.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
Esempio n. 25
0
    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.se.symbolic(limit):
            if BEST_EFFORT_MEMORY_STORING in self.state.options:
                conditional_size = self.state.se.max_int(limit)
            else:
                conditional_size = self.state.se.any_int(limit)
        else:
            max_memcpy_size = self.state.libc.max_buffer_size
            conditional_size = max(
                self.state.se.min_int(limit),
                min(self.state.se.max_int(limit), max_memcpy_size))

        l.debug("Memcpy running with conditional_size %d", 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
Esempio n. 26
0
    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
Esempio n. 27
0
    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
Esempio n. 28
0
    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
Esempio n. 29
0
    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[self.state.arch.name]['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(simuvex.SimProcedures['libc.so.6']['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)
Esempio n. 30
0
    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)

        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.any_int(
                    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.se.ite_dict(n - definite_size,
                                              conditional_rets, 2)
            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