示例#1
0
    def run(self, data, fmt):
        #pylint:disable=attribute-defined-outside-init

        self.argument_types = {0: self.ty_ptr(SimTypeString()),
                               1: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(self.state.arch.bits, True)
        try:
            fmt_str = self._parse(1)    
            items = fmt_str.interpret(2, self.arg, addr=data)
            return items
        except angr.SimUnsatError:
            return self.state.se.Unconstrained('sscanf', 32, uninitialized=False)
示例#2
0
    def run(self, a_addr, b_addr):
        self.argument_types = { 0: self.ty_ptr(SimTypeString()),
                                   1: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(32, True)

        strlen = angr.SIM_PROCEDURES['libc']['strlen']

        a_strlen = self.inline_call(strlen, a_addr)
        b_strlen = self.inline_call(strlen, b_addr)
        maxlen = self.state.se.BVV(max(a_strlen.max_null_index, b_strlen.max_null_index), self.state.arch.bits)

        strncmp = self.inline_call(angr.SIM_PROCEDURES['libc']['strncmp'], a_addr, b_addr, maxlen, a_len=a_strlen, b_len=b_strlen)
        return strncmp.ret_expr
示例#3
0
 def run(self, category, locale):
     self.argument_types = {
         0: SimTypeInt(32, True),
         1: self.ty_ptr(SimTypeString())
     }
     self.return_type = self.ty_ptr(SimTypeString())
     # FIXME: just symbolic maxlen string
     max_str_len = self.state.libc.max_str_len
     malloc = SIM_PROCEDURES['libc']['malloc']
     str_addr = self.inline_call(malloc, max_str_len).ret_expr
     return self.state.se.If(self.state.se.BoolS("setlocale_flag"),
                             str_addr,
                             self.state.se.BVV(0, self.state.arch.bits))
示例#4
0
    def run(self, data, fmt):
        #pylint:disable=attribute-defined-outside-init

        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: self.ty_ptr(SimTypeString())
        }
        self.return_type = SimTypeInt(self.state.arch.bits, True)

        fmt_str = self._parse(1)

        items = fmt_str.interpret(2, self.arg, addr=data)
        return items
示例#5
0
文件: wchar.py 项目: xjump/taint_angr
    def run(self, lpString1, lpString2):
        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: self.ty_ptr(SimTypeString())
        }
        self.return_type = SimTypeInt(signed=True)

        strcmp = angr.SIM_PROCEDURES['libc']['strcmp']
        return self.inline_call(strcmp,
                                lpString1,
                                lpString2,
                                wchar=True,
                                ignore_case=True).ret_expr
示例#6
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
示例#7
0
    def run(self, s):
        self.argument_types = {0: self.ty_ptr(SimTypeString())}
        self.return_type = self.ty_ptr(SimTypeString())

        strlen = angr.SIM_PROCEDURES['libc']['strlen']
        strncpy = angr.SIM_PROCEDURES['libc']['strncpy']
        malloc = angr.SIM_PROCEDURES['libc']['malloc']

        src_len = self.inline_call(strlen, s).ret_expr
        new_s = self.inline_call(malloc, src_len + 1).ret_expr

        self.inline_call(strncpy, new_s, s, src_len + 1, src_len=src_len)

        return new_s
示例#8
0
 def run(self, str_ptr, delim_ptr, str_strlen=None, delim_strlen=None):
     self.argument_types = {
         0: self.ty_ptr(SimTypeString()),
         1: self.ty_ptr(SimTypeString())
     }
     self.return_type = self.ty_ptr(SimTypeString())
     malloc = angr.SIM_PROCEDURES['libc']['malloc']
     token_ptr = self.inline_call(
         malloc, self.state.libc.strtok_token_size).ret_expr
     r = self.state.se.If(
         self.state.se.Unconstrained('strtok_case',
                                     self.state.arch.bits) == 0, token_ptr,
         self.state.se.BVV(0, self.state.arch.bits))
     self.state.libc.strtok_heap.append(token_ptr)
     return r
示例#9
0
    def run(self, s_addr, c_int, s_strlen=None):
        c = c_int[7:0]

        self.argument_types = {0: self.ty_ptr(SimTypeString()),
                       1: SimTypeInt(32, True)} # ?
        self.return_type = self.ty_ptr(SimTypeChar()) # ?

        s_strlen = self.inline_call(angr.SIM_PROCEDURES['libc']['strlen'], s_addr)

        chunk_size = None
        if MEMORY_CHUNK_INDIVIDUAL_READS in self.state.options:
            chunk_size = 1

        if self.state.solver.symbolic(s_strlen.ret_expr):
            l.debug("symbolic strlen")
            # TODO: more constraints here to make sure we don't search too little
            max_sym = min(self.state.solver.max_int(s_strlen.ret_expr)+1, self.state.libc.max_symbolic_strchr)
            a, c, i = self.state.memory.find(s_addr, c, s_strlen.max_null_index, max_symbolic_bytes=max_sym, default=0)
        else:
            l.debug("concrete strlen")
            max_search = self.state.solver.eval(s_strlen.ret_expr)+1
            a, c, i = self.state.memory.find(s_addr, c, max_search, default=0, chunk_size=chunk_size)

        if len(i) > 1:
            a = a.annotate(MultiwriteAnnotation())
            self.state.add_constraints(*c)

        return a
示例#10
0
    def run(self, addr_in): #pylint:disable=unused-argument
        # arg types: struct....... :(
        self.return_type = self.ty_ptr(SimTypeString())

        #TODO: return an IP address string
        ret_expr = self.state.solver.Unconstrained("inet_ntoa_ret", self.state.arch.bits)
        return ret_expr
示例#11
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
示例#12
0
    def run(self, scan, fmt):
        #pylint:disable=attribute-defined-outside-init

        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: self.ty_ptr(SimTypeString())
        }
        self.return_type = SimTypeInt(self.state.arch.bits, True)

        fmt_str = self._parse(1)

        _, items = fmt_str.interpret(self.arg(0),
                                     2,
                                     self.arg,
                                     region=self.state.memory)

        return items
示例#13
0
文件: 1356_atoi.py 项目: CAFA1/angrop
    def run(self, s):
        #pylint:disable=attribute-defined-outside-init

        self.argument_types = {0: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(self.state.arch, True)

        strtol = angr.SIM_PROCEDURES['libc']['strtol']
        return strtol.strtol_inner(s, self.state, self.state.memory, 10, True)[1]
示例#14
0
    def run(self, dst, src):
        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: self.ty_ptr(SimTypeString())
        }
        self.return_type = self.ty_ptr(SimTypeString())

        strlen = angr.SIM_PROCEDURES['libc']['strlen']
        strncpy = angr.SIM_PROCEDURES['libc']['strncpy']
        src_len = self.inline_call(strlen, src).ret_expr
        dst_len = self.inline_call(strlen, dst).ret_expr

        self.inline_call(strncpy,
                         dst + dst_len,
                         src,
                         src_len + 1,
                         src_len=src_len)
        return dst
示例#15
0
文件: puts.py 项目: xjump/taint_angr
    def run(self, string):
        self.argument_types = {0: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(32, True)

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

        strlen = angr.SIM_PROCEDURES['libc']['strlen']
        length = self.inline_call(strlen, string).ret_expr
        out = stdout.write(string, length)
        stdout.write_data(self.state.solver.BVV(b'\n'))
        return out + 1
示例#16
0
    def run(self, string):
        self.argument_types = {0: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(32, True)

        # TODO: use a write that's not a linux syscall
        write = angr.SIM_PROCEDURES['linux_kernel']['write']
        strlen = angr.SIM_PROCEDURES['libc']['strlen']

        length = self.inline_call(strlen, string).ret_expr
        self.inline_call(write, self.state.se.BVV(1, self.state.arch.bits), string, length)
        self.state.posix.write(1, self.state.se.BVV(0x0a, 8), 1)

        # TODO: return values
        return self.state.se.Unconstrained('puts', self.state.arch.bits)
示例#17
0
文件: scanf.py 项目: xjump/taint_angr
    def run(self, fmt):
        #pylint:disable=attribute-defined-outside-init

        self.argument_types = {0: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(self.state.arch.bits, True)

        fmt_str = self._parse(0)

        # we're reading from stdin so the region is the file's content
        simfd = self.state.posix.get_fd(0)
        if simfd is None:
            return -1

        items = fmt_str.interpret(1, self.arg, simfd=simfd)
        return items
示例#18
0
def check_fsb(state):
    if not state.project.is_hooked(state.addr):
        return False
    sim_func = state.project.hooked_by(state.addr)

    # check whether it is a format string function
    # is yes, which argument is the format
    for i in range(len(FORMAT_FUNCS)):
        FORMAT_FUNC = FORMAT_FUNCS[i]
        if sim_func.display_name in FORMAT_FUNC:
            pos = i
            break
    else:
        return False

    # perfrom calling convention analysis and extract the format argument

    # TODO: currently, the CFGFast will fail when auto_load_libs is True,
    # to circumvent that, we create a new project each time, which is
    # extremely slow
    proj = angr.Project(state.project.filename, auto_load_libs=False)
    proj.analyses.CFG() # fill in knowledge base
    proj.analyses.CompleteCallingConventions(recover_variables=True)
    func = proj.kb.functions[sim_func.display_name]

    # extract arguments across projects. I think it should be fine
    args = func.calling_convention.get_args(state)

    # now check if is a symbolic string
    fmt = args[pos]
    sim_str = SimTypeString()
    try:
        sim_str.extract(state, fmt)
    except ValueError:
        return True
    return False
示例#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
                # 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
示例#20
0
    def run(self, p_addr, flags):
        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: SimTypeInt(32, True)
        }
        self.return_type = SimTypeFd()

        strlen = angr.SIM_PROCEDURES['libc']['strlen']

        p_strlen = self.inline_call(strlen, p_addr)
        p_expr = self.state.memory.load(p_addr,
                                        p_strlen.max_null_index,
                                        endness='Iend_BE')
        path = self.state.se.eval(p_expr, cast_to=str)

        fd = self.state.posix.open(path, flags)
        return fd
示例#21
0
    def run(self, p_addr, flags, mode=0644):  # pylint:disable=unused-argument
        self.argument_types = {0: self.ty_ptr(SimTypeString()),
                               1: SimTypeInt(32, True)}
        self.return_type = SimTypeFd()

        strlen = angr.SIM_PROCEDURES['libc']['strlen']

        p_strlen = self.inline_call(strlen, p_addr)
        p_expr = self.state.memory.load(p_addr, p_strlen.max_null_index, endness='Iend_BE')
        try:
            path = self.state.se.eval(p_expr, cast_to=str)

            fd = self.state.posix.open(path, flags)
            if fd is None:
                return -1
            return fd
        except angr.SimUnsatError:
            return self.state.se.Unconstrained("open", 32, uninitialized=False)
示例#22
0
    def run(self, p_addr, flags, mode):  # pylint:disable=unused-argument
        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: SimTypeInt(32, True)
        }
        self.return_type = SimTypeFd()

        strlen = angr.SIM_PROCEDURES['libc']['strlen']

        p_strlen = self.inline_call(strlen, p_addr)
        p_expr = self.state.memory.load(p_addr,
                                        p_strlen.max_null_index,
                                        endness='Iend_BE')
        path = self.state.solver.eval(p_expr, cast_to=bytes)

        fd = self.state.posix.open(path, flags)
        if fd is None:
            return -1
        return fd
示例#23
0
    def run(self, fmt):
        #pylint:disable=attribute-defined-outside-init

        self.argument_types = {0: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(self.state.arch.bits, True)
        try:
            fmt_str = self._parse(0)

            # we're reading from stdin so the region is the file's content
            simfd = self.state.posix.get_fd(0)
            if simfd is None:
                return -1

            items = fmt_str.interpret(1, self.arg, simfd=simfd)
            return items
        except angr.SimUnsatError:
            return self.state.se.Unconstrained('scanf',
                                               32,
                                               uninitialized=False)
示例#24
0
    def run(self, fmt):
        #pylint:disable=attribute-defined-outside-init

        self.argument_types = {0: self.ty_ptr(SimTypeString())}
        self.return_type = SimTypeInt(self.state.arch.bits, True)

        fmt_str = self._parse(0)

        # we're reading from stdin so the region is the file's content
        f = self.state.posix.get_file(0)
        region = f.content
        start = f.pos

        (end, items) = fmt_str.interpret(start, 1, self.arg, region=region)

        # do the read, correcting the internal file position and logging the action
        self.state.posix.read_from(0, end - start)

        return items
示例#25
0
    def run(self, s_addr, c_int, s_strlen=None):
        c = c_int[7:0]

        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: SimTypeInt(32, True)
        }  # ?
        self.return_type = self.ty_ptr(SimTypeChar())  # ?

        s_strlen = self.inline_call(angr.SIM_PROCEDURES['libc']['strlen'],
                                    s_addr)

        if self.state.se.symbolic(s_strlen.ret_expr):
            l.debug("symbolic strlen")
            # TODO: more constraints here to make sure we don't search too little
            try:
                max_sym = min(self.state.se.max_int(s_strlen.ret_expr),
                              self.state.libc.max_symbolic_strchr)
                a, c, i = self.state.memory.find(s_addr,
                                                 c,
                                                 s_strlen.max_null_index,
                                                 max_symbolic_bytes=max_sym,
                                                 default=0)
            except angr.SimUnsatError:
                # XXX: reduce constraint
                max_sym = self.state.libc.max_symbolic_strchr
                a, c, i = self.state.memory.find(s_addr,
                                                 c,
                                                 self.state.libc.max_str_len,
                                                 max_symbolic_bytes=max_sym,
                                                 default=0)
        else:
            l.debug("concrete strlen")
            max_search = self.state.se.eval(s_strlen.ret_expr)
            a, c, i = self.state.memory.find(s_addr, c, max_search, default=0)

        if len(i) > 1:
            a = a.annotate(MultiwriteAnnotation())
            self.state.add_constraints(*c)

        return a
示例#26
0
    def run(self, nptr, endptr, base):

        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: self.ty_ptr(self.ty_ptr(SimTypeString())),
            2: SimTypeInt(self.state.arch, True)
        }

        self.return_type = SimTypeInt(self.state.arch, True)

        if self.state.solver.symbolic(base):
            l.warning("Concretizing symbolic base in strtol")
            base_concrete = self.state.solver.eval(base)
            self.state.add_constraints(base == base_concrete)

        base = self.state.solver.eval(base)

        if base == 0:
            # in this case the base is 16 if it starts with 0x, 8 if it starts with 0, 10 otherwise
            # here's the possibilities
            base_16_pred = self.state.solver.Or(
                self.state.memory.load(nptr,
                                       2) == self.state.solver.BVV(b"0x"),
                self.state.memory.load(nptr,
                                       3) == self.state.solver.BVV(b"+0x"),
                self.state.memory.load(nptr,
                                       3) == self.state.solver.BVV(b"-0x"))
            base_8_pred = self.state.solver.And(
                self.state.solver.Or(
                    self.state.memory.load(nptr,
                                           1) == self.state.solver.BVV(b"0"),
                    self.state.memory.load(nptr,
                                           2) == self.state.solver.BVV(b"+0"),
                    self.state.memory.load(nptr,
                                           2) == self.state.solver.BVV(b"-0")),
                self.state.solver.Not(base_16_pred))
            base_10_pred = self.state.solver.And(
                self.state.solver.Not(base_16_pred),
                self.state.solver.Not(base_8_pred))
            expressions = []
            values = []
            num_bytes_arr = []

            # read a string to long for each possibility
            pred_base = zip([base_16_pred, base_10_pred, base_8_pred],
                            [16, 10, 8])
            for pred, base in pred_base:
                expression, value, num_bytes = self.strtol_inner(
                    nptr, self.state, self.state.memory, base, True)
                expressions.append(self.state.solver.And(expression, pred))
                values.append(value)
                num_bytes_arr.append(num_bytes)

            # we would return the Or(expressions) as the indicator whether or not it succeeded, but it's not needed
            # for strtol
            # expression = self.state.solver.Or(expressions)
            value = self.state.solver.ite_cases(zip(expressions, values), 0)
            num_bytes = self.state.solver.ite_cases(
                zip(expressions, num_bytes_arr), 0)

            self.state.memory.store(endptr,
                                    nptr + num_bytes,
                                    condition=(endptr != 0),
                                    endness=self.state.arch.memory_endness)

            return value

        expression, value, num_bytes = self.strtol_inner(
            nptr, self.state, self.state.memory, base, True)
        self.state.memory.store(endptr,
                                nptr + num_bytes,
                                condition=(endptr != 0),
                                endness=self.state.arch.memory_endness)
        return self.state.solver.If(expression, value, 0)
示例#27
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
示例#28
0
    def run(self,
            haystack_addr,
            needle_addr,
            haystack_strlen=None,
            needle_strlen=None):
        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: self.ty_ptr(SimTypeString())
        }
        self.return_type = self.ty_ptr(SimTypeString())

        strlen = angr.SIM_PROCEDURES['libc']['strlen']
        strncmp = angr.SIM_PROCEDURES['libc']['strncmp']

        haystack_strlen = self.inline_call(
            strlen,
            haystack_addr) if haystack_strlen is None else haystack_strlen
        needle_strlen = self.inline_call(
            strlen, needle_addr) if needle_strlen is None else needle_strlen

        # naive approach
        haystack_maxlen = haystack_strlen.max_null_index
        needle_maxlen = needle_strlen.max_null_index

        l.debug("strstr with size %d haystack and size %d needle...",
                haystack_maxlen, needle_maxlen)

        if needle_maxlen == 0:
            l.debug("... zero-length needle.")
            return haystack_addr
        elif haystack_maxlen == 0:
            l.debug("... zero-length haystack.")
            return self.state.se.BVV(0, self.state.arch.bits)

        if self.state.se.symbolic(needle_strlen.ret_expr):
            cases = [[needle_strlen.ret_expr == 0, haystack_addr]]
            exclusions = [needle_strlen.ret_expr != 0]
            remaining_symbolic = self.state.libc.max_symbolic_strstr
            for i in range(haystack_maxlen):
                l.debug("... case %d (%d symbolic checks remaining)", i,
                        remaining_symbolic)

                # big hack!
                cmp_res = self.inline_call(strncmp,
                                           haystack_addr + i,
                                           needle_addr,
                                           needle_strlen.ret_expr,
                                           a_len=haystack_strlen,
                                           b_len=needle_strlen)
                c = self.state.se.And(*([
                    self.state.se.UGE(haystack_strlen.ret_expr, needle_strlen.
                                      ret_expr), cmp_res.ret_expr == 0
                ] + exclusions))
                exclusions.append(cmp_res.ret_expr != 0)

                if self.state.se.symbolic(c):
                    remaining_symbolic -= 1

                #print "CASE:", c
                cases.append([c, haystack_addr + i])
                haystack_strlen.ret_expr = haystack_strlen.ret_expr - 1

                if remaining_symbolic == 0:
                    l.debug("... exhausted remaining symbolic checks.")
                    break

            cases.append([
                self.state.se.And(*exclusions),
                self.state.se.BVV(0, self.state.arch.bits)
            ])
            l.debug("... created %d cases", len(cases))
            r = self.state.se.ite_cases(cases, 0)
            c = [self.state.se.Or(*[c for c, _ in cases])]
        else:
            needle_length = self.state.se.eval(needle_strlen.ret_expr)
            needle_str = self.state.memory.load(needle_addr, needle_length)

            r, c, i = self.state.memory.find(
                haystack_addr,
                needle_str,
                haystack_strlen.max_null_index,
                max_symbolic_bytes=self.state.libc.max_symbolic_strstr,
                default=0)

        self.state.add_constraints(*c)
        return r
示例#29
0
    def run(self,
            str_ptr,
            delim_ptr,
            save_ptr,
            str_strlen=None,
            delim_strlen=None):
        self.argument_types = {
            0: self.ty_ptr(SimTypeString()),
            1: self.ty_ptr(SimTypeString()),
            2: self.ty_ptr(self.ty_ptr(SimTypeString()))
        }
        self.return_type = self.ty_ptr(SimTypeString())

        if self.state.libc.simple_strtok:
            malloc = angr.SIM_PROCEDURES['libc']['malloc']
            token_ptr = self.inline_call(
                malloc, self.state.libc.strtok_token_size).ret_expr
            r = self.state.solver.If(
                self.state.solver.Unconstrained('strtok_case',
                                                self.state.arch.bits) == 0,
                token_ptr, self.state.solver.BVV(0, self.state.arch.bits))
            self.state.libc.strtok_heap.append(token_ptr)
            return r
        else:
            strstr = angr.SIM_PROCEDURES['libc']['strstr']
            strlen = angr.SIM_PROCEDURES['libc']['strlen']

            l.debug("Doin' a strtok_r!")
            l.debug("... geting the saved state")

            saved_str_ptr = self.state.memory.load(
                save_ptr,
                self.state.arch.bytes,
                endness=self.state.arch.memory_endness)
            start_ptr = self.state.solver.If(str_ptr == 0, saved_str_ptr,
                                             str_ptr)

            l.debug("... getting the lengths")
            str_strlen = self.inline_call(
                strlen, start_ptr) if str_strlen is None else str_strlen
            delim_strlen = self.inline_call(
                strlen, delim_ptr) if delim_strlen is None else delim_strlen

            l.debug(
                "... STRTOK SLOW PATH (symbolic-length delimiteter and/or string)"
            )
            l.debug("... calling strstr")
            where = self.inline_call(strstr,
                                     start_ptr,
                                     delim_ptr,
                                     haystack_strlen=str_strlen,
                                     needle_strlen=delim_strlen)
            write_length = self.state.solver.If(where.ret_expr != 0,
                                                delim_strlen.ret_expr, 0)
            write_content = self.state.solver.BVV(
                0, delim_strlen.max_null_index * 8)

            # do a symbolic write (we increment the limit because of the possibility that the write target is 0, in which case the length will be 0, anyways)
            l.debug("... doing the symbolic write")
            self.state.memory.store(where.ret_expr,
                                    write_content,
                                    size=write_length,
                                    strategy=["symbolic_nonzero", "any"],
                                    limit=str_strlen.max_null_index + 1)

            l.debug("... creating the return address")
            new_start = write_length + where.ret_expr
            new_state = self.state.solver.If(new_start != 0, new_start,
                                             start_ptr)

            l.debug("... saving the state")
            self.state.memory.store(save_ptr,
                                    new_state,
                                    endness=self.state.arch.memory_endness)

            l.debug("... done")
            return new_start