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()
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)
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
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
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)
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
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)
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
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
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)
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)
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
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
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
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)
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()
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
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
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)))
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
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))
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))
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)
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
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
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
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
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
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
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)