I am trying to create a padding oracle attack to decrypt a cipher that is encrypted with cbc and PKCS#7 padding.

My first step is just to try and decrypt the second block.

I have read a lot about it, and have started to code the first step of the attack, where I edit last byte in the first block and send it to the oracle. But there is a point of the attack/decryption method I'm a bit confused about regarding the xor of the bytes.

The part I don't understand completely is the math on how manipulating the last byte in the first block result in the last byte in the decrypted byte to turns out to be 0x01, 0x02 etc.

I haven't figured out how the math for that works, for what I have researched it should just be to xor OriginalByte xor TestByte xor 1.

Should that be equal to 0x01?

Here I have a string "TestBlockForStackBBBBBBBBBBBa31", it is 31 bytes. That means that it has to get padded with 1 to make it equal to 32 bytes so it fits inside 16 byte blocks. The string byte is as following (without encryption):


Then we decrypt the string with the key and IV below using cbc and PKCS#7.

byte[] Key = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9}; 
       //we don't need key the key under the attach, only under encryption.
byte[] IV  = new byte[]{2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2 };

We then get this result:

Ciphertext:  ;fŒ˜ÆOgÄ:VûÎ{Ž+6iXK¿îMŠžÌš 

Cipher bytes: 3B668C98C64F67C43A56FBCE7B8E150E9D2B1F3669584BBFEE4D8A0E189ECC9A

Under the padding oracle attack I edit the last byte in the first block

(3B668C98C64F67C43A56FBCE7B8E15 0E <--).

I know that when I edit the last byte in the first block to 0D the decryption result will have a 0x01 at the end. The first block is then going to look like this:


And what I then send to the oracle in this case DecryptStringFromBytes (code can be found in RijndaelManaged.CreateDecryptor Method) is the following first the edited chiper 3B668C98C64F67C43A56FBCE7B8E150D9D2B1F3669584BBFEE4D8A0E189ECC9A, then the key that is only 0 (Key = new byte[16]), then the same iv as above.

It then returns that the padding is valid. I did go into the function BCryptDecrypt (used inside the decryption call) and set a breakpoint to confirm this, and it is indeed 0x01.

The output bytes from the call BCryptDecrypt is then like this:

 [0]  0x95    byte        [1] 0x28    byte        [2] 0xE5    byte        [3] 0x18    byte
 [4]  0x90    byte        [5] 0x8E    byte        [6] 0x31    byte        [7] 0xFF    byte
 [8]  0xF0    byte        [9] 0x28    byte       [10] 0x86    byte       [11] 0x7B    byte
[12]  0x9D    byte       [13] 0x63    byte       [14] 0x2F    byte       [15] 0x01    byte

The decrypted file result that returns from the decrypter to the user looks like this:

Text :  ?????xi?G?w?T}!y?(???1??(?{?c/ Bytes : 
3F3F3F3F3F78693F473F773F547D21793F283F183F3F313F3F283F7B3F632F (Thay
have removed the 0x01 and the bytes is a bit different, maybe something
with how I formatted it or it does something more before returning the

So my questions are:

  • How does the info I did send turn out to be 0x01 at the end?
  • What do I need to xor to the result to get the plaintext/byte?
  • 1
    $\begingroup$ I do think this question is fundamentally on-topic here, even if it's a bit messy in some places. I feel like there really should be a canonical question for "how to carry out a CBC padding oracle attack step by step", but the only existing one I could find is this one, which is... not that great. :/ $\endgroup$ Commented May 15, 2019 at 16:52
  • $\begingroup$ @IlmariKaronen I have recently written a full text (in a different context) of how this works in general, I'll probably write something up later today (here and / or in a more generic Q/A). $\endgroup$
    – SEJPM
    Commented May 15, 2019 at 18:18
  • $\begingroup$ @SEJPM That had been very nice. Maybe you can link to the thing you did write :) If you are going to write more. Can you please make a eksempel showcasing what happens to the bytes. Using eksempel ciphers etc. Most article i have read does just explain with letters, without really explain good enough what does letters mean. That can be hard for people that are new to this and are looking to learn, at least for me. It had been much more easy to use the bytes from a chipper instead of the letters. The ideal thing had been to combane this two. $\endgroup$
    – yostart123
    Commented May 15, 2019 at 19:56
  • $\begingroup$ @SEJPM I am really going to appreciate it, and i don't think i am the only one that is going to. <3 $\endgroup$
    – yostart123
    Commented May 15, 2019 at 19:56
  • $\begingroup$ Something about your example is weird: The ciphertext is 32 bytes, it should be 48 bytes (including the IV) or does .NET transport that one out-of-band? $\endgroup$
    – SEJPM
    Commented May 15, 2019 at 20:43

1 Answer 1


You don't start by manipulating the last byte of the first block. Rather you manipulate the last byte of the last block. You start at the end and work backwards. The side-channel leak in the padding oracle attack is that the server distinguishes between a bad cipher and bad padding. This is the leak that lets you figure out the message.

If you try every possibility for the last byte, the server will tell you if the padding is bad. If you get no "bad padding" error you know the value you tried is likely 1 xor'd with what will decrypt the last byte of the actual message. So then you try changing the last two values to get "2" and "2". You already know to xor 2 with the last value at the end that gave no bad padding error. So it's a matter of figuring out the second to last byte and trying every byte until you get no padding error and so on.

The best way to understand this that I know of is to do the cryptopals challenge (google it). It's also very helpful to look at a diagram of how CBC works because you can visualize what's happening.

  • $\begingroup$ are you sure that you dont have to change the last byte before the block you are going to decrypt? :) Going to look for cryptopals challenge tomorrow :) Thanks for the comment :D $\endgroup$
    – yostart123
    Commented May 15, 2019 at 20:07
  • 1
    $\begingroup$ Actually yostart is right here. You want to manipulate the last byte of the plaintext which implies manipulation the second to last ciphertext block (which in this case is the first), because the IV is somehow missing. $\endgroup$
    – SEJPM
    Commented May 15, 2019 at 20:45

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.