I have a 128 bit AES cipher in CBC Mode with the IV prepended to the message. I am aware of the security issues here, but that is exactly the point of my example. I would like to change the plain text message via bit-flipping, which I have partially implemented in the example below:

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes

key = b'WOAH, SO SECRET!'
block_size = 16 # in bytes (128 bit)

def encrypt_data(data):
    iv = get_random_bytes(block_size)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    enc = cipher.encrypt(pad(data, block_size, style='pkcs7'))
    return iv + enc

def decrypt_data(data):
    iv = data[:block_size]
    cipher = AES.new(key, AES.MODE_CBC, iv)
    padded_params = cipher.decrypt(data[block_size:])
    return unpad(padded_params, block_size, style='pkcs7')

# 128 bit blocks for better visualization
plain = b'Hello everybody!' \
        b' This is a very ' \
        b'cool message,wow'

wanted = b'THIS CAN CHANGE!' \
         b' This is a very ' \
         b'cool message,wow'

cipher_text = bytearray(encrypt_data(plain))

for block in range(len(plain)//block_size):
        for i in range(block_size):
                block_idx = (block*block_size)+i
                xor_byte = plain[block_idx] ^ wanted[block_idx]

                cipher_text[block_idx] ^= xor_byte

result = decrypt_data(bytes(cipher_text))

Above code outputs:

b'THIS CAN CHANGE! This is a very cool message,wow'

Which is exactly what I want!

However, I only ever managed to change the first block sucessfully, by changing the preceding block of the cipher message (in this case IV, which does not affect the rest of the message). If I modify my example with a wanted message like that:

wanted = b'Hello everybody!' \
         b'THIS CAN CHANGE ' \
         b'cool message,wow'

My code outputs:

b'g\x114\xb4\xc4\xd6\xd6\x16\xcf\x88\x87\x99\xea@\xe4\x11THIS CAN CHANGE cool message,wow'

I understand, that this happens due to the fact of using CBC mode and the impact of blocks on each other as described here. But what exactly am I missing here? How can I change my message to the desired output after decryption?

b'Hello everybody!THIS CAN CHANGE cool message,wow'

I'd appreciate any push in the right direction.

  • $\begingroup$ Might be duplicate of Bit Flipping Attack on CBC Mode $\endgroup$
    – kelalaka
    Dec 6, 2019 at 13:06
  • $\begingroup$ I have read that already, but was still struggling $\endgroup$
    – nullchimp
    Dec 6, 2019 at 13:36
  • $\begingroup$ Hi could you please provide your final script? $\endgroup$
    – simonmysun
    Aug 15, 2022 at 5:27
  • $\begingroup$ Hi, you may find the code here: github.com/nullchimp/padding-oracle ... I have last tested it 2 years ago, so I am not sure if it still works $\endgroup$
    – nullchimp
    Oct 29, 2022 at 14:24

1 Answer 1


There is only one way I see how to avoid having this block of garbage in you plaintext after CBC bit flipping attack, but it requires to be able to see the result of the decryption and to know the whole plaintext you are attacking, which may not be the case in most practical scenarios.

Say you want to alter the third block of plaintext, P3:

  • Do your CBC bit flipping attack on P3 by modifying C2, the normal way
  • get the modified plaintext. P2 should be garbage
  • now modify C1 in order to “repair” P2, that is, C1 = (the garbage you got) XOR (the original P2)
  • this is going to mess up P1, so you now you modify the IV to “repair” P1
  • $\begingroup$ I'll give it a try and share an update soon $\endgroup$
    – nullchimp
    Dec 6, 2019 at 13:37
  • $\begingroup$ Thank you so much for your help! Your solution worked! $\endgroup$
    – nullchimp
    Dec 6, 2019 at 14:40
  • $\begingroup$ By "get the modified plaintext" do you mean decrypting ciphered text? I tried so and it seems working. But that would require the key. Is it possible to do so without knowing the key? $\endgroup$
    – simonmysun
    Aug 15, 2022 at 5:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.