from base64 import b64encode from Crypto.Random import get_random_bytes from Crypto.Cipher import ChaCha20_Poly1305 from pathlib import Path from zlib import compress
flag = Path("flag.txt").read_bytes() key = get_random_bytes(32)
try: whileTrue: append = input("Append whatever you want to the flag: ").encode() # gotta save on bandwidth! m = compress(flag + append) cipher = ChaCha20_Poly1305.new(key=key) cipher.update(m) c, tag = cipher.encrypt_and_digest(m) res = cipher.nonce + tag + c print(b64encode(res).decode()) except (KeyboardInterrupt, EOFError): pass
from base64 import * from pwn import * from string import *
sh = remote("tamuctf.com", 443, ssl=True, sni="criminal")
msg = b"gigem{" table = [i.encode() for i in ascii_lowercase+"_"] while(1): sh.recvuntil(b"Append whatever you want to the flag: ") sh.sendline(msg) res = b64decode(sh.recvline().strip().decode()) temp_len = len(res[12+16:]) for i in table: append = msg + i sh.recvuntil(b"Append whatever you want to the flag: ") sh.sendline(append) res = b64decode(sh.recvline().strip().decode()) length = len(res[12+16:]) if(length == temp_len): msg += i break print(msg)
#gigem{foiled_again}
PCG
题目描述:
1
QCG seems a little too simple, so instead I rolled my own rng using polynomials.
sh = remote("tamuctf.com", 443, ssl=True, sni="pcg")
points = [] m = int(sh.recvline().strip().decode()) T = [] for i inrange(256*3): t = int(sh.recvline().strip().decode()) T.append(t) for i inrange(len(T)-1): points.append((T[i],T[i+1]))
print("m =" , m) print("points =" , points) print("T =",T)
sh.interactive()
#gigem{p0lyn0m1al5_4r3_funny}
得到f(x)并计算接下来128个随机数:
1 2 3 4 5 6 7
PR = PolynomialRing(Zmod(m), 'x') f = PR.lagrange_polynomial(points) print(f) for i inrange(128): tt = f(T[-1]) T.append(tt) print(tt)
Jumbled
题目描述:
1
The RSA Public and Private keys are provided. However, the private key seems to be jumbled in a block size of 10 hex characters. Can you get the flag?
pripem = "" BLOCK_SIZE = 10 blocks = [] for i inrange(len(pri)//10): blocks.append(pri[10*i:10*i+10])
for i in blocks: for j in i: if(j == "0d"or j == "0a"): print("*" ,end="") else: print(chr(int(j,16)),end="") print()
''' -----BEGIN IENBG----- PRIVATE K TKAEIPV R *-M-*-Y-E- EY-----**M '''
#permutation for i in blocks: temp = [i[8],i[6],i[9],i[5],i[7],i[3],i[1],i[4],i[0],i[2]] for j in temp: print(chr(int(j,16)),end="")
print() d = 165256362365378633962296083771135407038026699717295555351716859079395620476165642731501900549887775497121080168180851957155268986745876979986226731585889976886837359456743753775028788280049190032572887402128718766395555960952472194713588403459107775960707064376615034000878349037951437654190347800868982293717655486543355290064798487196374748902866036013066392457458018702080850275261821212483956954132894024744768847485772347326562180294583357305409591048017004560050950841782237308140874043067649757249088082203601577081393135407431927587710161081829108984309876504298973617534523777641091443517585278194374522853 n = 21510240755391895797392251126333468065642811955059381948531217067500200157192587343981013021525313093852679704035885788909801119333395312090084093958181671132537557153359712792758811713027971732204030430334279725507975275100183059036632459180733954941681944147070942370040842822046123871981475320408243282191701896001902180703675695673251138391340023296500185391470273951722561424220840561040099780810789151859641139766606958023069344423617768698551243818313411124018247598802749326315083446422976866685184664968010286642320264785659560232284046763146464713273328278424445113308747581406364568448073987441571059968919 withopen(r"D:\题\2024\TAMUCTF 2024\jumbled\flag.txt.enc","rb") as f: c = f.read() c = bytes_to_long(c) print(long_to_bytes(pow(c,d,n)))
#gigem{jumbl3d_r54_pr1v473_k3y_z93kd74lx}
Smooth Signatures
题目描述:
1
I've heard signatures are pretty good tools for verifying the sender. Signatures are suposed to be personalized and unique, so surely this one is impossible to forge... right?
from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long from math import lcm,gcd from secrets import randbelow from hashlib import sha256
NUM_BITS = 2048
defgetModulus(bits): n = 1 primes = [] while n.bit_length() < bits: p = getPrime(24) if p notin primes: n *= p primes.append(p) return n,primes
defsign(n,msg,d): h = bytes_to_long(sha256(msg).digest()) k = randbelow(q-2)+1 x = pow(h,k,n) r = pow(x,d,n) s = pow(h+x,d,n) return r,s
defverify(n,msg,e,r,s): h = bytes_to_long(sha256(msg).digest()) v1 = pow(r,e,n) v2 = pow(s,e,n) return v2 == (v1 + h) % n
n,primes = getModulus(NUM_BITS) q = 1 for p in primes: q = lcm(q,p-1) msgs = [] e = 65537 d = pow(e,-1,q)
print(f"The modulus is ... a mystery left for you to unfold.") print(f"Your verification exponent {e = }") msg = input("Give the oracle a message to sign: ").encode() msgs.append(msg) r,s = sign(n,msg,d) print(f"Your verification signature is ({r}, {s})")
msg = input("Give the oracle another message to sign: ").encode() msgs.append(msg) r,s = sign(n,msg,d) print(f"Your second verification signature is ({r}, {s})")
comm = input("Ask the oracle a question: ").encode() r,s = input("Give the verification signature: ").split(",") r,s = int(r),int(s)
if comm in msgs: print("Hey, no cheating") exit() if verify(n,comm,e,r,s): if comm == b"What is the flag?": print("The flag is: ",end="") withopen("flag.txt","r") as flag: print(flag.read()) else: print("Not the right question.") else: print("Invalid signature")
仍然是靶机题,连接上后,题目会先生成一些数据:
生成一个光滑的模数n,其所有因子都是24bit的素数
计算n所有因子减去1的lcm(这一步其实就当成算n的欧拉函数就行,作用没区别)
取e=65537,并计算其关于lcm的逆元d
然后题目提供了两次签名的机会,他的签名操作是:
其中k是每次签名的临时密钥,d就是最开始生成的私钥。
两次签名之后,靶机要求我们提供消息”What is the flag?”以及他的签名,使得验签通过,就能拿到flag。他的验签操作是:
from Crypto.Util.number import * from gmpy2 import * from hashlib import sha256 from tqdm import * from pwn import *
#part1 get data sh = remote("tamuctf.com", 443, ssl=True, sni="smooth-signatures") e = 65537 msg = b"1" hm = bytes_to_long(sha256(msg).digest())
sh.recvuntil(b"Give the oracle a message to sign: ") sh.sendline(msg) sh.recvuntil(b"Your verification signature is ") r1,s1 = eval(sh.recvline().strip().decode())
sh.recvuntil(b"Give the oracle another message to sign: ") sh.sendline(msg) sh.recvuntil(b"Your second verification signature is ") r2,s2 = eval(sh.recvline().strip().decode())
#part2 get n k1n = s1**e - r1**e - hm k2n = s2**e - r2**e - hm n = gcd(k1n , k2n)
#part3 forge primes = [] for i in trange(2**23,2**25): if(n % i == 0): primes.append(i)
phi = 1 for i inrange(len(primes)): phi *= (primes[i] - 1)
d = inverse(e,phi) flag_msg = b"What is the flag?" h = bytes_to_long(sha256(flag_msg).digest()) s = pow(h,d,n)
sh.recvuntil(b"Ask the oracle a question: ") sh.sendline(flag_msg) sh.recvuntil(b"Give the verification signature: ") sh.sendline(b"0 , " + str(s).encode()) print(sh.recvline())
#gigem{sm00th_numb3rs_4r3_345y_70_f4c70r}
QCG
题目描述:
1
Java uses LCG for random number generation, so I rolled my own random nunber generator, QCG. Surely it is more secure than LCD.
F = [] PR.<a,b,c> = PolynomialRing(ZZ) for i inrange(9): f = a*data[i]^2 + b*data[i] + c - data[i+1] F.append(f) res = Ideal(F).groebner_basis()
print(res) m = ZZ(res[3].univariate_polynomial()(0)) c = ZZ(-res[2].univariate_polynomial()(0)) b = ZZ(-res[1].univariate_polynomial()(0)) a = ZZ(-res[0].univariate_polynomial()(0))
for i inrange(5): tt = (a*data[-1]^2 + b*data[-1] + c) % m data.append(tt) print(tt)
#gigem{lcg_but_h4rd3r_101}
Emoji Group
题目描述:
1
Emoji seem to have their own unique properties and strange combinations, so why not make a group out of them?
from secrets import multiply, g, identity, inverse, valid from random import getrandbits
defpower(p,x): out = identity while x: if x & 1: out = multiply(out,p) p = multiply(p,p) x >>= 1 return out
defencrypt(msg,e): generator = power(g,e) out = generator for c in msg: out += power(generator,ord(c)) return out
defdecrypt(ct,d): chars = [power(g,i) for i inrange(256)] plaintext = "" pt = power(ct[0],d) if pt != g: raise Exception("Invalid ciphertext") for c in ct[1:]: pt = power(c,d) plaintext += chr(chars.index(pt)) return plaintext
print("Give me a message to encrypt:") msg = input() e = 0 whilenot valid(e): e = getrandbits(32) ct = encrypt(msg,e) print(f"Your cipher text is:",ct) d = inverse(e) print(f"The original message was:",decrypt(ct,d))
withopen("flag.txt","r") as flag: e = 0 whilenot valid(e): e = getrandbits(32) print("The flag is:",encrypt(flag.read(),e))
while(1): dic = {} sh = remote("tamuctf.com", 443, ssl=True, sni="emoji-group") sh.recvuntil(b"Give me a message to encrypt:")
msg = "".join([chr(i) for i inrange(32,128)]).encode() sh.sendline(msg) sh.recvuntil(b"Your cipher text is: ") msg_enc = list(sh.recvline().strip().decode('utf-8')) for i inrange(32,128): dic[msg_enc[i-32+1]] = i dics.append([msg_enc[0],dic])
sh.recvuntil(b"The flag is:") flag_enc = list(sh.recvline().strip().decode('utf-8')) g = flag_enc[0] for i in dics: if(i[0] == g): for j in flag_enc[1:]: print(chr(i[1][j]),end="") exit() sh.close()