Ejemplo n.º 1
0
def find_prefix_len(oracle, blocksize):
    input_len = 2 * blocksize

    # increase input until we generate 2 identical blocks
    while True:
        # test with 2 different blocks to make sure that we're not using the
        # last bytes from the prefix
        input1 = bytes([0] * input_len)
        input2 = bytes([1] * input_len)
        blocks1 = get_blocks(oracle(input1), blocksize)
        blocks2 = get_blocks(oracle(input2), blocksize)

        if has_duplicates(blocks1) and has_duplicates(blocks2):
            break

        input_len += 1

    # find the index where the first of these 2 identical blocks is
    blocks = get_blocks(oracle(bytes([0] * input_len)), blocksize)
    first_idx = [i * blocksize for i in range(len(blocks)-1)
                 if blocks[i] == blocks[i+1]][0]

    padding = input_len - 2 * blocksize

    return first_idx - padding
Ejemplo n.º 2
0
def find_prefix_len(oracle, blocksize):
    input_len = 2 * blocksize

    # increase input until we generate 2 identical blocks
    while True:
        # test with 2 different blocks to make sure that we're not using the
        # last bytes from the prefix
        input1 = bytes([0] * input_len)
        input2 = bytes([1] * input_len)
        blocks1 = get_blocks(oracle(input1), blocksize)
        blocks2 = get_blocks(oracle(input2), blocksize)

        if has_duplicates(blocks1) and has_duplicates(blocks2):
            break

        input_len += 1

    # find the index where the first of these 2 identical blocks is
    blocks = get_blocks(oracle(bytes([0] * input_len)), blocksize)
    first_idx = [
        i * blocksize for i in range(len(blocks) - 1)
        if blocks[i] == blocks[i + 1]
    ][0]

    padding = input_len - 2 * blocksize

    return first_idx - padding
Ejemplo n.º 3
0
def main():

    SECRETS = [
        "MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=",
        "MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic=",
        "MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw==",
        "MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg==",
        "MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl",
        "MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA==",
        "MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw==",
        "MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8=",
        "MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g=",
        "MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93"
    ]

    for secret in SECRETS:
        iv, encrypted = get_secret(secret)

        blocks = [bytes(iv)] + get_blocks(encrypted)
        decrypted_blocks = [
            decrypt_block(padding_oracle, blocks[i - 1], blocks[i])
            for i in range(1, len(blocks))
        ]

        padded_plaintext = b"".join(decrypted_blocks)
        plaintext = unpad(padded_plaintext)

        print(plaintext.decode('ascii'))
        assert (b64encode(plaintext).decode('ascii') == secret)
Ejemplo n.º 4
0
def guess_blockmode(oracle):
    input_ = bytes([0x42] * 100)
    encrypted, answer = oracle(input_)
    blocks = get_blocks(encrypted)

    unique_blocks = len(set(blocks))

    guess = "ECB" if unique_blocks != len(blocks) else "CBC"

    assert (guess == answer)
Ejemplo n.º 5
0
def guess_blockmode(oracle):
    input_ = bytes([0x42] * 100)
    encrypted, answer = oracle(input_)
    blocks = get_blocks(encrypted)

    unique_blocks = len(set(blocks))

    guess = "ECB" if unique_blocks != len(blocks) else "CBC"

    assert(guess == answer)
Ejemplo n.º 6
0
def is_ecb(oracle, blocksize):
    encrypted = oracle(bytes([0x42] * 3 * blocksize))
    blocks = get_blocks(encrypted, blocksize)
    return has_duplicates(blocks)
Ejemplo n.º 7
0
prefix_padding_len = (blocksize - prefix_len % blocksize) % blocksize
prefix_padding = bytes([0] * prefix_padding_len)
prefix_blocks_len = (prefix_len + prefix_padding_len) // blocksize
assert(PREFIX_LEN == prefix_len)

plaintext = bytearray()

while True:  # can't tell when we're done beforehand, prefix is random
    for byte_idx in range(blocksize):
        last_known_block = get_last_known_block(plaintext, blocksize)

        input_, target_block_idx = target_next_byte(plaintext, blocksize)
        target_block_idx += prefix_blocks_len
        encrypted = oracle(prefix_padding + input_)

        target_block = get_blocks(encrypted, blocksize)[target_block_idx]

        block_prefix = last_known_block[1:]

        found_match = False
        for byte in range(256):
            ciphertext_guess = block_prefix + bytes([byte])
            encrypted_guess = oracle(prefix_padding + ciphertext_guess)
            guess = get_blocks(encrypted_guess, blocksize)[prefix_blocks_len]

            if target_block == guess:
                found_match = True
                plaintext.append(byte)
                stdout.write(chr(byte))
                stdout.flush()
                break
Ejemplo n.º 8
0
    """
    verified_byte = None
    for byte in valid_bytes:
        original_prev_block = bytes([0] * 14 + [0, byte])
        tampered_prev_block = bytes([0] * 14 + [1, byte])

        if (oracle(original_prev_block, current_block) and
                oracle(tampered_prev_block, current_block)):
            assert(verified_byte is None)
            verified_byte = byte

    return verified_byte


def get_expected_padding_byte(known_pre_xor):
    return len(known_pre_xor) + 1


for secret in SECRETS:
    iv, encrypted = get_secret(secret)

    blocks = [bytes(iv)] + get_blocks(encrypted)
    decrypted_blocks = [decrypt_block(padding_oracle, blocks[i-1], blocks[i])
                        for i in range(1, len(blocks))]

    padded_plaintext = b"".join(decrypted_blocks)
    plaintext = unpad(padded_plaintext)

    print(plaintext.decode('ascii'))
    assert(b64encode(plaintext).decode('ascii') == secret)
Ejemplo n.º 9
0
    for byte in valid_bytes:
        original_prev_block = bytes([0] * 14 + [0, byte])
        tampered_prev_block = bytes([0] * 14 + [1, byte])

        if (oracle(original_prev_block, current_block)
                and oracle(tampered_prev_block, current_block)):
            assert (verified_byte is None)
            verified_byte = byte

    return verified_byte


def get_expected_padding_byte(known_pre_xor):
    return len(known_pre_xor) + 1


for secret in SECRETS:
    iv, encrypted = get_secret(secret)

    blocks = [bytes(iv)] + get_blocks(encrypted)
    decrypted_blocks = [
        decrypt_block(padding_oracle, blocks[i - 1], blocks[i])
        for i in range(1, len(blocks))
    ]

    padded_plaintext = b"".join(decrypted_blocks)
    plaintext = unpad(padded_plaintext)

    print(plaintext.decode('ascii'))
    assert (b64encode(plaintext).decode('ascii') == secret)
Ejemplo n.º 10
0
from aes import get_blocks


with open('08.txt') as f:
    ciphertexts = [bytes.fromhex(line.strip()) for line in f.readlines()]

ciphertexts_blocks = [get_blocks(ciphertext) for ciphertext in ciphertexts]
uniques = [len(set(block)) for block in ciphertexts_blocks]
least_unique_idx = uniques.index(min(uniques))
ecb_encrypted = ciphertexts[least_unique_idx]
print("ECB: %s" % ecb_encrypted)
print("%i unique blocks out of %i" %
      (uniques[least_unique_idx], len(ciphertexts[least_unique_idx])/16))

assert(ecb_encrypted.startswith(
       b'\xd8\x80a\x97@\xa8\xa1\x9bx@\xa8\xa3\x1c\x81\n=\x08d\x9a\xf7'))
Ejemplo n.º 11
0
from aes import get_blocks

with open('08.txt') as f:
    ciphertexts = [bytes.fromhex(line.strip()) for line in f.readlines()]

ciphertexts_blocks = [get_blocks(ciphertext) for ciphertext in ciphertexts]
uniques = [len(set(block)) for block in ciphertexts_blocks]
least_unique_idx = uniques.index(min(uniques))
ecb_encrypted = ciphertexts[least_unique_idx]
print("ECB: %s" % ecb_encrypted)
print("%i unique blocks out of %i" %
      (uniques[least_unique_idx], len(ciphertexts[least_unique_idx]) / 16))

assert (ecb_encrypted.startswith(
    b'\xd8\x80a\x97@\xa8\xa1\x9bx@\xa8\xa3\x1c\x81\n=\x08d\x9a\xf7'))
Ejemplo n.º 12
0
def is_ecb(oracle, blocksize):
    encrypted = oracle(bytes([0x42] * 3 * blocksize))
    blocks = get_blocks(encrypted, blocksize)
    unique_blocks = len(set(blocks))
    return unique_blocks != len(blocks)
Ejemplo n.º 13
0
blocksize = guess_blocksize(oracle)
assert(16 == blocksize)

assert(is_ecb(oracle, blocksize))

bytes_count = len(oracle(bytes()))
plaintext = bytearray()

for _ in range(bytes_count):
    last_known_block = get_last_known_block(plaintext, blocksize)

    input_, target_block_idx = target_next_byte(plaintext, blocksize)
    encrypted = oracle(input_)

    target_block = get_blocks(encrypted)[target_block_idx]

    prefix = last_known_block[1:]

    found_match = False
    for byte in range(256):
        encrypted_guess = oracle(prefix + bytes([byte]))
        guess = get_blocks(encrypted_guess)[0]

        if target_block == guess:
            found_match = True
            plaintext.append(byte)
            stdout.write(chr(byte))
            stdout.flush()
            break
Ejemplo n.º 14
0
def is_ecb(oracle, blocksize):
    encrypted = oracle(bytes([0x42] * 3 * blocksize))
    blocks = get_blocks(encrypted, blocksize)
    return has_duplicates(blocks)
Ejemplo n.º 15
0
prefix_padding_len = (blocksize - prefix_len % blocksize) % blocksize
prefix_padding = bytes([0] * prefix_padding_len)
prefix_blocks_len = (prefix_len + prefix_padding_len) // blocksize
assert (PREFIX_LEN == prefix_len)

plaintext = bytearray()

while True:  # can't tell when we're done beforehand, prefix is random
    for byte_idx in range(blocksize):
        last_known_block = get_last_known_block(plaintext, blocksize)

        input_, target_block_idx = target_next_byte(plaintext, blocksize)
        target_block_idx += prefix_blocks_len
        encrypted = oracle(prefix_padding + input_)

        target_block = get_blocks(encrypted, blocksize)[target_block_idx]

        block_prefix = last_known_block[1:]

        found_match = False
        for byte in range(256):
            ciphertext_guess = block_prefix + bytes([byte])
            encrypted_guess = oracle(prefix_padding + ciphertext_guess)
            guess = get_blocks(encrypted_guess, blocksize)[prefix_blocks_len]

            if target_block == guess:
                found_match = True
                plaintext.append(byte)
                stdout.write(chr(byte))
                stdout.flush()
                break