Ejemplo n.º 1
0
    def advance(self, n, i, first):
        # add all intermediate states for each step
        for x in range(0, n):
            p1 = z3.BitVec("part" + str(self.states), 32)
            p2 = z3.BitVec("part" + str(self.states + 1), 32)
            p3 = z3.BitVec("part" + str(self.states + 2), 32)
            self.solver.add(p1 == self.current ^ (self.current << 13))
            self.solver.add(p2 == p1 ^ z3.LShR(p1, 14))
            self.solver.add(p3 == p2 ^ (p2 << 15))
            self.states += 3
            self.current = p3

        # if this is the "leak" at the beginning, add it directly
        if first > 0:
            self.solver.add((p3 & 0xFFFF) == first)
        # if this isn't, we've stopped on a stable state and should add constraints
        else:
            """
            unsigned char n = (x & (0xFF << i)) >> i;
            if (n != 0 && n == (n & -n)) {
            """
            n = z3.LShR(self.current & (0xFF << i), i)
            self.solver.add(n != 0)
            #self.solver.add(z3.LShR(self.current & (0xFF << i), i) != 0)
            self.solver.add(n == n & -n)
            #self.solver.add(z3.LShR(self.current & (0xFF << i), i) == (z3.LShR(self.current & (0xFF << i), i) & z3.LShR((-self.current) & (0xFF << i), i)))

        # update our guess if we're still SAT
        if self.check() != z3.sat:
            raise RuntimeError("UNSAT")
        else:
            print "NEW GUESS: %d" % self.get_seed()
Ejemplo n.º 2
0
def hamming_d(bv):
    '''
    Based on popcount64b from https://en.wikipedia.org/wiki/Hamming_weight

    Operation:
        Same as hamming_c except eventual we can guarantee that top bits are always
        0 so hamming & (1{k}0{k}) == 0, hence don't bother summing the odds.
        Further if hamming & (1{k}0{k}) == 0 then hamming & (0{k}1{k}) == hamming
        so don't bother masking at all.
    '''
    bsize = bv.size()
    b_point = bsize.bit_length()

    s = 2**((bsize - 1).bit_length())

    max_exp = (s - 1).bit_length()
    mvals = [(2**i, build_grouped_mask(2**i, bsize).value) for i in range(max_exp)]
    x = bv - (z3.LShR(bv, mvals[0][0]) & mvals[0][1])
    x = (x & mvals[1][1]) + (z3.LShR(x, mvals[1][0]) & mvals[1][1])

    for idx,i in enumerate(mvals[2:]):
        x = (x + z3.LShR(x, i[0])) & i[1]
        if i[0] > b_point:
            break

    if len(mvals) >= 3:
        for i in mvals[idx+3:]:
            x += z3.LShR(x, i[0])

    return x & (2**b_point - 1)
Ejemplo n.º 3
0
 def crc32(data, size, prev=0):
     crc = prev ^ 0xFFFFFFFF
     for i in range(0, size, 8):
         crc = crc ^ (z3.LShR(data, i) & 0xFF)
         for _ in range(8):
             crc = If(crc & 1 == BitVecVal(1, size),
                      z3.LShR(crc, 1) ^ polynomial, z3.LShR(crc, 1))
     return crc
Ejemplo n.º 4
0
    def __next__(self):
        s1 = self.state[0]
        s0 = self.state[1]

        self.state[0] = s0
        s1 ^= (s1 << 23)
        self.state[1] = s1 ^ s0 ^ z3.LShR(s1, 17) ^ z3.LShR(s0, 26)

        return self.state[1] + s0
Ejemplo n.º 5
0
def term_to_z3(t, env={}):
    if isinstance(t, (int, long)):
        return z3.BitVecVal(t, 64)
    if t in env:
        return env[t]

    assert isinstance(t, tuple), t
    op = t[0]
    if op == PLUS:
        assert len(t) == 3
        return term_to_z3(t[1], env) + term_to_z3(t[2], env)
    if op == AND:
        assert len(t) == 3
        return term_to_z3(t[1], env) & term_to_z3(t[2], env)
    if op == OR:
        assert len(t) == 3
        return term_to_z3(t[1], env) | term_to_z3(t[2], env)
    if op == XOR:
        assert len(t) == 3
        return term_to_z3(t[1], env) ^ term_to_z3(t[2], env)
    elif op == SHL1:
        assert len(t) == 2
        return term_to_z3(t[1], env) << 1
    elif op == SHR1:
        assert len(t) == 2
        return z3.LShR(term_to_z3(t[1], env), 1)
    elif op == SHR4:
        assert len(t) == 2
        return z3.LShR(term_to_z3(t[1], env), 4)
    elif op == SHR16:
        assert len(t) == 2
        return z3.LShR(term_to_z3(t[1], env), 16)
    elif op == NOT:
        assert len(t) == 2
        return ~term_to_z3(t[1], env)
    elif op == IF0:
        assert len(t) == 4
        return z3.If(
            term_to_z3(t[1], env) == 0, term_to_z3(t[2], env),
            term_to_z3(t[3], env))
        pass
    elif op == FOLD:
        _, bytes, start, fn = t
        _, (formal_y, formal_z), body = fn

        bytes = term_to_z3(bytes, env)
        accum = term_to_z3(start, env)
        new_env = dict(env)
        for i in range(8):
            new_env[formal_y] = \
                z3.Concat(zero56, z3.Extract(8*i+7, 8*i, bytes))
            new_env[formal_z] = accum
            accum = term_to_z3(body, new_env)
        return accum
    else:
        assert False, (op, t)
Ejemplo n.º 6
0
def crc32(input, round_xor, final_xor):
	state = z3.BitVecVal(0xffffffff, 32)

	for i in range(0, 32):
		state = z3.If(
			state & 1 == z3.LShR(input, i) & 1,
			z3.LShR(state, 1),
			z3.LShR(state, 1) ^ round_xor)

	return state ^ final_xor
Ejemplo n.º 7
0
    def Slice(var, start, cnt=1):
        if isinstance(start, z3.BitVecRef):
            zeroext = z3.ZeroExt(var.size() - start.size(), start)
            shifted = z3.LShR(var, zeroext * 8)
            var = shifted
        else:
            shifted = z3.LShR(var, start * 8)
            var = shifted

        if isinstance(cnt, z3.BitVecRef):
            cnt = cnt.as_long()
        return z3.Extract((cnt * 8) - 1, 0, var)
Ejemplo n.º 8
0
def hash2(name):
    h = z3.BitVecVal(0, 16)
    assert len(name) % 2 == 0  # for simplicity
    for i in range(0, len(name), 2):
        a = z3.BitVecVal(0, 16)
        a |= z3.Extract(15, 0, name[i])
        a |= z3.Extract(15, 0, name[i + 1]) << 8
        h ^= a
    a = z3.LShR(h, 10)
    b = z3.ZeroExt(8, z3.Extract(7, 0, h ^ z3.LShR(h, 5)))
    h = (a ^ b) & 0x1f
    return h
Ejemplo n.º 9
0
def z3crc32(bytes,
            hash_table_size):  # computes the crc32 checksum in z3 format
    checksum = 0x00000000ffffffff
    for byte in bytes:
        checksum ^= z3.ZeroExt(56, byte) & 0xff
        for _ in range(8):  # test each bit in the byte we just xor'd in
            checksum = z3.If(
                checksum & 1 == z3.BitVecVal(1, 64),
                z3.LShR(checksum, 1) ^
                0xedb88320,  # the binary representation of the CRC-32 polynomial
                z3.LShR(checksum, 1))
    return (checksum ^ 0xffffffff) % hash_table_size
Ejemplo n.º 10
0
def place_constraints(comps, fab_dims, wire_lengths):
    '''
        place_constraints :: {Component} -> (int, int) -> [int] -> z3.z3.BoolRef
    '''
    nnode = len(comps)

    #build bit mask
    mask, mrows, mcols, mwl = _build_standard_mask(fab_dims, wire_lengths)

    #print bitmask
    #for idx, v in enumerate(mask):
    #    print(v, end='')
    #    if (idx % mcols) == mcols - 1:
    #        print()

    imask = int(~mask)
    mask = int(mask)

    for comp in comps:
        comp.pos = z3.BitVec(comp.name, mrows * mcols)

    constraints = []
    for comp in comps:
        for adj in comp.inputs:
            #should dispatch to fabric to get the rules
            c = []
            for wl in wire_lengths:
                #should probably be comp.pos & (shifted adj.pos) != 0,
                #so that components can have variable size
                c.append(
                    z3.Or(
                        comp.pos == z3.LShR(adj.pos, wl),
                        comp.pos == adj.pos << wl,
                        comp.pos == z3.LShR(adj.pos, wl * mcols),
                        comp.pos == adj.pos << wl * mcols,
                    ))

            constraints.append(z3.Or(c))

        constraints.append(zu.hamming(comp.pos) == __COMP_AREA)
        #The following is insufficient to achieve the previous
        #constraints.append(comp.pos != 0)

        constraints.append(comp.pos & imask == 0)

    u = ft.reduce(lambda x, y: x | y, [c.pos for c in comps])
    constraints.append(zu.hamming(u) == nnode)

    return z3.And(constraints)
Ejemplo n.º 11
0
    def getEq(self):
        #print self.read_operands[1]
        sdir = ""

        src1, src2 = self.getOperands(self.read_operands)
        dst = self.getOperands(self.write_operands)[0]
        n = self.read_operands[1].getValue()

        if n > 0:
            sdir = "left"
        elif n < 0:
            sdir = "right"
            #self.read_operands[1].name = self.read_operands[1].name.replace("-","") #ugly hack!
        else:
            sdir = "null"

        #print self.read_operands[1].name

        #print sdir, src2.as_long()
        if sdir == "right":
            return [(z3.Extract(self.write_operands[0].getSizeInBits() - 1, 0,
                                z3.LShR(src1, -n)) == dst)]
        elif sdir == "left":
            return [(z3.Extract(self.write_operands[0].getSizeInBits() - 1, 0,
                                (src1 << n)) == dst)]
        elif sdir == "null":
            return [(src1 == dst)]
        else:
            assert (False)
Ejemplo n.º 12
0
def md5_compress(M, a=0x67452301, b=0xefcdab89, c=0x98badcfe, d=0x10325476):
    assert len(M) == 16
    neg = lambda n: (n ^ 0xFFFFFFFF) if isinstance(
        n, int) else ~n  # z3 supports ~ properly
    restrict = lambda v: (v & 0xFFFFFFFF) if isinstance(
        v, int) else v  # z3 already restricted
    shr = lambda v, s: (v >> s) if isinstance(v, int) else z3.LShR(v, s)
    rol = lambda v, s: restrict((v << s) | shr(v, 32 - s))
    A, B, C, D = a, b, c, d
    intermediate = []
    for i in range(64):
        if 0 <= i <= 15:
            F = (B & C) | (neg(B) & D)
            g = i
        elif 16 <= i <= 31:
            F = (D & B) | (neg(D) & C)
            g = (5 * i + 1) % 16
        elif 32 <= i <= 47:
            F = B ^ C ^ D
            g = (3 * i + 5) % 16
        elif 48 <= i <= 63:
            F = C ^ (B | neg(D))
            g = (7 * i) % 16
        F = restrict(F + A + K[i] + M[g])
        A = restrict(rol(F, s[i]) + B)
        cvt = lambda v: z3.BitVecVal(v, 32) if isinstance(v, int) else v
        intermediate.append(cvt(A) & hash_mask)
        A, B, C, D = D, A, B, C
    a, b, c, d = restrict(a + A), restrict(b + B), restrict(c +
                                                            C), restrict(d + D)
    return a, b, c, d, intermediate
Ejemplo n.º 13
0
def hash3(name):
    h = z3.BitVecVal(0, 32)
    for i in range(len(name)):
        for j in range(8):
            h = z3.If(z3.LShR(name[i], j) & 1 == 1, (h + 1) & 0xff, h)
        h &= 0x1f
    return h
Ejemplo n.º 14
0
def make_constraints_next(n_constraints: int,
                          slope: int = 0x5DEECE66D,
                          intercept: int = 0xB,
                          gen_bits=31):
    # Define some constants
    addend = z.BitVecVal(intercept, 64)
    multiplier = z.BitVecVal(slope, 64)
    mask = z.BitVecVal((1 << 48) - 1, 64)

    # Define symbolic variables for the seed variable
    seeds = {
        f'seed_{i}': z.BitVec(f'seed_{i}', 64)
        for i in range(n_constraints)
    }

    constraints = []

    # Build constraints for the relation in row 175
    for i in range(1, n_constraints):
        constraints.append(seeds[f'seed_{i}'] == z.simplify(
            (seeds[f'seed_{i - 1}'] * multiplier + addend) & mask))

    # Define symbolic variables for the output from next()
    next_outputs = {
        f'next_output_{i}': z.BitVec(f'output{i}', 32)
        for i in range(1, n_constraints)
    }

    # Build the constraints for the relation in row 176
    for i in range(1, n_constraints):
        constraints.append(next_outputs[f'next_output_{i}'] == z.simplify(
            z.Extract(31, 0, z.LShR(seeds[f'seed_{i}'], 48 - gen_bits))))

    return constraints, seeds, next_outputs
Ejemplo n.º 15
0
    def getEq(self):

        sdir = ""
        if self.read_operands[1].getValue() > 0:
            sdir = "left"
        elif self.read_operands[1].getValue() < 0:
            sdir = "right"
            self.read_operands[1].name = self.read_operands[1].name.replace(
                "-", "")  #ugly hack!
        else:
            sdir = "null"

        #print self.read_operands[1].name
        src1, src2 = self.getOperands(self.read_operands)
        dst = self.getOperands(self.write_operands)[0]

        #print sdir, src2.as_long()
        if sdir == "right":
            return [(z3.Extract(self.write_operands[0].size * 8 - 1, 0,
                                z3.LShR(src1, src2)) == dst)]
        elif sdir == "left":
            return [(z3.Extract(self.write_operands[0].size * 8 - 1, 0,
                                (src1 << src2)) == dst)]
        elif sdir == "null":
            return [(src1 == dst)]
        else:
            assert (False)
Ejemplo n.º 16
0
def untemper(y):
    y0 = z3.BitVec('y0', 32)
    y1 = z3.BitVec('y1', 32)
    y2 = z3.BitVec('y2', 32)
    y3 = z3.BitVec('y3', 32)

    equ = [
        y1 == y0 ^ ((z3.LShR(y0, 11)) & 0xffffffff),
        y2 == y1 ^ ((y1 << 7) & 0x9d2c5680),
        y3 == y2 ^ ((y2 << 15) & 0xefc60000), y == y3 ^ (z3.LShR(y3, 18))
    ]

    solver = z3.Solver()
    solver.add(equ)
    assert solver.check() == z3.z3.CheckSatResult(z3.Z3_L_TRUE)
    return solver.model()[y0].as_long()
Ejemplo n.º 17
0
    def from_ExprOp(self, expr):
        args = map(self.from_expr, expr.args)
        res = args[0]

        if len(args) > 1:
            for arg in args[1:]:
                if expr.op in self.trivial_ops:
                    res = eval("res %s arg" % expr.op)
                elif expr.op == ">>":
                    res = z3.LShR(res, arg)
                elif expr.op == "a>>":
                    res = res >> arg
                elif expr.op == "a<<":
                    res = res << arg
                elif expr.op == "idiv":
                    res = res / arg
                else:
                    raise NotImplementedError("Unsupported OP yet: %s" %
                                              expr.op)
        elif expr.op == 'parity':
            arg = z3.Extract(7, 0, res)
            res = z3.BitVecVal(1, 1)
            for i in xrange(8):
                res = res ^ z3.Extract(i, i, arg)
        elif expr.op == '-':
            res = -res
        else:
            raise NotImplementedError("Unsupported OP yet: %s" % expr.op)

        return res
Ejemplo n.º 18
0
 def getbit(self):
     nextdata = (self.state << 1)
     idx = self.state & self.feedback
     output = 0
     for shift in range(self.feedback.bit_length()):
         output ^= z3.LShR(idx, shift) & 1
     self.state = nextdata ^ output
     return output
Ejemplo n.º 19
0
 def lshr(self, ctx, return_type, a, atype, b, btype, nuw=False, nsw=False):
     assert atype == return_type
     assert atype == btype
     assert not nuw and not nsw
     return util.partial_eval(
         ctx,
         util.If(z3.ULT(b, z3.BitVecVal(btype.size(), btype.size())),
                 z3.LShR(a, b), self.get_poison(btype)))
Ejemplo n.º 20
0
    def from_ExprOp(self, expr):
        args = map(self.from_expr, expr.args)
        res = args[0]

        if len(args) > 1:
            for arg in args[1:]:
                if expr.op in self.trivial_ops:
                    res = eval("res %s arg" % expr.op)
                elif expr.op == ">>":
                    res = z3.LShR(res, arg)
                elif expr.op == "a>>":
                    res = res >> arg
                elif expr.op == "<<<":
                    res = z3.RotateLeft(res, arg)
                elif expr.op == ">>>":
                    res = z3.RotateRight(res, arg)
                elif expr.op == "idiv":
                    res = self._idivC(res, arg)
                elif expr.op == "udiv":
                    res = z3.UDiv(res, arg)
                elif expr.op == "imod":
                    res = res - (arg * (self._idivC(res, arg)))
                elif expr.op == "umod":
                    res = z3.URem(res, arg)
                else:
                    raise NotImplementedError("Unsupported OP yet: %s" %
                                              expr.op)
        elif expr.op == 'parity':
            arg = z3.Extract(7, 0, res)
            res = z3.BitVecVal(1, 1)
            for i in xrange(8):
                res = res ^ z3.Extract(i, i, arg)
        elif expr.op == '-':
            res = -res
        elif expr.op == "cnttrailzeros":
            size = expr.size
            src = res
            res = z3.If(src == 0, size, src)
            for i in xrange(size - 1, -1, -1):
                res = z3.If((src & (1 << i)) != 0, i, res)
        elif expr.op == "cntleadzeros":
            size = expr.size
            src = res
            res = z3.If(src == 0, size, src)
            for i in xrange(size, 0, -1):
                index = -i % size
                out = size - (index + 1)
                res = z3.If((src & (1 << index)) != 0, out, res)
        elif expr.op.startswith("zeroExt"):
            arg, = expr.args
            res = z3.ZeroExt(expr.size - arg.size, self.from_expr(arg))
        elif expr.op.startswith("signExt"):
            arg, = expr.args
            res = z3.SignExt(expr.size - arg.size, self.from_expr(arg))
        else:
            raise NotImplementedError("Unsupported OP yet: %s" % expr.op)

        return res
Ejemplo n.º 21
0
def ast_to_z3_expression(ast: Union[AstNode, AstLeaf], use_bitvecval=False):
    if not Z3_INSTALLED:
        raise D810Z3Exception("Z3 is not installed")
    if isinstance(ast, AstLeaf):
        if ast.is_constant():
            return z3.BitVecVal(ast.value, 32)
        return ast.z3_var
    if ast.opcode == m_neg:
        return -(ast_to_z3_expression(ast.left, use_bitvecval))
    elif ast.opcode == m_lnot:
        return not (ast_to_z3_expression(ast.left, use_bitvecval))
    elif ast.opcode == m_bnot:
        return ~(ast_to_z3_expression(ast.left, use_bitvecval))
    elif ast.opcode == m_add:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) + (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_sub:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) - (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_mul:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) * (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_udiv:
        return z3.UDiv(ast_to_z3_expression(ast.left, use_bitvecval=True),
                       ast_to_z3_expression(ast.right, use_bitvecval=True))
    elif ast.opcode == m_sdiv:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) / (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_umod:
        return z3.URem(ast_to_z3_expression(ast.left, use_bitvecval),
                       ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_smod:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) % (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_or:
        return (ast_to_z3_expression(ast.left,
                                     use_bitvecval)) | (ast_to_z3_expression(
                                         ast.right, use_bitvecval))
    elif ast.opcode == m_and:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) & (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_xor:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) ^ (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_shl:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) << (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_shr:
        return z3.LShR(ast_to_z3_expression(ast.left, use_bitvecval),
                       ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode == m_sar:
        return (ast_to_z3_expression(ast.left, use_bitvecval)) >> (
            ast_to_z3_expression(ast.right, use_bitvecval))
    elif ast.opcode in [m_xdu, m_xds, m_low, m_high]:
        return ast_to_z3_expression(ast.left, use_bitvecval)
    raise D810Z3Exception("Z3 evaluation: Unknown opcode {0} for {1}".format(
        opcode_to_string(ast.opcode), ast))
Ejemplo n.º 22
0
 def LShR(self, other):
     if isinstance(other, int):
         other = BVV(other, self.size)
     else:
         assert isinstance(other, BV)
         assert self.size == other.size
     if isinstance(other, BVV):
         return BVV((self.value >> other.value) & self._mask, self.size)
     return BVExpr(self.size, z3.LShR(self.z3obj, other.z3obj), self.interval.LShR(other.interval))
Ejemplo n.º 23
0
 def LShR(self, other):
     if isinstance(other, int):
         other = BVV(other, self.size)
     else:
         assert isinstance(other, BV)
         assert self.size == other.size
     new_interval = self.interval.LShR(other.interval)
     if new_interval.low == new_interval.high:
         # concrete path
         return BVV(self.size, new_interval.low)
     return BVExpr(self.size, z3.LShR(self.z3obj, other.z3obj), new_interval)
Ejemplo n.º 24
0
    def step(self):
        o = z3.Extract(self.nbits - 1, self.nbits - 1, self.state)
        state_n = self.state << 1
        i = self.state & self.poly
        next_bit = self.zero
        for _ in range(self.nbits):
            next_bit ^= (i & self.one)
            i = z3.LShR(i, 1)
        state_n ^= next_bit
        self.state = state_n

        return o
Ejemplo n.º 25
0
    def from_ExprOp(self, expr):
        args = map(self.from_expr, expr.args)
        res = args[0]

        if len(args) > 1:
            for arg in args[1:]:
                if expr.op in self.trivial_ops:
                    res = eval("res %s arg" % expr.op)
                elif expr.op == ">>":
                    res = z3.LShR(res, arg)
                elif expr.op == "a>>":
                    res = res >> arg
                elif expr.op == "a<<":
                    res = res << arg
                elif expr.op == "<<<":
                    res = z3.RotateLeft(res, arg)
                elif expr.op == ">>>":
                    res = z3.RotateRight(res, arg)
                elif expr.op == "idiv":
                    res = res / arg
                elif expr.op == "udiv":
                    res = z3.UDiv(res, arg)
                elif expr.op == "imod":
                    res = res % arg
                elif expr.op == "umod":
                    res = z3.URem(res, arg)
                else:
                    raise NotImplementedError("Unsupported OP yet: %s" %
                                              expr.op)
        elif expr.op == 'parity':
            arg = z3.Extract(7, 0, res)
            res = z3.BitVecVal(1, 1)
            for i in xrange(8):
                res = res ^ z3.Extract(i, i, arg)
        elif expr.op == '-':
            res = -res
        elif expr.op == "bsf":
            size = expr.size
            src = res
            res = z3.If((src & (1 << (size - 1))) != 0, size - 1, src)
            for i in xrange(size - 2, -1, -1):
                res = z3.If((src & (1 << i)) != 0, i, res)
        elif expr.op == "bsr":
            size = expr.size
            src = res
            res = z3.If((src & 1) != 0, 0, src)
            for i in xrange(size - 1, 0, -1):
                index = -i % size
                res = z3.If((src & (1 << index)) != 0, index, res)
        else:
            raise NotImplementedError("Unsupported OP yet: %s" % expr.op)

        return res
Ejemplo n.º 26
0
def reverse_crc32(target_crc, size, polynom=POLY_CRC32_REV):
    """Find all possible inputs of the given size that produce the given CRC32
    """
    assert -0x80000000 <= target_crc <= 0xffffffff
    target_crc &= 0xffffffff

    # Define the input
    input_data = z3.BitVec("input", size * 8)

    # Compute its CRC32
    current_crc = z3.BitVecVal(0xffffffff, 32)
    for input_pos in range(size):
        # NB: use LShR, not >>
        input_byte = z3.Extract(7, 0, z3.LShR(input_data, 8 * input_pos))
        current_crc ^= z3.ZeroExt(24, input_byte)
        for _ in range(8):
            carry = current_crc & 1
            current_crc = z3.LShR(current_crc, 1)
            current_crc ^= polynom * carry
        current_crc = z3.simplify(current_crc)
    current_crc = current_crc ^ 0xffffffff
    current_crc = z3.simplify(current_crc)

    # Craft a solver
    solver = z3.Solver()
    solver.add(current_crc == target_crc)

    # Enumerate all solutions
    solutions = []
    for model in get_solutions(solver):
        i_found = model[input_data].as_long()
        found = b''.join(
            struct.pack('B', (i_found >> (8 * i)) & 0xff)
            for i in range(size))
        if binascii.crc32(found) & 0xffffffff == target_crc:
            solutions.append(found)
        else:
            print("Warning: false-positive '{}' for CRC target 0x{:08x} (buggy z3)".format(
                hexlify_bksl(found), target_crc))
    return solutions
Ejemplo n.º 27
0
def f_e(a1):
    return (a1 << 56) ^ a1 & 0xFF00000000000000 | z3.LShR(
        (to16(a1) & 0xFF00), 8) ^ to8(a1) | z3.LShR(
            (a1 & 0xFF0000), 8) ^ to16(a1) & 0xFF00 | z3.LShR(
                (to32(a1) & 0xFF000000), 8) ^ a1 & 0xFF0000 | z3.LShR(
                    (a1 & 0xFF00000000), 8) ^ to32(a1) & 0xFF000000 | z3.LShR(
                        (a1 & 0xFF0000000000),
                        8) ^ a1 & 0xFF00000000 | z3.LShR(
                            (a1 & 0xFF000000000000),
                            8) ^ a1 & 0xFF0000000000 | z3.LShR(
                                (a1 & 0xFF00000000000000),
                                8) ^ a1 & 0xFF000000000000
Ejemplo n.º 28
0
 def from_ExprOp(cls, expr):
     args = map(cls.from_expr, expr.args)
     res = args[0]
     for arg in args[1:]:
         if expr.op in cls.trivial_ops:
             res = eval("res %s arg" % expr.op)
         elif expr.op == ">>":
             res = z3.LShR(res, arg)
         elif expr.op == "a>>":
             res = res >> arg
         elif expr.op == "a<<":
             res = res << arg
         else:
             raise NotImplementedError("Unsupported OP yet: %s" % expr.op)
     return res
Ejemplo n.º 29
0
def test_alphanum_guess(verbose=False):
    """Get alphanumetric strings matching a simple password checking algorithm
    from HackingWeek 2015, Reverse 4 challenge
    """
    solver = z3.Solver()
    input_chars = [z3.BitVec("x{}".format(i), 64) for i in range(10)]
    for char_var in input_chars:
        solver.add(z3.Or(
            z3.And(char_var >= 0x30, char_var <= 0x39),
            z3.And(char_var >= 0x41, char_var <= 0x5a),
            z3.And(char_var >= 0x61, char_var <= 0x7a),
        ))

    # Simple algorithm
    value = 0x555555
    for char_var in input_chars:
        value = value ^ char_var
        value = (value << 7) | z3.LShR(value, 25)
    assert value.size() == 64  # Sanity check
    solver.add(value == 0x7fd5c3fe7ffdf7fe)

    # Restrict the result space more
    solver.add(input_chars[0] == ord('P'))
    solver.add(input_chars[1] == input_chars[3])
    solver.add(input_chars[5] == ord('w'))
    solver.add(input_chars[6] == ord('a'))
    solver.add(input_chars[7] == ord('u'))
    solver.add(input_chars[8] == ord('t'))
    solver.add(input_chars[9] == ord('h'))

    # Find all solutions
    for model in get_solutions(solver):
        if not all(32 <= model[c].as_long() < 127 for c in input_chars):
            print("Skipping invalid solution because of buggy z3")
            continue
        found = ''.join(chr(model[c].as_long()) for c in input_chars)
        if verbose:
            print("Candidate {}".format(repr(found)))
        hexmd5 = hashlib.md5(found.encode('ascii')).hexdigest()
        if hexmd5 == '3efafa3e161a756e6e1711dbceaf9d68':
            print("Found password for simple algorithm: {}.".format(repr(found)))
            return
Ejemplo n.º 30
0
def hamming_c(bv):
    '''
    Based on popcount64a from https://en.wikipedia.org/wiki/Hamming_weight

    Operation:
        Basic idea is take the sum of the even and odd bits,
        hamming = (bv & (01)*) + ((bv & (10)*) >> 1)
        We now have hamming weight of each bit pair,
        next take the sum of the even and odd pairs
        hamming = (hamming & (0011)*) + ((hamming & (1100)*) >> 2)
        we now have the weight of each group of 4
    '''

    #Next power of 2 bits
    bsize = bv.size()
    s = 2**((bsize - 1).bit_length())

    max_exp = (s - 1).bit_length()
    mvals = [(2**i, build_grouped_mask(2**i, bsize).value) for i in range(max_exp)]
    return ft.reduce(lambda x, m: (x & m[1]) + (z3.LShR(x, m[0]) & m[1]), mvals, bv)