PKCS#7 not correct?
i tried with
////// exploit.py
from pwn import *
import json
import re
SERVER_IP = "94.237.54.69"
SERVER_PORT = 47940
BLOCK_SIZE = 16
def print_progress(current, total, prefix="", suffix=""):
bar_length = 40
filled = int(round(bar_length * current / float(total)))
percent = round(100.0 * current / float(total), 1)
bar = '#' * filled + '-' * (bar_length - filled)
print(f"\r{prefix} [{bar}] {percent}% {suffix}", end="")
if current == total:
print()
def is_hex(s):
"""Check if the string is a valid hexadecimal number."""
return re.fullmatch(r'^[0-9a-fA-F]+$', s) is not None
def get_token®:
r.recvuntil(b"> ")
r.sendline(b"1")
r.recvuntil(b"Send your credentials: ")
credentials = json.dumps({"username": "D-Cryp7", "password": "Cryp70Gr47Hy!", "token": ""})
r.sendline(credentials.encode())
resp = r.recvuntil(b"|--------------------------------------------------------|\n").decode()
token_hex = resp.split("Token: ")[1].split()[0]
if not is_hex(token_hex):
raise ValueError(f"Invalid hexadecimal token: {token_hex}")
print(f"[+] Obtained token (first 32 chars): {token_hex[:32]}...")
return bytes.fromhex(token_hex)
def retrieve_data®:
r.recvuntil(b"> ")
r.sendline(b"2") # Request encrypted data
# Read until the line containing "Encrypted data:"
r.recvuntil(b"Encrypted data: ")
# Read the encrypted data line
encrypted_data_line = r.recvline().strip().decode()
# Debug: Print the raw response for inspection
print(f"[DEBUG] Raw response from server: {encrypted_data_line}")
# Extract hexadecimal data (assuming it's the only hexadecimal string in the line)
hex_data = re.search(r'([0-9a-fA-F]+)', encrypted_data_line)
if not hex_data:
raise ValueError(f"No hexadecimal data found in response: {encrypted_data_line}")
hex_data = hex_data.group(1)
# Validate the extracted hexadecimal data
if not is_hex(hex_data):
raise ValueError(f"Invalid hexadecimal encrypted data: {hex_data}")
encrypted_data = bytes.fromhex(hex_data)
return encrypted_data
def is_valid_padding(r, ciphertext):
r.recvuntil(b"> ")
r.sendline(b"1")
r.recvuntil(b"Send your credentials: ")
token_hex = ciphertext.hex()
creds = json.dumps({"username": "D-Cryp7", "password": "Cryp70Gr47Hy!", "token": token_hex})
r.sendline(creds.encode())
resp = r.recv(timeout=10).decode()
return "Decryption error!" not in resp
def decrypt_block(r, prev_block, cipher_block):
intermediate = bytearray(16)
print(f"\n[+] Decrypting new block: {cipher_block.hex()}")
for pad_len in range(1, BLOCK_SIZE + 1):
current_byte = BLOCK_SIZE - pad_len
total_guesses = 256
print(f"[+] Decrypting byte {current_byte} (0x{current_byte:02x})")
for guess in range(256):
print_progress(guess, total_guesses-1,
prefix=f" Byte {current_byte} guesses",
suffix=f"Testing 0x{guess:02x}")
modified_prev = bytearray(prev_block)
for pos in range(current_byte + 1, BLOCK_SIZE):
modified_prev[pos] = prev_block[pos] ^ intermediate[pos] ^ pad_len
modified_prev[current_byte] = prev_block[current_byte] ^ guess ^ pad_len
if is_valid_padding(r, bytes(modified_prev) + cipher_block):
intermediate[current_byte] = guess
print(f"\n[+] Found valid byte {current_byte}: 0x{guess:02x}")
break
plaintext = bytes([intermediate[i] ^ prev_block[i] for i in range(16)])
print(f"[+] Decrypted block: {plaintext.hex()} → ASCII: {plaintext.decode(errors='replace')}")
return plaintext
def decrypt_data(r, iv, ciphertext):
blocks = [ciphertext[i:i+16] for i in range(0, len(ciphertext), 16)]
plaintext = b''
prev_block = iv
print(f"\n[+] Starting decryption of {len(blocks)} blocks:")
for i, block in enumerate(blocks):
print(f"\n[=== Decrypting block {i+1}/{len(blocks)} ===]")
plaintext_block = decrypt_block(r, prev_block, block)
plaintext += plaintext_block
prev_block = block
# Attempt to remove padding (if valid)
try:
padding_length = plaintext[-1]
if padding_length > BLOCK_SIZE or padding_length == 0:
print(f"[!] Warning: Invalid padding length ({padding_length}). Skipping padding removal.")
else:
plaintext = plaintext[:-padding_length]
except IndexError:
print("[!] Warning: No padding found. Returning full decrypted data.")
return plaintext
def extract_structured_data(decrypted):
"""Extract structured data (e.g., credit card numbers) from the decrypted output."""
# Look for patterns like XXXX-XXXX-XXXX-XXXX or XXXX XXXX XXXX XXXX
pattern = re.compile(r'(\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4})')
matches = pattern.findall(decrypted.decode(errors='replace'))
if matches:
return matches[0] # Return the first match
return None
def main():
# Step 1: Login and get token
print("[=== Step 1: Login and Get Token ===]")
r = remote(SERVER_IP, SERVER_PORT, timeout=10)
token = get_token®
input("\nPress Enter to proceed to Step 2...")
# Step 2: Retrieve user data
print("\n[=== Step 2: Retrieve User Data ===]")
encrypted_data = retrieve_data®
print(f"[+] Received encrypted data: {encrypted_data.hex()}")
input("\nPress Enter to proceed to Step 3...")
# Step 3: Decryption attack
print("\n[=== Step 3: Decryption Attack ===]")
iv = token[:16] # Use the first 16 bytes of the token as the IV
print(f"[+] Using IV from token: {iv.hex()}")
decrypted = decrypt_data(r, iv, encrypted_data)
# Extract structured data (e.g., credit card numbers)
structured_data = extract_structured_data(decrypted)
if structured_data:
print(f"\n[+] DECRYPTED DATA: {structured_data}")
else:
print(f"\n[!] No structured data found in decrypted output.")
print(f"[!] FULL DECRYPTED DATA (hex): {decrypted.hex()}")
print(f"[!] FULL DECRYPTED DATA (ASCII): {decrypted.decode(errors='replace')}")
r.close()
if __name__ == "__main__":
main()
////////
i got!
[+] Decrypted block: fd6d15cebd88cd0f6b6e0ad84b14e7d8 → ASCII: m\x15ν \x0fkn
K\x14
[!] Warning: Invalid padding length (216). Skipping padding removal.
[!] No structured data found in decrypted output.
[!] FULL DECRYPTED DATA (hex): 9f10c92b119c45a26f2416212a140950fd6d15cebd88cd0f6b6e0ad84b14e7d8
[!] FULL DECRYPTED DATA (ASCII): \x10 +\x11 E o$\x16!*\x14 P m\x15ν \x0fkn
K\x14
[*]Closed connection to 94.237.54.69 port 47940