1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
#include "../lib/lib.h"
#include "../lib/lib2.h"
#include "../lib/lib3.h"
#include <time.h>
/**
* First we try to break the last byte of a block.
* Do this by trying every byte
*
* Good description of the attack:
* https://blog.cloudflare.com/padding-oracles-and-the-decline-of-cbc-mode-ciphersuites/
*/
#define BLOCKSIZE 16
int main()
{
// intialize
srand(time(NULL));
generate_random_bytes(key, 16);
generate_random_bytes(iv, 16);
int length = 0, i;
char *encrypted = challenge17_encrypt(&length);
// detecting the length of the padding (need at least two blocks)
int nr_blocks = length / BLOCKSIZE;
nr_blocks--;
printf("length: %i, blocks: %i\n", length, nr_blocks);
char *tmp = malloc(length);
char *decrypted = malloc(length);;
memset(decrypted, 0xAA, length);
// try to break the last byte of the first block
char j;
int k;
for(k=nr_blocks-1;k>=0;k--) {
memcpy(tmp, encrypted, length);
printf("k is %i\n", k);
for(j=1;j<=BLOCKSIZE;j++) {
// created the right padding for the last j bytes
for(i=1;i<j;i++)
tmp[(k*BLOCKSIZE)+BLOCKSIZE-i] = decrypted[((k+1)*BLOCKSIZE)+BLOCKSIZE-i] ^ encrypted[(k*BLOCKSIZE)+BLOCKSIZE-i] ^ j;
for(i=0;i<256;i++) {
// cbc bit flipping
tmp[(k*BLOCKSIZE)+BLOCKSIZE-j] = i;
// retursn 1 if paddign is valid
if(cbc_padding_oracle(&tmp[k*BLOCKSIZE], 2*BLOCKSIZE)) {
// 0x01 for the last padding byte, next step it is 0x02
decrypted[((k+1)*BLOCKSIZE)+BLOCKSIZE-j] = (char) (i ^ (encrypted[(k*BLOCKSIZE)+BLOCKSIZE-j]) ^ j);
printf("got a hit %c\n", decrypted[((k+1)*BLOCKSIZE)+BLOCKSIZE-j+1]);
break;
}
}
}
}
printf("recovered plaintext: %s\n", &decrypted[BLOCKSIZE]);
}
|