Skip to content

中间人timing-attack padding oracle exp #39

@qwerty472123

Description

@qwerty472123

我没找到有人写这题非预期解的实现,故按题解中的描述实现了一份(还挺快的):

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions