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
0x01
at the end? - What do I need to xor to the result to get the plaintext/byte?
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.
– yostart123 May 15 '19 at 19:563B668C98C64F67C43A56FBCE7B8E380E9D2B1F3669584BBFEE4D8A0E189ECC9A
gets the result9528E518908E31FFF028867B9D630202
it has 0202 as padding. but i dont manege to get the plaintext bytes from the info we have ;/ Any idea what i ame doing wrong. The plaintext byte for the 0202 spot is 31 @SEJPM – yostart123 May 28 '19 at 18:42