ECB Orcale
ECB
Orcale属于选择明文攻击,需要拥有对明文的一定加密权限。
其利用了ECB加密模式不能抵抗 Replay
Attacks(重放攻击)的特点。
攻击原理
目标Orcale常形如固定后缀,对于攻击者传递的字符串m,该Orcale会将(m+flag)填充后加密之。
此时,攻击者可以先爆破出flag的长度,随后通过控制m,将待加密的明文(填充后的)制备为形如“控制域+填充域+待解域”的形式。
以block大小为16为例,各个域的说明如下:
控制域:大小为16,每次爆破控制域中的第i位,使之遍历 \((0,255)\)。该位其前的内容应为已解密内容,其后的内容应与“待解域”的填充部分全等。
填充域:大小为16*k(\(k \in Z_+\)),通过调整m,该域内容应为任意内容 + flag的待解密其它部分。
待解域:大小为16,该域内容中应为待解密的一位c + 已解密的flag + 填充部分。
核心是利用ECB加密各部分相独立的特性,让控制域和待解域的内容进行碰撞;一旦加密得到的密文相同,说明明文也一定相同,此时就碰撞得到了flag的一位。
攻击实现
假设加密orcale形如下文:
1
2
3
4
5
6
7
8
9
10
11
12
13
14from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from secret import flag,key
def encrypt(msg:bytes):
aes = AES.new(key,AES.MODE_ECB)
plain = pad(msg+flag,16)
return aes.encrypt(plain).hex()
if __name__=='__main__':
while True:
ipt = bytes.fromhex(input('encrypt :'))
cipher = encrypt(ipt)
print(f'result : {cipher}')
我们的攻击思路:
1.
爆破出flag的长度(或,构造临界点,即让我们知道初始状态下应如何做才能控制“待解域”的填充部分已知)。
2. 对于第i位,构造明文(控制域+填充域+待解域的非填充部分),传递之
3.
若加密结果第一组和最后一组相同,说明得到碰撞,即获得了flag的一位。如此重复,直至明文全部解密完成
“临界点”:当添加一个
byte
的明文后,发现得到cipher的长度增加了16(BLOCK_SIZE
),这是因为pad
的规则要求填充位数不能为0。因此,此时实际被加密的明文恰好就是(
msg + flag + b'\x10' * 16
)。如果再给msg添加1位,就可以把flag的一位“挤”到后面(当然,相应的填充内容也会变成
b'\x0f'
)。(为了保证控制域的内容完全可控,msg应当从16位开始,或者在临界点后再向msg添加17位开始爆破)
1 | from pwn import * |
Symmetry
游戏链接:
Cryptohack
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
30from Crypto.Cipher import AES
KEY = ?
FLAG = ?
def encrypt(plaintext, iv):
plaintext = bytes.fromhex(plaintext)
iv = bytes.fromhex(iv)
if len(iv) != 16:
return {"error": "IV length must be 16"}
cipher = AES.new(KEY, AES.MODE_OFB, iv)
encrypted = cipher.encrypt(plaintext)
ciphertext = encrypted.hex()
return {"ciphertext": ciphertext}
def encrypt_flag():
iv = os.urandom(16)
cipher = AES.new(KEY, AES.MODE_OFB, iv)
encrypted = cipher.encrypt(FLAG.encode())
ciphertext = iv.hex() + encrypted.hex()
return {"ciphertext": ciphertext}
本题的核心点在于OFB这个模式的“对称性”:OFB中并没有所谓“解密”操作(虽然很多流密码其实都没有解密操作,“加密”只是生成密钥流的过程,最终将该流和明文异或而得)。
考虑OFB的加密过程如图:
显然,只要攻击者获得了前一组密文并拥有加密权限,则其传递该组密文作为"iv",即可解密后一组密文。
进一步地,若攻击者拥有全部的密文和iv,则其可以解密全部明文(将iv和密文再走一遍加密流程即可)。
exp即为获得(iv+密文)后直接传回交互式窗口,decode即可。
flag: crypto{0fb_15_5ymm37r1c4l_!!!11!}