#!/usr/bin/env python3 from Cryptodome.Random import get_random_bytes from pwn import * HOST = "130.192.5.212" PORT = "6544" lenFlag = len("CRYPTO25{}")+36 # 46 total server = remote(HOST, PORT) #padding1 + padding2 = 10 PAD_NUM = 10 #AES block 16 #server.send(b"enc\n") flagGuessed = b'' sleepT = 0.1 pad1Len = 0 pad2Len = 0 #print(server.recv(1024)) # Indovina for i in range(1,6): pad=b'A'*(16-i) secondBlock=b'B'*16 thirdBlock=b'B'*16 print(server.recvline()) print(server.recvline()) print(server.recvline()) print(server.recvline()) server.send(b'enc\n') toSend = pad + secondBlock + thirdBlock print(f"Sending {toSend} with len {len(toSend)}") server.send( toSend.hex()) server.send(b'\n') ciphertext = server.recvline().strip(b"> >").strip() ciphertext = bytes.fromhex(ciphertext.decode('utf-8')) if ciphertext[16:32] == ciphertext[32:48]: pad1Len = i pad2Len = 10-i print(f"Found the right padding num:{pad1Len} and second pad len:{pad2Len}") break assert(pad1Len <= 6) assert(pad2Len > 0) print('-------') pad2Guessed = b'' sleepT = 0.1 # Conoscere pad2 serve solo per indovinare il primo blocco for i in range(pad2Len): pad1 = b'A' * (16-pad1Len) data = b'B' * (16 - (len(pad2Guessed)+1) ) fPayload = data + pad2Guessed for g in range(255): assert(g != 255) server.recvline() server.recvline() server.recvline() server.recvline() guess = g.to_bytes() server.send(b'enc\n') toSend = pad1 + fPayload + guess + data print(f"Sending {toSend} with len {len(toSend)} and PAD2Len:{pad2Len} len Fpayload:{len(fPayload)} and len data:{len(data)}") server.send( toSend.hex()) server.send(b'\n') ciphertext = server.recvline().strip(b"> >").strip() ciphertext = bytes.fromhex(ciphertext.decode('utf-8')) if ciphertext[16:32] == ciphertext[32:48]: print(f"Matched guess: {guess}") pad2Guessed += guess print(f"Already Guessed: {pad2Guessed}") break assert(len(pad2Guessed) == pad2Len) print(f"FOUND PADDING 2:{pad2Guessed}") # Mi servono 6 byte di padding firstBlock = b'CRYPTO25{' # flag CRYPTO25{df0b0f03-0bd4-4dc8 # CRYPTO25{df0b0f03-0bd4-4dc8-9043-bcdac301684c} #firstBlock = b'CRYPTO25{df0b0f0' #secondBlock =b'' #secondBlock = b'3-0bd4-4dc8-9043' firstBlock = b'' secondBlock = b'' thirdBlock = b'' # Devo tagliare il PADDING2 quindi mando un blocco che contiene il PADDING2 - i primi X Byte + blocco che gia' conosco + guess # Dopo mando X Byte di A in modo che in questo blocco finiscano gli stessi byte del padding2 che ho tagliato # Comparo il terzo blocco che sara' PADDIN2 tagliato + Byte della flag che ho + Byte della flag che voglio indovinare pad1 = b'A' * (16 - pad1Len) for i in range(7): for guess in string.printable: server.recvline() server.recvline() server.recvline() server.recvline() guess = bytes(guess,'utf-8') server.send(b'enc\n') # Lunghezza che mi serve per avere blocco + guess nel blocco che mando lenNeeded = 16 - len(firstBlock) - 1 # Questo blocco fa da cuscinetto e serve solo per tagliare i primi byte che ignoro del padding2 aggiunti dal server # Se devo scartare i primi 3 byte quindi questo sara' 16 - 3 byte lungo useless = b'Z' * (16 - (pad2Len - lenNeeded)) if(pad2Len > lenNeeded ): # 1 Blocco + 2 Blocco da controllare + 3 blocco inutile toSend = pad1 + pad2Guessed[(pad2Len - lenNeeded):] + firstBlock + guess + useless #print(f"Payload len: {len(fPayload+pad2Guessed+guess+fPayload)}") print(f"Sending {toSend} with len {len(toSend)} len data:{len(data)}") server.send( toSend.hex()) server.send(b'\n') ciphertext = server.recvline().strip(b"> >").strip() ciphertext = bytes.fromhex(ciphertext.decode('utf-8')) if ciphertext[16:32] == ciphertext[48:64]: print(f"Matched guess: {guess}") firstBlock += guess print(f"FLAG Already Guessed: {firstBlock}") break for i in range(16): for guess in string.printable: server.recvline() server.recvline() server.recvline() server.recvline() guess = bytes(guess,'utf-8') server.send(b'enc\n') # Per indovinare il secondo blocco possiamo usare il primo, tagliandolo in base a quanto # conosco del secondo blocco, metto sempre in mezzo un blocco cuscinetto (alla fine e' meglio avere due blocchi cuscinetto) che include byte a caso # + padding2 messo dal server # + i byte della flag che gia' conosco e voglio tagliare, in modo che quelli del secondo blocco della flag siano comparabili con guess useless = b'Z' * (32 - pad2Len - (len(secondBlock) + 1)) toSend = pad1 + firstBlock[len(secondBlock)+1:] + secondBlock + guess + useless print(f"Sending {toSend} len first+second+guess:{len(firstBlock[len(secondBlock)+1:]+secondBlock+guess)} len useless:{len(useless)} len pad2:{pad2Len}") server.send( toSend.hex()) server.send(b'\n') ciphertext = server.recvline().strip(b"> >").strip() ciphertext = bytes.fromhex(ciphertext.decode('utf-8')) if ciphertext[16:32] == ciphertext[64:80]: print(f"Matched guess: {guess}") secondBlock += guess print(f"FLAG Already Guessed: {firstBlock + secondBlock}") break for i in range(16): for guess in string.printable: server.recvline() server.recvline() server.recvline() server.recvline() guess = bytes(guess,'utf-8') server.send(b'enc\n') # Per indovinare il secondo blocco possiamo usare il primo, tagliandolo in base a quanto # conosco del secondo blocco, metto sempre in mezzo un blocco cuscinetto che include byte a caso + padding2 messo dal server # + i byte della flag che gia' conosco e voglio tagliare, in modo che quelli del secondo blocco della flag siano comparabili con guess useless = b'Z' * (48 - pad2Len - (len(thirdBlock) + 16 + 1)) toSend = pad1 + secondBlock[len(thirdBlock)+1:] + thirdBlock + guess + useless print(f"Sending {toSend} len second+third+guess:{len(secondBlock[len(thirdBlock)+1:]+thirdBlock+guess)} len useless:{len(useless)} len pad2:{pad2Len}") server.send( toSend.hex()) server.send(b'\n') ciphertext = server.recvline().strip(b"> >").strip() ciphertext = bytes.fromhex(ciphertext.decode('utf-8')) if ciphertext[16:32] == ciphertext[80:96]: print(f"Matched guess: {guess}") thirdBlock += guess print(f"FLAG Already Guessed: {firstBlock + secondBlock + thirdBlock}") break