[BSidesSF2020]haystack

附件
# uncompyle6 version 3.2.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: /home/david/Projects/BSidesCTF/2020/challenges/haystack/challenge/chaffing.py
# Size of source mod 2**32: 2094 bytes
import hmac, hashlib, random, struct
CHAFF_SIZE = 32
SIG_SIZE = 16
ALL_BYTES = set((c for c in range(256)))
KEY = b'af5f76f605a700ae8c0895c3e6175909'

def byte(v):
    return bytes([v])


def sign_byte(val, key):
    return (hmac.new(key,
      val, digestmod=hashlib.sha256)).digest()[:SIG_SIZE]


def chaff_byte(val, key):
    msgs = {}
    msgs[val[0]] = sign_byte(val, key)
    while len(msgs) < CHAFF_SIZE:
        vals = list(ALL_BYTES - set(msgs.keys()))
        c = random.choice(vals)
        if c == val:
            raise ValueError('Chose duplicate!')
        fake_sig = bytes(random.choices(list(ALL_BYTES), k=SIG_SIZE))
        msgs[c] = fake_sig

    pieces = []
    for k, v in msgs.items():
        pieces.append(b'%s%s' % (byte(k), v))

    random.shuffle(pieces)
    return b''.join(pieces)


def chaff_msg(val, key):
    if not isinstance(val, bytes):
        val = val.encode('utf-8')
    msg_out = []
    for b in val:
        msg_out.append(chaff_byte(byte(b), key))

    outval = b''.join(msg_out)
    return struct.pack('>I', len(val)) + outval


def winnow_msg(val, key):
    if not isinstance(val, bytes):
        val = val.encode('utf-8')
    msglen = struct.unpack('>I', val[:4])[0]
    val = val[4:]
    chunk_len = (SIG_SIZE + 1) * CHAFF_SIZE
    expected_len = chunk_len * msglen
    if len(val) != expected_len:
        raise ValueError('Expected length %d, saw %d.' % (expected_len, len(val)))
    pieces = []
    for c in range(msglen):
        chunk = val[chunk_len * c:chunk_len * (c + 1)]
        res = winnow_byte(chunk, key)
        pieces.append(res)

    return b''.join(pieces)


def winnow_byte(val, key):
    while val:
        c = byte(val[0])
        sig = val[1:SIG_SIZE + 1]
        if sign_byte(c, key) == sig:
            return c
        val = val[SIG_SIZE + 1:]

    raise ValueError('No valid sig found!')


def main():
    inp = b'This is a test message!'
    msg = chaff_msg(inp, KEY)
    ret = winnow_msg(msg, KEY)
    if inp != ret:
        print('Wrong ret: %s' % ret)


if __name__ == '__main__':
    main()
# okay decompiling .\chaffing.pyc

  

#exp.py
import hmac, hashlib, random, struct
from collections import Counter
CHAFF_SIZE = 32
SIG_SIZE = 16
ALL_BYTES = set((c for c in range(256)))
def extract(val):
    if not isinstance(val, bytes):
        val = val.encode('utf-8')
    msglen = struct.unpack('>I', val[:4])[0]
    val = val[4:]
    chunk_len = (SIG_SIZE + 1) * CHAFF_SIZE
    expected_len = chunk_len * msglen
    if len(val) != expected_len:
        raise ValueError('Expected length %d, saw %d.' % (expected_len, len(val)))
    pieces = []
    for c in range(msglen):
        chunk = val[chunk_len * c:chunk_len * (c + 1)]
        res = extract_byte_sig_pairs(chunk)
        pieces.extend(res)
    return pieces


def extract_byte_sig_pairs(val):
    res = []
    while val:
        c = (val[0])
        sig = val[1:SIG_SIZE + 1]
        res.append((c, sig))
        val = val[SIG_SIZE + 1:]
    return res

msg = open('1.txt', 'rb').read()
ret = extract(msg)
c = Counter(ret)
real = c.most_common(256)
print(real)


def decode(val, d):
    if not isinstance(val, bytes):
        val = val.encode('utf-8')
    msglen = struct.unpack('>I', val[:4])[0]
    val = val[4:]
    chunk_len = (SIG_SIZE + 1) * CHAFF_SIZE
    expected_len = chunk_len * msglen
    if len(val) != expected_len:
        raise ValueError('Expected length %d, saw %d.' % (expected_len, len(val)))
    pieces = []
    for c in range(msglen):
        chunk = val[chunk_len * c:chunk_len * (c + 1)]
        res = decode_byte(chunk, d)
        pieces.append(res)
    return b''.join(pieces)


def decode_byte(val, d):
    while val:
        c = (val[0])
        sig = val[1:SIG_SIZE + 1]
        if sig in d and d[sig] == c:
            return c
        val = val[SIG_SIZE + 1:]
    raise ValueError("WTF")

d = {s: b for (b, s), c in real}
print('\n')
print('\n')
print('\n')
print(d)
print(decode(msg,d))

  

posted @ 2020-04-05 13:02  S4tan  阅读(486)  评论(0编辑  收藏  举报