NewStarCTF flip-flop 复现(CBC字节翻转攻击)
NewStarCTF flip-flop 复现(CBC字节翻转攻击)
本来是一道nc题. 这里复现就把拿到admin权限为目标了.
题目
import os
from Crypto.Cipher import AES
auth_major_key = os.urandom(16) # 密钥
from flag import secret
BANNER = """
Login as admin to get the flag !
"""
MENU = """
Enter your choice
[1] Create NewStarCTF Account
[2] Create Admin Account
[3] Login
[4] Exit
"""
print(BANNER)
def bxor(b1, b2): # 二进制内容异或
result = b""
for b1, b2 in zip(b1, b2):
result += bytes([b1 ^ b2])
return result
while True:
print(MENU)
option = int(input('> '))
if option == 1:
auth_pt = b'NewStarCTFer____' # 明文
user_key = os.urandom(16) # iv
cipher = AES.new(auth_major_key, AES.MODE_CBC, user_key)
code = cipher.encrypt(auth_pt) # 加密得到密文code
print(f'here is your authcode: {user_key.hex() + code.hex()}') # 给出iv和密文
elif option == 2:
print('GET OUT !!!!!!')
elif option == 3:
authcode = input('Enter your authcode > ')
user_key = bytes.fromhex(authcode)[:16] # 解密iv
code = bytes.fromhex(authcode)[16:] # 需解密的密文
cipher = AES.new(auth_major_key, AES.MODE_CBC, user_key)
auth_pt = cipher.decrypt(code) # 解出的明文
if auth_pt == b'AdminAdmin______': # 目标明文
a = user_key.hex() + code.hex()
print(a)
elif auth_pt == b'NewStarCTFer____':
print('Have fun!!')
else:
print('Who are you?')
elif option == 4:
print('ByeBye')
exit(0)
else:
print("WTF")
明文16字节, 故加解密时不考虑分割.
属于CBC字节翻转攻击.
CBC加密模式原理如下:
初始给定向量iv, 对明文加密,上一次的密文为下一次加密的iv.
解题思路
我们要得到admin权限,需要把解密得到的明文从'NewStarCTFer____'
改成'AdminAdmin______'
.
但是不能通过修改最后的密文来实现(因为密钥未知).
所以我们只能从iv下手了.
对于最后一次加密,设密文为m, iv(上一次加密得到的密文)为Cn-1, 加密得到密文为Cn, 我们需要明文从m改为m', 需要将Cn改为C'n.
把一次加解密过程抽象为函数Enc()
和Dec()
则能推出:
\[Enc(m\oplus C_{n-1}) = C_n\\
\Rightarrow m = Dec(C_n)\oplus C_{n-1}...(1)\\
\]
同理得到:
\[m' = Dec(C_n)\oplus C'_{n-1}...(2)
\]
将(1)式与(2)式异或:
\[m\oplus m' = C_{n-1}\oplus C'_{n-1}\\
C'_{n-1} = m\oplus m' \oplus C_{n-1}
\]
我们将其前推到第一次加密, 可得:
\[iv' = m\oplus m' \oplus iv
\]
由此可以写出攻击解密脚本.
Exp
def bxor(b1, b2): # 对二进制数据进行异或
result = b""
for b_1, b_2 in zip(b1, b2):
result += bytes([b_1 ^ b_2])
return result
authcode = "" # 这里是得到的数据
user_key = bytes.fromhex(authcode)[:16] # 拿出iv
code = bytes.fromhex(authcode)[16:] # 结果密文
user_key = bxor(user_key, b'AdminAdmin______') # 异或目标明文
user_key = bxor(user_key, b'NewStarCTFer____') # 异或原明文
authcode = user_key.hex() + code.hex() # 最终结果:经过构造的authcode
print(authcode)
最后感谢猫神和黄gg的帮助.