Ejemplo n.º 1
0
 def mark_boundaries(self, var_1, var_2):
     key = (var_1.conc_addr, var_2.conc_addr)
     if key in self.bounds_marked:
         return
     self.bounds_marked.add(key)
     diff = var_2.conc_addr - var_1.conc_addr
     self.solver.add(claripy.SLE(var_1.sym_addr + diff, var_2.sym_addr))
     self.stack.unsafe_constraints.append(
         claripy.SLT(var_1.sym_addr + diff, var_2.sym_addr))
Ejemplo n.º 2
0
 def get_filter_constraints(self, filter_opts):
     res = list()
     for opt in filter_opts:
         if opt["type"] == "limit_symbol":
             claripy_obj = self.symbols[opt["symbol_id"]].claripy_obj
             expr = claripy.And(claripy.SGE(claripy_obj, int(opt["min"])),
                                claripy.SLE(claripy_obj, int(opt["max"])))
             res.append(expr)
     return res
Ejemplo n.º 3
0
 def check_symbol_range(state, range_symbols):
     for sid in range_symbols:
         symbol, rmin, rmax = range_symbols[sid]
         if not state.solver.satisfiable(extra_constraints=[
             claripy.And(
                 claripy.SGE(symbol, rmin),
                 claripy.SLE(symbol, rmax)
             )
         ]):
             return False
     return True
Ejemplo n.º 4
0
    def sym_link(self, stack, solver):
        solver.add(stack.sym_size >= stack.conc_size)
        solver.add(stack.sym_size % (stack.arch.bytes) == 0)
        stack.unsafe_constraints.append(stack.sym_size > stack.conc_size)

        first = stack.variables[stack.addr_list[0]]
        solver.add(first.sym_addr >= (first.conc_addr + stack.conc_size) -
                   stack.sym_size)
        var_list = list(stack)
        for var, next_var in zip(var_list, var_list[1:] + [None]):
            var.sym_link(solver, stack)
            stack.unsafe_constraints.extend(var.unsafe_constraints)
            if var.conc_addr % (stack.arch.bytes) == 0:
                solver.add(var.sym_addr % (stack.arch.bytes) == 0)

            if var.special:
                # We're one of the args that needs to stay fixed relative somewhere
                pass
            elif next_var is None or next_var.special_bottom:
                # If we're the last free-floating variable, set a solid bottom
                solver.add(var.sym_addr <= var.conc_addr)
                if var.size is not None:
                    solver.add(
                        claripy.SLE(var.sym_addr, var.sym_addr + var.size))
                    solver.add(var.sym_addr + var.size <= next_var.sym_addr)
                    stack.unsafe_constraints.append(
                        var.sym_addr + var.size < next_var.sym_addr)
            else:
                # Otherwise we're one of the free-floating variables
                solver.add(var.sym_addr <= var.sym_addr + var.size)
                stack.unsafe_constraints.append(
                    var.sym_addr + var.size < next_var.sym_addr)
                if self.safe:
                    solver.add(var.sym_addr + var.size == next_var.sym_addr)
                else:
                    solver.add(var.sym_addr + var.size <= next_var.sym_addr)
Ejemplo n.º 5
0
    def claripy_ast_from_ail_condition(self, condition) -> claripy.ast.Base:

        # Unpack a condition all the way to the leaves
        if isinstance(condition, claripy.ast.Base):  # pylint:disable=isinstance-second-argument-not-valid-type
            return condition

        def _op_with_unified_size(op, conv, operand0, operand1):
            # ensure operand1 is of the same size as operand0
            if isinstance(operand1, ailment.Expr.Const):
                # amazing - we do the eazy thing here
                return op(conv(operand0), operand1.value)
            if operand1.bits == operand0.bits:
                return op(conv(operand0), conv(operand1))
            # extension is required
            assert operand1.bits < operand0.bits
            operand1 = ailment.Expr.Convert(None, operand1.bits, operand0.bits, False, operand1)
            return op(conv(operand0), conv(operand1))

        _mapping = {
            'LogicalAnd': lambda expr, conv: claripy.And(conv(expr.operands[0]), conv(expr.operands[1])),
            'LogicalOr': lambda expr, conv: claripy.Or(conv(expr.operands[0]), conv(expr.operands[1])),
            'CmpEQ': lambda expr, conv: conv(expr.operands[0]) == conv(expr.operands[1]),
            'CmpNE': lambda expr, conv: conv(expr.operands[0]) != conv(expr.operands[1]),
            'CmpLE': lambda expr, conv: conv(expr.operands[0]) <= conv(expr.operands[1]),
            'CmpLEs': lambda expr, conv: claripy.SLE(conv(expr.operands[0]), conv(expr.operands[1])),
            'CmpLT': lambda expr, conv: conv(expr.operands[0]) < conv(expr.operands[1]),
            'CmpLTs': lambda expr, conv: claripy.SLT(conv(expr.operands[0]), conv(expr.operands[1])),
            'CmpGE': lambda expr, conv: conv(expr.operands[0]) >= conv(expr.operands[1]),
            'CmpGEs': lambda expr, conv: claripy.SGE(conv(expr.operands[0]), conv(expr.operands[1])),
            'CmpGT': lambda expr, conv: conv(expr.operands[0]) > conv(expr.operands[1]),
            'CmpGTs': lambda expr, conv: claripy.SGT(conv(expr.operands[0]), conv(expr.operands[1])),
            'Add': lambda expr, conv: conv(expr.operands[0]) + conv(expr.operands[1]),
            'Sub': lambda expr, conv: conv(expr.operands[0]) - conv(expr.operands[1]),
            'Mul': lambda expr, conv: conv(expr.operands[0]) * conv(expr.operands[1]),
            'Not': lambda expr, conv: claripy.Not(conv(expr.operand)),
            'Xor': lambda expr, conv: conv(expr.operands[0]) ^ conv(expr.operands[1]),
            'And': lambda expr, conv: conv(expr.operands[0]) & conv(expr.operands[1]),
            'Or': lambda expr, conv: conv(expr.operands[0]) | conv(expr.operands[1]),
            'Shr': lambda expr, conv: _op_with_unified_size(claripy.LShR, conv, expr.operands[0], expr.operands[1]),
            'Shl': lambda expr, conv: _op_with_unified_size(operator.lshift, conv, expr.operands[0], expr.operands[1]),
            'Sar': lambda expr, conv: _op_with_unified_size(operator.rshift, conv, expr.operands[0], expr.operands[1]),
        }

        if isinstance(condition, (ailment.Expr.Load, ailment.Expr.DirtyExpression, ailment.Expr.BasePointerOffset,
                                  ailment.Expr.ITE, ailment.Stmt.Call)):
            var = claripy.BVS('ailexpr_%s' % repr(condition), condition.bits, explicit_name=True)
            self._condition_mapping[var.args[0]] = condition
            return var
        elif isinstance(condition, ailment.Expr.Register):
            var = claripy.BVS('ailexpr_%s-%d' % (repr(condition), condition.idx), condition.bits, explicit_name=True)
            self._condition_mapping[var.args[0]] = condition
            return var
        elif isinstance(condition, ailment.Expr.Convert):
            # convert is special. if it generates a 1-bit variable, it should be treated as a BVS
            if condition.to_bits == 1:
                var_ = self.claripy_ast_from_ail_condition(condition.operands[0])
                name = 'ailcond_Conv(%d->%d, %s)' % (condition.from_bits, condition.to_bits, repr(var_))
                var = claripy.BoolS(name, explicit_name=True)
            else:
                var_ = self.claripy_ast_from_ail_condition(condition.operands[0])
                name = 'ailexpr_Conv(%d->%d, %s)' % (condition.from_bits, condition.to_bits, repr(var_))
                var = claripy.BVS(name, condition.to_bits, explicit_name=True)
            self._condition_mapping[var.args[0]] = condition
            return var
        elif isinstance(condition, ailment.Expr.Const):
            var = claripy.BVV(condition.value, condition.bits)
            return var
        elif isinstance(condition, ailment.Expr.Tmp):
            l.warning("Left-over ailment.Tmp variable %s.", condition)
            if condition.bits == 1:
                var = claripy.BoolV('ailtmp_%d' % condition.tmp_idx)
            else:
                var = claripy.BVS('ailtmp_%d' % condition.tmp_idx, condition.bits, explicit_name=True)
            self._condition_mapping[var.args[0]] = condition
            return var

        lambda_expr = _mapping.get(condition.verbose_op, None)
        if lambda_expr is None:
            raise NotImplementedError("Unsupported AIL expression operation %s. Consider implementing." % condition.op)
        r = lambda_expr(condition, self.claripy_ast_from_ail_condition)
        if r is NotImplemented:
            r = claripy.BVS("ailexpr_%r" % condition, condition.bits, explicit_name=True)
            self._condition_mapping[r.args[0]] = condition
        else:
            # don't lose tags
            r = r.annotate(TagsAnnotation(**condition.tags))
        return r
Ejemplo n.º 6
0
 def run(self, _, length):  # pylint: disable=W0221
     bvs = claripy.BVS("Random.nextInt", 32)
     cs = claripy.And(claripy.SGE(bvs, 0), claripy.SLE(bvs, length))
     self.state.add_constraints(cs)
     return bvs
Ejemplo n.º 7
0
    def constrain_variables(self, func, solver, stack):
        self.offsets = self.funcdata[func.addr]
        self.bounds_marked = set()
        self.stack = stack
        self.solver = solver

        # do some sanity checking first
        top = min(self.offsets)
        for addr in stack.addr_list:
            if addr < top:
                raise Exception("Provided vars miss an access (off the top!)")
            base_addr = addr
            while base_addr not in self.offsets:
                base_addr -= 1
            this_offset = addr - base_addr
            if this_offset >= self.offsets[base_addr][0]:
                raise Exception(
                    "Provided vars miss an access (between the cracks!)")

        i = 0
        while i < len(stack.addr_list):
            addr = stack.addr_list[i]
            if addr in self.offsets:
                if i != 0 and self.offsets[stack.addr_list[
                        i - 1]][0] + stack.addr_list[i - 1] > addr:
                    raise Exception("Provided vars have an overlap!")
                i += 1
                continue
            stack.merge_up(i)

        # standard stuff
        stack.alloc_op.apply_constraints(solver)
        solver.add(stack.alloc_op.symval == -stack.sym_size)
        for op in stack.dealloc_ops:
            op.apply_constraints(solver)
            solver.add(op.symval == 0)

        solver.add(stack.sym_size % stack.arch.bytes == 0)
        solver.add(claripy.SGE(stack.sym_size, stack.conc_size))
        stack.unsafe_constraints.append(
            claripy.SGT(stack.sym_size, stack.conc_size))
        stack.unsafe_constraints.append(
            claripy.SGE(stack.sym_size, stack.conc_size * 2))
        stack.unsafe_constraints.append(
            claripy.SLT(stack.sym_size, stack.conc_size * 3))

        # loop through variables, add the important constraints!
        i = 0
        while i < len(stack.addr_list):
            addr = stack.addr_list[i]
            var = stack.variables[addr]
            var.size = self.offsets[addr][0]
            fix = self.offsets[addr][1]
            if fix == 'TOP':
                var.special_top = True
            elif fix == 'BOTTOM':
                var.special_bottom = True

            align = self.offsets[addr][2]
            if align != 1:
                solver.add(var.sym_addr % align == 0)
            var.sym_link(
                solver,
                stack)  # this hooks up the constrains to actual immediates
            # also the top/bottom fixing happens in there

            if i != 0:
                prev_var = stack.variables[stack.addr_list[i - 1]]
                self.mark_boundaries(prev_var, var)
            if i != len(stack.addr_list) - 1:
                next_var = stack.variables[stack.addr_list[i + 1]]
                self.mark_boundaries(var, next_var)

                # ew. ew ew ew ew ew ew!!!
                diff = next_var.conc_addr - var.conc_addr
                solver.add(claripy.SLT(var.sym_addr, var.sym_addr + diff))
            if i == 0:
                solver.add(claripy.SLE(-stack.sym_size, var.sym_addr))

            i += 1
Ejemplo n.º 8
0
    def claripy_ast_from_ail_condition(self, condition):

        # Unpack a condition all the way to the leaves
        if isinstance(condition, claripy.ast.Base):
            return condition

        _mapping = {
            'LogicalAnd':
            lambda expr, conv: claripy.And(conv(expr.operands[0]),
                                           conv(expr.operands[1])),
            'LogicalOr':
            lambda expr, conv: claripy.Or(conv(expr.operands[0]),
                                          conv(expr.operands[1])),
            'CmpEQ':
            lambda expr, conv: conv(expr.operands[0]) == conv(expr.operands[1]
                                                              ),
            'CmpNE':
            lambda expr, conv: conv(expr.operands[0]) != conv(expr.operands[1]
                                                              ),
            'CmpLE':
            lambda expr, conv: conv(expr.operands[0]) <= conv(expr.operands[1]
                                                              ),
            'CmpLEs':
            lambda expr, conv: claripy.SLE(conv(expr.operands[0]),
                                           conv(expr.operands[1])),
            'CmpLT':
            lambda expr, conv: conv(expr.operands[0]) < conv(expr.operands[1]),
            'CmpLTs':
            lambda expr, conv: claripy.SLT(conv(expr.operands[0]),
                                           conv(expr.operands[1])),
            'CmpGE':
            lambda expr, conv: conv(expr.operands[0]) >= conv(expr.operands[1]
                                                              ),
            'CmpGEs':
            lambda expr, conv: claripy.SGE(conv(expr.operands[0]),
                                           conv(expr.operands[1])),
            'CmpGT':
            lambda expr, conv: conv(expr.operands[0]) > conv(expr.operands[1]),
            'CmpGTs':
            lambda expr, conv: claripy.SGT(conv(expr.operands[0]),
                                           conv(expr.operands[1])),
            'Add':
            lambda expr, conv: conv(expr.operands[0]) + conv(expr.operands[1]),
            'Sub':
            lambda expr, conv: conv(expr.operands[0]) - conv(expr.operands[1]),
            'Not':
            lambda expr, conv: claripy.Not(conv(expr.operand)),
            'Xor':
            lambda expr, conv: conv(expr.operands[0]) ^ conv(expr.operands[1]),
            'And':
            lambda expr, conv: conv(expr.operands[0]) & conv(expr.operands[1]),
            'Or':
            lambda expr, conv: conv(expr.operands[0]) | conv(expr.operands[1]),
            'Shr':
            lambda expr, conv: claripy.LShR(conv(expr.operands[0]), expr.
                                            operands[1].value)
        }

        if isinstance(condition,
                      (ailment.Expr.Load, ailment.Expr.DirtyExpression,
                       ailment.Expr.BasePointerOffset)):
            var = claripy.BVS('ailexpr_%s' % repr(condition),
                              condition.bits,
                              explicit_name=True)
            self._condition_mapping[var] = condition
            return var
        elif isinstance(condition, ailment.Expr.Register):
            var = claripy.BVS('ailexpr_%s-%d' %
                              (repr(condition), condition.idx),
                              condition.bits,
                              explicit_name=True)
            self._condition_mapping[var] = condition
            return var
        elif isinstance(condition, ailment.Expr.Convert):
            # convert is special. if it generates a 1-bit variable, it should be treated as a BVS
            if condition.to_bits == 1:
                var_ = self.claripy_ast_from_ail_condition(
                    condition.operands[0])
                name = 'ailcond_Conv(%d->%d, %s)' % (
                    condition.from_bits, condition.to_bits, repr(var_))
                var = claripy.BoolS(name, explicit_name=True)
            else:
                var_ = self.claripy_ast_from_ail_condition(
                    condition.operands[0])
                name = 'ailexpr_Conv(%d->%d, %s)' % (
                    condition.from_bits, condition.to_bits, repr(var_))
                var = claripy.BVS(name, condition.to_bits, explicit_name=True)
            self._condition_mapping[var] = condition
            return var
        elif isinstance(condition, ailment.Expr.Const):
            var = claripy.BVV(condition.value, condition.bits)
            return var
        elif isinstance(condition, ailment.Expr.Tmp):
            l.warning("Left-over ailment.Tmp variable %s.", condition)
            if condition.bits == 1:
                var = claripy.BoolV('ailtmp_%d' % condition.tmp_idx)
            else:
                var = claripy.BVS('ailtmp_%d' % condition.tmp_idx,
                                  condition.bits)
            self._condition_mapping[var] = condition
            return var

        lambda_expr = _mapping.get(condition.verbose_op, None)
        if lambda_expr is None:
            raise NotImplementedError(
                "Unsupported AIL expression operation %s. Consider implementing."
                % condition.op)
        r = lambda_expr(condition, self.claripy_ast_from_ail_condition)
        if r is NotImplemented:
            r = claripy.BVS("ailexpr_%r" % condition,
                            condition.bits,
                            explicit_name=True)
            self._condition_mapping[r] = condition
        return r
Ejemplo n.º 9
0
    def __init__(self):
        
        build_tree({
            "id": 1,
            "block": "B1",
            "children": [
                {
                    "id": 2,
                    "block": "B2",
                    "children": []
                }, 
                {
                    "id": 3,
                    "block": "B4",
                    "children": []
                }
            ]
        }, TreePrunerTests.t1, 0)
        TreePrunerTests.l1 = build_identity_dict({"B1", "B2", "B4"})

        build_tree({
            "id": 9,
            "block": "B7",
            "children": [
                {
                    "id": 1,
                    "block": "B5",
                    "children": [
                        {
                            "id": 2,
                            "block": "B3",
                            "children": [
                                {
                                    "id": 4,
                                    "block": "B2",
                                    "children": []
                                },
                                {
                                    "id": 5,
                                    "block": "B1",
                                    "children": [
                                        {
                                            "id": 6,
                                            "block": "B6",
                                            "children": []
                                        }
                                    ]
                                }
                            ]
                        }, 
                        {
                            "id": 3,
                            "block": "B4",
                            "children": [
                                {
                                    "id": 7,
                                    "block": "B3",
                                    "children": [
                                        {
                                            "id": 8,
                                            "block": "B1",
                                            "children": []
                                        }
                                    ]
                                },
                                {
                                    "id": 11,
                                    "block": "B8",
                                    "children": []
                                }
                            ]
                        }
                    ]
                },
                {
                    "id": 10,
                    "block": "B9",
                    "children": []
                }
            ]
        }, TreePrunerTests.t2, 0)
        TreePrunerTests.l2 = build_identity_dict({"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9"})

        build_tree({
            "id": 1,
            "block": "B1",
            "children": [
                {
                    "id": 2,
                    "block": "B2",
                    "children": []
                }, 
                {
                    "id": 3,
                    "block": "B1",
                    "children": [
                        {
                            "id": 4,
                            "block": "B2",
                            "children": []
                        },
                        {
                            "id": 5,
                            "block": "B1",
                            "children": [
                                {
                                    "id": 6,
                                    "block": "B2",
                                    "children": []
                                },
                                {
                                    "id": 7,
                                    "block": "B1",
                                    "children": [
                                        {
                                            "id": 8,
                                            "block": "B2",
                                            "children": []
                                        },
                                        {
                                            "id": 9,
                                            "block": "B1",
                                            "children": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }, TreePrunerTests.t3, 0)
        TreePrunerTests.l3 = build_identity_dict({"B1", "B2"})

        s1 = claripy.BVS('s1', 32)
        build_tree({
            "id": 1,
            "block": "B1",
            "children": [
                {
                    "id": 2,
                    "block": "B2",
                    "children": [],
                    "constraints": [
                        claripy.SGT(s1, 0)
                    ]
                }, 
                {
                    "id": 3,
                    "block": "B4",
                    "children": [],
                    "constraints": [
                        claripy.SLE(s1, 0)
                    ]
                }
            ]
        }, TreePrunerTests.t4, 0)
        TreePrunerTests.l4 = build_identity_dict({"B1", "B2", "B4"})
        TreePrunerTests.s4 = {
            's1': Symbol('s1', '', s1, 1, "", "UNKNOWN")
        }

        build_tree({
            "id": 1,
            "block": "B1",
            "children": [
                {
                    "id": 2,
                    "block": "B3",
                    "constraints": [
                        claripy.SLE(s1, 10)
                    ],
                    "children": []
                },
                {
                    "id": 3,
                    "block": "B2",
                    "constraints": [
                        claripy.SGT(s1, 10)
                    ],
                    "children": [
                        {
                            "id": 4,
                            "block": "B4",
                            "constraints": [
                                claripy.SGT(s1, 10),
                                claripy.SLE(s1, 20)
                            ],
                            "children": []
                        },
                        {
                            "id": 5,
                            "block": "B5",
                            "constraints": [
                                claripy.SGT(s1, 20)
                            ],
                            "children": []
                        }
                    ]
                }
            ]
        }, TreePrunerTests.t5, 0)
        TreePrunerTests.l5 = build_identity_dict({"B1", "B2", "B3", "B4", "B5"})
        TreePrunerTests.s5 = {
            's1': Symbol('s1', '', s1, 1, "", "UNKNOWN")
        }

        build_tree({
            "id": 1,
            "block": "B1",
            "children": [
                {
                    "id": 2,
                    "block": "B2",
                    "children": []
                },
                {
                    "id": 3,
                    "block": "B1",
                    "children": [
                        {
                            "id": 4,
                            "block": "B2",
                            "children": []
                        },
                        {
                            "id": 5,
                            "block": "B1",
                            "children": [
                                {
                                    "id": 6,
                                    "block": "B2",
                                    "children": []
                                },
                                {
                                    "id": 7,
                                    "block": "B1",
                                    "children": [
                                        {
                                            "id": 8,
                                            "block": "B2",
                                            "children": []
                                        },
                                        {
                                            "id": 9,
                                            "block": "B1",
                                            "children": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }, TreePrunerTests.t6, 0)
        TreePrunerTests.l6 = build_identity_dict({"B1", "B2"})