这道题来自NewStar CTF

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
from Crypto.Cipher import AES
from Crypto.Util.number import *
import os

KEY = b"fake_key_fake_ke"
FLAG = "flag{fake_flag_fake_flag}"

def decrypt(c):
AES_ECB = AES.new(KEY, AES.MODE_ECB)
decrypted = AES_ECB.decrypt(long_to_bytes(c))

return decrypted.hex()

def encrypt():
iv = os.urandom(16)
AES_CBC = AES.new(KEY, AES.MODE_CBC, iv)
encrypted = AES_CBC.encrypt(FLAG.encode())
print('iv:',iv.hex())

return iv.hex() + encrypted.hex()

c=encrypt()
print('encrypt:',c)
print('decrypt:',decrypt(int(c,16)))

#encrypt: f2040fe3063a5b6c65f66e1d2bf47b4cddb206e4ddcf7524932d25e92d57d3468398730b59df851cbac6d65073f9e138
#什么是AES啊😭,求求你帮我解密吧,我什么都会做的!!!!!😭

'''
什么都会做?那就去学习一下AES吧……
我这次就先给你解一下好了,不用谢喵
decrypt: f9899749fec184d81afecd35da430bc394686e847d72141b3a955a4f6e920e7d91cb599d92ba2a6ba51860bb5b32f23b
这对吗?哦不对不对,哦对的对的。
'''

可以看到加密使用CBC模式,解密是用ECB模式,这样肯定是会出错的,我们先要想想这么操作会发生什么?

CBC依赖于初始向量IV和key,每个后续块依赖于前一个加密块(通过 XOR 操作,先异或再单独加密)

ECB只有单一的key,解密特点是一对一,也就是说解密是块独立的

我们需要先将这两个字符串转换成字节形式并分块(这里是16字节一块),方便AES后续计算

由于CBC解密时,是当前块先解密再和前一个加密块异或,那么现在当前独立的解密块知道了,前一个加密块也知道了,不久可以进行还原了吗
这里还有一个细节,因为出题人是将iv加在前面的,而又因为16个字节一组,所以这并不影响我们获取flag,不用管加密的第一组块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from binascii import unhexlify

cbc_en = 'f2040fe3063a5b6c65f66e1d2bf47b4cddb206e4ddcf7524932d25e92d57d3468398730b59df851cbac6d65073f9e138'
ecb_de = 'f9899749fec184d81afecd35da430bc394686e847d72141b3a955a4f6e920e7d91cb599d92ba2a6ba51860bb5b32f23b'

cbc_bytes = unhexlify(cbc_en)
ecb_bytes = unhexlify(ecb_de)

cbc_blocks = [cbc_bytes[i:i + 16] for i in range(0, len(cbc_bytes), 16)]
ecb_blocks = [ecb_bytes[i:i + 16] for i in range(0, len(ecb_bytes), 16)]

decrypted_blocks = []

for i in range(1, len(cbc_blocks)):
current_cbc_block = cbc_blocks[i]
previous_cbc_block = cbc_blocks[i - 1]
decrypted_block = ecb_blocks[i]

recovered_block = bytes(a ^ b for a, b in zip(decrypted_block, previous_cbc_block))
decrypted_blocks.append(recovered_block)

final_decrypted_bytes = b''.join(decrypted_blocks)
print(final_decrypted_bytes)