def c17(filename): """ This program performs the padding oracle attack on AES cipher in CBC mode """ with open(filename, "r") as file: lines = file.readlines() bsize = 16 for line in lines: # convert each line to ASCII data = base.base64_to_hex(line).decode('hex') # obtain ciphertext from encryption oracle # this is equivalent to getting a cookie ct, iv = base.c17_encrypt_oracle(data) size = len(ct) / bsize # divide the ciphertext into blocks - size 16 blocks = [ct[i * bsize: (i + 1) * bsize] for i in range(size)] sol = [] prev = iv padding = 0x1 for block in blocks: # decrypt current block (cur) # by modifying previous block (prev) base.solve_po(block, prev, bsize - 1, "", padding, bsize, iv, sol) prev = block print ''.join(sol)
def c12(): unknown_string = '' with open("ip12.txt","r") as file: b64_unknown_string = file.read().strip('\n') unknown_string = base.base64_to_hex(b64_unknown_string).decode('hex') unknown_size = len(unknown_string) unknown_ct = base.AES_128_ECB(unknown_string) prefix_size = len(unknown_ct) - 1 print prefix_size prefix = "A" * prefix_size known = "" while prefix_size > 0: pt = prefix + unknown_string ct = base.AES_128_ECB(pt) size = len(prefix) + len(known) + 1 # brute force byte by byte for i in range(256): pt2 = prefix + known + chr(i) ct2 = base.AES_128_ECB(pt2) if ct[0:size] == ct2[0:size]: known += chr(i) break # adjust prefix by popping the last byte, since we know a new byte prefix = prefix[:-1] prefix_size = len(prefix) print known
def c18(): """ This program performs AES decryption in CTR mode """ ciphertext = base.base64_to_hex("L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syLXzhPweyyMTJULu/6/kXX0KSvoOLSFQ==").decode('hex') key = "YELLOW SUBMARINE" # print base.aes_ctr_decrypt(ciphertext, key, 16) print base.aes_ctr_manual_decrypt(ciphertext, key)
def c19(filename): """ This program reads 40 strings and encrypts them under AES - CTR Then it attempts to crack the CTR mode without knowing the key using the fact that the nonce is repeated """ with open(filename, "r") as file: lines = file.readlines() ciphers = [] key = Random.get_random_bytes(16) nonce = 0xdeadbeef for line in lines: plaintext = base.base64_to_hex(line.strip("\n")).decode('hex') ciphers.append(base.aes_ctr_encrypt(plaintext, key, nonce, 16)) # get tbe minimum length cipher min_len = 10000000 for cipher in ciphers: cur_len = len(cipher) if min_len > cur_len: min_len = cur_len # brute force each byte, column-wise, since each column entry # is encrypted with the same byte of the keystream as it is # repeated. key_bytes = [0x0] * min_len idx = 0 for i in range(min_len): for brute in range(256): deciphered = [ord(cipher[i]) ^ brute for cipher in ciphers] if base.is_all_ascii(deciphered): key_bytes[idx] = brute idx += 1 break # expand key now, start from 11th byte of key key_bytes = base.expand_ctr_key(ciphers[-12], key_bytes, 've', 10) key_bytes = base.expand_ctr_key(ciphers[-4], key_bytes, 'l', 12) key_bytes = base.expand_ctr_key(ciphers[3], key_bytes, 'ntury', 13) key_bytes = base.expand_ctr_key(ciphers[20], key_bytes, 'eet', 18) key_bytes = base.expand_ctr_key(ciphers[21], key_bytes, 'ful', 21) key_bytes = base.expand_ctr_key(ciphers[19], key_bytes, 'ill', 24) key_bytes = base.expand_ctr_key(ciphers[-7], key_bytes, 'rt', 27) key_bytes = base.expand_ctr_key(ciphers[-11], key_bytes, 'ht', 29) key_bytes = base.expand_ctr_key(ciphers[-15], key_bytes, 'd', 31) key_bytes = base.expand_ctr_key(ciphers[-13], key_bytes, 'd', 32) key_bytes = base.expand_ctr_key(ciphers[4], key_bytes, 'ead', 33) key_bytes = base.expand_ctr_key(ciphers[-3], key_bytes, 'n', 36) # decipher all ciphertexts now with the guessed key plaintexts = [] for cipher in ciphers: pbytes = base.equal_size_xor(bytearray(cipher), key_bytes) plaintexts.append(''.join([chr(byte) for byte in pbytes])) print '\n'.join(plaintexts)
def c10(filename): f = open(filename,"r") data = f.readlines() f.close() pad = "\x04" decoded_data = base.base64_to_hex(''.join(data).strip()).decode('hex') block_size = 16 key = "YELLOW SUBMARINE" iv = ''.join(["\x00" for i in range(block_size)]) blocks = [str(decoded_data[i*block_size : (i+1)*block_size]) for i in range(int(len(decoded_data)/block_size))] op = [] size = len(blocks) for i in range(size): pt = base.AES_ECB_decrypt(blocks[i],key) res = base.equal_size_xor(bytearray(pt),bytearray(iv)) res = base.bytearray_to_ASCII(res) op.append(res) iv = blocks[i] plaintext = base.pkcs7_unpad(''.join(op)) print plaintext
def c20(filename): """ This program reads 40 strings and encrypts them under AES - CTR Then it attempts to crack the CTR mode without knowing the key using the fact that the nonce is repeated """ with open(filename, "r") as file: lines = file.readlines() ciphers = [] key = Random.get_random_bytes(16) nonce = 0xdeadbeef for line in lines: plaintext = base.base64_to_hex(line.strip("\n")).decode('hex') #print plaintext ciphers.append(base.aes_ctr_encrypt(plaintext, key, nonce, 16)) # get tbe minimum length cipher min_len = 10000000 for cipher in ciphers: cur_len = len(cipher) if min_len > cur_len: min_len = cur_len # brute force each byte, column-wise, since each column entry # is encrypted with the same byte of the keystream as it is # repeated. key_bytes = [0x0] * min_len idx = 0 for i in range(min_len): for brute in range(256): deciphered = [ord(cipher[i]) ^ brute for cipher in ciphers] if base.is_all_ascii_expanded(deciphered): #print ''.join([chr(byte) for byte in deciphered]) key_bytes[idx] = brute idx += 1 break # expand key now, start from 11th byte of key key_bytes = base.expand_ctr_key(ciphers[8], key_bytes, 'irteenth', 13) key_bytes = base.expand_ctr_key(ciphers[4], key_bytes, 'e', 21) key_bytes = base.expand_ctr_key(ciphers[-9], key_bytes, 'rite', 22) key_bytes = base.expand_ctr_key(ciphers[-4], key_bytes, 'ing', 26) key_bytes = base.expand_ctr_key(ciphers[-8], key_bytes, 'out', 29) key_bytes = base.expand_ctr_key(ciphers[-26], key_bytes, 'and', 32) key_bytes = base.expand_ctr_key(ciphers[-17], key_bytes, 'ey', 35) key_bytes = base.expand_ctr_key(ciphers[-16], key_bytes, 'ence', 37) key_bytes = base.expand_ctr_key(ciphers[25], key_bytes, 'n', 41) key_bytes = base.expand_ctr_key(ciphers[29], key_bytes, 're', 42) key_bytes = base.expand_ctr_key(ciphers[-17], key_bytes, 'nt', 44) key_bytes = base.expand_ctr_key(ciphers[-11], key_bytes, 'n', 46) key_bytes = base.expand_ctr_key(ciphers[-24], key_bytes, 'dge', 47) key_bytes = base.expand_ctr_key(ciphers[5], key_bytes, 'ypse', 50) key_bytes = base.expand_ctr_key(ciphers[-23], key_bytes, 'y', 54) key_bytes = base.expand_ctr_key(ciphers[-18], key_bytes, 't', 55) key_bytes = base.expand_ctr_key(ciphers[16], key_bytes, 'ime', 56) key_bytes = base.expand_ctr_key(ciphers[-2], key_bytes, 'kin', 59) key_bytes = base.expand_ctr_key(ciphers[22], key_bytes, 'ate', 62) key_bytes = base.expand_ctr_key(ciphers[6], key_bytes, 'lty', 65) key_bytes = base.expand_ctr_key(ciphers[16], key_bytes, 'ght', 68) key_bytes = base.expand_ctr_key(ciphers[22], key_bytes, 'ate', 71) key_bytes = base.expand_ctr_key(ciphers[7], key_bytes, 'ssion', 74) key_bytes = base.expand_ctr_key(ciphers[-17], key_bytes, 'n', 79) key_bytes = base.expand_ctr_key(ciphers[8], key_bytes, 't', 80) key_bytes = base.expand_ctr_key(ciphers[5], key_bytes, 'e', 81) key_bytes = base.expand_ctr_key(ciphers[-28], key_bytes, 'lance', 82) key_bytes = base.expand_ctr_key(ciphers[4], key_bytes, 'row', 87) key_bytes = base.expand_ctr_key(ciphers[17], key_bytes, 'ble', 90) key_bytes = base.expand_ctr_key(ciphers[11], key_bytes, 'st', 93) key_bytes = base.expand_ctr_key(ciphers[-26], key_bytes, 'on', 95) key_bytes = base.expand_ctr_key(ciphers[26], key_bytes, 'rve', 97) key_bytes = base.expand_ctr_key(ciphers[-19], key_bytes, 'ull', 100) key_bytes = base.expand_ctr_key(ciphers[21], key_bytes, 'ace', 103) key_bytes = base.expand_ctr_key(ciphers[26], key_bytes, 'hole', 106) # decipher all ciphertexts now with the guessed key plaintexts = [] for cipher in ciphers: pbytes = base.equal_size_xor(bytearray(cipher), key_bytes) plaintexts.append(''.join([chr(byte) for byte in pbytes])) print '\n'.join(plaintexts)
def c14(): """ This function performs leverages ECB's statelessnes to exploit ciphers where we have the form <RandomMessage, AttackerMessage, Cipher> The challenge encountered by an attacker in this case is that the attacker does not know the size of the random prefix, and therefore does not know where the ciphertext begins. To circumvent this, the attacker can inject 3 contiguous blocks with the same plaintext. There are 2 possible cases a) If the random prefix is a multiple of block_size, then we get 3 consecutive ciphertext blocks that have the same value b) If the random prefix is not a multiple of the block_size, then we get 2 blocks that have the same value in the ciphertext In either case, we can read the consecutive blocks and identify the location where they end. This allows the attacker to identify the position of the actual ciphertext. Now the attacker can allocate another block whose last byte is filled by the ciphertext and brute force the ciphertext byte by byte as before. """ # read the encrypted target string target_string = '' blk_size = 16 with open("../inputs/ip12.txt", "r") as file: target_string = file.read().strip('\n') target_string = base.base64_to_hex(target_string).decode('hex') # generate a random prefix prefix_size = random.randint(0, 100) prefix = '' for i in range(prefix_size): prefix += chr(random.randint(0, 255)) # create 3 blocks attacker_test = "a" * blk_size * 3 test_cipher = base.AES_128_ECB(prefix + attacker_test + target_string) # detect 2 consecutive blocks pos = 0 # divide the input into blocks of size blk_size blocks = [test_cipher[i*blk_size:(i+1)*blk_size] for i in range(len(test_cipher)/blk_size)] blocks_size = len(blocks) # look for 2 consecutive blocks that have the exact same value for i in range(blocks_size - 1): if blocks[i] == blocks[i+1]: pos = (i+1)*blk_size + blk_size print blocks[i] , i # check if there is a 3rd consecutive block if i < blocks_size - 2: if blocks[i+1] == blocks[i+2]: pos = (i+2)*blk_size + blk_size break # now we know where our blocks end, so we can reliably identify where the # ciphertext begins prefix_len = pos - blk_size*3 while prefix_len < pos - blk_size*2: attack_size = blk_size attack_pad_size = attack_size - prefix_len % attack_size attacker_string = "A" * attack_pad_size # input to the AES ECB oracle will be plaintext # which has a random prefix, attacker controlled data, followed by # the target string that we intend to decrypt plaintext = prefix + attacker_string + target_string known = 0 recover = "" unknown = len(target_string) pre = prefix + attacker_string sz = len(pre) print prefix_len, prefix_size # brute force each byte of the ciphertext # until we uncover the entire ciphertext while known < unknown: plaintext = pre[:-1] + target_string[known:] ciphertext = base.AES_128_ECB(plaintext) # brute force the byte for b in range(256): fake_plaintext = pre[:-1] + chr(b) + target_string[known + 1:] fake_ciphertext = base.AES_128_ECB(fake_plaintext) if fake_ciphertext[0:sz] == ciphertext[0:sz]: known += 1 recover += chr(b) break print recover,"\n\n" prefix_len += 1