Files
2025-06-02 19:35:30 +02:00

166 lines
6.7 KiB
Python

#!/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