缘起
最近做到做到这道题, flag[42:48] = aes_256_ecb_decode("c6e1d72b1102f9b96b20c1f00cc7a178d5b3f99193faaa60e53b45b9e644d782", key)
, 自己用Py没解出来...
import binascii
from Crypto.Cipher import AES
data = binascii.unhexlify(b"c6e1d72b1102f9b96b20c1f00cc7a178d5b3f99193faaa60e53b45b9e644d782")
key = b"ctfhub".ljust(32, b'\0')
cipher = AES.new(key, AES.MODE_ECB)
data = cipher.decrypt(data)
print(data)
print(data.decode(errors='ignore'))
#b'\x91\xcf\xc0\x8f{P\xfc\xe6\xd6\\=\xfb\xcc\x97\xe0V\xa8\x9a\xec\xcfJLsb3x\x13>2& \x15'
#{P\=̗VJLsb3x>2&
磨难
自己尝试了在所有其他在线解密的网站均无法得出答案, 所以想是不是自己的padding搞错了, 所以我试试, 试了好几天, 无果. 那就配合这个网站再试, 看来下大佬们说要输出选hex, 想了想c6e1d72b1102f9b96b20c1f00cc7a178d5b3f99193faaa60e53b45b9e644d782
明显没有大于f的, 也就是hex, 尝试了换换其他参数, ECB, 256位, ctfhub, hex
必选其他随意. 然后发现我选no padding时Response是
{"status":1,"info":"ok","data":["62013}\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"]}
所以大概可以肯定就是b'\0'填充.
灵感
既然不是填充的问题, 解密也不成, 那我尝试加密看看有没有效果呢?失败.
import base64
from bf import _bf
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import binascii
import exrex
from itertools import product
# xuHXKxEC+blrIMHwDMeheNWz+ZGT+qpg5TtFueZE14I=
# Y3RmaHViAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
# c6e1d72b1102f9b96b20c1f00cc7a178d5b3f99193faaa60e53b45b9e644d782
key = b"ctfhub"
msg = b"62013}"
key = key.ljust(32, b"\0")
msg = msg.ljust(32, b"\0")
cipher = AES.new(key, AES.MODE_ECB)
msg_en = cipher.encrypt(msg).hex()
print(msg_en)
# b3742f3ac154cd15101618711eb4f3491c78ce108072c1d50c02f7951228a586
不过由此得知base64应该是xuHXKxEC+blrIMHwDMeheNWz+ZGT+qpg5TtFueZE14I=
. 忽然想到是不是语言的原因, 我用的Py, 在线的大部分应该是JS, 那么这个网站是什么呢?看了网页的Response:nginx,emmm,试了试dirsearch, 然后看了作者最开始的文章写的是wordpress搭建博客, 初步考虑是php. 好, 那就php, 搜了下php ecb写法, 失败.
<?php
$key = 'ctfhub';
$data = '62013}';
$encrypted = base64_encode(openssl_encrypt($data, "AES-256-ECB", $key, 1));
echo $encrypted;
# DGB0/QZE+e6J6JiC+gSZvw==
这是为啥呢?真是烦人啊. 看了看作者博客是14年搭建的, 那么google限制下时间是2014年及以前的, emmm, 写法没啥变化, 2010年及以前呢? mcrypt_encrypt映入眼帘, 看了眼文档MCRYPT_RIJNDAEL_256不是 AES-256,它是 Rijndael 分组密码的不同变体。
找了下ecb写法和在线的php网站, 终于成功了, 喜极而泣啊!
咱们就是说, 咱们就是说, 咱们就是说, 咱们就是说, 咱们就是说, 咱们就是说, 咱们就是说, 咱们就是说, 咱们就是说, 咱们就是说.
<?php
# php4
# https://onlinephp.io/
$key = 'ctfhub';
$plaintext = "62013}";
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key,
$plaintext, MCRYPT_MODE_ECB);
$ciphertext = $ciphertext;
$ciphertext_base64 = base64_encode($ciphertext);
echo $ciphertext_base64;
$ciphertext_dec = base64_decode($ciphertext_base64);
$plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key,
$ciphertext_dec, MCRYPT_MODE_ECB);
echo $plaintext_dec;
# xuHXKxEC+blrIMHwDMeheNWz+ZGT+qpg5TtFueZE14I=
# 62013}锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷
?>
成功
那么问题又来了, 咋用Py写呢? 看了网上的代码都是Py2的, 结果Py2也报错. 然后发现了py3rijndael, 魔改了一下py2的代码.
from py3rijndael.rijndael import Rijndael as rijndael
import base64
import binascii
KEY_SIZE = 16
BLOCK_SIZE = 32
def encrypt(key, plaintext):
padded_key = key.ljust(KEY_SIZE, b"\0")
padded_text = plaintext + (BLOCK_SIZE - len(plaintext) % BLOCK_SIZE) * b"\0"
r = rijndael(padded_key, BLOCK_SIZE)
ciphertext = b""
for start in range(0, len(padded_text), BLOCK_SIZE):
ciphertext += r.encrypt(padded_text[start : start + BLOCK_SIZE])
encoded = base64.b64encode(ciphertext)
return encoded
def decrypt(key, encoded):
padded_key = key.ljust(KEY_SIZE, b"\0")
ciphertext = base64.b64decode(encoded)
r = rijndael(padded_key, BLOCK_SIZE)
padded_text = b""
for start in range(0, len(ciphertext), BLOCK_SIZE):
padded_text += r.decrypt(ciphertext[start : start + BLOCK_SIZE])
plaintext = padded_text.split(b"\x00", 1)[0]
return plaintext
key = b"ctfhub"
text = b"62013}"
encoded = encrypt(key, text)
print(repr(encoded))
decoded = decrypt(
key,
base64.b64encode(
binascii.unhexlify(
b"c6e1d72b1102f9b96b20c1f00cc7a178d5b3f99193faaa60e53b45b9e644d782"
)
),
)
print(repr(decoded))
# b'xuHXKxEC+blrIMHwDMeheNWz+ZGT+qpg5TtFueZE14I='
# b'62013}'
想法
以后ctfhub的题第一想法就得是php环境去解题, 不行就上老版本.
功不唐捐啊!