Пример #1
0
def brute_force_ecb_padding(plaintext, block_size, oracle):
    """Helper function to brute force the PKCS7 padding for the ECB break
    :param plaintext: The current plaintext guess
    :param block_size: The block size of the oracle
    :param oracle: ECB encryption oracle that encrypts AES-128-ECB(your-string || unknown-string, random-key)
    :return: The correct unknown-string or None on failure to match
    """
    last_block_start = round_down(len(plaintext), block_size)
    expected_ciphertext = oracle('')

    # The plaintext may have padding bytes in it so try padding all slices of the last block
    # When the encryption of the plaintext + padding matches the encryption of an empty string we know the plaintext
    # is correct
    for i in xrange(last_block_start, len(plaintext)):
        plaintext_guess = plaintext[:i]

        # Now pad it manually since the hidden string will be appended
        plaintext_guess_w_padding = pkcs7_pad(plaintext_guess, block_size)

        guess_ciphertext = oracle(plaintext_guess_w_padding)[:len(expected_ciphertext)]

        if guess_ciphertext == expected_ciphertext:
            return plaintext_guess

    return None
Пример #2
0
def break_ecb_encryption(oracle):
    """Break ECB encryption with a chosen plaintext attack
    :param oracle: ECB encryption oracle that encrypts AES-128-ECB(your-string || unknown-string, random-key)
    :return: The unknown-string encrypted by the ECB encryption oracle
    """
    block_size = detect_oracle_block_size(oracle)
    mode = detect_aes_mode(oracle)

    if mode != AesMode.ECB:
        raise Exception('Oracle mode != ECB')

    # Account for oracles that prepend data
    oracle = get_no_prefix_oracle(oracle, block_size)

    total_length = len(oracle(''))

    plaintext = 'A' * (block_size-1)

    for i in xrange(total_length):
        decrypt_oracle = get_decryption_oracle(oracle, plaintext[-(block_size-1):], block_size)

        current_block_base = round_down(i, block_size)
        input_pad = 'A' * (block_size - (i % block_size) - 1)

        ciphertext = oracle(input_pad)[current_block_base:current_block_base+block_size]

        try:
            plaintext += decrypt_oracle[ciphertext]
        except KeyError:
            # If we're on the last block we will start running into problems with changing padding. Just brute force
            # the padding bytes.
            if (total_length - i) < block_size:
                # Drop the A's added to the plaintext that allowed us to brute force the first block
                plaintext = plaintext[15:]
                plaintext = brute_force_ecb_padding(plaintext, block_size, oracle)
                break
            else:
                raise

    return plaintext