第三届黄河流域公安院校网络空间安全技能挑战赛
Sandwitch
简单padding的coppersmith
from Crypto.Util.number import *
n = 130210658110511504736422597261591182174531847806532340762131145212035478695205314931974421838392310731226415266775095601890938846830080329061111533796518633011922277343217149648494987341818402753017296362015915834670450122261511337212801488239810623226740266516836721952886027130703886460578247562781194524199
c = 58274335440051115211211273605191310114692293785750437685473044454042062899661976407492451518086227780147882738264722645944582899451063113444881286175099872016956825274378613983870549046907444680021237171113596116147511706486372974792692071549068969896395366667516390709069131700584308236332248449116109156503
e = 3
pad1 = b'easy_problem'
pad2 = b'How_to_solve_it'
P.<x> = PolynomialRing(Zmod(n))
f = ((bytes_to_long(pad1)*2^(15*8+39*8)+x*2^(15*8)+bytes_to_long(pad2))^e - c).monic()
roots = f.small_roots(X=2^(39*8),beta=0.5,epsilon=0.01)
print(long_to_bytes(int(roots[0])))
# b'flag{A_C0pper5mi1tH_4Ues7iOn_SplIt_Pad}'因式分解
tellasecret.py
import string
from secret import hint
from secret import encrypt
import random
dicts = string.ascii_lowercase +"{=}"
key = (''.join([random.choice(dicts) for i in range(4)])) * 8
assert(len(hint) == 32)
assert(len(key) == 32)
cipher = encrypt(hint, key) # vigenere
print(cipher)
# cp=wmaunapgimjfpopeblvup=aywqygb维吉尼亚解密,使用itertools的product(可重复遍历组合)而不是combination(不可重复遍历组合),对结果搜索tellasecret
import string
import itertools
dicts = string.ascii_lowercase +"{=}"
dicts1 = {i:index for index,i in enumerate(dicts)}
dicts2 = {index:i for index,i in enumerate(dicts)}
def vigenere_decrypt(cipher, key):
message = ''
for i in range(len(cipher)):
message += dicts2[(dicts1[cipher[i]] - dicts1[key[i]]) % len(dicts)]
return message
str = 'cp=wmaunapgimjfpopeblvup=aywqygb'
keys = itertools.product(dicts, repeat=4)
for k in keys:
key = ''.join(k)*8
message = vigenere_decrypt(str, key)
print(message,file=open('output.txt','a'))
# tellasecret{a=secert}keepsilentt因式分解.py
from Crypto.Util.number import *
from gmpy2 import*
from secret import flag,a,b,c
m = bytes_to_long(flag)
p = getPrime(256)
q = getPrime(256)
n = p * q
e = 65537
_q = int(bin(q)[2:][::-1] , 2)
c = pow(m,e,n)
print('n =',n)
print('c =',c)
'''
n = 7688109450918412752403544831281002390909833419780604228031807748258766149305710928557842935597759373483911172486806200079137977020089610947423466744079981
c = 6470273779347221033316093386019083111753019159457126878637258794718443144439812725263309232245307744208957171971247518708231996986359926490571921925899978
'''
assert a**3+b**3+c**3 == 3*a*b*c
gift = secert**3 - 9*secert + 8
print(gift)
assert 3*(p ^ _q) == a + b + c
#16174454302590604301534105361719250538317088773024913985896374029052621214070408075926265229111851489902642328975085914458074453963086159246933939207642987161923181946601656883349077418380372857072224674380642689142603970810010050解方程得到secret,即得到a,又assert a**3+b**3+c**3 == 3*a*b*c -> a=b=c->p^_q =a,剪枝得p,q
import sympy
g = 16174454302590604301534105361719250538317088773024913985896374029052621214070408075926265229111851489902642328975085914458074453963086159246933939207642987161923181946601656883349077418380372857072224674380642689142603970810010050
a = sympy.Symbol('a')
f = a**3 - 9*a + 8 - g
result = sympy.solve([f],[a])[0][0]
print(result)
from Crypto.Util.number import *
e = 65537
n = 7688109450918412752403544831281002390909833419780604228031807748258766149305710928557842935597759373483911172486806200079137977020089610947423466744079981
c = 6470273779347221033316093386019083111753019159457126878637258794718443144439812725263309232245307744208957171971247518708231996986359926490571921925899978
p0_q = result
test = bin(p0_q)[2:].zfill(256)
def find(ph,qh,pl,ql):
l = len(ph)
tmp0 = int(ph + '0'*(256-2*l) + pl, 2)
tmp1 = int(ph + '1'*(256-2*l) + pl, 2)
tmq0 = int(qh + '0'*(256-2*l) + ql, 2)
tmq1 = int(qh + '1'*(256-2*l) + ql, 2)
if tmp0 * tmq0 > n:
return
if tmp1 * tmq1 < n:
return
if l>0 and int(pl,2)*int(ql,2) % 2**(l-1) != n % 2**(l-1):
return
if l == 128:
p = tmp0
if n % p == 0:
q = n // p
print(long_to_bytes(pow(c,inverse(e, (p-1)*(q-1)),n)))
return
else:
if test[l] == "1" and test[255 - l] == "1":
find(ph + "1", qh + "0", "1" + pl, "0" + ql)
find(ph + "0", qh + "0", "1" + pl, "1" + ql)
find(ph + "1", qh + "1", "0" + pl, "0" + ql)
find(ph + "0", qh + "1", "0" + pl, "1" + ql)
elif test[l] == "1" and test[255 - l] == "0":
find(ph + "1", qh + "0", "0" + pl, "0" + ql)
find(ph + "0", qh + "0", "0" + pl, "1" + ql)
find(ph + "1", qh + "1", "1" + pl, "0" + ql)
find(ph + "0", qh + "1", "1" + pl, "1" + ql)
elif test[l] == "0" and test[255 - l] == "1":
find(ph + "0", qh + "0", "1" + pl, "0" + ql)
find(ph + "0", qh + "1", "0" + pl, "0" + ql)
find(ph + "1", qh + "0", "1" + pl, "1" + ql)
find(ph + "1", qh + "1", "0" + pl, "1" + ql)
elif test[l] == "0" and test[255 - l] == "0":
find(ph + "0", qh + "0", "0" + pl, "0" + ql)
find(ph + "1", qh + "0", "0" + pl, "1" + ql)
find(ph + "0", qh + "1", "1" + pl, "0" + ql)
find(ph + "1", qh + "1", "1" + pl, "1" + ql)
find('','','','')
# b'flag{80a59062-9bbf-99a3-6af0-a24e94032163}'Lattice
from Crypto.Util.number import *
from Crypto.Cipher import AES
import os
# from secret import flag
import numpy as np
flag = b"flag{fake_flag}"
def gen(q, n, N, sigma):
t = np.random.randint(0, high=q // 2, size=n)
s = np.concatenate([np.ones(1, dtype=np.int32), t])
A = np.random.randint(0, high=q // 2, size=(N, n))
e = np.round(np.random.randn(N) * sigma**2).astype(np.int32) % q
b = ((np.dot(A, t) + e).reshape(-1, 1)) % q
P = np.hstack([b, -A])
return P, s
def enc(P, M, q):
N = P.shape[0]
n = len(M)
r = np.random.randint(0, 2, (n, N))
Z = np.zeros((n, P.shape[1]), dtype=np.int32)
Z[:, 0] = 1
C = np.zeros((n, P.shape[1]), dtype=np.int32)
for i in range(n):
C[i] = (np.dot(P.T, r[i]) + (np.floor(q / 2) * Z[i] * M[i])) % q
return C
q = 127
n = 3
N = int(1.1 * n * np.log(q))
sigma = 1.0
P, s = gen(q, n, N, sigma)
def prep(s):
return np.array([int(b) for char in s for b in f"{ord(char):08b}"], dtype=np.int32)
hint =
C = enc(P, prep(hint), q)
P = P.tolist()
C = C.tolist()
print(f"{P=}")
print(f"{C=}")
'''
P=[]
C=[]
'''
iv =
key = os.urandom(16)
encrypted = AES.new(key=key, iv=iv, mode=AES.MODE_CBC).encrypt(b"".join([np.pad(i.encode(), 16) for i in flag]))
leak =
print(leak)
print(key)
print(encrypted)
'''
-3.257518803980229925210589904230583482986646342139415561576950148286382674434770529248486501793457710730252401258721482142654716015216299244487794967600132597049154513815052213387666360825101667524635777006510550117512116441539852315185793280311905620746025669520152068447372368293640072502196959919309286241
b'\x8fj\x94\x98-\x1fd\xd5\x89\xbe\xa9*Tu\x90\xb7'
b'\x9fT@\xbc\x82\x8esQ\x1e\xd8\x1d\xdb\x9b\xb4\xf8rU\xc8\xa0\xcb\xaf H\xa9.\x04\x1e\xd2\x92\x1f\x0fBja-\x965x\xa8@\xc9x\xf9\xaf\x87\xd1\xa5}\xfc\x1b\xe0#\xc3m\xc9\x8973\x1c\x1f\x13\x8f\xb2a\xae\xa9]\xb9\xc2\xe8\x83A\x80\x13g\xc9a\x1c<\x8a\x9c&\xd9\xbd\x06\xef\xba9\xb0\x03\x9f\x022\xc9\x13\x9a\xffXPG\xc6o\xc0\xeaV7)XG9L\x84N7U\xe3Wn0G\x8e\xd3\x04(\n\x08\xb9\x17\xe6\xf1\xaa\xb7\x8a@$\x16\x13\x06A\x00\xc9Z\xdf\x7fQ\xc9\x08\xb4\xf3P\xfcpe\xe2\xeb\x96\x0e(-\xde\x17\xd1\x01\x1c_\x82\x8b\x9fw\xc8\x86\xfbw\xb5\xf7\xd0\xc8\x1784\xe3?\x00\x0b.)\xb7\xbc\x8e{\xe0\xae\x8d$\x0f\x19\'\xb6\xee@d\x00\xd9\x84\x8c\x0e\xa3,\xc6a\xa3\xba*1\xfd<\xfd\x18\xd6\x9e\x8c4\x8e#\xfd\xbd&0R\xeddE,\xed\xb6\x1e\x00\x11\xa6K\xd3\x1dT\x8c5\x8e\x00\xea\x10\xe9\'u"B#\xa1#\xd8\xe3\xf5j\xbc\x94M\xda\xe3\xcb*\xf0W1\xa0\x80\x1d\xfc\xbfo\x01?(da\r\xb6\x86\xd0\x90\x88Z\xa1`B\x89\x89\x89\xb3v\xa5\xf0\xe0\x0c\x8e\xcc+P\xfc\xfd#\x83\xe9\x93\x96\n\xf2\xa5\xfb\xc3\xc5\xaa\x9e\x89\x93\xb6\xf5\xea\x8c%NY\xc3\x0eR\xfas\xa1\x13\xf2/*\xce\x8b_:_r\xeb\xbe\x0b\x8a\x8c\x97\x7f|m}\xae\xa9I\x95\xcc\xe7\x80\xa5yC4\x1f5\xa4P\xc5\xbf.\xf9V\xe8|\xbb\xc3\xcb\x98&\'JB\x99\x94\xc0\r$\x0b\xbe48u\xeb\xca\xa1\xfbb\xd8_R\x97\x8e\xaeI\xfc\xc2\xb2\xd2#@\xec\x16\xf1\xd7eCQ\x1cO\x13\xca\xb5\xd3\x1a\xb1\xf1_D\x80\x06\xa5\xbe\xbev\xbd\xd6\xbb\x9a\xc9x\x9cf:\xcb>\xa2\xe1\xcad\xde]aw\xa0\xdc\xb2\xb3{+\x85\x8d\x8b\xc5\rT\xcc\xd9X\xd5\x9b\r<\x99m\xb8b6s\xbfp\x0eo~\xe9&\xb2{\xbe\xee\x93\xd2N1\\\x94\x968IWO7\xcb\xb6e\x80\xf7\x9air\xb2~\x17\x1cF\x0f\x82T]RBX\xdex\x13\x85\xfa\xcd-\xce\xdc\xe4\xe5^\x99u\xb5\x01\xd0-\xc3C\xcd\xc4y6\xb7\x9d|L1\xe74\xf7\x8cH\xe9\xa9\xfav\n\xec;\xf2\xa2w\xfb\x13_b\r)z!\xa3\xc8\xa8\xc2\xd2\x10\x00\x11\x11\r\xb2&\xfb\x04&\x84">x6l[\x06n>\xa0\xbe\x9c`\xa7\x9e\xe0\xfb\x85\x91\xc4,\xcf\xac\xe11@a\xed3@\xfd}\x8e\xfaTp\xcb7\xe7\xbf\xd4\xe0~b\xd9\xe0<\xba\x81\xd4"e\xfc\x939|j#0H\x86\xf8\x0b\x03\xd2\xe8\xf5\xe55\xdc\xc8\x06\\\xb7)\xcc\x9b\'\xf12'
'''解法一
第一段:LWE
from sage.modules.free_module_integer import IntegerLattice
import numpy as np
# ====slove_t====
def Babai(B, t):
B = IntegerLattice(B, lll_reduce=True).reduced_basis
G = B.gram_schmidt()[0]
b = t
for i in reversed(range(B.ncols())):
b -= B[i] * ((b * G[i]) / (G[i] * G[i])).round()
return t - b
P=[[87, -27, -52, -29], [57, -41, -24, -60], [76, -17, -55, -37], [75, -46, -33, -21], [121, -55, -33, -34], [47, -4, -34, -45], [112, -33, -44, -16], [74, -44, -5, -25], [20, -21, -16, -49], [89, -21, -54, -24], [18, -23, -53, -1], [35, -40, -4, -29], [105, -54, -2, -8], [44, -24, -43, -36], [111, -15, -15, -54]]
P = np.array(P)
A_list= list(-P[:,1:])
b_list= list(P[:,0])
q = 127
# b = A*x+e mod q
A = matrix(ZZ, A_list)
b = vector(ZZ, b_list)
r = A.nrows()
c = A.ncols()
pIr = q*identity_matrix(r)
M = block_matrix([[pIr], [A.transpose()]])
br = Babai(M, b)
print(f'e = {b-br}')
R = IntegerModRing(q)
Ar = matrix(R, A_list)
t = Ar.solve_right(br)
print(f't = {t}')
s = np.concatenate([np.ones(1, dtype=np.int32), t])
# e = (0, 1, -1, 1, 0, -1, 1, 0, 0, -1, -1, 0, -1, 0, 1)
# t = (26, 24, 54)第二段:hint
from Crypto.Util.number import long_to_bytes
# ====slove_hint====
s = np.concatenate([np.ones(1, dtype=np.int32), t])
C=[]
m = list(np.dot(C,s) % q)
hint=''
for i in m:
if int(i) > q - 15 or int(i) < 15:
hint += '0'
else:
hint += '1'
print(long_to_bytes(int(hint, 2)))
# b"Congratulations,you're amazing!Here's a hint: sin(iv) + leak * cos(iv) = 0, keep it up! @V@"第三段:三角格规约求iv
from Crypto.Util.number import long_to_bytes
# ====slove_iv====
t = 3.257518803980229925210589904230583482986646342139415561576950148286382674434770529248486501793457710730252401258721482142654716015216299244487794967600132597049154513815052213387666360825101667524635777006510550117512116441539852315185793280311905620746025669520152068447372368293640072502196959919309286241
a = arctan(t)
ts = 2^1024
A = int(a*ts)
Pi = int((pi).n(1024)*ts)
G = Matrix([[1,0,-ts],[0,1,int(Pi)],[0,0,A]])
m = G.LLL()[0][0]
iv = long_to_bytes(int(m))
print(f'iv = {iv}')
# b'?\xaa =t\xbc\xddQ\xac/yq\x13\xc3\x7f\xb9'第四段:AES解密+unpad
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
iv = b'?\xaa =t\xbc\xddQ\xac/yq\x13\xc3\x7f\xb9'
key = b'\x8fj\x94\x98-\x1fd\xd5\x89\xbe\xa9*Tu\x90\xb7'
c = b'\x9fT@\xbc\x82\x8esQ\x1e\xd8\x1d\xdb\x9b\xb4\xf8rU\xc8\xa0\xcb\xaf H\xa9.\x04\x1e\xd2\x92\x1f\x0fBja-\x965x\xa8@\xc9x\xf9\xaf\x87\xd1\xa5}\xfc\x1b\xe0#\xc3m\xc9\x8973\x1c\x1f\x13\x8f\xb2a\xae\xa9]\xb9\xc2\xe8\x83A\x80\x13g\xc9a\x1c<\x8a\x9c&\xd9\xbd\x06\xef\xba9\xb0\x03\x9f\x022\xc9\x13\x9a\xffXPG\xc6o\xc0\xeaV7)XG9L\x84N7U\xe3Wn0G\x8e\xd3\x04(\n\x08\xb9\x17\xe6\xf1\xaa\xb7\x8a@$\x16\x13\x06A\x00\xc9Z\xdf\x7fQ\xc9\x08\xb4\xf3P\xfcpe\xe2\xeb\x96\x0e(-\xde\x17\xd1\x01\x1c_\x82\x8b\x9fw\xc8\x86\xfbw\xb5\xf7\xd0\xc8\x1784\xe3?\x00\x0b.)\xb7\xbc\x8e{\xe0\xae\x8d$\x0f\x19\'\xb6\xee@d\x00\xd9\x84\x8c\x0e\xa3,\xc6a\xa3\xba*1\xfd<\xfd\x18\xd6\x9e\x8c4\x8e#\xfd\xbd&0R\xeddE,\xed\xb6\x1e\x00\x11\xa6K\xd3\x1dT\x8c5\x8e\x00\xea\x10\xe9\'u"B#\xa1#\xd8\xe3\xf5j\xbc\x94M\xda\xe3\xcb*\xf0W1\xa0\x80\x1d\xfc\xbfo\x01?(da\r\xb6\x86\xd0\x90\x88Z\xa1`B\x89\x89\x89\xb3v\xa5\xf0\xe0\x0c\x8e\xcc+P\xfc\xfd#\x83\xe9\x93\x96\n\xf2\xa5\xfb\xc3\xc5\xaa\x9e\x89\x93\xb6\xf5\xea\x8c%NY\xc3\x0eR\xfas\xa1\x13\xf2/*\xce\x8b_:_r\xeb\xbe\x0b\x8a\x8c\x97\x7f|m}\xae\xa9I\x95\xcc\xe7\x80\xa5yC4\x1f5\xa4P\xc5\xbf.\xf9V\xe8|\xbb\xc3\xcb\x98&\'JB\x99\x94\xc0\r$\x0b\xbe48u\xeb\xca\xa1\xfbb\xd8_R\x97\x8e\xaeI\xfc\xc2\xb2\xd2#@\xec\x16\xf1\xd7eCQ\x1cO\x13\xca\xb5\xd3\x1a\xb1\xf1_D\x80\x06\xa5\xbe\xbev\xbd\xd6\xbb\x9a\xc9x\x9cf:\xcb>\xa2\xe1\xcad\xde]aw\xa0\xdc\xb2\xb3{+\x85\x8d\x8b\xc5\rT\xcc\xd9X\xd5\x9b\r<\x99m\xb8b6s\xbfp\x0eo~\xe9&\xb2{\xbe\xee\x93\xd2N1\\\x94\x968IWO7\xcb\xb6e\x80\xf7\x9air\xb2~\x17\x1cF\x0f\x82T]RBX\xdex\x13\x85\xfa\xcd-\xce\xdc\xe4\xe5^\x99u\xb5\x01\xd0-\xc3C\xcd\xc4y6\xb7\x9d|L1\xe74\xf7\x8cH\xe9\xa9\xfav\n\xec;\xf2\xa2w\xfb\x13_b\r)z!\xa3\xc8\xa8\xc2\xd2\x10\x00\x11\x11\r\xb2&\xfb\x04&\x84">x6l[\x06n>\xa0\xbe\x9c`\xa7\x9e\xe0\xfb\x85\x91\xc4,\xcf\xac\xe11@a\xed3@\xfd}\x8e\xfaTp\xcb7\xe7\xbf\xd4\xe0~b\xd9\xe0<\xba\x81\xd4"e\xfc\x939|j#0H\x86\xf8\x0b\x03\xd2\xe8\xf5\xe55\xdc\xc8\x06\\\xb7)\xcc\x9b\'\xf12'
aes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
m = aes.decrypt(c)
mm = [m[i:i + 16] for i in range(0, len(m), 16)]
flag = b''.join([unpad(i, 16) for i in mm])
print(flag)
# b'flag{6ef25d1e-bb76-8e53-dbc4-1e56585f9aa9}'解法二
CBC的特征+flag的第一个字符f被pad为16位,直接异或出iv
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
encrypted = b'\x9fT@\xbc\x82\x8esQ\x1e\xd8\x1d\xdb\x9b\xb4\xf8rU\xc8\xa0\xcb\xaf H\xa9.\x04\x1e\xd2\x92\x1f\x0fBja-\x965x\xa8@\xc9x\xf9\xaf\x87\xd1\xa5}\xfc\x1b\xe0#\xc3m\xc9\x8973\x1c\x1f\x13\x8f\xb2a\xae\xa9]\xb9\xc2\xe8\x83A\x80\x13g\xc9a\x1c<\x8a\x9c&\xd9\xbd\x06\xef\xba9\xb0\x03\x9f\x022\xc9\x13\x9a\xffXPG\xc6o\xc0\xeaV7)XG9L\x84N7U\xe3Wn0G\x8e\xd3\x04(\n\x08\xb9\x17\xe6\xf1\xaa\xb7\x8a@$\x16\x13\x06A\x00\xc9Z\xdf\x7fQ\xc9\x08\xb4\xf3P\xfcpe\xe2\xeb\x96\x0e(-\xde\x17\xd1\x01\x1c_\x82\x8b\x9fw\xc8\x86\xfbw\xb5\xf7\xd0\xc8\x1784\xe3?\x00\x0b.)\xb7\xbc\x8e{\xe0\xae\x8d$\x0f\x19\'\xb6\xee@d\x00\xd9\x84\x8c\x0e\xa3,\xc6a\xa3\xba*1\xfd<\xfd\x18\xd6\x9e\x8c4\x8e#\xfd\xbd&0R\xeddE,\xed\xb6\x1e\x00\x11\xa6K\xd3\x1dT\x8c5\x8e\x00\xea\x10\xe9\'u"B#\xa1#\xd8\xe3\xf5j\xbc\x94M\xda\xe3\xcb*\xf0W1\xa0\x80\x1d\xfc\xbfo\x01?(da\r\xb6\x86\xd0\x90\x88Z\xa1`B\x89\x89\x89\xb3v\xa5\xf0\xe0\x0c\x8e\xcc+P\xfc\xfd#\x83\xe9\x93\x96\n\xf2\xa5\xfb\xc3\xc5\xaa\x9e\x89\x93\xb6\xf5\xea\x8c%NY\xc3\x0eR\xfas\xa1\x13\xf2/*\xce\x8b_:_r\xeb\xbe\x0b\x8a\x8c\x97\x7f|m}\xae\xa9I\x95\xcc\xe7\x80\xa5yC4\x1f5\xa4P\xc5\xbf.\xf9V\xe8|\xbb\xc3\xcb\x98&\'JB\x99\x94\xc0\r$\x0b\xbe48u\xeb\xca\xa1\xfbb\xd8_R\x97\x8e\xaeI\xfc\xc2\xb2\xd2#@\xec\x16\xf1\xd7eCQ\x1cO\x13\xca\xb5\xd3\x1a\xb1\xf1_D\x80\x06\xa5\xbe\xbev\xbd\xd6\xbb\x9a\xc9x\x9cf:\xcb>\xa2\xe1\xcad\xde]aw\xa0\xdc\xb2\xb3{+\x85\x8d\x8b\xc5\rT\xcc\xd9X\xd5\x9b\r<\x99m\xb8b6s\xbfp\x0eo~\xe9&\xb2{\xbe\xee\x93\xd2N1\\\x94\x968IWO7\xcb\xb6e\x80\xf7\x9air\xb2~\x17\x1cF\x0f\x82T]RBX\xdex\x13\x85\xfa\xcd-\xce\xdc\xe4\xe5^\x99u\xb5\x01\xd0-\xc3C\xcd\xc4y6\xb7\x9d|L1\xe74\xf7\x8cH\xe9\xa9\xfav\n\xec;\xf2\xa2w\xfb\x13_b\r)z!\xa3\xc8\xa8\xc2\xd2\x10\x00\x11\x11\r\xb2&\xfb\x04&\x84">x6l[\x06n>\xa0\xbe\x9c`\xa7\x9e\xe0\xfb\x85\x91\xc4,\xcf\xac\xe11@a\xed3@\xfd}\x8e\xfaTp\xcb7\xe7\xbf\xd4\xe0~b\xd9\xe0<\xba\x81\xd4"e\xfc\x939|j#0H\x86\xf8\x0b\x03\xd2\xe8\xf5\xe55\xdc\xc8\x06\\\xb7)\xcc\x9b\'\xf12'
message_pad = pad(b'f', 16)
key = b'\x8fj\x94\x98-\x1fd\xd5\x89\xbe\xa9*Tu\x90\xb7'
myaes = AES.new(key, AES.MODE_ECB)
iv = bytes([a^b for a, b in zip(myaes.decrypt(encrypted[:16]), message_pad)])
print(iv)
c = b'\x9fT@\xbc\x82\x8esQ\x1e\xd8\x1d\xdb\x9b\xb4\xf8rU\xc8\xa0\xcb\xaf H\xa9.\x04\x1e\xd2\x92\x1f\x0fBja-\x965x\xa8@\xc9x\xf9\xaf\x87\xd1\xa5}\xfc\x1b\xe0#\xc3m\xc9\x8973\x1c\x1f\x13\x8f\xb2a\xae\xa9]\xb9\xc2\xe8\x83A\x80\x13g\xc9a\x1c<\x8a\x9c&\xd9\xbd\x06\xef\xba9\xb0\x03\x9f\x022\xc9\x13\x9a\xffXPG\xc6o\xc0\xeaV7)XG9L\x84N7U\xe3Wn0G\x8e\xd3\x04(\n\x08\xb9\x17\xe6\xf1\xaa\xb7\x8a@$\x16\x13\x06A\x00\xc9Z\xdf\x7fQ\xc9\x08\xb4\xf3P\xfcpe\xe2\xeb\x96\x0e(-\xde\x17\xd1\x01\x1c_\x82\x8b\x9fw\xc8\x86\xfbw\xb5\xf7\xd0\xc8\x1784\xe3?\x00\x0b.)\xb7\xbc\x8e{\xe0\xae\x8d$\x0f\x19\'\xb6\xee@d\x00\xd9\x84\x8c\x0e\xa3,\xc6a\xa3\xba*1\xfd<\xfd\x18\xd6\x9e\x8c4\x8e#\xfd\xbd&0R\xeddE,\xed\xb6\x1e\x00\x11\xa6K\xd3\x1dT\x8c5\x8e\x00\xea\x10\xe9\'u"B#\xa1#\xd8\xe3\xf5j\xbc\x94M\xda\xe3\xcb*\xf0W1\xa0\x80\x1d\xfc\xbfo\x01?(da\r\xb6\x86\xd0\x90\x88Z\xa1`B\x89\x89\x89\xb3v\xa5\xf0\xe0\x0c\x8e\xcc+P\xfc\xfd#\x83\xe9\x93\x96\n\xf2\xa5\xfb\xc3\xc5\xaa\x9e\x89\x93\xb6\xf5\xea\x8c%NY\xc3\x0eR\xfas\xa1\x13\xf2/*\xce\x8b_:_r\xeb\xbe\x0b\x8a\x8c\x97\x7f|m}\xae\xa9I\x95\xcc\xe7\x80\xa5yC4\x1f5\xa4P\xc5\xbf.\xf9V\xe8|\xbb\xc3\xcb\x98&\'JB\x99\x94\xc0\r$\x0b\xbe48u\xeb\xca\xa1\xfbb\xd8_R\x97\x8e\xaeI\xfc\xc2\xb2\xd2#@\xec\x16\xf1\xd7eCQ\x1cO\x13\xca\xb5\xd3\x1a\xb1\xf1_D\x80\x06\xa5\xbe\xbev\xbd\xd6\xbb\x9a\xc9x\x9cf:\xcb>\xa2\xe1\xcad\xde]aw\xa0\xdc\xb2\xb3{+\x85\x8d\x8b\xc5\rT\xcc\xd9X\xd5\x9b\r<\x99m\xb8b6s\xbfp\x0eo~\xe9&\xb2{\xbe\xee\x93\xd2N1\\\x94\x968IWO7\xcb\xb6e\x80\xf7\x9air\xb2~\x17\x1cF\x0f\x82T]RBX\xdex\x13\x85\xfa\xcd-\xce\xdc\xe4\xe5^\x99u\xb5\x01\xd0-\xc3C\xcd\xc4y6\xb7\x9d|L1\xe74\xf7\x8cH\xe9\xa9\xfav\n\xec;\xf2\xa2w\xfb\x13_b\r)z!\xa3\xc8\xa8\xc2\xd2\x10\x00\x11\x11\r\xb2&\xfb\x04&\x84">x6l[\x06n>\xa0\xbe\x9c`\xa7\x9e\xe0\xfb\x85\x91\xc4,\xcf\xac\xe11@a\xed3@\xfd}\x8e\xfaTp\xcb7\xe7\xbf\xd4\xe0~b\xd9\xe0<\xba\x81\xd4"e\xfc\x939|j#0H\x86\xf8\x0b\x03\xd2\xe8\xf5\xe55\xdc\xc8\x06\\\xb7)\xcc\x9b\'\xf12'
key = b'\x8fj\x94\x98-\x1fd\xd5\x89\xbe\xa9*Tu\x90\xb7'
myaes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
decrypted_bytes = myaes.decrypt(c)
# print(decrypted_bytes)
messages = [decrypted_bytes[i:i + 16] for i in range(0, len(decrypted_bytes), 16)]
flag = "".join([chr(message[0]) for message in messages])
print(flag)
# flag{6ef25d1e-bb76-8e53-dbc4-1e56585f9aa9}Happy
task.py
#!/usr/bin/env python
# Simplify the problem by happy4321
import os, utils
from secret import flag
assert flag.startswith(b'flag{') and flag.endswith(b'}')
seed = int(os.urandom(16).hex(), 16)
gen = utils.Gen(seed)
msg = b'Happy4321: ' + flag
enc = bytes(m ^ next(gen) for m in msg).hex()
print(enc)
# cd1dd7c7a9cfe3c0067ff64694e64c38aa759c81d1c8f48cf6f7ee1df2d1e58584da52644ea56bd24dadca6bd5a6899a92b118f57de2529670264d48utils.py
class Gen:
def __init__(self, state):
self.nbits = 128
self.state = state & ((1 << self.nbits) - 1)
self.mask = 109908700282042807039366676242995409413
def func0(self, steps=1):
for _ in range(steps):
res = self.state & self.mask
bit = sum([(res >> i) & 1 for i in range(self.nbits)]) & 1
self.state = ((self.state << 1) ^ bit) & ((1 << self.nbits) - 1)
return bit
def __next__(self):
out = 0
for _ in range(8):
bit = self.func0(2023)
out = (out << 1) ^ bit
return outAnalyse:
seed转换为1x128的矩阵
则变换矩阵为含mask的128x128矩阵,在GF(2)上有:
[staten][OImask0mask1+]=[staten+1]
Exp:
(直接把class Gen复制进来跑出来的是乱码😕)
# sagemath 10.6
from Crypto.Util.number import *
enc = 'cd1dd7c7a9cfe3c0067ff64694e64c38aa759c81d1c8f48cf6f7ee1df2d1e58584da52644ea56bd24dadca6bd5a6899a92b118f57de2529670264d48'
mask = 109908700282042807039366676242995409413
flag_know = b'Happy4321: flag{'
enc_know = bytes.fromhex(enc)[:16]
leak = ''.join([bin(i)[2:].zfill(8) for i in [a^^b for a,b in zip(flag_know,enc_know)]])
mask = bin(mask)[2:].zfill(128)
def get_seed(leak,mask):
change_m = matrix(GF(2),128,128)
for i in range(127):
change_m[i+1,i] = 1
for i in range(128):
change_m[i,-1] = mask[i]
M = list()
for i in range(16*8):
M.append((change_m ^ (2023*(i+1))).T[-1].list())
seed = ''.join(map(str,(matrix(GF(2),list(leak)) / matrix(GF(2),M).T).list()))
return int(seed,2)
seed = get_seed(leak,mask)
print(f'seed = {seed}')
import utils
gen = utils.Gen(seed)
enc = bytes.fromhex(enc)
flag = bytes(e ^^ next(gen) for e in enc)
print(flag)
# Happy4321: flag{The_matrix_is_as_charming_as_the_starry_sky}