-
Notifications
You must be signed in to change notification settings - Fork 66
Open
Labels
Description
我没找到有人写这题非预期解的实现,故按题解中的描述实现了一份(还挺快的):
from pwn import *
from hashlib import sha256
from utils import *
import time
is_remote = True if 1 == 1 else False # chang this for switch remote/local
if is_remote:
r = remote('202.38.93.111', 10041)
r.sendlineafter('token:', 'xxx:yyy') # your token
else:
r = process(['python3', './entry.py'])
r.sendlineafter('to play (1/2/3)? ', '3') # chang this for switch task2/3
def enc(prefix, suffix):
r.sendlineafter('talk to? ', 'Alice')
r.sendlineafter('s your name? ', bytes(prefix).hex())
r.sendlineafter(' else do you want to say? ', bytes(suffix).hex())
c = r.recvuntil('Whom do')
return bytes.fromhex(c.split(b'please take it to Bob:\n')[1].split(b'\nWhom do')[0].decode())
prelen = len(b"Thanks " + b" for taking my flag: ")
def calc_len():
global prelen
st = len(enc(b'',b''))
app = 0
while True:
app += 1
if len(enc(b'a' * app,b'')) != st:
break
return st - app - prelen - 16 - len(hmac_crc128(b'x' * 16,b'y' * 16))
def oracle_test(data):
r.sendlineafter('talk to? ', 'Bob')
r.sendlineafter('essage from Alice: ', bytes(data).hex())
t = time.time()
c = r.recvuntil('Whom do')
t = time.time() - t
return t
def original_oracle(data):
r.sendlineafter('talk to? ', 'Bob')
r.sendlineafter('essage from Alice: ', bytes(data).hex())
t = time.time()
c = r.recvuntil('Whom do')
t = time.time() - t
if t < theta:
return False
return True
test_cnt = 5
def oracle(data):
global test_cnt
t_cnt = 0; f_cnt = 0
for i in range(test_cnt):
if original_oracle(data):
t_cnt += 1
else:
f_cnt += 1
if (t_cnt == 0 and f_cnt >= 2) or (f_cnt == 0 and t_cnt >= 2):
break
if t_cnt > test_cnt // 2 or f_cnt > test_cnt // 2:
break
return True if t_cnt > f_cnt else False
alphabet = b'qwertyuiopasdfghjklzxcvbnm' # more possible char in flag (for speed up)
morePoss = b'0123456789_' + alphabet + alphabet.upper() + b'{}\n'
def padding_attack(chiper, required, known = b''):
for i in range(len(chiper), len(chiper) - required, -1):
if i + len(known) > len(chiper):
continue
cons = (len(chiper) - i) % 16
val = cons + 1
cur = None
in_chiper = chiper[i - 17]
pre = chiper[: i - 17]
suffix = bytes([known[j] ^ chiper[i - 16 + j] ^ val for j in range(cons)])
suffix += chiper[i - 16 + cons : len(chiper) - (len(chiper) - i) // 16 * 16]
poss = []
for j in morePoss:
poss.append(j ^ val ^ in_chiper)
for j in range(256):
if j not in poss:
poss.append(j)
for j in poss:
if oracle(pre + bytes([j]) + suffix):
cur = j ^ val ^ in_chiper
if val == 1:
if j != in_chiper:
break
else:
break
if cur == None:
print('failed')
quit()
else:
known = bytes([cur]) + known
#if len(chiper) == i:
# known = known * known[0] # is padding
print(known)
flag_len = calc_len()
rubbish_len = 3000 # change this when the network is slow
rubbish_len = rubbish_len + 16 - (rubbish_len + prelen + flag_len) % 16
wanted_cnt = flag_len
known = b''
good = enc(b'*'*rubbish_len, b'')
t1 = oracle_test(good)
bad = good[:-1] + bytes([good[-1] ^ 1])
t2 = oracle_test(bad)
goods = enc(b'*'*(rubbish_len - wanted_cnt), b'')
t1s = oracle_test(goods)
bads = goods[:-1] + bytes([goods[-1] ^ 1])
t2s = oracle_test(bads)
print('good time = ', t1s, '~', t1)
print('bad time = ', t2s, '~', t2)
if t1s < t2:
print('waring: bad oracle!')
theta = (t1s + t2) / 2
print('suggest theta = ', theta)
padding_attack(enc(b'*'*rubbish_len, b'')[:-32], wanted_cnt, known)