题目如下:
import binascii
import hashlib
from flag import flag
from Crypto.Cipher import AES
from Crypto.Util import *
import os
key1 = os.urandom(32)
key2 = b'tn*-ix6L*tCa*}i*'
key_len = len(key2)
assert flag.startswith(b'flag{')
assert (flag[13] == 45 and flag[18] == 45 and flag[23] == 45 and flag[28] == 45)
flag1 = b"2023: " + flag[:13] + flag[14:18] + flag[19:23]
flag2 =
h = binascii.unhexlify(hashlib.sha256(key2).hexdigest())[:11]
gift1 = b'***********************************************************************************************'
gift2 = b'I tell you this, for when my days have come to an end , you, shall be King.' + h
def encrypt1(message, key):
cipher = AES.new(key, AES.MODE_CTR, counter=Counter.new(128))
ciphertext = cipher.encrypt(message)
return ciphertext.hex()
def encrypt2(message, key, iv):
padding = bytes((key_len - len(message) % key_len) * '&', encoding='utf-8')
message += padding
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(message)
return ciphertext.hex()
print("enc_gift1 = " + encrypt1(gift1, key1))
print("enc_flag = " + encrypt1(flag1, key1))
print("enc_gift2 = " + encrypt2(gift2, key2, flag2))
# enc_gift1 = bad7dbcff968d7cdbf51da011fe94e176fc8e7528e4dd85d2d5fc20ba69cefb7bfd03152a2874705bd2d857ea75b3216a830215db74772d9b9e9c218271d562694d3642d2917972fdb8c7363d8125730a50824cd8dc7e34cd4fa54be427cca
# enc_flag = c1c78891e30cd4c0aa5ed65c17e8550429c4e640881f9f1d6a56df
# enc_gift2 = ********c********b**************4***5********3****6a*****a**2********c*8******7***********3***5***2********e*5*************a******5**c***74***********fee046b4d2918096cfa3b76d6622914395c7e28eef
题目使用AES-CTR工作模式对gift1和flag1进行加密,使用的是相同的密钥key1
根据CTR工作原理
gift1 ⊕ key1 = enc_gift1
flag1 ⊕ key1 = enc_flag1
我们计算enc_gift1 ⊕ enc_flag1 得到 gift1 ⊕ flag1 这个结果再 与 flag1异或计算,即可得到gift1
def xor(a,b):
temp = ""
for x, y in zip(a, b):
temp += chr(x ^ y)
return temp.encode('latin1')
enc_gift1 = 'bad7dbcff968d7cdbf51da011fe94e176fc8e7528e4dd85d2d5fc20ba69cefb7bfd03152a2874705bd2d857ea75b3216a830215db74772d9b9e9c218271d562694d3642d2917972fdb8c7363d8125730a50824cd8dc7e34cd4fa54be427cca'
enc_flag = 'c1c78891e30cd4c0aa5ed65c17e8550429c4e640881f9f1d6a56df'
enc_flag = bytes.fromhex(enc_flag)
enc_gift1 = bytes.fromhex(enc_gift1)[:len(enc_flag)]
gift1 = xor(xor(enc_flag,enc_gift1),b"2023: flag{")
# print(gift1)
#gift1: b'I am Deathw'
通过计算,得到gift1的值为 I am Deathw 根据题目名Neltharion_and_Arthas搜索一下,发现《魔兽》系列游戏及其衍生作品中的角色,角色台词语录内容如下:
I am Deathwing, the destroyer, the end of all things,inevitable,indomitable,I am the cataclysm
因此,gift1的内容就是I am Deathwing, the destroyer, the end of all things,inevitable,indomitable,I am the cataclysm
第二部分题目使用AES-CBC模式对gift2进行加密,key2作为对称密钥,flag2作为初始向量iv
由于key2有4个字符不确定,所以需要对key2进行暴力破解,但是我们需要寻找猜解时的验证条件。
AES分组长为16字节,enc_gift2给出的信息就是最后一个密文分组918096cfa3b76d6622914395c7e28eef以及倒数第二个密文分组的后5个字节fee046b4d2
h = binascii.unhexlify(hashlib.sha256(key2).hexdigest())[:11]
gift2 = b'I tell you this, for when my days have come to an end , you, shall be King.'+h
这两行可知,gift2的明文长度不满足其分组长,最后一个分组只有6个字符,还需要填充10个字符
padding = bytes((key_len - len(message) % key_len) * '&', encoding='utf-8')
这一行代码可知,这里填充的字符是 & ,也就是说倒数第二个明文分组的最后十个字符是 &
根据填充字符是&这一条件,再结合CBC模式的加密过程,可以用最后一个密文分组AES用key2解密再与其前一个分组的密文分组进行异或计算,最后十个字符若都是 & 则证明该key2是正确的。通过这个条件,可以得到key2。解密代码如下:
charlist = printable[:95]
pad_10chars = "fee046b4d2"
LastBlock = bytes.fromhex("918096cfa3b76d6622914395c7e28eef")
pad_c = bytes.fromhex(pad_10chars)
def brute_forcing():
for x in tqdm(charlist):
for y in charlist:
for z in charlist:
for w in charlist:
key2 = 'tn%s-ix6L%stCa%s}i%s' % (x, y, z, w)
cipher = AES.new(key2.encode(), AES.MODE_ECB)
message = cipher.decrypt(LastBlock)
pad_m = xor(message[-5:], pad_c)
if pad_m == b"&" * 5:
return key2
key2 = brute_forcing()
#key2:tn5-ix6L#tCaG}i6
得到key2之后需要求初始向量flag2,再回想CBC模式的加密流程图,我们现在知道明文gift2以及最后一个密文分组enc_gift2,那么就将最后一个密文分组解密,再与最后一个明文分组异或,得到前一个密文分组,再将其与对应的明文分组异或,得到前前一个密文分组......以此类推,我们就能得到初始向量flag2的值,解密代码如下:
key2 = b'tn5-ix6L#tCaG}i6'
h = binascii.unhexlify(hashlib.sha256(key2).hexdigest())[:11]
gift2 = b'I tell you this, for when my days have come to an end , you, shall be King.' + h + b'&'*10
Last_Cipher_Block = "918096cfa3b76d6622914395c7e28eef"
now_cipher = bytes.fromhex(Last_Cipher_Block)
for temp in range(6):
mBlock = gift2[80-temp*16:96-temp*16]
# print(mBlock)
dec_ = AES.new(key2,AES.MODE_ECB)
dec_m = dec_.decrypt(now_cipher)
pre_cipher = xor(dec_m,mBlock)
now_cipher = pre_cipher
print(now_cipher.decode())
#flag2:a3eae82b4c491e0e
合起来就就是正确答案了