오라클 패딩 공격 (Oracle Padding Attack)
2020. 4. 12. 16:05
저장을 안해두니 다시 짜기 귀찮음;;
예제는 noxCTF2018 JavaCorporation
서버
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import socket import threading import random from Crypto.Cipher import AES key = 'NotGonnaHappenAA' class ThreadedServer(object): def __init__(self, host, port): self.host = host self.port = port self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind((self.host, self.port)) def listen(self): self.sock.listen(20) while True: client, address = self.sock.accept() client.settimeout(60) threading.Thread(target = self.listenToClient,args = (client,address)).start() def getIV(self): return ''.join([chr(random.randrange(0, 256)) for i in range(16)]) def encrypt(self, plaintext): iv = self.getIV() aes = AES.new(key, AES.MODE_CBC, iv) return iv + aes.encrypt(plaintext) def decrypt(self, ciphertext): aes = AES.new(key, AES.MODE_CBC, ciphertext[:16]) return aes.decrypt(ciphertext[16:]) def pkcs5(self, s): pad_len = ((-len(s)) % 16) if pad_len == 0: pad_len = 16 return s + chr(pad_len) * pad_len def check_pad(self, s): pad_len = ord(s[-1]) if pad_len > 16 or pad_len == 0: return False pad = s[-pad_len:] for byte in pad: if ord(byte) != pad_len: return False return True def listenToClient(self, client, address): while True: try: length = int(client.recv(2)) if (length % 16 != 0 or length <= 16): client.close() break else: ciphertext = client.recv(length) plaintext = self.decrypt(ciphertext) if self.check_pad(plaintext): client.send('1') else: client.send('0') except Exception as e: print e client.close() return False if __name__ == "__main__": ThreadedServer('0.0.0.0', 3141).listen() | cs |
어택
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | import socket BLOCK_SIZE = 16 def check_pad(cipher): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('127.0.0.1', 3141)) sock.send(cipher) result = b"" for i in range(0x20,0x40): result += sock.recv(1) sock.close() return result def unpadding_pkcs7(block): len_b = len(block) n_padd = ord(block[-1]) if(n_padd==0): raise ValueError('bad padding') for c in range(0, n_padd): if(n_padd != ord(block[len_b-1-c])): raise ValueError('bad padding') unpad_block = block[:-n_padd] return unpad_block def get_nextBlock_decrypt(cipher, iv): knownP = b"" for padding_len in range(1,BLOCK_SIZE+1): candiP = b"" result = b"" for startIdx in range(0x0, 0x81, 0x20): sendFeed = b"" for i in range(startIdx,startIdx+0x20): makeIV = b"\x00"*(BLOCK_SIZE-padding_len) + bytes([i ^ (iv[-padding_len]) ^ padding_len]) for j in range(0,len(knownP)): makeIV += bytes([(iv[len(makeIV)]) ^ (knownP[j]) ^ padding_len]) sendFeed += str(len(makeIV+cipher)).encode('utf-8')+makeIV+cipher # length send result += check_pad(sendFeed) print(result) candiP = result.decode().find("1") candiP= bytes([candiP]) knownP = candiP + knownP return knownP def OraclePaddingAttack(cipher): KnownP = b"" ciphers = [] for i in range(0, len(cipher), BLOCK_SIZE): ciphers.append(cipher[i:i+BLOCK_SIZE]) for i, c in enumerate(ciphers[1:]): preIV = ciphers[i] KnownP += get_nextBlock_decrypt(c, preIV) print(KnownP) return KnownP cipher = open("Encrypted.txt","rb").read() print("len : %d " % len(cipher)) plain = OraclePaddingAttack(cipher) print(plain) | cs |
https://github.com/mwielgoszewski/python-paddingoracle
from paddingoracle import BadPaddingException, PaddingOracle from pwn import * r = remote('chal.noxale.com', 3141) with open('Encrypted.txt', 'rb') as f: data = f.read() iv = data[:16] cipher = data[16:] class PadBuster(PaddingOracle): def __init__(self, **kwargs): super(PadBuster, self).__init__(**kwargs) def oracle(self, data, **kwargs): r.send(bytes(48)) r.send(iv+data) if r.recv(1) == '0': raise BadPaddingException padbuster = PadBuster() value = padbuster.decrypt(cipher, block_size=16, iv=iv) print('Decrypted: %r' % (value))
'Crypto' 카테고리의 다른 글
ECC calculator (0) | 2019.11.02 |
---|---|
RSA LSB Oracle Attack ( + 키 값 계속 바뀔 시도 가능) (0) | 2019.10.12 |
[Crypto] CTR 모드 공격 Break fixed-nonce CTR (0) | 2019.09.17 |
JohnTheRipper Password 크랙 재시도가 안될시 해결법 (0) | 2018.11.27 |
배낭암호(Knapshot) (0) | 2018.11.26 |