if __name__=="__main__": l = lfsr(KEY,MASK,LENGTH) r = '' for i in range(63): b = 0 for j in range(8): b = (b<<1)+l.next() r += pad(bin(b)[2:]) with open('output','w') as f: f.write(r)
# In[90]: F2 = GF(2) X = [] S = [] LENGTH = 256 for i in range(len(cipher) - LENGTH): X.append(cipher[i : i + LENGTH]) S.append(cipher[i + LENGTH]) X = Matrix(F2, X) S = Matrix(F2, S)
# In[91]: X, S # Out[91]: (248 x 256 dense matrix over Finite Field of size 2, 1 x 248 dense matrix over Finite Field of size 2)
# In[94]: MASK = [] for suf in suffix: X_n = X c = cipher + list(suf) for i in range(len(cipher) - LENGTH, len(cipher) - LENGTH + 8): v = vector(F2, c[i : i + LENGTH]) X_n = X_n.stack(v) S_n = Matrix(F2, list(S[0]) + c[-8:]).T try: msk = X_n.solve_right(S_n) MASK.append(msk.T) except: pass
# In[95]: defdecrypt(cipher, feedback): assert(len(cipher) == LENGTH) cur = cipher key = '' for i in range(LENGTH): right = [cur[j] for j in feedback[1:]] left = right.count(1) % 2 key = str(left) + key cur = [left] + cur[:-1] key = int(key, 2) return key
# In[96]: KEY = [] for msk in MASK: feedback = [] fb = list(msk[0]) for i in range(LENGTH): if fb[i] == 1: feedback.append(i) feedback.append(LENGTH) delta = feedback[0] + 1 feedback = [_ - delta for _ in feedback] KEY.append(decrypt(cipher[:LENGTH], feedback))
# In[97]: import hashlib
# In[98]: for k in KEY: flag = hashlib.sha256(hex(k)[2:].encode()).hexdigest() if flag[:4] == "1224": print("de1ctf{" + flag + "}") break # de1ctf{1224473d5e349dbf2946353444d727d8fa91da3275ed3ac0dedeb7e6a9ad8619}
#!/usr/bin/env sage import re, itertools from pwn import * from sys import argv from functools import reduce from Crypto.Util.number import *
#context.log_level = 'debug'
io = remote(argv[1], argv[2])
defcrack_LCG(): io.sendlineafter("Your choice:\n", "2") data = [] for i in range(6): io.recvuntil(":") data.append(int(io.recvline().strip())) delta = [d1 - d0 for (d0, d1) in zip(data, data[1:])] m_mul = [d0 * d2 - d1 * d1 for (d0, d1, d2) in zip(delta, delta[1:], delta[2:])] m = reduce(GCD, m_mul) factors = factor(m) if len(factors) > 1: for (prime, degree) in factors: if size(prime) == 64: m = prime break m //= (prime**degree) s0, s1, s2 = data[0], data[1], data[2] A = Matrix([ [s0 ,s1 ,1/m ,0 ,0 ], [1 ,1 ,0 ,1/m ,0 ], [-s1 ,-s2 ,0 ,0 ,1 ], [m ,0 ,0 ,0 ,0 ], [0 ,m ,0 ,0 ,0 ] ]) A = A.LLL() a, b = None, None for l in A: if l[0] == 0and l[1] == 0: if l[-1] == 1: a, b = l[2] * m, l[3] * m elif l[-1] == -1: a, b = -l[2] * m, -l[3] * m else: continue ifnot a ornot b: print("[!] crack_LCG failed.") returnFalse a %= m b %= m res = (a * data[-1] + b) % m io.sendlineafter("Input the level code:\n", str(res)) returnTrue
defget_LFSR(): io.sendlineafter("Your choice:\n", "1") cipher = "" for i in range(9): io.sendlineafter("Input your answer:\n", "2333") ct = int(re.findall(r"\d+", io.recvline().decode("utf-8"))[0]) cipher += bin(ct)[2:].rjust(8, "0") cipher = [int(i) for i in cipher] assert(len(cipher) == 72) return cipher
defcrack_LFSR(cipher): F2 = GF(2) X, S = [], [] LENGTH = 39 for i in range(len(cipher) - LENGTH): X.append(cipher[i : i + LENGTH]) S.append(cipher[i + LENGTH]) X, S = Matrix(F2, X), Matrix(F2, S) suffix = list(itertools.product(range(2), repeat=6)) MASK = [] for suf in suffix: X_n = X c = cipher + list(suf) for i in range(len(cipher) - LENGTH, len(cipher) - LENGTH + 6): v = vector(F2, c[i : i + LENGTH]) X_n = X_n.stack(v) S_n = Matrix(F2, list(S[0]) + c[-6:]).T try: msk = X_n.solve_right(S_n) MASK.append(msk.T) except: pass return MASK
defpredict_LFSR(ct, msk): F2 = GF(2) nxt = 0 for i in range(8): x = F2(0) for j in range(39): x += ct[j] * msk[j] ct = ct[1:] + [int(x)] nxt += (int(x) << (7 - i)) io.sendlineafter("Input your answer:\n", str(nxt)) if"Right!"in io.recvline().decode("utf-8"): return ct else: print("[!] predict_LFSR failed.") returnNone
defmain(): if crack_LCG(): print("[+] crack_LCG success.") else: returnFalse cipher = get_LFSR() MASK = crack_LFSR(cipher) if len(MASK): print("[+] {} masks have been found.".format(len(MASK))) else: print("[!] crack_LFSR failed.") returnFalse ct = cipher[-39:] msk = list(MASK[randrange(0, len(MASK))][0]) #msk = list(MASK[0][0]) ct = predict_LFSR(ct, msk) ifnot ct: returnFalse else: for i in range(498): ct = predict_LFSR(ct, msk) returnTrue
n = 15518961041625074876182404585394098781487141059285455927024321276783831122168745076359780343078011216480587575072479784829258678691739 M = 0x924cba6ae99dfa084537facc54948df0c23da044d8cabe0edd75bc6
defprime_power_factor(n): div = [] for (p, r) in factor(n): if r == 1: div.append(p) else: div = div + [p**i for i in range(1, r + 1)] return div[::-1]
# divided by divisor(p) such that ord_p(65537)\nmid order defsub_Gen_M_smaller(M, order): M_factor = [_[0] for _ in M.factor()] for p in M_factor: p_order = Zmod(p)(65537).multiplicative_order() if order % p_order != 0: M //= p return M, Zmod(M)(65537).multiplicative_order()
# Get M' smaller than M defGen_M_smaller(M, bound): candidates = [(M, Zmod(M)(65537).multiplicative_order())] whileTrue: M_smaller, order = candidates[-1][0], candidates[-1][1] order_factor = prime_power_factor(order) candidates = [] for p in order_factor: new_M, new_order = sub_Gen_M_smaller(M_smaller, order // p) param = (log(order, 2) - log(new_order, 2)) / (log(M_smaller, 2) - log(new_M, 2)) # 衡量阶下降速度的参数 candidates.append((new_M, new_order, param)) candidates = sorted(candidates, key=lambda x:x[2]) if size(candidates[-1][0]) < bound: break return M_smaller, order
defcoppersmith_univariate(f, n, beta, mm, tt, XX): assert(f.is_monic() and0 < beta <= 1) #epsilon = beta / 7 dd = f.degree() # degree of polynomial #mm = ceil(beta**2 / (dd * epsilon)) # optimized param #tt = floor(dd * mm * (1 / beta - 1)) # optimized param #XX = ceil(n**(beta**2 / dd - epsilon)) # |x| < XX nn = mm * dd + tt # change ring of f and x to ZZ fZ = f.change_ring(ZZ) x = fZ.parent().gen() # instruct matrix A_list = [] for i in range(mm): for j in range(dd): A_list.append((XX * x)**j * n**(mm - i) * fZ(XX * x)**i) A_list += [(XX * x)**i * fZ(XX * x)**mm for i in range(tt)] A = Matrix(ZZ, nn) for i in range(nn): for j in range(i + 1): A[i, j] = A_list[i][j] # LLL to solve SVP AL = A.LLL(early_red=True, use_siegel=True) f_smaller = 0 for i in range(nn): f_smaller += (AL[0, i] * x**i) / (XX**i) candidates = f_smaller.roots() roots = [] for root, _ in candidates: if root.is_integer(): res = fZ(ZZ(root)) if gcd(res, n) >= n**beta: # module's size satisfies roots.append(ZZ(root)) return roots
M_smaller, order = Gen_M_smaller(M, 512 // 4) c = discrete_log(Mod(n, M_smaller), Mod(65537, M_smaller))
PR.<k> = PolynomialRing(Zmod(n), implementation='NTL') beta = 0.48 mm = 5 tt = 6 XX = int((2 * n**beta) / M_smaller) #XX = ceil(n**(beta**2 - beta/7)) for a in tqdm(range(c // 2, (c + order) // 2)): f = k * M_smaller + Integer(pow(65537, a, M_smaller)) roots = coppersmith_univariate(f.monic(), n, beta, mm, tt, XX) if len(roots): print(roots[0]) print(gcd(roots[0] * M_smaller + Integer(pow(65537, a, M_smaller)), n)) break ''' 0%| | 5/600600 [00:00<17:58:28, 9.28it/s] 1426982562847111986146541 3386619977051114637303328519173627165817832179845212640767197001941 '''
from hashlib import md5 from base64 import b64decode from Crypto.Cipher import AES from Crypto.Util.number import *
r = 6753785483255906709117615805253027649453460653974415214642466102672301763943358839905575042938258141827000621474498066533397472809407687579125519939754658 ps = [] with open("ps", "r") as f: for line in f: ps.append(int(line[:-1])) ps_dict = dict() # ps_dict[i]'s suffix satisfies '1' + i * '0' for p in ps: for i in range(512): if ((2**i) & p) != 0: ps_dict[i] = p break
choose = [0] * 512 for i in range(512): if ((2**i) & r) != 0: r ^= ps_dict[i] choose[ps.index(ps_dict[i])] = 1 choose = int(''.join(str(_) for _ in choose), 2)