Example #1
0
 def eval_exprslice(self, expr, **kwargs):
     """[DEV]: Evaluate an ExprSlice using the current state"""
     arg = self.eval_expr_visitor(expr.arg, **kwargs)
     if arg.is_id(TOPSTR):
         ret = exprid_top(expr)
     else:
         ret = ExprSlice(arg, expr.start, expr.stop)
     return ret
Example #2
0
    def categorize(self, node, lvl=0, **kwargs):
        """Recursively apply rules to @node

        @node: ExprNode to analyze
        @lvl: actual recusion level
        """

        expr = node.expr
        log_reduce.debug("\t" * lvl + "Reduce...: %s", node.expr)
        if isinstance(expr, ExprId):
            node = ExprNodeId(expr)
        elif isinstance(expr, ExprInt):
            node = ExprNodeInt(expr)
        elif isinstance(expr, ExprLoc):
            node = ExprNodeLoc(expr)
        elif isinstance(expr, ExprMem):
            arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs)
            node = ExprNodeMem(ExprMem(arg.expr, expr.size))
            node.arg = arg
        elif isinstance(expr, ExprSlice):
            arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs)
            node = ExprNodeSlice(ExprSlice(arg.expr, expr.start, expr.stop))
            node.arg = arg
        elif isinstance(expr, ExprOp):
            new_args = []
            for arg in node.args:
                new_a = self.categorize(arg, lvl=lvl + 1, **kwargs)
                assert new_a.expr.size == arg.expr.size
                new_args.append(new_a)
            node = ExprNodeOp(ExprOp(expr.op, *[x.expr for x in new_args]))
            node.args = new_args
            expr = node.expr
        elif isinstance(expr, ExprCompose):
            new_args = []
            new_expr_args = []
            for arg in node.args:
                arg = self.categorize(arg, lvl=lvl + 1, **kwargs)
                new_args.append(arg)
                new_expr_args.append(arg.expr)
            new_expr = ExprCompose(*new_expr_args)
            node = ExprNodeCompose(new_expr)
            node.args = new_args
        elif isinstance(expr, ExprCond):
            cond = self.categorize(node.cond, lvl=lvl + 1, **kwargs)
            src1 = self.categorize(node.src1, lvl=lvl + 1, **kwargs)
            src2 = self.categorize(node.src2, lvl=lvl + 1, **kwargs)
            node = ExprNodeCond(ExprCond(cond.expr, src1.expr, src2.expr))
            node.cond, node.src1, node.src2 = cond, src1, src2
        else:
            raise TypeError("Unknown Expr Type %r", type(expr))

        node.info = self.apply_rules(node, lvl=lvl, **kwargs)
        log_reduce.debug("\t" * lvl + "Reduce result: %s %r", node.expr,
                         node.info)
        return node
def simp_slice(e_s, expr):
    "Slice optimization"

    # slice(A, 0, a.size) => A
    if expr.start == 0 and expr.stop == expr.arg.size:
        return expr.arg
    # Slice(int) => int
    if expr.arg.is_int():
        total_bit = expr.stop - expr.start
        mask = (1 << (expr.stop - expr.start)) - 1
        return ExprInt(int((expr.arg.arg >> expr.start) & mask), total_bit)
    # Slice(Slice(A, x), y) => Slice(A, z)
    if expr.arg.is_slice():
        if expr.stop - expr.start > expr.arg.stop - expr.arg.start:
            raise ValueError('slice in slice: getting more val', str(expr))

        return ExprSlice(expr.arg.arg, expr.start + expr.arg.start,
                         expr.start + expr.arg.start + (expr.stop - expr.start))
    if expr.arg.is_compose():
        # Slice(Compose(A), x) => Slice(A, y)
        for index, arg in expr.arg.iter_args():
            if index <= expr.start and index+arg.size >= expr.stop:
                return arg[expr.start - index:expr.stop - index]
        # Slice(Compose(A, B, C), x) => Compose(A, B, C) with truncated A/B/C
        out = []
        for index, arg in expr.arg.iter_args():
            # arg is before slice start
            if expr.start >= index + arg.size:
                continue
            # arg is after slice stop
            elif expr.stop <= index:
                continue
            # arg is fully included in slice
            elif expr.start <= index and index + arg.size <= expr.stop:
                out.append(arg)
                continue
            # arg is truncated at start
            if expr.start > index:
                slice_start = expr.start - index
            else:
                # arg is not truncated at start
                slice_start = 0
            # a is truncated at stop
            if expr.stop < index + arg.size:
                slice_stop = arg.size + expr.stop - (index + arg.size) - slice_start
            else:
                slice_stop = arg.size
            out.append(arg[slice_start:slice_stop])

        return ExprCompose(*out)

    # ExprMem(x, size)[:A] => ExprMem(x, a)
    # XXXX todo hum, is it safe?
    if (expr.arg.is_mem() and
          expr.start == 0 and
          expr.arg.size > expr.stop and expr.stop % 8 == 0):
        return ExprMem(expr.arg.arg, size=expr.stop)
    # distributivity of slice and &
    # (a & int)[x:y] => 0 if int[x:y] == 0
    if expr.arg.is_op("&") and expr.arg.args[-1].is_int():
        tmp = e_s.expr_simp_wrapper(expr.arg.args[-1][expr.start:expr.stop])
        if tmp.is_int(0):
            return tmp
    # distributivity of slice and exprcond
    # (a?int1:int2)[x:y] => (a?int1[x:y]:int2[x:y])
    if expr.arg.is_cond() and expr.arg.src1.is_int() and expr.arg.src2.is_int():
        src1 = expr.arg.src1[expr.start:expr.stop]
        src2 = expr.arg.src2[expr.start:expr.stop]
        return ExprCond(expr.arg.cond, src1, src2)

    # (a * int)[0:y] => (a[0:y] * int[0:y])
    if expr.start == 0 and expr.arg.is_op("*") and expr.arg.args[-1].is_int():
        args = [e_s.expr_simp_wrapper(a[expr.start:expr.stop]) for a in expr.arg.args]
        return ExprOp(expr.arg.op, *args)

    # (a >> int)[x:y] => a[x+int:y+int] with int+y <= a.size
    # (a << int)[x:y] => a[x-int:y-int] with x-int >= 0
    if (expr.arg.is_op() and expr.arg.op in [">>", "<<"] and
          expr.arg.args[1].is_int()):
        arg, shift = expr.arg.args
        shift = int(shift)
        if expr.arg.op == ">>":
            if shift + expr.stop <= arg.size:
                return arg[expr.start + shift:expr.stop + shift]
        elif expr.arg.op == "<<":
            if expr.start - shift >= 0:
                return arg[expr.start - shift:expr.stop - shift]
        else:
            raise ValueError('Bad case')

    return expr
Example #4
0
 def eval_exprslice(self, expr, **kwargs):
     """[DEV]: Evaluate an ExprSlice using the current state"""
     arg = self.eval_expr_visitor(expr.arg, **kwargs)
     ret = ExprSlice(arg, expr.start, expr.stop)
     return ret
Example #5
0
    def apply_expr_on_state_visit_cache(self, expr, state, cache, level=0):
        """
        Deep First evaluate nodes:
            1. evaluate node's sons
            2. simplify
        """

        if expr in cache:
            ret = cache[expr]
        elif expr in state:
            return state[expr]
        elif expr.is_int():
            ret = expr
        elif expr.is_id():
            if isinstance(expr.name,
                          asmblock.asm_label) and expr.name.offset is not None:
                ret = ExprInt(expr.name.offset, expr.size)
            elif expr in self.regstop:
                ret = exprid_top(expr)
            else:
                ret = state.get(expr, expr)
        elif expr.is_mem():
            ret = self.manage_mem(expr, state, cache, level)
        elif expr.is_cond():
            cond = self.apply_expr_on_state_visit_cache(
                expr.cond, state, cache, level + 1)
            src1 = self.apply_expr_on_state_visit_cache(
                expr.src1, state, cache, level + 1)
            src2 = self.apply_expr_on_state_visit_cache(
                expr.src2, state, cache, level + 1)
            if cond.is_id(TOPSTR) or src1.is_id(TOPSTR) or src2.is_id(TOPSTR):
                ret = exprid_top(expr)
            else:
                ret = ExprCond(cond, src1, src2)
        elif expr.is_slice():
            arg = self.apply_expr_on_state_visit_cache(expr.arg, state, cache,
                                                       level + 1)
            if arg.is_id(TOPSTR):
                ret = exprid_top(expr)
            else:
                ret = ExprSlice(arg, expr.start, expr.stop)
        elif expr.is_op():
            args = []
            for oarg in expr.args:
                arg = self.apply_expr_on_state_visit_cache(
                    oarg, state, cache, level + 1)
                assert oarg.size == arg.size
                if arg.is_id(TOPSTR):
                    return exprid_top(expr)
                args.append(arg)
            ret = ExprOp(expr.op, *args)
        elif expr.is_compose():
            args = []
            for arg in expr.args:
                arg = self.apply_expr_on_state_visit_cache(
                    arg, state, cache, level + 1)
                if arg.is_id(TOPSTR):
                    return exprid_top(expr)

                args.append(arg)
            ret = ExprCompose(*args)
        else:
            raise TypeError("Unknown expr type")
        ret = self.expr_simp(ret)
        assert expr.size == ret.size
        cache[expr] = ret
        return ret
Example #6
0
expr_compose = STR_EXPRCOMPOSE + LPARENTHESIS + pyparsing.delimitedList(expr, delim=',') + RPARENTHESIS
expr_op = STR_EXPROP + LPARENTHESIS + string + STR_COMMA + pyparsing.delimitedList(expr, delim=',') + RPARENTHESIS
expr_aff = STR_EXPRASSIGN + LPARENTHESIS + expr + STR_COMMA + expr + RPARENTHESIS

expr << (expr_int | expr_id | expr_loc | expr_slice | expr_mem | expr_cond | \
         expr_compose | expr_op | expr_aff)

def parse_loc_key(t):
    assert len(t) == 2
    loc_key, size = LocKey(t[0]), t[1]
    return ExprLoc(loc_key, size)

expr_int.setParseAction(lambda t: ExprInt(*t))
expr_id.setParseAction(lambda t: ExprId(*t))
expr_loc.setParseAction(parse_loc_key)
expr_slice.setParseAction(lambda t: ExprSlice(*t))
expr_mem.setParseAction(lambda t: ExprMem(*t))
expr_cond.setParseAction(lambda t: ExprCond(*t))
expr_compose.setParseAction(lambda t: ExprCompose(*t))
expr_op.setParseAction(lambda t: ExprOp(*t))
expr_aff.setParseAction(lambda t: ExprAssign(*t))


def str_to_expr(str_in):
    """Parse the @str_in and return the corresponoding Expression
    @str_in: repr string of an Expression"""

    try:
        value = expr.parseString(str_in)
    except:
        raise RuntimeError("Cannot parse expression %s" % str_in)
Example #7
0
from miasm2.expression.parser import str_to_expr
from miasm2.expression.expression import ExprInt, ExprId, ExprSlice, ExprMem, \
    ExprCond, ExprCompose, ExprOp, ExprAff, ExprLoc, LocKey

for expr_test in [
        ExprInt(0x12, 32),
        ExprId('test', 32),
        ExprLoc(LocKey(12), 32),
        ExprSlice(ExprInt(0x10, 32), 0, 8),
        ExprMem(ExprInt(0x10, 32), 32),
        ExprCond(ExprInt(0x10, 32), ExprInt(0x11, 32), ExprInt(0x12, 32)),
        ExprCompose(ExprInt(0x10, 16), ExprInt(0x11, 8), ExprInt(0x12, 8)),
        ExprInt(0x11, 8) + ExprInt(0x12, 8),
        ExprAff(ExprId('EAX', 32), ExprInt(0x12, 32)),
]:

    print 'Test: %s' % expr_test
    assert str_to_expr(repr(expr_test)) == expr_test