因为 cryptohack 有声明不能随便在公网上发题解, 我就自己模仿了一道:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Util.number import bytes_to_long
import os
KEY = os.urandom(16)
FLAG = b"flag{cracked_AES_mode_ECB}"
def encrypt(plaintext):
padded = pad(plaintext + FLAG, 16)
aes_cipher = AES.new(KEY, AES.MODE_ECB)
try:
ciphertext = aes_cipher.encrypt(padded)
except ValueError as e:
return {"error": str(e)}
return {"ciphertext": hex(bytes_to_long(ciphertext))}
if __name__ == "__main__":
while(1):
ipt = input("get me plaintext: ").replace("n", "")
print(encrypt(ipt.encode()))
+------------------+-----------------------------------------+
| plaintext | FLAG + padding |
+------------------+-----------------------------------------+
+-----------------------------+-----------------------------------------+
| plaintext[:-1] + FLAG[0] | FLAG[1:] + padding |
+-----------------------------+-----------------------------------------+
$ python3 ecb.py
get me plaintext: AAAAAAAAAAAAAAA
{'ciphertext': '0xb02177b29a20ecafa81fd200a75a8602463dc67bbdf13d3381ca88032722bc3432852a5732a03d96f8d3304e11b19854'}
get me plaintext: AAAAAAAAAAAAAAAf
{'ciphertext': '0xb02177b29a20ecafa81fd200a75a86021d7f6e048bcfd0a8096edc1c3e92fd9ff1839cc000a2850e6b176ef2955ae65a'}
AAAAAAAAAAAAAAA
和加密 AAAAAAAAAAAAAAAf
得到的密文是一样的, 可以看到第一个块明文得到的密文都是b02177b29a20ecafa81fd200a75a8602
依次类推现在我输入AAAAAAAAAAAAAA和AAAAAAAAAAAAAAfl得到的结果是一样的。但是, 这样只能 leak 出 FLAG 的前 16 个字节。
这里的 flag 长度是 26,该怎么做?当然我们不会提前知道 flag 的长度,就需要我们自己去测试
padded = pad(plaintext + FLAG, 16)
chr(16- (len(plaintext)% 16))
。
$ python3 ecb.py
get me plaintext:
{'ciphertext': '0x1d7f6e048bcfd0a8096edc1c3e92fd9ff1839cc000a2850e6b176ef2955ae65a'}
get me plaintext: A
{'ciphertext': '0x949817ef138474006bb308a9e662a7eef493c81f9e71011fdc683a29e8136c2'}
get me plaintext: AA
{'ciphertext': '0x86e1a263789cf51be1abde312de355556b1d70a9579b7c65e38ec671508d687f'}
get me plaintext: AAA
{'ciphertext': '0x1c57f1b3b5e5ebff64d3f4a84ed358df7937551e0b09bbe8f38130a0dd910483'}
get me plaintext: AAAA
{'ciphertext': '0xc8e8483775163e1e66d3694efc835a964fd10885a86af40f5a7d6debed88b91f'}
get me plaintext: AAAAA
{'ciphertext': '0x5912c97a6f0c3c85cf7069c9522632cb2c61ec6bf5658a49ef3e3839e463de7c'}
get me plaintext: AAAAAA
{'ciphertext': '0x8022b3f5730d2a1605a88691259f6bc2ebbd0e0d23ab5c91955931da30512c5cb528aea0db7185345a43142e500da5a7'}
什么都不输入时密文的长度是32字节, 说明密文的长度小
于等于32大于等于16。
可以发现我们在输入6个A时密文长度发生了变化,就说明
实际上padding的长度是6。
flag的长度为:32-6=26
。现在知道了flag的长度为26,
我们需要开始构造 payload。
leak flag第一个字节的payload是:“A” * 31 + x(我懒得计算,直接padding到
两个块的大小-1,x是任意可见字符)。
步骤:
获取“A”*31的对应的密文 获取“A”*31+x的密文 对比“A”*31和“A”*31+x的密文, 若一样flag第一个字节就是x flag+=x
依次类推第二个字节:“A”*30+flag+y;密文一样flag+=y 第三个字节:“A”*29+flag+z;密文一样flag+=z … 使用 netcat 把脚本挂在任意端口上
ncat -vc "python3 ecb.py" -kl 4444
写 payload
from pwn import *
import string
dictionary = string.ascii_letters + "{}_"
r = remote("127.0.0.1", 4444)
r.recv()
payload = "A" * 31
flag_len = 26
flag = ""
enc = {}
for i in range(flag_len):
r.sendline(payload[:31 - i])
rmsg = r.recv().decode().split("'")[3]
enc[rmsg[:66]] = i
print(enc)
for _ in range(26):
for i in dictionary:
payload_t = payload[:31 - len(flag)] + flag + i
r.sendline(payload_t)
rmsg = r.recv().decode().split("'")[3]
if(rmsg[:66] in enc):
flag += i
print("[+] " + flag)
break
continue
$ python3 s.py
[127.0.0.1 on port 4444: Trying 127.0.0.1 ] Opening connection to
Ncat: Connection from 127.0.0.1.
[127.0.0.1 on port 4444: Done ] Opening connection to
{'0x4cc46e408643df98294c3a029b87a529e28ead847e5174b2f10408de75581d1b': 0, '0x4cc46e408643df98294c3a029b87a529e77f612771a72e186375695804e86e4b': 1, '0x4cc46e408643df98294c3a029b87a52912e4118061b66d5e94d70ae2ce784e19': 2, '0x4cc46e408643df98294c3a029b87a529cd749aaac684fd6491609e5e843e4579': 3, '0x4cc46e408643df98294c3a029b87a529cda6e90fcc48e4990530fbd9fc40012a': 4, '0x4cc46e408643df98294c3a029b87a52972c2b8fc24ffe34e14a1b6dc8a89549d': 5, '0x4cc46e408643df98294c3a029b87a529388fa7a21ce25f3d794e09f8ddcad45e': 6, '0x4cc46e408643df98294c3a029b87a529fe6311195ba985f312068395a1f62007': 7, '0x4cc46e408643df98294c3a029b87a5292919ce6419b4abe58b0f4fc77734c140': 8, '0x4cc46e408643df98294c3a029b87a5298ecb7c4951685e0b3dccbe8e71c9e271': 9, '0x4cc46e408643df98294c3a029b87a529b47a3f4e8aee1344e12f750d29c75043': 10, '0x4cc46e408643df98294c3a029b87a529f7021ab32f9741a071b7e6417246905c': 11, '0x4cc46e408643df98294c3a029b87a529cbbdcccadf2f314f503074e29ccab6ca': 12, '0x4cc46e408643df98294c3a029b87a529d2b44b726ab280f22f0c0cf6489800ed': 13, '0x4cc46e408643df98294c3a029b87a529a98f93e2454a22d4db76941869a24e26': 14, '0x4cc46e408643df98294c3a029b87a5297f332d05f521ad2ea18a9601d4278476': 15, '0xe28ead847e5174b2f10408de75581d1bff4c98ed808d0ffc5074275c691e9a84': 16, '0xe77f612771a72e186375695804e86e4bdf4d25f279e8c9b4cf58b94871e289c2': 17, '0x12e4118061b66d5e94d70ae2ce784e19c0a9dae9978c5cfe96820cac56af86c6': 18, '0xcd749aaac684fd6491609e5e843e4579dc5ac2bae75ea045f84e99488bad71e1': 19, '0xcda6e90fcc48e4990530fbd9fc40012aac2e0c742b37884dd0e3343238ee3475': 20, '0x72c2b8fc24ffe34e14a1b6dc8a89549d44e17809ee1edff1a3f71cf67602e8d9': 21, '0x388fa7a21ce25f3d794e09f8ddcad45e102296eab403ced8c4bd46586c26b3a0': 22, '0xfe6311195ba985f312068395a1f62007e8ead991da1cb947048878c28ea686d4': 23, '0x2919ce6419b4abe58b0f4fc77734c140bea486e51039708ae1c53ffc1f8d7adb': 24, '0x8ecb7c4951685e0b3dccbe8e71c9e271c78e0c81f59b9ca5b6d315fe8bc206cc': 25}
[ ] f
[ ] fl
[ ] fla
[ ] flag
[ ] flag{
[ ] flag{c
[ ] flag{cr
[ ] flag{cra
[ ] flag{crac
[ ] flag{crack
[ ] flag{cracke
[ ] flag{cracked
[ ] flag{cracked_
[ ] flag{cracked_A
[ ] flag{cracked_AE
[ ] flag{cracked_AES
[ ] flag{cracked_AES_
[ ] flag{cracked_AES_m
[ ] flag{cracked_AES_mo
[ ] flag{cracked_AES_mod
[ ] flag{cracked_AES_mode
[ ] flag{cracked_AES_mode_
[ ] flag{cracked_AES_mode_E
[ ] flag{cracked_AES_mode_EC
[ ] flag{cracked_AES_mode_ECB
[ ] flag{cracked_AES_mode_ECB}
点分享 点收藏 点点赞 点在看 本文始发于微信公众号(SecIN技术平台):原创 | ECB Byte-at-a-Time
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论