# TCP1P CTF 2024 - Skibidi Format **Title:** Skibidi Format **Description:** So my friend just made a new image format and asked me to give him a test file, so I gave him my favorite png of all time. But the only thing I receive back is just my image with his new format and its "specification" file, don't know what that is. Can you help me read this file? **Files:** - [spec.html](https://github.com/xtasy94/CTFW/blob/main/CTF_Files/TCP1PCTF/spec.html) - [suisei.skibidi](https://github.com/xtasy94/CTFW/blob/main/CTF_Files/TCP1PCTF/suisei.skibidi) ## Solution: I started by examining the provided "specification" file (spec.html) to understand the structure of the `.skibidi` image format, I found that the specification detailed the file format with a `58-byte` header follow by encrypted and compressed pixel data: ```bash +----------------------+-----------------------+ | Header | Data Section | +----------------------+-----------------------+ | Magic Number (4B) | Encrypted Data | | Width (4B) | | | Height (4B) | | | Channels (1B) | | | Compression ID (1B) | | | AES Key (32B) | | | AES IV (12B) | | +----------------------+-----------------------+ Total Header Size: 58 bytes ``` We also had the process used in the `spec.html` file: 1. **Load `input.png`:** - Image dimensions: **800x600** pixels - Color channels: **4** (RGBA) 2. **Compress Pixel Data:** - Compression Method: **Zstandard (`zstd`)** - Compressed Data Size: **X** bytes 3. **Encrypt Compressed Data:** - AES-256-GCM with randomly generated key and IV - Encrypted Data Size: **Y** bytes 4. **Construct Header:** - Magic Number: `"SKB1"` - Width: **800** (`0x02000000` in little endian) - Height: **600** (`0x25800000` in little endian) - Channels: **4** - Compression Method: **1** (Zstandard) - AES Key: **32** random bytes - AES IV: **12** random bytes 5. **Write to `output.skibidi`:** - Header (58 bytes) - Encrypted Data (**Y** bytes) ___ Now to decode the `.skibidi file`, I need to reverse this process: 1. Read and parse the header to extract necessary information 2. Decrypt the data section using `AES-256-GCM` 3. Decompress the decrypted data using `Zstandard` 4. Convert the resulting raw pixel data into an image Now, based on this, I wrote a [Python script](https://github.com/xtasy94/CTFW/blob/main/CTF_Files/TCP1PCTF/decrypt.py) which would perform these for me: ```python from Crypto.Cipher import AES import zstandard from PIL import Image import io def read_skibidi_file(file_path): with open(file_path, "rb") as file: magic_number = file.read(4) if magic_number != b"SKB1": raise ValueError("Invalid Skibidi file format") width = int.from_bytes(file.read(4), "little") height = int.from_bytes(file.read(4), "little") channels = int.from_bytes(file.read(1), "little") compression_method = int.from_bytes(file.read(1), "little") aes_key = file.read(32) aes_iv = file.read(12) encrypted_data = file.read() print(f"Image dimensions: {width}x{height}") print(f"Channels: {channels}") print(f"Compression method: {compression_method}") cipher = AES.new(aes_key, AES.MODE_GCM, nonce=aes_iv) decrypted_data = cipher.decrypt(encrypted_data) decompression_methods = [ lambda d: zstandard.ZstdDecompressor().decompress(d), lambda d: zstandard.ZstdDecompressor().decompress( d, max_output_size=width * height * channels ), lambda d: d, ] for method in decompression_methods: try: decompressed_data = method(decrypted_data) break except Exception as e: print(f"Decompression attempt failed: {str(e)}") else: raise ValueError("All decompression attempts failed") print(f"Decompressed data size: {len(decompressed_data)} bytes") expected_size = width * height * channels print(f"Expected data size: {expected_size} bytes") if len(decompressed_data) != expected_size: print("Warning: Decompressed data size does not match expected size") mode = {1: "L", 3: "RGB", 4: "RGBA"}.get(channels) if not mode: raise ValueError(f"Unsupported number of channels: {channels}") try: image = Image.frombytes(mode, (width, height), decompressed_data) except Exception as e: print(f"Error creating image: {str(e)}") with open("raw_data.bin", "wb") as f: f.write(decompressed_data) print("Raw decompressed data saved to 'raw_data.bin'") raise return image def main(): input_file = "suisei.skibidi" output_file = "output.png" try: image = read_skibidi_file(input_file) image.save(output_file) print(f"Successfully decoded {input_file} and saved as {output_file}") except Exception as e: print(f"Error: {str(e)}") if __name__ == "__main__": main() ``` ```bash $ python decrypt.py Image dimensions: 3840x2160 Channels: 4 Compression method: 1 Decompression attempt failed: could not determine content size in frame header Decompressed data size: 33177600 bytes Expected data size: 33177600 bytes Successfully decoded suisei.skibidi and saved as output.png ``` The script successfully decoded the image and saved it as `decoded_image.png`. Opening this PNG file revealed the flag: ![output_11zon](https://hackmd.io/_uploads/rJkcqLYyJx.png) `TCPIP{S3ems_L1k3_Sk1b1dI_T0il3t_h4s_C0nsUm3d_My_fr13nD_U72Syd6}`