if __name__ == "__main__": oracle = PaddingOracle('10.9.0.80', 5000)
# Get the IV + Ciphertext from the oracle iv_and_ctext = bytearray(oracle.ctext) IV = iv_and_ctext[00:16] C1 = iv_and_ctext[16:32] # 1st block of ciphertext C2 = iv_and_ctext[32:48] # 2nd block of ciphertext print("C1: " + C1.hex()) print("C2: " + C2.hex())
############################################################### # Here, we initialize D2 with C1, so when they are XOR-ed, # The result is 0. This is not required for the attack. # Its sole purpose is to make the printout look neat. # In the experiment, we will iteratively replace these values. D2 = bytearray(16)
D2[0] = C1[0] D2[1] = C1[1] D2[2] = C1[2] D2[3] = C1[3] D2[4] = C1[4] D2[5] = C1[5] D2[6] = C1[6] D2[7] = C1[7] D2[8] = C1[8] D2[9] = C1[9] D2[10] = C1[10] D2[11] = C1[11] D2[12] = C1[12] D2[13] = C1[13] D2[14] = C1[14] D2[15] = C1[15] ############################################################### # In the experiment, we need to iteratively modify CC1 # We will send this CC1 to the oracle, and see its response. CC1 = bytearray(16)
############################################################### # In each iteration, we focus on one byte of CC1. # We will try all 256 possible values, and send the constructed # ciphertext CC1 + C2 (plus the IV) to the oracle, and see # which value makes the padding valid. # As long as our construction is correct, there will be # one valid value. This value helps us get one byte of D2. # Repeating the method for 16 times, we get all the 16 bytes of D2.
K = 1 for i inrange(256): CC1[16 - K] = i status = oracle.decrypt(IV + CC1 + C2) if status == "Valid": print("Valid: i = 0x{:02x}".format(i)) print("CC1: " + CC1.hex()) ###############################################################
# Once you get all the 16 bytes of D2, you can easily get P2 P2 = xor(C1, D2) print("P2: " + P2.hex())
if __name__ == "__main__": oracle = PaddingOracle('10.9.0.80', 6000)
# Get the IV + Ciphertext from the oracle iv_and_ctext = bytearray(oracle.ctext) print(len(iv_and_ctext)) # Num of ctext num = int(len(iv_and_ctext)/16 - 1) plain_text = '' for n inrange(num): C = iv_and_ctext[(n)*16: (n+1)*16] if n == 0: print(f"IV: " + C.hex()) else: print(f"C{n}: " + C.hex()) # initialize D, IV, P D = bytearray(16) CC = bytearray(16) P = bytearray(16) # Solve D for K inrange(1, 17): for i inrange(256): CC[16 - K] = i # initialize input tmp_input = iv_and_ctext[0:(n+2)*16] tmp_input[n*16:(n+1)*16] = CC status = oracle.decrypt(tmp_input) if status == "Valid": print("Valid: i = 0x{:02x}".format(i)) print("D: "+ D.hex()) print("CC: " + CC.hex()) # Update D D[16 - K] = i^K # Update CC for j inrange(1, K+1): CC[16 - j] = D[16 - j]^(K+1) break # Once you get all the 16 bytes of D2, you can easily get P2 P = xor(C, D) print("P: " + P.hex()) for j inrange(16): plain_text += chr(P[j]) print("Plaintext: " + plain_text)