Crypto
LLL-I
from Crypto.Util.number import bytes_to_long
from numpy import eye, matrix
from random import randint
from secret import flag
assert len(flag) % 4 == 0
Length = len(flag)//4
Noise = [[randint( 1, pow(2,90) ) for i in range(4)] for j in range(4)]
Noise[0]= [bytes_to_long(flag[i * Length : (i+1)* Length]) for i in range(4)]
M = matrix(Noise)
def Orthogonal_Matrix(n, p):
up = matrix(eye(n, dtype=int))
low = matrix(eye(n, dtype=int))
for i in range(n-1):
for j in range(i+1, n):
up[ i,j] = randint(1, p)
low[j,i] = randint(1, p)
return up * low
C = Orthogonal_Matrix(4, 65537)
print((C*M).tolist())
按照题目提示,直接调用LLL算法即可
(不懂)
from Crypto.Util.number import long_to_bytes
L=[[1849784703482951012865152264025674575, 2664848085955925754350117767673627932, 2099783527396520151610274180590854166, 1020558595577301617108111920545804527], [1207449566811121614020334020195802372, 1954621976999112878661150903673543232, 1326050406731534201574943690688237338, 1361813208094227445768111591959011963], [888810907577479776819993141014777624, 1216302736807928240875874427765340645, 1027359437421599069599327712873719567, 238961447144792739830554790892164336], [60622164517940943037274386912282, 82958508138755168576836012717468, 70072118066826856564329627650828, 16296740862142507745322242235326]]
L=matrix(ZZ,L)
L=L.LLL()
flag=b""
for i in L[0]:
flag+=long_to_bytes(abs(i))
print(flag)
#b'0xGame{04679c42-2bc1-42b2-b836-1b0ca542f36b}'
LLL-II
from Crypto.Util.number import getPrime, inverse
from secret import seed, flag
from hashlib import md5
def MD5(m):return md5(str(m).encode()).hexdigest()
assert flag == '0xGame{' + MD5(seed) + '}'
assert seed.bit_length() == 510
class LuanGao:
def __init__(self, bits:int, seed:int):
self.bits = bits
self.m = getPrime(self.bits)
self.a = getPrime(self.bits // 2)
self.cur = (self.a * seed) % self.m
def extract(self):
ret = self.cur
b = getPrime(self.bits // 4)
self.cur = ( self.a * self.cur + b ) % self.m
return ret
C = LuanGao(512, seed)
Cs = [C.extract() for _ in range(5)]
print(f'Cs = {Cs}')
print(f'C.m = {C.m}')
\[X_{i+1}=aX_i+b_i\mod m=aX_i+b_i+k_im\\ b_i=X_{i+1}-aX_i+k_im\\ 构造格L=\left( \begin{matrix} m & 0 & \cdots & 0 & 0 & 0\\ 0 & m & \cdots & 0 & 0 & 0\\ \vdots & \vdots &\ddots & \vdots & \vdots & \vdots\\ 0 & 0 & \cdots & m & 0 & 0\\ X_1 & X_2 & \cdots & X_4 & 1 & 0\\ X_2 & X_3 & \cdots & X_5 & 0 & K\\ \end{matrix} \right)\\ (k_1,k_2,\dots,k_4,-a,1)L=(b_1,b_2,\cdots,b_4,-a,K)\\ 另一种格构造格L=\left( \begin{matrix} m & 0 & \cdots & 0 & 0 & 0\\ 0 & m & \cdots & 0 & 0 & 0\\ \vdots & \vdots &\ddots & \vdots & \vdots & \vdots\\ 0 & 0 & \cdots & m & 0 & 0\\ X_1 & X_2 & \cdots & X_4 & \frac{K}{m} & 0\\ X_2 & X_3 & \cdots & X_5 & 0 & K\\ \end{matrix} \right)\\ (k_1,k_2,\dots,k_4,-a,1)L=(b_1,b_2,\cdots,b_4,-a*\frac{K}{m},K) \]
from Crypto.Util.number import *
from hashlib import md5
def MD5(m):return md5(str(m).encode()).hexdigest()
n = 12813864523019740432913161815051292412705285817864701047922722497269479288096574264414061282833203433542813637861620032851255308640850882149603687035724753
x = [11804527453299586684489593808016317337345238230165321056832279785591503368758306671170625597063579251464905729051049524014502008954170088604924368057540940, 4930922884306486570759661288602557428608315558804950537470100263019228888817481617065454705843164809506859574053884206133344549895853064735361336486560981, 5380263856446165449531647111260010594620416730932539097782399557603420658350407080366132490174060420530708293564252852668431923560882648691392446521188465, 10746696290782998433216934286282230556131938525513632178308443345441147075710552571129957873399395862207656161609046567289600084193860244770966610161184627, 2195032957511830992558961021566904850278796737316238566513837995297394215638259916944087623923636789312134734949452839561765171446217520081402769962517110]
Ge = Matrix(QQ,6,6)
for i in range(4):
Ge[i,i] = n
Ge[-2,i] = x[i]
Ge[-1,i] = x[i+1]
Ge[-1,-1] = 2^510
Ge[-2,-2] = 1
for i in Ge.LLL():
if abs(i[-1]) == 2^510:
a = int(abs(i[-2]))
s=int((inverse_mod(a,n)*x[0])%n)
flag='0xGame{' + MD5(s) + '}'
print(flag)
LLL-III
from Crypto.Util.number import *
from secret import seed,flag
from hashlib import md5
def MD5(m):return md5(str(m).encode()).hexdigest()
assert flag == '0xGame{' + MD5(seed) + '}'
assert seed.bit_length() == 256
class LCG:
def __init__(self,bits:int,seed:int):
self.m = getPrime(bits+1)
self.a = getPrime(bits)
self.b = getPrime(bits)
self.cur = ( self.a * seed + self.b ) % self.m
def extract(self):
ret=self.cur >> 115
self.cur = ( self.a * self.cur + self.b ) % self.m
return ret
lcg=LCG(bits=256,seed=seed)
out = []
for _ in range(20):
out.append(lcg.extract())
print(f'm = {lcg.m}')
print(f'a = {lcg.a}')
print(f'b = {lcg.b}')
print(f'out = {out}')
SHCTF-week3有一题一样的,我直接来一首复制粘贴。
抄袭文献[LCG | DexterJie'Blog
我们有:
\[H_2+L_2=a(H_1+L_1)+b\mod p\\ L_2=aL_1+(aH_1+b-H_2)\mod p\\ \]记\(A_1=a,B_1=(aH_1+b-H_2)\mod p\)
继续推导有:
\[H_3+L_3=a(H_2+L_2)+b\mod p\\ L_3=aL_2+(aH_2+b-H_3)\mod p\\ 将上面L_2,带入得:\\ L_3=a^2L_1+a(aH_1+b-H_2)+(aH_2+b-H_3)\\ \]记\(A_2=a^2,B_2=(aB_1+(aH_2+b-H_3))\mod p\)
所以我们有一般式
\[L_{i+1}=A_iL_1+B_i\mod p\\ A_i=a^i\mod p\\ B_i=aB_{i-1}+(aH_i+b-H_{i+1})\mod p \]我们构造格
\[L=\left( \begin{matrix} p & 0 & 0 & 0\\ 0 & p & 0 & 0\\ A_1 & A_2 & 1 & 0\\ B_1 & B_2 & 0 & 1\\ \end{matrix} \right)\\ (k_1,k_2,L_1,1)L=(L_2,L_3,L_1,1)\\ 最后为了使目标向量得所有元素大小相同,需要进行配平\\ 让L得最后一行最后一个元素乘上一个K=2^{115}(seed缺失的位数)\\ 最后L=\left( \begin{matrix} p & 0 & 0 & 0\\ 0 & p & 0 & 0\\ A_1 & A_2 & 1 & 0\\ B_1 & B_2 & 0 & K\\ \end{matrix} \right)\\ (k_1,k_2,L_1,1)L=(L_2,L_3,L_1,K)\\ \](代码直接抄了)
from hashlib import md5
def MD5(m):return md5(str(m).encode()).hexdigest()
p = 181261975027495237253637490821967974838107429001673555664278471721008386281743
a = 80470362380817459255864867107210711412685230469402969278321951982944620399953
b = 108319759370236783814626433000766721111334570586873607708322790512240104190351
c = [2466192191260213775762623965067957944241015, 1889892785439654571742121335995798632991977, 1996504406563642240453971359031130059982231, 1368301121255830077201589128570528735229741, 3999315855035985269059282518365581428161659, 3490328920889554119780944952082309497051942, 2702734706305439681672702336041879391921064, 2326204581109089646336478471073693577206507, 3428994964289708222751294105726231092393919, 1323508022833004639996954642684521266184999, 2208533770063829989401955757064784165178629, 1477750588164311737782430929424416735436445, 973459098712495505430270020597437829126313, 1849038140302190287389664531813595944725351, 1172797063262026799163573955315738964605214, 1754102136634863587048191504998276360927339, 113488301052880487370840486361933702579704, 2862768938858887304461616362462448055940670, 3625957906056311712594439963134739423933712, 3922085695888226389856345959634471608310638]
h = [0] + c
length = len(h)
for i in range(length):
h[i] <<= 115
A = [1]
B = [0]
for i in range(1, len(h)-1):
A.append(a*A[i-1] % p)
B.append((a*B[i-1]+a*h[i]+b-h[i+1]) % p)
A = A[1:]
B = B[1:]
Ge = Matrix(ZZ,length,length)
for i in range(len(A)):
Ge[i,i] = p
Ge[-2,i] = A[i]
Ge[-1,i] = B[i]
K = 2**115
Ge[-2,-2] = 1
Ge[-1,-1] = K
for line in Ge.LLL():
if abs(line[-1]) == K:
L1 = line[-2]
seed1 = h[1] + L1
seed = (seed1 - b) * inverse_mod(a,p) % p
flag = '0xGame{' + MD5(int(seed)) + '}'
print(flag)
ECC-baby
from Crypto.Util.number import getPrime
from Crypto.Cipher import AES
from secret import key, flag
from random import randint
from hashlib import md5
from Util import *
def Pad(m):
while len(m) % 16 != 0: m += b'\x00'
return m
def MD5(m):
return md5(str(m).encode()).digest()
def Encrypt(E, G, P, m):
k = randint(1,E.p)
G_= k * G
P_= k * P
M = getrandpoint(E)
C = M + P_
Cipher = AES.new(MD5(M.x), AES.MODE_ECB)
enc = Cipher.encrypt( Pad(m) ).hex()
return (G_, C, enc)
p = 4559252311
a = 1750153947
b = 3464736227
curve = Curve(a, b, p)
G = getrandpoint(curve)
P = key * G
G_, C, enc = Encrypt(curve, G, P, flag)
print(f'G = {G }')
print(f'P = {P }')
print(f'G_= {G_}')
print(f'C = {C }')
print(f'enc= {enc}')
直接放sage里,求解离散对数问题得到k,就可以解密了
p = 4559252311
a = 1750153947
b = 3464736227
E = EllipticCurve(GF(p),[a,b]) #建立椭圆曲线E
G = E(2909007728,1842489211)
P = E(1923527223,2181389961)
G_= E(1349689070,1217312018)
C = E(662346568,2640798701)
k = G.discrete_log(G_)
M=C-k*P
from hashlib import md5
def MD5(m):
return md5(str(m).encode()).digest()
from Crypto.Cipher import AES
enc= "29bb47e013bd91760b9750f90630d8ef82130596d56121dc101c631dd5d88201a41eb3baa5aa958a6cd082298fc18418"
enc=bytes.fromhex(enc)
Cipher = AES.new(MD5(int(M.xy()[0])), AES.MODE_ECB)
flag = Cipher.decrypt(enc)
print(flag)
#b'0xGame{0b0e28c2-b36d-d745-c0be-fcf0986f316a}\x00\x00\x00\x00'
ECC-DH
#!/usr/local/bin/python
from Crypto.Cipher import AES
from hashlib import md5
from Util import *
from secret import flag
def MD5(m):return md5( str(m).encode() ).digest()
assert proof_of_work()
a = 10809567548006703521
b = 9981694937346749887
p = 25321837821840919771
E = Curve(a, b, p)
G = getrandpoint(E)
print(f'[+] Share G : {G}')
a = randint(1, E.p)
A = a * G
print(f'[+] Alice_PubKey : {A}')
B_x = int( input("[+] Give me the Bob_PubKey.x\n> ") )
B = Point(B_x, E.find_y(B_x), E)
print(f'[+] Bob_PubKey : {B}')
Share_Key = a*B
Cipher = AES.new(MD5(Share_Key.x), AES.MODE_ECB)
ct = Cipher.encrypt(flag)
print(f'[+] Alice tell Bob : {ct.hex()}')
我们发送G的x坐标,share_key就是Alice_Pubkey了
from string import ascii_letters, digits
from hashlib import sha256
from itertools import product
from pwn import *
context(log_level = 'debug')
ip = '118.195.138.159' #要netcat的ip
port = 10004 #端口
io = remote(ip,port)
def proof():
io.recvuntil(b'XXXX+')
proof = io.recvuntil(b')')[:-1]
io.recvuntil(b'== ')
hash = io.recvuntil(b'\n')[:-1].decode()
dict = ascii_letters + digits
for word in product(dict, repeat=4):
word = ''.join(word).encode()
if sha256( (word+proof) ).hexdigest() == hash: break
io.sendlineafter(b'XXXX: ',word)
proof() #交验证码
a = 10809567548006703521
b = 9981694937346749887
p = 25321837821840919771
E = EllipticCurve(GF(p),[a,b]) #建立椭圆曲线E
io.recvuntil(b'G : ')
G=eval(io.recvline().strip().decode())
G=E(G)
io.recvuntil(b'Alice_PubKey : ')
Alice_PubKey=eval(io.recvline().strip().decode())
Alice_PubKey=E(Alice_PubKey)
io.recvuntil(b'>')
io.sendline(str(int(G.xy()[0])).encode())
io.recvuntil(b'Alice tell Bob : ')
ct=io.recvline().strip().decode()
ct=bytes.fromhex(ct)
from hashlib import md5
def MD5(m):
return md5(str(m).encode()).digest()
from Crypto.Cipher import AES
Cipher = AES.new(MD5(int(Alice_PubKey.xy()[0])), AES.MODE_ECB)
flag = Cipher.decrypt(ct)
print(flag)
io.interactive() #进入交互模式
io.close()
EzLogin-I
#!/usr/local/bin/python
from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from datetime import datetime
from os import urandom
import json
from secret import flag1,flag2
MENU = "\
+--------------+\n\
| [R] Regist |\n\
| [L] Login |\n\
| [F] Getflag |\n\
+--------------+\n\
"
KEY = urandom(16)
def pad(data: bytes):
l = 16 - len(data) % 16
return data + bytes([l]*l)
def unpad(data: bytes):
for i in range(1, data[-1] + 1):
if data[-1] != data[-i]:
raise UnpadError("Unpad error")
return data[:-data[-1]]
def encrypt(data):
IV = urandom(16)
ENC = AES.new(KEY, AES.MODE_CBC, IV)
result = ENC.encrypt( pad( data.encode() ) )
return b64encode(IV + result).decode()
def decrypt(data):
data = b64decode(data)
IV, C = data[:16], data[16:]
DEC = AES.new(KEY, AES.MODE_CBC, IV)
result = DEC.decrypt( C )
return unpad(result).decode()
def register():
username = input("[+] username:\n>").strip()
if "admin" in username:
print("[!] Cannot register as admin user!")
else:
now = datetime.now()
time = int(datetime.timestamp(now))
cookie = {}
cookie["username"] = username
cookie["time"] = time
print(f'[+] cookie : {encrypt(json.dumps(cookie))}')
return
def login():
cookie = input("[+] cookie:\n>").strip()
try:
cookie = decrypt(cookie.encode())
cookie = json.loads(cookie)
username = cookie["username"]
except (json.decoder.JSONDecodeError):
print("[!] JSON Wrong")
return 0
except TypeError:
print("[!] TypeError Wrong")
return 0
except :
print("[!] Unkown Wrong")
return 0
if username == "admin":
print(f"[+] Here is flag1 : {flag1}")
else:
print(f"[+] Welcome to 0xGame2024 Crypto! {username}")
return 1
def getflag2():
print(f"[+] Here is flag2 : {encrypt(flag2)}")
return
print(MENU)
while True:
choice = input('[+] Tell me your choice:\n>')
if choice == 'R':
register()
elif choice == 'L':
while True:
if login():break
elif choice == 'F':
getflag2()
else:
print("[!] Invalid choice")
我们能够控制IV,那就简单了
主要就是CBC先解密在异或,我们需要的'admin'在第一个分组中,直接控制调IV对应的值就好了。
from pwn import *
from base64 import *
r=remote("118.195.138.159",10005)
r.recvuntil(b'>')
r.sendline(b'R')
r.recvuntil(b'>')
r.sendline(b'Admin')
r.recvuntil(b'cookie : ')
enc=r.recvline().strip()
enc = b64decode(enc)
IV, C = enc[:16], enc[16:]
"""
import json
cookie = {}
cookie["username"] = "username"
cookie["time"] = "time"
print(json.dumps(cookie))
#{"username": "username", "time": "time"}
"""
pre=b'{"username": "'
my_iv=b''
my_iv=IV[:len(pre)]+int.to_bytes(IV[len(pre)]^ord('A')^ord('a'))+IV[len(pre)+1:]
my_enc=my_iv+C
payload=b64encode(my_enc)
r.recvuntil(b'>')
r.sendline(b'L')
r.recvuntil(b'>')
r.sendline(payload)
r.interactive()
r.close()
EzLogin-II
附件同上题
原理我就不说了,可以跟着我的代码然后看La佬的博客块密码 | Lazzaro
讲讲这题我遇到的问题:
1.由于这个unpad是自定义的,观察就可以发现,最后一个字节为0x00的时候是百分百过的,所以如果不知道明文,就有点难受了,不然就多运行几次
2.decrypt()函数最后会对unpad后的结果进行decode(),所以就算unpad过了,这里也可以过不了,不能按教程一般说直接给key初始化成0,可以将key初始化成IV(处理后面几个块就是初始化成前一个块)
3.当你解决上面几个问题后,你还会发现,每次出的时候,会发现得到的结果前面几个字符会不正确,如果直接猜显然不符合密码人。经过自己本地调试,会发现,只剩前面几个字符的时候居然能json.loads,太坑了,这里就不能只看'JSON Wrong'了。根据服务器的回显,这里对应的是TypeError Wrong,所以可以两个一次判断(或者直接判断'Unkown Wrong'不在回显就好了)
from pwn import *
from base64 import *
r=remote("118.195.138.159",10005)
r.recvuntil(b'>')
r.sendline(b'F')
r.recvuntil(b'flag2 : ')
flag2=r.recvline().strip()
flag2 = b64decode(flag2)
IV, C = flag2[:16], flag2[16:]
r.recvuntil(b'>')
r.sendline(b'L')
block_size=16
block_count=len(C)//block_size
for i in range(block_count):
#IV=C[block_size*(i-1):block_size*(i-1)+block_size] #爆破后面几个块的时候用的
key=[0]*block_size
for j in range(block_size):
key[j]=IV[j]
tmp_flag=[0]*block_size
for j in range(block_size):
for k in range(256):
key[-j-1]=k
tmp_iv=bytes(key)
payload=tmp_iv+C[block_size*i:block_size*i+block_size]
payload=b64encode(payload)
r.recvuntil(b'>')
r.sendline(payload)
json_wrong=r.recvline()
if b'JSON' in json_wrong or b'TypeError' in json_wrong:
tmp_flag[-j-1]=k^(j+1)
#print(tmp_flag[-j-1]^IV[-j-1]) # 人工判断字符对不对,可以加个chr看字符
for l in range(j+1):
key[-l-1]=tmp_flag[-l-1]^(j+2)
break
flag=b''
for j in range(block_size):
flag+=int.to_bytes(tmp_flag[j]^IV[j])
print(flag)
IV=C[block_size*i:block_size*i+block_size]
r.close()
#b'0xGame{6e02937e-'
#634d-4f6f-8ef6-e
"""
# 本地调试,不懂的可以自己尝试在自己觉得有问题的地方print一下,看看结果符不符合自己预期
from base64 import *
from Crypto.Cipher import AES
from os import urandom
import json
KEY = urandom(16)
flag2='0xGame{04679c42-2bc1-42b2-b836-1b0ca542f36b}'
def pad(data: bytes):
l = 16 - len(data) % 16
return data + bytes([l]*l)
def unpad(data: bytes):
for i in range(1, data[-1] + 1):
if data[-1] != data[-i]:
raise UnpadError("Unpad error")
return data[:-data[-1]]
def encrypt(data):
IV = urandom(16)
ENC = AES.new(KEY, AES.MODE_CBC, IV)
result = ENC.encrypt( pad( data.encode() ) )
return b64encode(IV + result).decode()
def decrypt(j,data):
data = b64decode(data)
IV, C = data[:16], data[16:]
DEC = AES.new(KEY, AES.MODE_CBC, IV)
result = DEC.decrypt( C )
result=unpad(result)
result=result.decode()
return result
flag2=encrypt(flag2)
flag2 = b64decode(flag2)
IV, C = flag2[:16], flag2[16:]
block_size=16
block_count=len(C)//block_size
for i in range(block_count):
key=[0]*block_size
for j in range(block_size):
key[j]=IV[j]
tmp_flag=[0]*block_size
for j in range(block_size):
for k in range(256):
key[-j-1]=k
tmp_iv=bytes(key)
payload=tmp_iv+C[block_size*i:block_size*i+block_size]
payload=b64encode(payload)
try:
cookie = decrypt(j,payload)
cookie = json.loads(cookie)
print(i,j)
except (json.decoder.JSONDecodeError):
tmp_flag[-j-1]=k^(j+1)
for l in range(j+1):
key[-l-1]=tmp_flag[-l-1]^(j+2)
break
except TypeError:
print("[!] TypeError Wrong")
except :
pass
flag=b''
for j in range(block_size):
flag+=int.to_bytes(tmp_flag[j]^IV[j])
print(flag)
IV=C[block_size*i:block_size*i+block_size]
"""
标签:self,crypto,0xGame2024,flag,print,import,week3,data,block
From: https://www.cnblogs.com/naby/p/18508959