2日目の朝8時に起きて「SECCON予選そういえば今日までじゃん」となったので解きました。
個人チームfelviで参加して229位/799位、266ptsでした。
coffee_break以外にもBeeeeeeeeeerなども解きましたが解説がしんどいので他のつよつよの方に譲ります……
coffee_break (crypto)
encrypt.py
import sys
from Crypto.Cipher import AES
import base64
def encrypt(key, text):
s = ''
for i in range(len(text)):
s += chr((((ord(text[i]) - 0x20) + (ord(key[i % len(key)]) - 0x20)) % (0x7e - 0x20 + 1)) + 0x20)
return s
key1 = "SECCON"
key2 = "seccon2019"
text = sys.argv[1]
enc1 = encrypt(key1, text)
cipher = AES.new(key2 + chr(0x00) * (16 - (len(key2) % 16)), AES.MODE_ECB)
p = 16 - (len(enc1) % 16)
enc2 = cipher.encrypt(enc1 + chr(p) * p)
print(base64.b64encode(enc2).decode('ascii'))
# ここまで元のコード
# 元のコードの下に追記
def decrypt(key, s):
text = ""
for i in range(len(s)):
temp = ord(s[i]) - ord(key[i % len(key)]) + 0x20
while(temp < 0x20):
temp += 95
text += chr(temp)
return text
enctext = "FyRyZNBO2MG6ncd3hEkC/yeYKUseI/CxYoZiIeV2fe/Jmtwx+WbWmU1gtMX9m905"
enc2 = cipher.decrypt(base64.b64decode(enctext)).decode("ascii")
print(decrypt(key1, enc2))
encrypt.pyは二段階で暗号化していて、
enc1の1段階目でを文字をずらし、
enc2の2段階目でAES暗号化をしているだけです。
それを逆順にたどっていけば元の文字列が出てきます。
後ろに余計な文字がくっついていますが、これはAES暗号化する平文が16バイトの倍数でなければならず適当な文字でパディングをしているためです。
encrypt.py
enc2 = cipher.encrypt(enc1 + chr(p) * p)
なので}以降は無視して送信しましょう。
flag.txt
SECCON{Success_Decryption_Yeah_Yeah_SECCON}?AA56