Exemple #1
0
    def is_byte_swap(self):
        try:
            self.model_variable()
        except ModelIsConstrained:
            return False

        # Figure out if this might be a byte swap
        byte_values_len = len(self.byte_values)
        #print self.byte_values
        if 1 < byte_values_len <= self.var.src.var.type.width:
            var = create_BitVec(self.var.src, self.var.src.var.type.width)
           
            ordering = list(reversed([
                self.byte_values[x]
                for x in sorted(self.byte_values.keys())
            ]))

            reverse_var = Concat(
                *reversed([
                    Extract(i-1, i-8, var)
                    for i in range(len(ordering) * 8, 0, -8)
                ])
            )

            if len(ordering) < 4:
                reverse_var = Concat(
                    Extract(
                        31,
                        len(ordering)*8, var
                    ),
                    reverse_var
                )

            reversed_ordering = reversed(ordering)
            reversed_ordering = Concat(*reversed_ordering)

            # The idea here is that if we add the negation of this, if it's
            # not satisfiable, then that means there is no value such that
            # the equivalence does not hold. If that is the case, then this
            # should be a byte-swapped value.

            self.solver.add(
                Not(
                    And(
                        var == ZeroExt(
                            var.size() - len(ordering)*8,
                            Concat(*ordering)
                        ),
                        reverse_var == ZeroExt(
                            reverse_var.size() - reversed_ordering.size(),
                            reversed_ordering
                        )
                    )
                )
            )

            if self.solver.check() == unsat:
                return True

        return False
Exemple #2
0
    def visit_MLIL_LSL(self, expr):
        left, right = self.visit_both_sides(expr)

        if right.size() != left.size():
            right = ZeroExt(left.size() - right.size(), right)

        return left << right
    def evaluate_MLIL_MULU_DP(self, state):
        # TODO: CONFIRM THIS IS CORRECT
        # FIXME: Possibly broken on 64 bit; Might also be SET_VAR_SPLIT_SSA.

        operand_1, operand_2 = self.instructions_to_operands(
            self.instruction.operands, state, self.instruction.size)

        result_size = self.instruction.size * 8 * 2

        result = ZeroExt(result_size // 2, operand_1) * ZeroExt(
            result_size // 2, operand_2)

        return [result]
    def visit_MLIL_SET_VAR_SSA_FIELD(self, expr):
        # expr.size will be the width of the field, so we need the dest's real
        # width
        dest = create_BitVec(expr.dest, expr.dest.var.type.width)
        prev = create_BitVec(expr.prev, expr.prev.var.type.width)

        mask = (1 << (expr.size * 8) - 1) << (expr.offset * 8)

        mask = ~mask & ((1 << (expr.dest.var.type.width * 8)) - 1)

        src = self.visit(expr.src)

        self.visited.add(expr.dest)

        if expr.instr_index in self.to_visit:
            self.to_visit.remove(expr.instr_index)

        if src is not None:
            self.solver.add(
                dest == (
                    (prev & mask) | ZeroExt(
                            (
                                expr.dest.var.type.width -
                                (expr.size + expr.offset)
                            ) * 8,
                            (src << (expr.offset * 8))
                    )
                )
            )
    def instructions_to_operands(self,
                                 instructions: List[MediumLevelILInstruction],
                                 state, size: int):
        """
        Get operands from instruction list, increasing their size if needed.

        :instructions: List of instructions to convert to operands
        :state: Current active state
        :size: Minimum size in bytes of the operands
        """
        operands = []
        largest_size = size * 8
        for instruction in instructions:
            ops = MLILInstructionExecutor(self.bv, instruction).execute(state)
            # TODO: Is this needed:
            for op in ops:
                if op.size() > largest_size:
                    largest_size = op.size()
                operands.append(op)

        for i, op in enumerate(operands):
            if op.size() < largest_size:
                operands[i] = ZeroExt(largest_size - op.size(), op)

        return operands
    def visit_MLIL_ZX(self, expr):
        src = self.visit(expr.src)

        if src is not None:
            return ZeroExt(
                (expr.size - expr.src.size) * 8,
                src
            )
Exemple #7
0
    def add_account(self, bytecode: str, addr: BitVecRef = None) -> BitVecRef:
        # アカウント番号とAccount address生成
        new_num = len(self.accounts)
        new_addr = ZeroExt(96, BitVec('address{}'.format(new_num),
                                      160)) if addr is None else addr
        # Account生成
        account = Account(bytecode, new_num)

        # アドレスとAccountインスタンスの対応をaccountsに保存
        self.accounts[str(new_addr)] = account

        return new_addr
Exemple #8
0
 def add_account(self,
                 bytecode: Bytecode,
                 addr: BitVecRef = None) -> BitVecRef:
     # generate account number and account address
     new_num = len(self.accounts)
     new_addr = ZeroExt(96, BitVec('address{}'.format(new_num),
                                   160)) if addr is None else addr
     # generate Account object
     account = Account(bytecode, new_num)
     # アドレスとAccountインスタンスの対応をaccountsに保存
     self.accounts[str(new_addr)] = account
     return new_addr
    def execute(self, state):
        """
        Execute instruction that this class was initialized with.

        :state: Current active state
        """

        operation = self.instruction.operation.name
        log.log_debug("Evaluating {}: {} @ {}".format(
            operation, self.instruction, hex(self.instruction.address)))

        try:
            if self.instruction.value.is_constant:
                size = self.instruction.size * 8
                return [BitVecVal(self.instruction.value.value, size)]
        except AttributeError:
            pass

        executor = getattr(self, "evaluate_" + operation, None)

        if executor is not None:
            result = executor(state)
        else:
            raise NotImplementedError(repr(operation))

        for i in range(len(result)):
            width = self.instruction.size * 8
            if operation.endswith("_DP"):
                # Double precision
                width = width * 2
            if width < result[i].size():
                result[i] = Extract(width - 1, 0, result[i])
            if width > result[i].size():
                result[i] = ZeroExt(width - result[i].size(), result[i])

        log.log_debug("Completed {}: {} @ {}".format(
            operation, self.instruction, hex(self.instruction.address)))

        return result
Exemple #10
0
 def visit_MLIL_CMP_NE(self, expr):
     left = self.visit(expr.left)
     right = self.visit(expr.right)
     if right.size() != left.size():
         right = ZeroExt(left.size() - right.size(), right)
     return left != right
 def evaluate_MLIL_ZX(self, state):
     # TODO: Confirm size
     [operand] = self.instructions_to_operands(self.instruction.operands,
                                               state, self.instruction.size)
     return [ZeroExt(32, operand)]
Exemple #12
0
def ADDMOD(x, y, m):
	return If(m == 0, 0, Extract(x.size() - 1, 0, URem(ZeroExt(1, x) + ZeroExt(1, y), ZeroExt(1, m))))
Exemple #13
0
def MULMOD(x, y, m):
	return If(m == 0, 0, Extract(x.size() - 1, 0, URem(ZeroExt(x.size(), x) * ZeroExt(x.size(), y), ZeroExt(m.size(), m))))
Exemple #14
0
def to_smt(r):
    # type: (Rtl) -> Tuple[List[ExprRef], Z3VarMap]
    """
    Encode a concrete primitive Rtl r sa z3 query.
    Returns a tuple (query, var_m) where:
        - query is a list of z3 expressions
        - var_m is a map from Vars v with non-BVType to their correspodning z3
          bitvector variable.
    """
    assert r.is_concrete()
    # Should contain only primitives
    primitives = set(PRIMITIVES.instructions)
    assert set(d.expr.inst for d in r.rtl).issubset(primitives)

    q = []  # type: List[ExprRef]
    m = {}  # type: Z3VarMap

    # Build declarations for any bitvector Vars
    var_to_bv = {}  # type: Z3VarMap
    for v in r.vars():
        typ = v.get_typevar().singleton_type()
        if not isinstance(typ, BVType):
            continue

        var_to_bv[v] = BitVec(v.name, typ.bits)

    # Encode each instruction as a equality assertion
    for d in r.rtl:
        inst = d.expr.inst

        exp = None  # type: ExprRef
        # For prim_to_bv/prim_from_bv just update var_m. No assertion needed
        if inst == prim_to_bv:
            assert isinstance(d.expr.args[0], Var)
            m[d.expr.args[0]] = var_to_bv[d.defs[0]]
            continue

        if inst == prim_from_bv:
            assert isinstance(d.expr.args[0], Var)
            m[d.defs[0]] = var_to_bv[d.expr.args[0]]
            continue

        if inst in [bvadd, bvult]:  # Binary instructions
            assert len(d.expr.args) == 2 and len(d.defs) == 1
            lhs = d.expr.args[0]
            rhs = d.expr.args[1]
            df = d.defs[0]
            assert isinstance(lhs, Var) and isinstance(rhs, Var)

            if inst == bvadd:  # Normal binary - output type same as args
                exp = (var_to_bv[lhs] + var_to_bv[rhs])
            else:
                assert inst == bvult
                exp = (var_to_bv[lhs] < var_to_bv[rhs])
                # Comparison binary - need to convert bool to BitVec 1
                exp = If(exp, BitVecVal(1, 1), BitVecVal(0, 1))

            exp = mk_eq(var_to_bv[df], exp)
        elif inst == bvzeroext:
            arg = d.expr.args[0]
            df = d.defs[0]
            assert isinstance(arg, Var)
            fromW = arg.get_typevar().singleton_type().width()
            toW = df.get_typevar().singleton_type().width()

            exp = mk_eq(var_to_bv[df], ZeroExt(toW - fromW, var_to_bv[arg]))
        elif inst == bvsignext:
            arg = d.expr.args[0]
            df = d.defs[0]
            assert isinstance(arg, Var)
            fromW = arg.get_typevar().singleton_type().width()
            toW = df.get_typevar().singleton_type().width()

            exp = mk_eq(var_to_bv[df], SignExt(toW - fromW, var_to_bv[arg]))
        elif inst == bvsplit:
            arg = d.expr.args[0]
            assert isinstance(arg, Var)
            arg_typ = arg.get_typevar().singleton_type()
            width = arg_typ.width()
            assert (width % 2 == 0)

            lo = d.defs[0]
            hi = d.defs[1]

            exp = And(
                mk_eq(var_to_bv[lo], Extract(width // 2 - 1, 0,
                                             var_to_bv[arg])),
                mk_eq(var_to_bv[hi],
                      Extract(width - 1, width // 2, var_to_bv[arg])))
        elif inst == bvconcat:
            assert isinstance(d.expr.args[0], Var) and \
                isinstance(d.expr.args[1], Var)
            lo = d.expr.args[0]
            hi = d.expr.args[1]
            df = d.defs[0]

            # Z3 Concat expects hi bits first, then lo bits
            exp = mk_eq(var_to_bv[df], Concat(var_to_bv[hi], var_to_bv[lo]))
        else:
            assert False, "Unknown primitive instruction {}".format(inst)

        q.append(exp)

    return (q, m)