Exemplo 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.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
Exemplo n.º 2
0
 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)
Exemplo n.º 3
0
 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)
Exemplo n.º 4
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)

        simfd = self.state.posix.get_fd(fd)
        if simfd is None:
            return -1

        return simfd.read(dst, length)
Exemplo n.º 5
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
        length = self.state.posix.read(fd, dst, length)

        return length
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
 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)
Exemplo n.º 8
0
    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
Exemplo n.º 9
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)

        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)
Exemplo n.º 10
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.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
Exemplo n.º 11
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)
Exemplo n.º 12
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:
                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
Exemplo n.º 13
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]

        # 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
Exemplo n.º 14
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)

        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)
Exemplo n.º 15
0
 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)
Exemplo n.º 16
0
Arquivo: read.py Projeto: CAFA1/angrop
    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
Exemplo n.º 17
0
 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)
Exemplo n.º 18
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)

        addr = self.state.libc.heap_location
        self.state.libc.heap_location += size
        return addr
Exemplo n.º 19
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 = 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
Exemplo n.º 20
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.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
Exemplo n.º 21
0
    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
Exemplo n.º 22
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
                # 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
Exemplo 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
Exemplo n.º 24
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_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)
Exemplo n.º 25
0
    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
Exemplo n.º 26
0
 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)