Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

中间人timing-attack padding oracle exp #39

Open
qwerty472123 opened this issue Nov 9, 2020 · 0 comments
Open

中间人timing-attack padding oracle exp #39

qwerty472123 opened this issue Nov 9, 2020 · 0 comments
Labels

Comments

@qwerty472123
Copy link

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

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)
@taoky taoky added the solution label Nov 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants