-
Notifications
You must be signed in to change notification settings - Fork 0
/
12.py
executable file
·61 lines (49 loc) · 1.59 KB
/
12.py
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env python3
import secrets
from collections import Counter
from mycrypto import aes_128_ecb_encrypt, chop, detect_ecb_basic, read_b64
k = secrets.token_bytes(16)
suffix = read_b64('data/12.txt')
def oracle(p: bytes) -> bytes:
return aes_128_ecb_encrypt(p + suffix, k)
# only works without prefix
def guess_bs() -> int:
for bs in range(4, 64):
c = oracle(b'a' * bs * 2)
freq = Counter(chop(c, bs))
if max(freq.values()) > 1:
return bs
return -1
def solve_ecb_suffix(bs: int) -> bytes:
suffix = b''
prev = b'a' * bs
# might not be accurate due to padding but whatever
num_blocks = len(chop(oracle(b'')))
# i is the block where the leak is happening
for i in range(num_blocks):
known = b''
while len(known) < bs:
input_block = prev[len(known) + 1:]
leak = chop(oracle(input_block))[i]
lookup = {}
for guess in range(128):
plain = input_block + known + bytes([guess])
outcome = chop(oracle(plain))[0]
lookup[outcome] = guess
try:
known += bytes([lookup[leak]])
except Exception:
# hit the padding
# last byte is unneeded
return (suffix + known)[:-1]
assert len(known) == bs
suffix += known
prev = known
return suffix
def main():
bs = guess_bs()
assert bs == 16
assert detect_ecb_basic(oracle(b'a' * bs * 4))
print(solve_ecb_suffix(bs).decode('ascii'))
if __name__ == "__main__":
main()