Created
July 15, 2015 14:34
-
-
Save k3170makan/b1528efd412813408eb1 to your computer and use it in GitHub Desktop.
A script I used to learn padding oracle attacks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python | |
| from base64 import b64encode,b64decode | |
| import readline | |
| import struct | |
| from Crypto.Cipher import AES | |
| from sys import argv,exit | |
| from os import urandom | |
| from random import random | |
| BS = 16 | |
| pad = lambda s: s + (BS - len(s) % BS) * chr((BS - len(s) % BS)) | |
| def encrypt(iv,key,plain): | |
| return AES.new(key,AES.MODE_CBC,iv).encrypt(plain) | |
| def decrypt(iv,key,cipher): | |
| plaintext = AES.new(key,AES.MODE_CBC,iv).decrypt(cipher) | |
| try: | |
| string = "%s" % (ord(plaintext[len(plaintext)-1])) | |
| #print "padding length : '%s'" % (string) <--- uncomment this if you're havin a hard time with the attack :) | |
| #print "intermediated value : '%s'" % (pretty_print(plaintext)) | |
| except ValueError,e: | |
| print "decrypt:",e | |
| raise e | |
| padding_length = int(string) | |
| incorrect = False | |
| for c in plaintext[len(plaintext)-padding_length:]: | |
| try: | |
| c = int("%s" % (ord(c))) | |
| except: | |
| print "c convert:",e | |
| raise e | |
| if c != padding_length: | |
| incorrect = True | |
| if incorrect == True: | |
| return False | |
| return plaintext[:len(plaintext)-padding_length] | |
| def gen_rand_plaintext(length): | |
| return b64encode("".join([chr(int(random()*1000)%255) for c in range(length)])) | |
| def pretty_print(text): | |
| string = " ".join([ "%02x" % (ord(c)) for c in text]) | |
| return string | |
| def unpretty_print(text): | |
| return ''.join([chr(int(c,16)) for c in text.split(" ")]) | |
| def rlinput(prompt,prefill=''): | |
| readline.set_startup_hook(lambda: readline.insert_text(prefill)) | |
| try: | |
| return raw_input(prompt) | |
| finally: | |
| readline.set_startup_hook() | |
| def block_wise_print(text): | |
| string = " " | |
| newlines = 0 | |
| char_count = 0 | |
| chars = text.split(" ") | |
| for char in chars: | |
| string += char+" " | |
| char_count+=1 | |
| if char_count % 16 == 0: | |
| string += "\n" | |
| return string[1:] | |
| if __name__ == "__main__": | |
| while True: | |
| plaintext = pad("P"*33) | |
| key = "A"*32 | |
| iv = "B"*16 | |
| cipher = encrypt(iv,key,plaintext) | |
| plaintext = decrypt(iv,key,cipher) | |
| print "plaintext [%s]:" % (len(plaintext)) | |
| print block_wise_print(pretty_print(plaintext)) | |
| print "cipher [%s]:" % (len(cipher)) | |
| print block_wise_print(pretty_print(cipher)) | |
| print "decrypted [%s]:" % (len(plaintext)) | |
| print block_wise_print(pretty_print(plaintext)) | |
| while True: | |
| line = rlinput('>',pretty_print(cipher)) | |
| cipher = unpretty_print(line) | |
| line = line.split(" ") | |
| user_cipher = ''.join([chr(int(c,16)) for c in line]) | |
| plain = decrypt(iv,key,user_cipher) | |
| if plain != False: | |
| print "decrypted [%s]:" % (len(plain)) | |
| print block_wise_print(pretty_print(plain)) | |
| print "[x]",plain |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment