def compute_logical(vec, X, Y, ctx, use_esf): nbits = X.nbits e = imm(1) for i in range(nbits): e *= X.eval(vec, i, use_esf) + Y.eval(vec, i, use_esf) + imm(1) simplify_inplace(e) return e
def test_mba(self): # x^y = (x+y) - ((x&y)<<1) e = TAst.bvsub( TAst.bvadd(self.x8_t, self.y8_t), TAst.bvshl(TAst.bvand(self.x8_t, self.y8_t), TAst.bv(1, 8))) ea = tritonast2arybo(e, use_exprs=False, use_esf=True) simplify_inplace(expand_esf_inplace(ea)) self.assertEqual(ea, self.x8 ^ self.y8)
def find_esfs_degree(e, d): esfs = [] while True: esf, anf_esf = find_one_esf(e, d) if esf is None: break e += anf_esf simplify_inplace(e) esfs.append(esf) return esfs
def compute(self, vec, i, args, ctx, use_esf): if ((self.mask >> i) & 1) == 1: return imm(1) args = list(args) ret = esf(1, args) for i in range(2, len(args) + 1): ret += esf(i, args) if not use_esf: expand_esf_inplace(ret) simplify_inplace(ret) return ret
def compute_binop_(vec, i, X, Y, CC, use_esf): carry = CC.carry sum_args = simplify_inplace(X + Y) ret = simplify_inplace(sum_args + carry) carry = esf(2, [X + imm(1), Y, carry]) if not use_esf: expand_esf_inplace(carry) carry = simplify_inplace(carry) CC.carry = carry return ret
def compute_binop_(vec, i, X, Y, CC, use_esf): carry = CC.carry sum_args = simplify_inplace(X + Y) ret = simplify_inplace(sum_args + carry) # TODO: optimize this like in mba_if carry = esf(2, [X, Y, carry]) if not use_esf: expand_esf_inplace(carry) simplify_inplace(carry) CC.carry = carry return ret
def L(K): state = K for i in range(8): v = mba64.from_cst(0) for k in range(8): for j in range(8): v ^= mba64.from_vec( mba64.from_cst(A[k * 8 + j]).vec * state[i * 8 + k].vec[7 - j]) simplify_inplace(v) for k in range(8): for b in range(8): state[i * 8 + k].vec[b] = simplify_inplace(v[(7 - k) * 8 + b]) return state
def astEquals(self, ast, v): if self.use_expr: e = tritonast2arybo(ast, use_exprs=True, use_esf=False) e = eval_expr(e, use_esf=False) v = expand_esf_inplace(v) v = simplify_inplace(v) else: e = tritonast2arybo(ast, use_exprs=False, use_esf=True) self.assertEqual(e, v)
def app_inverse(A): M = A.matrix() NL = A.nl() V = A.cst() Minv = M.inverse() if Minv.ncols() == 0: return None N = V.size() mba = MBA(N) Y = mba.var('Y') G0 = Minv * Y.vec + Minv * V G1nl = simplify_inplace(Minv * NL(Y.vec)) # Check if G1 is inversible through a dependency graph DG = nx.DiGraph() idx_base = Y[0].sym_idx() for i, e in enumerate(G1nl): for d in get_depends_as_set(e): DG.add_edge(Y[i].sym_idx() - idx_base, d.sym_idx() - idx_base) if not nx.is_directed_acyclic_graph(DG): return None # Use the graph to get the inverse of G1 X = mba.var('X') resolve_order = nx.topological_sort(DG, reverse=True) solved = dict() for i in resolve_order: e = G1nl[i] if e.is_imm() and e.imm_value() == 0: solved[i] = X[i] else: # Doing this in the reversed topological order should make this always work! solved[i] = simplify_inplace(X[i] + simplify_inplace( subs_exprs(G1nl[i], [Y[j] for j in six.iterkeys(solved)], list(six.itervalues(solved))))) G1inv = Vector(N) for i in range(N): G1inv[i] = solved.get(i, X[i]) G1inv = MBAVariable(mba, G1inv) Finv = G1inv.eval({X: G0}) Finv = MBAVariable(mba, Finv) return Finv.vectorial_decomp([Y])
def compute_arybo(Z): C = mba.from_cst(0xFFFFFFFF) A = 0 for N in range(0, 4): C_ = (C >> (A * 8)) & 0xFF Z_ = (Z >> (N * 8)) & 0xFF t = Z_ ^ C_ T_ = mba.from_vec(simplify(S(t.vec))) B = C >> 8 C = B ^ T_ C = (~C) return simplify_inplace(C)
def find_one_esf(e, d): h = SymbolsHist() h.compute(e, d) #for v in h: print(v) # "Invert" the histogram hinv = collections.defaultdict(list) max_count = 0 for v in h: c = v.count() hinv[c].append(v.sym()) if max_count < c: max_count = c #print(hinv) # Compute the maximum number of arguments for this degree nterms = 0 for a in e.args(): if a.is_mul() and a.args().size() == d: nterms += 1 max_args = solve_binomial(d, nterms) #print("max_args: %d" % max_args) # Compute the exact counts we will search from counts_args = filter(lambda v: v[0] <= max_count, ((int(binom(A - 1, d - 1)), A) for A in reversed(range(d + 1, max_args + 1)))) for ca in counts_args: c, nargs = ca #print(d,c) cur_args = [] for i in range(c, max_count + 1): cur_args += hinv.get(i, []) if len(cur_args) < nargs: continue for A in reversed(range(nargs, max_args + 1)): #print(d, "test %d args among %d (%d)" % (A, len(cur_args), binom(len(cur_args),A))) # TODO: optimize this for args in itertools.combinations(cur_args, A): args = sorted(args) test_esf = esf(d, list(args)) anf_esf = simplify_inplace(expand_esf(test_esf)) if e.contains(anf_esf): #print("[+] found", test_esf) return test_esf, anf_esf return None, None
def simp_inplace(L): for o in L: simplify_inplace(o) return L
def xor512(A, B): return [simplify_inplace(A[i] ^ B[i]) for i in range(64)]
def S(K): return [mba8.from_vec(simplify_inplace(sbox(K[i].vec))) for i in range(64)]
def step(b): new = S((b[10] ^ b[12] ^ b[13] ^ b[15]).vec) new = mba8.from_vec(simplify_inplace(new)) return [new] + b[:15]
def eval(self, vec, i, use_esf): return simplify_inplace( self.e.eval(vec, i, self.ctx, self.args, use_esf))
def compute_logical(vec, X, Y, ctx, use_esf): return simplify_inplace( ExprCmpEq.compute_logical(vec, X, Y, ctx, use_esf) + imm(1))