예제 #1
0
def test_fake_ciphertext_decryption_oracle(amount=5):
    for _ in range(amount):
        new_plaintext = random_bytes(randint(1, 10))
        new_plaintext_padded = add_padding(new_plaintext, block_size)

        print("Test small: cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle)")
        new_ciphertext = cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle)
        decrypted = h2b(subprocess.check_output(
            ['python', cbc_oracles_path, 'decrypt', b2h(new_ciphertext)]).strip().decode())
        assert decrypted == new_plaintext

    for _ in range(amount):
        new_plaintext = random_bytes(randint(10, 50))
        new_plaintext_padded = add_padding(new_plaintext, block_size)

        print("Test large: cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle)")
        new_ciphertext = cbc.fake_ciphertext(new_plaintext_padded, decryption_oracle=decryption_oracle, padding_oracle=padding_oracle)
        decrypted = h2b(subprocess.check_output(
            ['python', cbc_oracles_path, 'decrypt', b2h(new_ciphertext)]).strip().decode())
        assert decrypted == new_plaintext
예제 #2
0
def test_bit_flipping():
    print("Test: cbc.bit_flipping(ciphertext=ciphertext[-2*AES.block_size:],"
          "plaintext=add_padding(plaintext)[-AES.block_size:],\nwanted_last_block=wanted, block_size=AES.block_size)")

    plaintext = bytes(b"money=10000&userdata=whateverdata%20huehuehue%20spam%20and%20eggs")
    wanted = add_padding(bytes(b'&admin=true'))
    ciphertext = h2b(subprocess.check_output(['python', cbc_oracles_path, 'encrypt', b2h(plaintext)]).strip().decode())

    fake_cipher = cbc.bit_flipping(ciphertext=ciphertext[-2*AES.block_size:], plaintext=add_padding(plaintext)[-AES.block_size:],
                                   wanted=wanted, block_size=AES.block_size)
    fake_cipher = ciphertext[-AES.block_size*2:] + fake_cipher
    decrypted = h2b(subprocess.check_output(['python', cbc_oracles_path, 'decrypt', b2h(fake_cipher)]).strip().decode())
    assert decrypted[-len("&admin=true"):] == bytes(b"&admin=true")
예제 #3
0
def encryption_oracle_des(payload):
    global constant, prefix_len, suffix_len, secret
    if secret:
        if constant:
            payload = random_bytes(prefix_len) + payload + secret
        else:
            payload = random_bytes(random.randint(1, 50)) + payload + secret
    else:
        if constant:
            payload = random_bytes(prefix_len) + payload + random_bytes(
                suffix_len)
        else:
            payload = random_bytes(random.randint(
                1, 50)) + payload + random_bytes(random.randint(1, 50))

    payload = add_padding(payload, DES3.block_size)
    cipher = DES3.new(key_DES3, DES3.MODE_ECB)
    return cipher.encrypt(payload)
예제 #4
0
def test_iv_as_key(from_test=1):
    global iv_as_key
    iv_as_key = True
    plaintext = random_bytes(randint(1, 40))
    plaintext_padded = add_padding(plaintext, block_size)
    ciphertext = encrypt(plaintext, iv_as_key=iv_as_key)

    if from_test <= 1:
        print("Test 1: cbc.iv_as_key()")
        key = cbc.iv_as_key(ciphertext[AES.block_size:], plaintext_padded, padding_oracle=padding_oracle)
        assert key == KEY

    if from_test <= 2:
        print("Test 2: cbc.iv_as_key()")
        key = cbc.iv_as_key(ciphertext[AES.block_size:], plaintext_padded, decryption_oracle=decryption_oracle)
        assert key == KEY

    iv_as_key = False
예제 #5
0
def decrypt(encryption_oracle, constant=True, block_size=16, prefix_size=None, secret_size=None,
            alphabet=None):
    """Given encryption oracle which produce ecb(prefix || our_input || secret), find secret
    
    Args:
        encryption_oracle(callable)
        constant(bool): True if prefix have constant length (secret must have constant length)
        block_size(int/None)
        prefix_size(int/None)
        secret_size(int/None)
        alphabet(string): plaintext space
    
    Returns:
        secret(string)
    """
    log.debug("Start decrypt function")
    if not alphabet:
        alphabet = bytes(string.printable.encode())

    if not block_size:
        block_size = find_block_size(encryption_oracle, constant)

    if constant:
        log.debug("constant == True")
        if not prefix_size or not secret_size:
            prefix_size, secret_size = find_prefix_suffix_size(encryption_oracle, block_size)

        """Start decrypt"""
        secret = bytes(b'')
        aligned_bytes = random_bytes(1) * (block_size - (prefix_size % block_size))
        if len(aligned_bytes) == block_size:
            aligned_bytes = bytes(b'')

        aligned_bytes_suffix = random_bytes(1) * (block_size - (secret_size % block_size))
        if len(aligned_bytes_suffix) == block_size:
            aligned_bytes_suffix = bytes(b'')

        block_to_find_position = -1
        controlled_block_position = (prefix_size+len(aligned_bytes)) // block_size

        while len(secret) < secret_size:
            if (len(secret)+1) % block_size == 0:
                block_to_find_position -= 1
            payload = aligned_bytes + aligned_bytes_suffix + random_bytes(1) + secret
            enc_chunks = chunks(encryption_oracle(payload), block_size)
            block_to_find = enc_chunks[block_to_find_position]

            log.debug("To guess at position {}:".format(block_to_find_position))
            log.debug("Plain: " + print_chunks(chunks(bytes(b'P'*prefix_size) + payload + bytes(b'S'*secret_size), block_size)))
            log.debug("Encry: " + print_chunks(enc_chunks)+"\n")

            for guessed_char in range(256):
                guessed_char = bytes([guessed_char])
                payload = aligned_bytes + add_padding(guessed_char + secret, block_size)
                enc_chunks = chunks(encryption_oracle(payload), block_size)

                log.debug("Plain: " + print_chunks(chunks(bytes(b'P'*prefix_size) + payload + bytes(b'S'*secret_size), block_size)))
                log.debug("Encry: " + print_chunks(enc_chunks)+"\n")
                if block_to_find == enc_chunks[controlled_block_position]:
                    secret = guessed_char + secret
                    log.debug("Found char, secret={}".format(repr(secret)))
                    break
            else:
                log.critical_error("Char not found, try change alphabet. Secret so far: {}".format(repr(secret)))
        log.success("Secret(hex): {}".format(b2h(secret)))
        return secret
    else:
        log.debug("constant == False")
예제 #6
0
def encrypt(data, iv_as_key=False):
    iv = random_bytes(block_size)
    if iv_as_key:
        iv = KEY
    aes = AES.new(KEY, AES.MODE_CBC, iv)
    return iv + bytes(aes.encrypt(add_padding(data)))
예제 #7
0
def test_decrypt(from_test=1):
    original_plaintext = random_bytes(randint(1, 40))
    original_ciphertext = encrypt(original_plaintext)
    original_plaintext = add_padding(original_plaintext, block_size)

    if from_test <= 1:
        print("Test 1: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True)")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True)
        assert decrypted == original_plaintext

    if from_test <= 2:
        data = original_ciphertext[:-block_size - 1] + bytes(b'A') + original_ciphertext[-block_size:]
        print("Test 2: cbc.decrypt(data, padding_oracle=padding_oracle, is_correct=False)")
        decrypted = cbc.decrypt(data, padding_oracle=padding_oracle, is_correct=False)
        assert decrypted[-block_size:-1] == original_plaintext[-block_size:-1]

    if from_test <= 3:
        print("Test 3: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False)")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False)
        assert decrypted[:-1] == original_plaintext[:-1]

    if from_test <= 4:
        iv = original_ciphertext[:block_size]
        data = original_ciphertext[block_size:]
        print("Test 4: cbc.decrypt(data, padding_oracle=padding_oracle, iv=iv)")
        decrypted = cbc.decrypt(data, padding_oracle=padding_oracle, iv=iv)
        assert decrypted == original_plaintext

    if from_test <= 5:
        if len(original_plaintext) > block_size:
            print("Test 5: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=2)")
            decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=2)
            assert decrypted == original_plaintext[-block_size * 2:]

    if from_test <= 6:
        print("Test 6: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=1, is_correct=True)")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, amount=1, is_correct=True)
        assert decrypted == original_plaintext[-block_size:]

    if from_test <= 7:
        print("Test 7: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \
                                 known_plaintext=original_plaintext)")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True,
                                known_plaintext=original_plaintext)
        assert decrypted == original_plaintext

    if from_test <= 8:
        print("Test 8: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \
                                 known_plaintext=original_plaintext[-4:])")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True,
                                known_plaintext=original_plaintext[-4:])
        assert decrypted == original_plaintext

    if from_test <= 9:
        print("Test 9: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \
                                 known_plaintext=original_plaintext[-7:], amount=1)")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True,
                                known_plaintext=original_plaintext[-7:], amount=1)
        assert decrypted == original_plaintext[-block_size:]

    if from_test <= 10:
        print("Test 10: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False, \n \
                                 known_plaintext=original_plaintext[-7:], amount=1)")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=False,
                                known_plaintext=original_plaintext[-7:], amount=1)
        assert decrypted == original_plaintext[-block_size:]

    if from_test <= 11:
        print("Test 11: cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True, \n \
                                 known_plaintext=original_plaintext[-block_size - 3:])")
        decrypted = cbc.decrypt(original_ciphertext, padding_oracle=padding_oracle, is_correct=True,
                                known_plaintext=original_plaintext[-block_size - 3:])
        assert decrypted == original_plaintext

    if from_test <= 12:
        print("Test 12: cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle, is_correct=True, \n \
                                 known_plaintext=original_plaintext[-block_size - 3:])")
        decrypted = cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle,
                                known_plaintext=original_plaintext[-block_size - 3:], is_correct=True)
        assert decrypted == original_plaintext

    if from_test <= 13:
        print("Test 13: cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle)")
        decrypted = cbc.decrypt(original_ciphertext, decryption_oracle=decryption_oracle)
        assert decrypted == original_plaintext