def test_bit_flipping(): target = b'THISISWHATIWANTTOSEE' fixed = b'THISCANNOTBECHANGED!' attacker = bit_utils.bytes_xor(fixed, target) result = bit_utils.bytes_xor(fixed, attacker) print(f"target={target}") print(f"fixed={fixed}") print(f"attacker={attacker}") print(f"result={result}")
def key_from_most_commmon(ciphertext : bytes, plaintext_most_commont = ' '.encode('ascii')): # assume the most common ciphertext char corresponds to plaintext_most_common counter = Counter(ciphertext) most_common_ct = counter.most_common()[0][0] indices = [i for i, b in enumerate(ciphertext) if b == most_common_ct] key = bytes_xor([most_common_ct][0], plaintext_most_commont[0]) # print(f"most common: ct={most_common_ct} indices={indices} key={key}") return key
def decrypt_cbc(ciphertext, key, iv): BLOCK_SIZE = 16 assert len(iv) == BLOCK_SIZE assert len(ciphertext) % BLOCK_SIZE == 0 ct_blocks = bit_utils.chunkify(ciphertext, BLOCK_SIZE) prev_ct = iv plaintext = bytes(0) for ct_block in ct_blocks: ecb_out = decrypt_ecb(ct_block, key) plaintext += bit_utils.bytes_xor(ecb_out, prev_ct) prev_ct = ct_block return plaintext
def encrypt_cbc(plaintext, key, iv): BLOCK_SIZE = 16 assert len(iv) == BLOCK_SIZE assert len(plaintext) % BLOCK_SIZE == 0 pt_blocks = bit_utils.chunkify(plaintext, BLOCK_SIZE) prev_ct_block = iv ciphertext = bytes(0) for pt_block in pt_blocks: ecb_in = bit_utils.bytes_xor(pt_block, prev_ct_block) prev_ct_block = encrypt_ecb(ecb_in, key) ciphertext += prev_ct_block return ciphertext
if __name__ == "__main__": ciphertext_no_user_data = format_and_pad_and_encrypt("") # print(f"ciphertext_no_user_data={ciphertext_no_user_data.hex()} len={len(ciphertext_no_user_data)})") # make sure this doesn't work # attempt_priviledge_escalation('admin=true') empty_user_data_len = len(ciphertext_no_user_data) # make our plaintext as long as the prefix and suffix so we can guess were it is in the ciphertext # using all zeros here eliminates one XOR operation attacker_plaintext = b'\ff' * empty_user_data_len original_ciphertext = bytearray( format_and_pad_and_encrypt(attacker_plaintext)) target_plaintext = 'admin=true '.encode('ascii') print("original ciphertext:") bit_utils.print_hex_block(original_ciphertext) print(f"target_plaintext: {target_plaintext}") bit_utils.print_hex_block(target_plaintext) # modify ciphertext block that will be XORed with attacker_plaintext so that the result is target_plaintext # [A=ecb(a^iv)][B=ecb(b^A)][C=ecb(c^B)][D=ecb(d^C)] original_prev_block_ciphertext = original_ciphertext[ empty_user_data_len:empty_user_data_len + 16] mod_prev_block_ciphertext = bit_utils.bytes_xor( original_prev_block_ciphertext, bit_utils.bytes_xor(target_plaintext, attacker_plaintext)) attacker_ciphertext = bytearray(original_ciphertext) attacker_ciphertext[empty_user_data_len:empty_user_data_len + 16] = mod_prev_block_ciphertext print("modified ciphertext:") bit_utils.print_hex_block(attacker_ciphertext) print(f"is_admin={is_admin(attacker_ciphertext)}")