from Crypto.Util.number import * flag = b"whuctf{}" blen = 512
l = len(flag) // 4#未知 n = 2 X = [] a = [bytes_to_long(flag[i * l: i * l + l]) for i inrange(2)] #切成两部分 b = 0 p = getPrime(blen)
for i inrange(2): X.append(getRandomNBitInteger(blen)) b = (a[i] * X[i]) % p assert b.bit_length() < 110
print("p =", p) print("X =", X)
# p = 12478746590758967738992827236548867094406642228843048782158822830242432957850861746109083849369751421558416546441433265483311369062332823391326650330844473 # X = [4370703796271085517745653374714633557060694569231794372714420305839580193452505356598920188429238758568075323630107438853033389535935767953293146851021439, 5636765597544539887670148818611437395262628189014720546978418282055551396918915796702935478309173130501906553399905160951176701403838275497327658585404887]
n = 2 X = [] a = [bytes_to_long(flag[i * l: i * l + l]) for i inrange(2, 4)] print(a) p = getPrime(blen)
for i inrange(n): X.append(getRandomNBitInteger(blen)) b = (a[i] * X[i]) % p assert b.bit_length() <= 55
s = getRandomNBitInteger(55) P = p - s
print("P =", P) print("X =", X)
# P = 8064317391291915578249751043887298750752952396481901402238164933671762816998644264248732894561122039999833298392825353792148892469165631966482732750535761 # X = [6042201174605160506707043360458329015685676206288676104013330039569480295420873678739841513174948925787517746114885517054730046775608073287427260847787072, 6232867934334525782602291010514616748943593081406115516232887372014738839717093295759414233886061184914495957664550361507367497641317336980894814940037711]
简单分析可知分为两个部分,前半段是 b = kp + aiXi
本质是两个方程,这里有两种方法可以解决,都写一下
M0 = L0.LLL()[0] v0 = L0.solve_left(M0) for i inrange(1,10000): a0 = abs(v0[0]) * i m0 = long_to_bytes(int(a0)) tag = True for m in m0: ifnotchr(m) in string.printable: tag = false break if tag: print(long_to_bytes(int(a0)))
from Crypto.Util.number import * import gmpy2 from sage.allimport * import libnum import string from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from hashlib import sha256
X = [1266403423628708294851978766647131186574350037928491893316575383770634141679199238688724846443316942748685589080912612989737322832820423142859211423222170, 10633805933378187507165706136587361125130747673943368523389315948924728188453225153073019422908293191827053741582511390426559341625596650317484672418362991] P = 12727949469666331910572325155797935927989546075198211256583307434798528241134917675474139742863165705376701853130873014549089300596914514323642506815012401 ct = b'\xe9\x87\x942\xbc\x94`t\x85^r\xb8\xd2\x00\xfb\xb0Ni\x08\xcf\x07\xf1\xae\x95U{\xf1\xd4\xda}@H' # 这里s只有100位,可以估计二者是几乎相等的
L0 = Matrix(ZZ,[ [1,X[0]], [0,P] ])
M0 = L0.LLL() W0 = M0[0]
v0 = L0.solve_left(W0)
L1 = Matrix(ZZ,[ [1,X[1]], [0,P] ])
M1 = L1.LLL() W1 = M1[0]
v1 = L1.solve_left(W1)
for i inrange(1,10000): a = abs(v0[0] * v1[0]) * i key = sha256(str(a).encode()).digest()[:16] iv = b"0" * 16 AES_cipher = AES.new(key, AES.MODE_CBC, iv) decrypted_data = unpad(AES_cipher.decrypt(ct), AES.block_size) m0 = decrypted_data.decode() tag = True for m in m0: ifnot m in string.printable: tag = false break if tag: print(m0)
import os import socket import threading from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad, unpad from string import ascii_lowercase
global flag
defxor(a, b): iflen(a) < len(b): a, b = b, a c = [] for i inrange(len(a)): c.append(a[i] ^ b[i % len(b)]) returnbytes(c)
defencrypt2(self, data): """拼接flag,将每个块的加密结果异或得到最终结果""" data = data + self.flag pdata = pad(data, AES.block_size) c = self.cipher.encrypt(pdata) C = [c[i : i + 16] for i inrange(0, len(c), 16)] for i inrange(1, len(C)): C[0] = xor(C[0], C[i]) return C[0].hex().encode()
defchallenge(client: socket.socket): cipher = myAES() client.sendall(b"Here is an AES system, try hack it !\n") client.sendall(b"\t1. Encrypt 1 \n") client.sendall(b"\t2. Encrypt 2 \n") while1: try: client.sendall(b"your choice > ") try: cho = int(client.recv(1024).decode().strip()) except ValueError: client.sendall(b"Invalid choice!\n") continue except: break if cho == 1: client.sendall(b"Input your data(hex): ") try: data = bytes.fromhex(client.recv(1024).strip().decode()) iflen(data) == 0: client.sendall(b"No input!\n") continue client.sendall(b"Encrypted data(hex): " + cipher.encrypt1(data) + b"\n") except Exception as e: print(e) client.sendall(b"Invalid data!\n") elif cho == 2: client.sendall(b"Input your data(hex): ") try: data = bytes.fromhex(client.recv(1024).strip().decode()) iflen(data) == 0: client.sendall(b"No input!\n") continue client.sendall(b"Encrypted data(hex): " + cipher.encrypt2(data) + b"\n") except Exception as e: print(e) client.sendall(b"Invalid data!\n") continue else: client.sendall(b"Invalid choice!\n") continue
if __name__ == "__main__": flag = os.getenv("GZCTF_FLAG") flag = flag.lstrip("WHUCTF{").rstrip("}") charset = ascii_lowercase + "_" assertlen(flag) % 16 == 3 assertall(c in charset for c in flag) flag = flag.encode() main()
defgetTail(): """尾部有几个字节数据的单块""" encflag = enc1(b"\x00" * flag_len) print("flag密文:", encflag.hex()) #flag各个块加密后的结果 encflag = [encflag[i : i + 16] for i inrange(0, len(encflag), 16)] #密文分块 for i in product(charset[::-1], repeat=tail_len): data = ("".join(i)).encode() print(data) #穷举所有可能的flag末尾3位 pdata = pad(data, AES.block_size) res = enc2(pdata) if res == xor(*encflag[: len(encflag) - 1]): print("尾部:", data) return data
defrecover(): """逐字节破解""" flag = getTail() mask = enc2(b"a" * 32) #得到encflag0 XOR encflag1 XOR encPad(flag2) mask = xor(*[mask[i : i + 16] for i inrange(0, len(mask), 16)]) for i inrange(1, flag_len + 1 - tail_len): c1 = enc1(b"\x00" * (flag_len + i)) c1 = [c1[_ : _ + 16] for _ inrange(0, len(c1), 16)] for j in charset: data = flag + j.encode() print(data) pdata = pad(data, AES.block_size) res = enc2(pdata) if xor(res, mask) == xor(*c1[(flag_len // 16) :]): flag += j.encode() print(flag[tail_len:] + flag[:tail_len]) break flag = flag[tail_len:] + flag[:tail_len] flag = "WHUCTF{" + flag.decode() + "}" print(flag)