#include "lib3.h" #include "lib2.h" #include "lib.h" #define NR_STIRNGS_CHALLENGE17 10 char *challenge17_encrypt(int *length) { int i, t; char **string; char **decoded; string = malloc(sizeof(char *)*NR_STIRNGS_CHALLENGE17); decoded = malloc(sizeof(char *)*NR_STIRNGS_CHALLENGE17); char filename[] = "task17_0"; for(i=0;i<10;i++) { filename[strlen(filename)-1] = (char) (i+'0'); t = read_base64_file(filename, &string[i]); decoded[i] = malloc(t); length[i] = decode_base64(string[i], decoded[i]); printf("read: %s\n", string[i]); } // choose one randomly int random = rand() % NR_STIRNGS_CHALLENGE17; int padding; printf("plaintext: %s\n", string[random]); *length = strlen(string[random]); char *padded_string = __pkcs7_padding(string[random], *length, 16, &padding); char *encrypted = malloc(strlen(padded_string)); *length += padding; aes_cbc(padded_string, strlen(padded_string), encrypted, key, iv, 1); return encrypted; } int cbc_padding_oracle(char *encrypted, int length) { char *decrypted = malloc(length); char *unpadded= malloc(length); aes_cbc(encrypted, length, decrypted, key, iv, 0); int valid = valid_pkcs7_padding(decrypted, length, unpadded, 16); free(decrypted); free(unpadded); return valid; } /** * format is: 64 nonce concat with 64 bit counter * calle has to make sure that nonce is at least 8 bytes * its all little endian */ int aes_ctr(char *in, int length_in, char *out, char *string_key, char *nonce) { long counter; unsigned char tmp[16]; char keystream[16]; long nr_blocks = length_in / BLOCKSIZE; int length_last_block = length_in % BLOCKSIZE; memcpy(tmp, nonce, 16); for(counter=0;counterindex = MT_19937_N; mt_19937->mt[0] = seed; memset(&mt_19937->mt[1], 0, 623); for(i=1;i<=MT_19937_N;i++) { mt_19937->mt[i] = (1812433253 * (mt_19937->mt[i-1] ^ (mt_19937->mt[i-1] >> 30))) + i; // only the last 32 bit mt_19937->mt[i] &= 0xFFFFFFFF; } } void mt_19937_generate(struct mt_19937_state *mt_19937) { unsigned int i, x; for(i=0;i<=MT_19937_N;i++) { // x is the first bit of mt[i] plus the last 31 bits of the // next number x = (((mt_19937->mt[i] & MT_19937_UPPER_MASK) + (mt_19937->mt[(i+1) % 624] & MT_19937_LOWER_MASK) )& 0xFFFFFFFF); mt_19937->mt[i] = mt_19937->mt[(i+397) % MT_19937_N] ^ x >> 1; if (x % 2) mt_19937->mt[i] ^= 0x9908b0df; } mt_19937->index = 0; } unsigned int mt_19937(struct mt_19937_state *mt_19937_st) { unsigned int y = 0x0; if(mt_19937_st->index >= MT_19937_N) mt_19937_generate(mt_19937_st); y = mt_19937_st->mt[mt_19937_st->index]; y = y ^ (y >> 11); y = y ^ ((y << 7) & 0x9D2C5680); y = y ^ ((y << 15) & 0xEFC60000); y = y ^ (y >> 18); mt_19937_st->index++; return (y & 0xFFFFFFFF); } unsigned int mt_19937_timestamp_orcale(struct mt_19937_state *mt_19937_st) { sleep(random_number_between(40,1000)); unsigned int seed = time(NULL); printf("timestamp orcale seed: %u\n", seed); mt_19937_seed(seed, mt_19937_st); sleep(random_number_between(40,1000)); return mt_19937(mt_19937_st); } /*** * is there a more clever way to do this than brute force? * **/ void mt_19937_brute_force_timestamp() { struct mt_19937_state mt_state; unsigned int start = time(NULL); int rnd = mt_19937_timestamp_orcale(&mt_state); unsigned int stop = time(NULL); unsigned int i; // try every seed between start and stop for(i=start;start<=stop;i++) { mt_19937_seed(i, &mt_state); if (rnd == mt_19937(&mt_state)) { printf("found seed: %u\n", i); break; } } } int unshift_right_xor(int number, int shifts) { /** * restore shift bits in every round **/ int rounds = 0; int restore = 0; while(rounds*shifts < 32) { // take #shift bit be on, begin on the left and go to the right unsigned int tmp = (0xFFFFFFFF << (32-shifts)) >> (rounds*shifts); unsigned int tmp2 = number & tmp; number ^= tmp2 >> shifts; restore |= tmp2; rounds++; } return restore; } /*** * why the fuck is the reverse AND working? **/ int unshift_left_xor(int number, int shifts, unsigned int mask) { int rounds = 0; int restore = 0; while(rounds*shifts < 32) { // take #shift bit be on, begin on the right and shift it to left every round unsigned int tmp = (0xFFFFFFFF >> (32-shifts)) << (rounds*shifts); unsigned int tmp2 = number & tmp; number ^= tmp2 << shifts & mask; restore |= tmp2; rounds++; } return restore; } int mt_19937_stream_cipher(char *in, int length_in, char *out, int seed) { struct mt_19937_state mt_state; char keystream; int i, tmp; mt_19937_seed(seed, &mt_state); for(i=0;i