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):
54657374426C6F636B466F72537461636B4242424242424242424242613331
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:
3B668C98C64F67C43A56FBCE7B8E150D
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 bytes?)
So my questions are:
- How does the info I did send turn out to be
0x01at the end? - What do I need to xor to the result to get the plaintext/byte?