bit_iter = iter(unknown_bits) decoded_unknown_chars = [] used = 0 for p_ch, c_ch inzip(plain_unknown, cipher_unknown): if should_consume(p_ch): try: b = next(bit_iter) except StopIteration: raise SystemExit("ran out of bits while decoding unknown region") used += 1 if b == "1": decoded_unknown_chars.append(chr(ord(c_ch) - STEP)) else: decoded_unknown_chars.append(c_ch) else: decoded_unknown_chars.append(c_ch)
if __name__ == "__main__": flag = open("flag.txt", "rb").read().strip() assert flag.startswith(b"LilacCTF{") and flag.endswith(b"}") flag = flag[9:-1] exps = get_exps(flag, 384) p = getPrime(384) R = PolynomialRing(Zmod(p**3), names="x,y") x, y = R.gens() I = R.ideal([x**3 + y**5 + 13 * x * y - 37, y**3 + x**5 + 37 * x - 13]) # noqa: E741 S = R.quotient(I, names=("x,y")) g = S(x**2 + y**2 + 13 * x + 37 * y + 1337) print(p) for e in exps: print(g**e)
for b in basis: prod_poly = g_poly * b reduced_poly = quotient_ring(prod_poly).lift() coeffs = [reduced_poly.monomial_coefficient(mon) for mon in basis] matrix_cols.append(coeffs)
M = matrix(base_ring, matrix_cols).transpose() return M
import gmpy2 from Crypto.Util.number import isPrime, bytes_to_long from sympy.ntheory import sqrt_mod from sympy.ntheory.modular import crt from secret import p, q, r, pp import os
assert p == pp**2 + 3 * pp + 3and q == pp**2 + 5 * pp + 7 assert isPrime(p) and isPrime(q) and isPrime(r)
m = bytes_to_long(os.getenv("FLAG", "LilacCTF{fake_flag}").encode().strip()) n = p * q * r e = 65537 c = pow(m, e, n)
print(f"{n = }") print(f"{c = }")
whileTrue: x = int(input("🧭 > ")) _, is_psq = gmpy2.iroot(x, 2) assertnot is_psq, "👿" assert80 < x < 100 print(oracle(x))
''' n = 320463398964822335046388577512598439169912412662663009494347432623554394203670803089065987779128504277420596228400774827331351610218400792101575854579340551173392220602541203502751384517150046009415263351743602382113258267162420601780488075168957353780597674878144369327869964465070900596283281886408183175554478081038993938477659926361457163384937565266894839330377063520304463379213493662243218514993889537829099698656597997161855278297938355255410088350528543369288722795261835727770017939399082258134647208444374973242138569356754462210049877096486232693547694891534331539434254781094641373606991238019101335437 c = 80140760654462267017719473677495407945806989083076205994692983838456863987736401342704400427420046369099889997909749061368480651101102957366243793278412775082041015336890704820532767466703387606369163429880159007880606865852075573350086563934479736264492605192640115037085361523151744341819385022516548746015224651520456608321954049996777342018093920514055242719341522462068436565236490888149658105227332969276825894486219704822623333003530407496629970767624179771340249861283624439879882322915841180645525481839850978628245753026288794265196088121281665948230166544293876326256961232824906231788653397049122767633 x = 96 res = 34484956620179866074070847926139804359063142072294116788718557980902699327115656987124274229028140189100320603969008330866286764246306228523522742687628880235600852992498136916120692433600681811756379032521946702982740835213837602607673998432757011503342362501420917079002053526006602493983327263888542981905944223306284758287900181549380023600320809126518577943982963226746085664799480543700126384554756984361274849594593385089122492057335848048936127343198814676002820177792439241938851191156589839212021554296197426022622140915752674220260151964958964867477793087927995204920387657229909976501960074230485827919 '''
from Crypto.Util.number import long_to_bytes, inverse import math
# 题目数据 n = 320463398964822335046388577512598439169912412662663009494347432623554394203670803089065987779128504277420596228400774827331351610218400792101575854579340551173392220602541203502751384517150046009415263351743602382113258267162420601780488075168957353780597674878144369327869964465070900596283281886408183175554478081038993938477659926361457163384937565266894839330377063520304463379213493662243218514993889537829099698656597997161855278297938355255410088350528543369288722795261835727770017939399082258134647208444374973242138569356754462210049877096486232693547694891534331539434254781094641373606991238019101335437 res = 34484956620179866074070847926139804359063142072294116788718557980902699327115656987124274229028140189100320603969008330866286764246306228523522742687628880235600852992498136916120692433600681811756379032521946702982740835213837602607673998432757011503342362501420917079002053526006602493983327263888542981905944223306284758287900181549380023600320809126518577943982963226746085664799480543700126384554756984361274849594593385089122492057335848048936127343198814676002820177792439241938851191156589839212021554296197426022622140915752674220260151964958964867477793087927995204920387657229909976501960074230485827919 c = 80140760654462267017719473677495407945806989083076205994692983838456863987736401342704400427420046369099889997909749061368480651101102957366243793278412775082041015336890704820532767466703387606369163429880159007880606865852075573350086563934479736264492605192640115037085361523151744341819385022516548746015224651520456608321954049996777342018093920514055242719341522462068436565236490888149658105227332969276825894486219704822623333003530407496629970767624179771340249861283624439879882322915841180645525481839850978628245753026288794265196088121281665948230166544293876326256961232824906231788653397049122767633 e = 65537
# 1. 手动实现ECM defadd(P, Q, n): if P isNone: return Q if Q isNone: return P x1, y1 = P x2, y2 = Q # 结果为无穷远点 if x1 == x2 and (y1 + y2) % n == 0: returnNone # 计算斜率的分子和分母 if x1 == x2: num, den = (3 * x1 * x1) % n, (2 * y1) % n else: num, den = (y2 - y1) % n, (x2 - x1) % n # 【核心】检查分母是否暴露了因子 g = math.gcd(den, n) if1 < g < n: raise ValueError(g) # 抛出因子 # 正常加法逻辑 m = (num * pow(den, -1, n)) % n x3 = (m * m - x1 - x2) % n y3 = (m * (x1 - x3) - y1) % n return (x3, y3)
defmul(P, k, n): res, base = None, P while k: if k & 1: res = add(res, base, n) base = add(base, base, n) k >>= 1 return res
# 2. 执行攻击 print("[*] Starting ECM - CM Attack...") G = (4, res) try: mul(G, n, n) except ValueError as e_val: fact = e_val.args[0] print(f"[+] Caught factor: {fact}") # 3. 恢复参数 pp, p, q, r # 我们知道 4p - 3 = (2pp+3)^2 或 4q - 3 = (2pp+5)^2 # 这里的 fact 可能是 p, q, 或 pq defrecover_all(f): for candidate in [f, n // f]: # 尝试解 4x - 3 = S^2 S2 = 4 * candidate - 3 S = math.isqrt(S2) if S * S == S2: # 进一步判断是 p 还是 q (对应常数项 3 或 5) for c_val in [3, 5]: if (S - c_val) % 2 == 0: pp = (S - c_val) // 2 p = pp**2 + 3*pp + 3 q = pp**2 + 5*pp + 7 r = n // (p * q) return p, q, r returnNone
params = recover_all(fact) if params: p, q, r = params print(f"[+] Recovered: p={p}, q={q}, r={r}") # 4. 解密 phi = (p - 1) * (q - 1) * (r - 1) d = inverse(e, phi) flag = long_to_bytes(pow(c, d, n)) print(f"\n[!] FLAG: {flag.decode()}") else: print("[-] Parameter recovery failed.")
uint64_tinverse(uint64_t a, uint64_t m){ int64_t t = 0, newt = 1; int64_t r = m, newr = a; while (newr != 0) { int64_t quotient = r / newr; t = t - quotient * newt; swap(t, newt); r = r - quotient * newr; swap(r, newr); } if (t < 0) t += m; return (uint64_t)t; }
while (context.get_context_data(ct.parms_id())->next_context_data()) { evaluator.mod_switch_to_next_inplace(ct); }
auto context_low = context.get_context_data(ct.parms_id()); auto context_high = context.get_context_data(context.first_parms_id()); auto &mod_high = context_high->parms().coeff_modulus(); int q_low = context_low->parms().coeff_modulus().back().value();