-
Notifications
You must be signed in to change notification settings - Fork 64
/
mitm_exp3.py
109 lines (93 loc) · 3.09 KB
/
mitm_exp3.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import os
os.environ['PWNLIB_NOTERM'] = "true"
from pwn import remote
from sage.all import *
# context.log_level = 'debug'
r = remote('127.0.0.1', 10041)
r.recvuntil('token: ')
r.sendline('这里填写你的 token')
r.recvuntil('? ')
r.sendline('3')
def enc(name, extra):
r.recvuntil('? ')
r.sendline('Alice')
r.recvuntil('? ')
r.sendline(name.hex())
r.recvuntil('? ')
r.sendline(extra.hex())
r.recvuntil(':\n')
return bytes.fromhex(r.recvline().decode().strip())
def check(cipher):
r.recvuntil('? ')
r.sendline('Bob')
r.recvuntil(': ')
r.sendline(cipher.hex())
reply = r.recvline()
return b'Thanks' in reply
assert check(enc(b'abc', b'def'))
# 16 IV
# 7 text
# ? name
# 21 text
# flag
# ? extra
# 16 crc128
# 16 padding
def xor(b1, b2):
return bytes([x ^ y for x, y in zip(b1, b2)])
def crc128(msg):
crc = (1 << 128) - 1
for b in msg:
crc ^= b
for _ in range(8):
crc = (crc >> 1) ^ (0xB595CF9C8D708E2166D545CF7CFDD4F9 & -(crc & 1))
return (crc ^ ((1 << 128) - 1)).to_bytes(16, "big")
l = len(enc(b'', b''))
payload = b''
while len(enc(b'', payload)) == l:
payload += b'a'
flaglen = l + 16 - 16 - 16 - 16 - 7 - 21 - len(payload)
print(flaglen)
N = 150
flag = b''
while len(flag) < flaglen:
namelen = 16 - (7 + 21 + flaglen - len(flag)) % 16 + 1 + 16 + 16 * N
prefixlen = 7 + namelen + 21 + flaglen - len(flag) - 1
assert prefixlen % 16 == 0
ct = enc(namelen * b'a', b'a' * 32)
blk_flagprev_c = ct[prefixlen: prefixlen + 16]
blk_flag_c = ct[prefixlen + 16: prefixlen + 16 + 16]
blk_flagnext_c = ct[prefixlen + 32: prefixlen + 16 + 32]
blk_flagnext_p = (b'_' + flag + b'a' * 32)[16:32]
changes = []
strs = []
for i in range(N):
blk0_c = ct[16 * i + 16: 16 * i + 16 + 16]
blk1_c = ct[16 * i + 32: 16 * i + 16 + 32]
blk1_p = b'a' * 16
change = xor(xor(xor(blk0_c, blk1_p), blk_flag_c), blk_flagnext_p) + xor(blk1_c, blk_flagnext_c)
strs.append(b'\x00' * 16 * (i + 1) + change + b'\x00' * 16 * (N - 1 - i))
changes.append(crc128(strs[-1]))
A = Matrix(GF(2), 128, N)
for i in range(128):
for j in range(N):
A[i, j] = (int.from_bytes(changes[j], 'big') >> i) & 1
for c in range(256):
blk_flag_p = (bytes([c]) + flag + b'a' * 32)[:16]
target = xor(xor(xor(b"Thanks aaaaaaaaa", ct[:16]), blk_flagprev_c), blk_flag_p) + xor(ct[16:32], blk_flag_c)
target_str = target + b'\x00' * 16 * N
target = crc128(target_str)
B = vector(GF(2), 128)
for i in range(128):
B[i] = (int.from_bytes(target, 'big') >> i) & 1
result = A.solve_right(B)
# x = b'\x00' * 16 * (N + 1)
# for i in range(N):
# if result[i]:
# x = xor(x, strs[i])
# assert crc128(x) == target
payload = ct[:16] + blk_flag_c + b''.join(blk_flagnext_c if result[i] else ct[16 * i + 32: 16 * i + 16 + 32] for i in range(N)) + ct[16+16+16*N:]
if check(payload):
flag = bytes([c]) + flag
print(flag)
break