summaryrefslogtreecommitdiff
path: root/set7
diff options
context:
space:
mode:
authorBenedict <benedict@0xb8000.de>2017-01-28 15:35:04 +0100
committerBenedict <benedict@0xb8000.de>2017-02-21 13:00:27 +0100
commitced18e8eac298708e3b452714b3d55a0bf982cd9 (patch)
treee3c7eac09da6e38bc9ee402e007e58db9f893cc0 /set7
parent18acbfa8d29fd1ca9c90fb252b735b2901bbe7fa (diff)
set7: task51: completed
Diffstat (limited to 'set7')
-rw-r--r--set7/task51.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/set7/task51.c b/set7/task51.c
new file mode 100644
index 0000000..b380a0b
--- /dev/null
+++ b/set7/task51.c
@@ -0,0 +1,190 @@
+#include "../lib/lib.h"
+#include "../lib/lib2.h"
+#include "../lib/lib3.h"
+#include "../lib/lib4.h"
+#include "../lib/lib5.h"
+#include "../lib/lib7.h"
+#include <zlib.h>
+
+
+void generate_random_printable_bytes(char *s, unsigned int length)
+{
+ int i;
+
+ for(i=0;i<length;i++)
+ s[i] = random_number_between(33,127);
+}
+
+void format_request(char **res, char *content, char *secret)
+{
+ char *request_template =
+ "POST / HTTP/1.1\n"
+ "Host: hapless.com\n"
+ "Cookie: sessionid=%s\n"
+ "Content-Length: %i\n\n\n"
+ "%s";
+
+ // 10 for the content length as max
+ *res = malloc(strlen(request_template)+10+strlen(content)+strlen(secret));
+ sprintf(*res, request_template, secret, strlen(content), content);
+}
+
+void my_compress(char *toCompress, char **compressed, int *compressed_length)
+{
+ // 20 bytes for metadata and bla but normally it should be smaller
+ // than the uncompressed one
+ *compressed = malloc(strlen(toCompress)+20);
+ // compress
+ z_stream defstream;
+ defstream.zalloc = Z_NULL;
+ defstream.zfree = Z_NULL;
+ defstream.opaque = Z_NULL;
+
+ defstream.avail_in = strlen(toCompress);
+ defstream.next_in = toCompress;
+ defstream.avail_out = strlen(toCompress)+20;
+ defstream.next_out = *compressed;
+
+ deflateInit(&defstream, Z_BEST_COMPRESSION);
+ deflate(&defstream, Z_FINISH);
+ deflateEnd(&defstream);
+
+ *compressed_length = defstream.total_out;
+ //printf("uncompressed/compressed: %i/%i\n", strlen(toCompress), defstream.total_out);
+
+}
+int oracle_count = 0;
+
+int compression_oracle(char *content, char* secret, int stream_cipher)
+{
+ oracle_count++;
+ char *res;
+ char *compressed;
+ int compressed_length;
+ format_request(&res, content, secret);
+ //printf("%s\n", res);
+ my_compress(res, &compressed, &compressed_length);
+ // encrypt
+ // using AES_CTR, plaintext and ciphertext length are the same
+ // do it anyway
+ if(stream_cipher == 1) {
+ char *encrypted = malloc(compressed_length);
+ generate_random_bytes(key, 16);
+ generate_random_bytes(nonce, 16);
+ aes_ctr(compressed, compressed_length, encrypted, key, nonce);
+ return compressed_length;
+ }
+ else {
+ // do CBC encryption aka add padding
+ char *encrypted;
+ int pad_len = aes_cbc_padded(compressed, compressed_length, &encrypted,
+ key, iv, 1);
+ return pad_len;
+ }
+}
+
+int max_int_index(int *numbers, int length)
+{
+ int i;
+ int max = 0;
+ int index = 0;
+
+ for(i=0;i<length;i++) {
+ if(numbers[i] > max) {
+ max = numbers[i];
+ index = i;
+ }
+ }
+
+ return index;
+}
+
+int main()
+{
+ srand(time(NULL));
+ char *known_text = "Cookie: sessionid=";
+ char *secret = "TmV2ZXIgcmV2ZWFsIHRoZSBXdS1UYW5nIFNlY3JldCE=";
+ // generate password between 33, 127
+ // assume here that the session id is printable (HTTP is text protocol)
+ char *t = malloc(strlen(known_text)+50);
+ memset(t, 0, strlen(known_text)+50);
+ memcpy(t, known_text, strlen(known_text));
+ int max, res, i, k;
+
+ // assume that the string we wanne find is less than 100 bytes
+ for(k=0;k<100;k++) {
+ t[strlen(known_text)+k] = 0x09;
+ max = compression_oracle(t, secret, 1);
+ for(i=33;i<128;i++) {
+ t[strlen(known_text)+k] = (char) i;
+ res = compression_oracle(t, secret, 1);
+ if(res < max)
+ break;
+ }
+ if(max == res)
+ break;
+ }
+
+ printf("found string : %s\n", t);
+ printf("should string: Cookie: sessionid=%s\n", secret);
+ // doing binary search above would reduce the calls to the orcale
+ // significant
+ printf("calls to the oracle: %i\n", oracle_count);
+
+
+ // with cbc
+ // length will always be a multiple of the block size
+ oracle_count = 0;
+ printf("with CBC mode\n");
+ // because we only get multiple of 16 as result we have to take
+ // care that a complete block gets compressed
+ // we than need control over the size of the request so that
+ // is is a multiple of 16 BEFORE padding
+ // otherwise we compress 15 bytes and use one block less
+ char *kt = malloc(strlen(known_text)+strlen(secret));
+ memcpy(kt, known_text, strlen(known_text));
+ memcpy(&kt[strlen(known_text)], secret, strlen(secret));
+ // one block which should be compressed away
+ // 6 is the alignment to get a full block
+ char rand[17+6];
+ char ttt[18+8];
+ int j,l;
+ generate_random_printable_bytes(rand, 16+8);
+ rand[17] = '\0';
+ char *raw_request;
+ char *compressed;
+ int compressed_length;
+ int pad;
+ int counts[127-33];
+ int times = 8;
+ char found_sec_cbc[100];
+
+ format_request(&raw_request, "AAAAAAAAAAAAAAAA", secret);
+ my_compress(raw_request, &compressed, &compressed_length);
+ __pkcs7_padding(compressed, compressed_length, 16, &pad);
+ int max_ = compression_oracle(rand, secret, 0);
+
+ memcpy(&ttt[pad], &known_text[strlen(known_text)-16], 16);
+ for(l=0;l<strlen(secret);l++) {
+ memset(&counts, 0, sizeof(int)*(127-33));
+ generate_random_printable_bytes(ttt, pad);
+ for(i=0;i<15;i++)
+ ttt[pad+i] = ttt[pad+i+1];
+ for(k=0;k<10;k++) {
+ for(i=33;i<127;i++) {
+ ttt[pad+15] = i;
+ ttt[pad+16] = '\0';
+ int len = compression_oracle(ttt, secret, 0);
+ if( len < max_)
+ break;
+ }
+ counts[i-33]++;
+ }
+ i = max_int_index(counts, 127-33);
+ found_sec_cbc[l] = (char) (i + 33);
+ }
+ found_sec_cbc[l] = '\0';
+ printf("should: %s\n", secret);
+ printf("is : %s\n", found_sec_cbc);
+ printf("calls to the oracle: %i\n", oracle_count);
+}