crypto

1.mid_math

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from sage.all import *
from Crypto.Util.number import *
from tqdm import tqdm
from random import randint
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

flag = b'LILCTF{test_flag}'

p = getPrime(64)
P = GF(p)

key = randint(2**62, p)

def mul(vector, c):
return [vector[0]*c, vector[1]*c, vector[2]*c, vector[3]*c, vector[4]*c]

v1 = [getPrime(64), getPrime(64), getPrime(64), getPrime(64), getPrime(64)]
v2 = [getPrime(64), getPrime(64), getPrime(64), getPrime(64), getPrime(64)]
v3 = [getPrime(64), getPrime(64), getPrime(64), getPrime(64), getPrime(64)]
v4 = [getPrime(64), getPrime(64), getPrime(64), getPrime(64), getPrime(64)]
v5 = [getPrime(64), getPrime(64), getPrime(64), getPrime(64), getPrime(64)]
a, b, c, d, e = getPrime(64), getPrime(64), getPrime(64), getPrime(64), 0

A = matrix(P, [v1, v2, v3, v4, v5])
B = matrix(P, [mul(v1,a), mul(v2,b), mul(v3, c), mul(v4, d), mul(v5, e)])
C = A.inverse() * B
D = C**key

key = pad(long_to_bytes(key), 16)
aes = AES.new(key,AES.MODE_ECB)
msg = aes.encrypt(pad(flag, 64))

print(f"p = {p}")
print(f'C = {[i for i in C]}'.replace('(', '[').replace(')', ']'))
print(f'D = {[i for i in D]}'.replace('(', '[').replace(')', ']'))
print(f"msg = {msg}")

#p = 14668080038311483271
#C = [[11315841881544731102, 2283439871732792326, 6800685968958241983, 6426158106328779372, 9681186993951502212], [4729583429936371197, 9934441408437898498, 12454838789798706101, 1137624354220162514, 8961427323294527914], [12212265161975165517, 8264257544674837561, 10531819068765930248, 4088354401871232602, 14653951889442072670], [6045978019175462652, 11202714988272207073, 13562937263226951112, 6648446245634067896, 13902820281072641413], [1046075193917103481, 3617988773170202613, 3590111338369894405, 2646640112163975771, 5966864698750134707]]
#D = [[1785348659555163021, 3612773974290420260, 8587341808081935796, 4393730037042586815, 10490463205723658044], [10457678631610076741, 1645527195687648140, 13013316081830726847, 12925223531522879912, 5478687620744215372], [9878636900393157276, 13274969755872629366, 3231582918568068174, 7045188483430589163, 5126509884591016427], [4914941908205759200, 7480989013464904670, 5860406622199128154, 8016615177615097542, 13266674393818320551], [3005316032591310201, 6624508725257625760, 7972954954270186094, 5331046349070112118, 6127026494304272395]]
#msg = b"\xcc]B:\xe8\xbc\x91\xe2\x93\xaa\x88\x17\xc4\xe5\x97\x87@\x0fd\xb5p\x81\x1e\x98,Z\xe1n`\xaf\xe0%:\xb7\x8aD\x03\xd2Wu5\xcd\xc4#m'\xa7\xa4\x80\x0b\xf7\xda8\x1b\x82k#\xc1gP\xbd/\xb5j"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from sage.all import *

p = 14668080038311483271
F = GF(p)

# 定义矩阵 C 和 D
C = matrix(F, [
[11315841881544731102, 2283439871732792326, 6800685968958241983, 6426158106328779372, 9681186993951502212],
[4729583429936371197, 9934441408437898498, 12454838789798706101, 1137624354220162514, 8961427323294527914],
[12212265161975165517, 8264257544674837561, 10531819068765930248, 4088354401871232602, 14653951889442072670],
[6045978019175462652, 11202714988272207073, 13562937263226951112, 6648446245634067896, 13902820281072641413],
[1046075193917103481, 3617988773170202613, 3590111338369894405, 2646640112163975771, 5966864698750134707]
])

D = matrix(F, [
[1785348659555163021, 3612773974290420260, 8587341808081935796, 4393730037042586815, 10490463205723658044],
[10457678631610076741, 1645527195687648140, 13013316081830726847, 12925223531522879912, 5478687620744215372],
[9878636900393157276, 13274969755872629366, 3231582918568068174, 7045188483430589163, 5126509884591016427],
[4914941908205759200, 7480989013464904670, 5860406622199128154, 8016615177615097542, 13266674393818320551],
[3005316032591310201, 6624508725257625760, 7972954954270186094, 5331046349070112118, 6127026494304272395]
])

# 计算特征值(忽略0)
eig_C = [x for x in C.eigenvalues() if x != 0] # 提取C的非零特征值
eig_D = [x for x in D.eigenvalues() if x != 0] # 提取D的非零特征值

# 对每一对特征值解离散对数
for lambda_i, mu_i in zip(eig_C, eig_D): # 将非零特征值配对
try:
# 在指定范围内求解离散对数: μ_i ≡ λ_i^key mod p
key = discrete_log(mu_i, F(lambda_i), bounds=(262, p))
print(f"Potential key from eigenvalues: {key}")

# 验证 key 是否正确
if C
key == D: # 检查 C^key 是否等于 D
print(f"Verified key: {key}")
break # 找到正确密钥则停止
except ValueError: # 处理离散对数无解的情况
continue
1
2
3
4
5
Potential key from eigenvalues: 977169478748826373
Potential key from eigenvalues: 9711059833940755678
Potential key from eigenvalues: 96997216499095342
Potential key from eigenvalues: 5273966641785501202
Verified key: 5273966641785501202

这个key我也验算过了,没有问题,但是正常AES-ECB解密没办法解,ai写的也不行,于是我去查了一下key未满16字节的填充方式:缺几个字节就补成几,比如缺8个字节,就补08*8(转成16进制之后)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import unpad
from Cryptodome.Util.number import long_to_bytes

# 原始密文
msg = b"\xcc]B:\xe8\xbc\x91\xe2\x93\xaa\x88\x17\xc4\xe5\x97\x87@\x0fd\xb5p\x81\x1e\x98,Z\xe1n`\xaf\xe0%:\xb7\x8aD\x03\xd2Wu5\xcd\xc4#m'\xa7\xa4\x80\x0b\xf7\xda8\x1b\x82k#\xc1gP\xbd/\xb5j"

# 已知的密钥数值
key_int = 5273966641785501202

# 将整数密钥转换为字节
key_bytes = long_to_bytes(key_int)

# 已知密钥字节长度(5273966641785501202 = 0x493A4EEDB9EC0F2 -> 7字节)
key_len = len(key_bytes) # 应该是7字节

# 尝试所有可能的填充长度(1-16字节)
for pad_len in range(1, 17):
# 构建可能的密钥(原始密钥 + PKCS#7填充)
possible_key = key_bytes + bytes([pad_len]) * pad_len

# 取前16字节作为密钥
if len(possible_key) < 16:
aes_key = possible_key.ljust(16, b'\x00') # 确保长度16
else:
aes_key = possible_key[:16]

# 尝试解密
try:
cipher = AES.new(aes_key, AES.MODE_ECB)
decrypted = cipher.decrypt(msg)

# 尝试解填充
unpadded = unpad(decrypted, 64) # 原始块大小64

# 检查flag前缀
if unpadded.startswith(b'LILCTF{') and b'}' in unpadded:
flag = unpadded.decode('utf-8')
print(f"✓ 成功解密! 填充长度: {pad_len}")
print(f"使用的密钥: {aes_key.hex()}")
print(f"Flag: {flag}")
break

except (ValueError, UnicodeDecodeError):
# 尝试不解填充直接检查
if b'LILCTF{' in decrypted:
# 找到flag的起始位置
start_idx = decrypted.index(b'LILCTF{')
end_idx = decrypted.find(b'}', start_idx)
if end_idx != -1:
flag = decrypted[start_idx:end_idx + 1].decode('utf-8')
print(f"✓ 找到flag! 填充长度: {pad_len}")
print(f"使用的密钥: {aes_key.hex()}")
print(f"Flag: {flag}")
break
else:
print(f"⚠ 发现部分flag但没有结束符: {decrypted[start_idx:].decode('utf-8', errors='replace')}")
else:
# 检查常见的填充错误
last_byte = decrypted[-1]
if 0 < last_byte <= 64:
# 可能是无效的PKCS#7填充
possible_unpadded = decrypted[:-last_byte]
if b'LILCTF{' in possible_unpadded:
print(f"⚠ 可能有效: 填充长度 {pad_len}, 解密数据后{len(decrypted)}字节")
# 进一步检查


1
2
3
4
0x4930e4b7d0e27612
✓ 成功解密! 填充长度: 8
使用的密钥: 4930e4b7d0e276120808080808080808
Flag: LILCTF{Are_y0u_5till_4wake_que5t1on_m4ker!}