from random import randint, choice, shuffle from Crypto.Util.number import * from Crypto.Cipher import AES from hashlib import md5 from secret import flag
p = getPrime(round(20.25)) a, b, d = randint(0, p), randint(0, p), 14 A, B, seed, secret = [], [], [randint(0, p) for _ inrange(4)], [randint(0, p) for _ inrange(d)]
PR.<x> = PolynomialRing(GF(p)) PRq = PR.quo(PR(list(b"DASCTF_XHLJ2025"))) for i inrange(ord("🚩") % sum(list(map(ord, "flag")))): #351 A += [PRq.random_element().list()] B += [(PRq(A[i]) * PRq(secret) + PRq([choice(seed) for _ inrange(d)])).list()] seed = [(a * _ + b) % p for _ in seed]
a=[var(f"a{i}")for i inrange(14)] s=[var(f"s{i}")for i inrange(14)] e=[var(f"e{i}")for i inrange(14)] y=var("y") z=sum([a[i]*s[i]for i inrange(14)]) f=(z-y-e[0])*(z-y-e[1])*(z-y-e[2])*(z-y-e[3]) f=f.expand() print(f.coefficient(s0)(s1=0,s2=0,s3=0,s4=0,s5=0,s6=0,s7=0,s8=0,s9=0,s10=0,s11=0,s12=0,s13=0,e0=0,e1=0,e2=0,e3=0)) #-4*a0*y^3
PR.<x>=PolynomialRing(GF(p)) R.<x> = PR.quo(PR(list(b"DASCTF_XHLJ2025"))) abars=[var(f"abar{i}")for i inrange(15)] sbars=[var(f"sbar{i}")for i inrange(15)] ebars=[var(f"ebar{i}")for i inrange(4)] ybar=var("ybar") kbar=var("kbar") ALLZEROS=dict(zip(abars+sbars+ebars+[ybar,kbar],[0]*(15+15+4+2))) zas=sum([abars[i]*sbars[i]for i inrange(15)]) f=(zas-ybar-kbar*ebars[0])*(zas-ybar-kbar*ebars[1])*(zas-ybar-kbar*ebars[2])*(zas-ybar-kbar*ebars[3]) f=f.expand() from tqdm import * Ams=[R(A[i]).matrix().change_ring(ZZ).T for i inrange((351))] M=[] negy4=[] for T inrange(1): a14=Integer(GF(p)((1-K**T)/(1-K))) for i in trange(14): lineA=list(Ams[][i])+[a14] bi=B[T][i] negy4.append((-bi**4)%p) linevec=[] coeffs=lineA+[bi]+[Integer(pow(K,T,p))] coeffDict=dict(zip(abars+[ybar,kbar],coeffs)) fi=(f(coeffDict)) for j inrange(15): linevec.append(int(fi.coefficient(sbars[j])(ALLZEROS))%p) for j inrange(15): linevec.append(int(fi.coefficient(sbars[j]**2)(ALLZEROS))%p) for j inrange(15): linevec.append(int(fi.coefficient(sbars[j]**3)(ALLZEROS))%p) for j inrange(15): linevec.append(int(fi.coefficient(sbars[j]**4)(ALLZEROS))%p) #double symbol for j1 inrange(15): for j2 inrange(j1+1,15): linevec.append(int(fi.coefficient(sbars[j1]*sbars[j2])(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]**2*sbars[j2])(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]*sbars[j2]**2)(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]**2*sbars[j2]**2)(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]**3*sbars[j2])(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]*sbars[j2]**3)(ALLZEROS))%p) for j1 inrange(15): for j2 inrange(j1+1,15): for j3 inrange(j2+1,15): linevec.append(int(fi.coefficient(sbars[j1]*sbars[j2]*sbars[j3])(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]**2*sbars[j2]*sbars[j3])(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]*sbars[j2]**2*sbars[j3])(ALLZEROS))%p) linevec.append(int(fi.coefficient(sbars[j1]*sbars[j2]*sbars[j3]**2)(ALLZEROS))%p) for j1 inrange(15): for j2 inrange(j1+1,15): for j3 inrange(j2+1,15): for j4 inrange(j3+1,15): linevec.append(int(fi.coefficient(sbars[j1]*sbars[j2]*sbars[j3]*sbars[j4])(ALLZEROS))%p) for j1 inrange(15): linevec.append(4*int(fi.coefficient(sbars[j1]*ebars[0])(ALLZEROS))%p) linevec.append(6*int(fi.coefficient(sbars[j1]*ebars[0]*ebars[1])(ALLZEROS))%p) linevec.append(4*int(fi.coefficient(sbars[j1]*ebars[0]*ebars[1]*ebars[2])(ALLZEROS))%p) linevec.append(4*int(fi.coefficient(sbars[j1]**2*ebars[0])(ALLZEROS))%p) linevec.append(6*int(fi.coefficient(sbars[j1]**2*ebars[0]*ebars[1])(ALLZEROS))%p) linevec.append(4*int(fi.coefficient(sbars[j1]**3*ebars[0])(ALLZEROS))%p) for j1 inrange(15): for j2 inrange(j1+1,15): linevec.append(4*int(fi.coefficient(sbars[j1]*sbars[j2]*ebars[0])(ALLZEROS))%p) linevec.append(6*int(fi.coefficient(sbars[j1]*sbars[j2]*ebars[0]*ebars[1])(ALLZEROS))%p) linevec.append(4*int(fi.coefficient(sbars[j1]**2*sbars[j2]*ebars[0])(ALLZEROS))%p) linevec.append(4*int(fi.coefficient(sbars[j1]*sbars[j2]**2*ebars[0])(ALLZEROS))%p) for j1 inrange(15): for j2 inrange(j1+1,15): for j3 inrange(j2+1,15): linevec.append(4*int(fi.coefficient(sbars[j1]*sbars[j2]*sbars[j3]*ebars[0])(ALLZEROS))%p) linevec.append(4*int(fi.coefficient(ebars[0])(ALLZEROS))%p) linevec.append(6*int(fi.coefficient(ebars[0]*ebars[1])(ALLZEROS))%p) linevec.append(4*int(fi.coefficient(ebars[0]*ebars[1]*ebars[2])(ALLZEROS))%p) linevec.append(1*int(fi.coefficient(ebars[0]*ebars[1]*ebars[2]*ebars[3])(ALLZEROS))%p)
#sage A=[442656,[...]] B=['b',[...]] C='355799be839f2aece47ac7c125c026e86c5956a75b073aa29e645d6731b4336d998576cfe56f6ef0bfb33db5154b' K,_=A.pop(0),B.pop(0) n,m=len(A[0]),len(A) p=next_prime(max([max(A[i]) for i inrange (len(A))])) for i inrange(3): p=next_prime(p) PR.<x>=PolynomialRing(Zmod(p)) R.<x> = PR.quo(PR(list(b"DASCTF_XHLJ2025"))) TRR=PolynomialRing(Zmod(p),names=[f"sbar{i}"for i inrange(15)]+["ebar"]) *sbars,ebar=TRR.gens() vsbars=vector(sbars) vecs13=vector(sbars[:-1]) listPoly=((sum(sbars)-ebar-1)**4) monomialArr=listPoly.monomials() # print(monomialArr) MAarr=[R(Ax).matrix() for Ax in A] vecs=vector(sbars[:14]) M=[] y=[] from tqdm import * fs4arr=[] for T in trange(351): AT=MAarr[T].change_ring(ZZ) vecsT=vecs*AT for i inrange(14): linevec=[] fs=vecsT[i] fs+=sum([K**j for j inrange(T)]) * sbars[14]+ K**T * ebar - B[T][i] fs4 = (fs**4) fs4arr.append(fs4) print(len(fs4arr)) M=[] y=[] for i inrange(len(fs4arr)): coeff=fs4arr[i].coefficients() if(len(coeff)==4845): M.append(coeff[:-1]) y.append(-coeff[-1]) M=matrix(GF(p),M) y=vector(GF(p),y) s=M.solve_right(y) *secret,b,_=s[-16:] err=R(B[-1])-R(A[-1])*R(secret) seterr=set([K*i+b for i inlist(err)]) from itertools import * from Crypto.Cipher import AES from hashlib import md5 for seed in permutations(seterr): flag = AES.new(key=md5(str([b]+list(seed)+secret).encode()).digest(), nonce=b"Xenny.fans.club", mode=AES.MODE_CTR).decrypt(bytes.fromhex(C)) if(b"DASCTF"in flag): print(flag) break #b'DASCTF{jUsT_Lin34R1ZE_4nD_5OLv3_L1n3ar_SySt3m}'
from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic from Crypto.Util.number import * from Crypto.Cipher import AES from secret import flag import random
defgenerate_irreducible_polynomial(R, n): whileTrue: f = R.random_element(degree=n) while f.degree() != n: f = R.random_element(degree=n) if f.is_irreducible(): return f
q = 41 n = 128 F = GF(q) R = PolynomialRing(F,'x') x = R.gen() f = generate_irreducible_polynomial(R,n).monic() F1 = generate_irreducible_polynomial(R,n).monic() F2 = generate_irreducible_polynomial(R,n).monic()
k1 = GF(q^n, name = 'a', modulus = f) k2 = GF(q^n, name = 'b', modulus = F1) k3 = GF(q^n, name = 'c', modulus = F2)
from Crypto.Util.number import * from Crypto.Cipher import AES from hashlib import sha256 import socketserver import signal import os import string import random from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 from Crypto.Util.number import getPrime,getStrongPrime from Crypto.Random import get_random_bytes from sympy import nextprime
classTask(socketserver.BaseRequestHandler): def_recvall(self): BUFF_SIZE = 4096 data = b'' whileTrue: part = self.request.recv(BUFF_SIZE) data += part iflen(part) < BUFF_SIZE: break return data.strip()
self.send(b"welcome to my proxy encryption program with watermarking") messages=[] while1: self.send(b"1 for free encrypt with time limit") self.send(b"2 for check your watermarking ") self.send(b"plz input function code") try: mode=int(self.recv()) except: self.send(b"plz input right function code") continue if mode==1: if maxlens<=0: self.send(b"sorry, no free chance, try last time~") continue self.send(b"now choose your n bitlens") self.send(b"1. 1024 2. 2048 3. 4096") try: mode=int(self.recv()) except: self.send(b"plz input right function code") continue if mode==1: newparameter=1024 if mode==2: newparameter=2048 if mode==3: newparameter=4096 if newparameter!= RSAparameter: RSAparameter=newparameter p=getStrongPrime(RSAparameter//2) q=getStrongPrime(RSAparameter//2) n=p*q phi=(p-1)*(q-1) self.send(b"your n is changed to") self.send(hex(n).encode()) try: rsa_key = RSA.construct((n, e)) public_key = rsa_key.publickey().export_key() cipher = PKCS1_v1_5.new(RSA.import_key(public_key)) self.send(b"plz input your message with hex") message=self.recv().decode() #print(message,len(message)) messages.append(message) message=watermark[:RSAparameter//16]+bytes.fromhex(message) #print(message)
c = (cipher.encrypt(message)).hex().encode() #print(c) self.send(c) e=nextprime(e) maxlens-=RSAparameter except: self.send(b"wrong~ try again") continue elif mode==2: if maxlens>0: self.send(b"sorry, not even yet~") continue self.send(b"now give me your message without free chance") e=65537 d=pow(e,-1,phi) rsa_key = RSA.construct((n, e,d)) public_key = rsa_key.publickey().export_key() cipher = PKCS1_v1_5.new(rsa_key) cts=self.recv().decode() cts=bytes.fromhex(cts) try: p = (cipher.decrypt(cts,b"bad cipertext")) print(p) except Exception as e: print(e) self.send(b"wrong~ try again") continue if p[:RSAparameter//16]!=watermark[:RSAparameter//16]: self.send(b"not used the watermark!") continue if p[RSAparameter//16:].hex() in messages: self.send(b"not cost!") continue f=open("./flag","rb") flag=f.read() f.close() self.send(b"cong! your flag is "+flag) self.request.close()
from line_profiler import LineProfiler from secret import get_key from license import RicKV import os
flag = os.getenv('DASFLAG') smoke_key = get_key() # the key just printable, this function is to make all users key different
deflogin(password): iflen(password) != len(smoke_key): returnFalse for i inrange(len(password)): if password[i] != smoke_key[i]: returnFalse returnTrue
defcheck_password(user_input,pro=False): profiler = LineProfiler() profiler.add_function(login) profiler.enable_by_count() is_valid = login(user_input) profiler.disable_by_count() x = profiler.get_stats().timings hacker,hacker_pro = [],[] for i in x: for j in x[i]: hacker.append((j[0],j[-1])) hacker_pro.append(j) return is_valid, hacker_pro if pro else hacker
defadd_round(self, s, k): for i inrange(4): for j inrange(4): s[i*4+j] ^= k[i]
defsub(self,s): for i inrange(16): index = self.S2[i] temp = s[index] s[i] = self.S1[temp]
defmix_1(self,s,r): for i inrange(16): s[i] = s[i] ^ self.subkeys[i][r]
defmix_2(self,s,x): for i inrange(0,16,4): x[i//4] = Xor(s[i:i + 4])
defflip(self, plaintext): assertlen(plaintext) == 8 S = [int(_, 16) for _ inlist(plaintext.hex())] X = [0for _ inrange(4)] for r inrange(self.round): self.mix_1(S,r) self.sub(S) self.mix_2(S,X) self.add_round(S,X)
S = [S[i] ^ self.subkeys[self.round][i] for i inrange(16)] returnbytes.fromhex("".join("{:x}".format(_) for _ in S))
defcheck(self,liscense): liscense= base64.b64decode(liscense) assertlen(liscense) % 8 == 0 l = b"\x00" * 8 for i inrange(0,len(liscense),8): l = bytes(d^j for d,j inzip(l,liscense[i:i+8])) l = self.flip(l) l = bytes(d^j for d,j inzip(l,liscense[i:i+8])) returnnotany(l)
deflogin(password):#10 iflen(password) != len(smoke_key):#11 returnFalse#12 for i inrange(len(password)):#13 if password[i] != smoke_key[i]:#14 returnFalse#15 returnTrue#16
可以发现,login 函数在比较两个字符串是否相等时:先比较了字符串长度是否相等,然后是一个 for 循环进行的逐位比较而非 == 直接比较。加上前面返回的状态信息,因此可以考虑对状态进行爆破攻击。
然而,没有进入 pro 状态时,只会返回行号和时间 (单位为$10^{-6}s$)。在 login 函数中,如果长度不匹配,则会执行 11和12行的内容。如果行号匹配了,那么会执行11,13,14,15行内容。因此可以在没有进入pro状态时,根据返回状态,获取Key的长度(最终为24位)。但如果想要爆破,还要考虑每一行的执行时间,但由于机器波动,本地测试时,一般第一次时间为 0.9到1.6毫秒之间,但也有可能偶尔超过2毫秒,且超过2毫秒的概率不低,并且也不一定是正确的key。因此只判断时间是不可行的,必须进入pro模式,得到每一行的执行次数。。。
import random import hashlib for key inrange(1,11111111111): S1 = [i for i inrange(16)] x = hashlib.sha256(str(key).encode("utf-8")).digest() random.seed(x) random.shuffle(S1) for i inrange(16): id = S1[i] tmp = S1.index(id) if tmp == S1[id] and S1[id]+id == 15: print(S1[id],id) print(key) print(S1) exit(0)