Block Cipher Buccaneers - Crypto
Points: 421 | Flag: BCCTF{BLoCk_c1pH3r_Mod3} | Solved by: Smothy @ 0xN1umb

what we got
zip with 3 files:
left.bmp- unencrypted, showsBCCTF{BLmiddle.bin- openssl encrypted, the mystery meatright.bmp- unencrypted, shows3r_Mod3}
challenge says "our best cryptanalysts don't think it's possible to crack the password" which is basically them telling us nah don't even try bruteforcing lol
the solve
the challenge name literally screams ECB mode. classic ECB penguin attack fr
in ECB mode every 16-byte block gets encrypted independently - same plaintext block = same ciphertext block every time. so the image "structure" is preserved even tho the colors are scrambled
from PIL import Image
from collections import Counter
# strip the 16-byte openssl header (Salted__ + salt)
with open('images/middle.bin', 'rb') as f:
f.read(16)
ct = f.read()
# bmp header is 138 bytes, pixel data starts after that
pixel_ct = ct[138:]
# split into 16-byte blocks (4 pixels each in RGBA)
blocks = [pixel_ct[i:i+16] for i in range(0, len(pixel_ct)-15, 16)]
# most common block = white background
block_counts = Counter(bytes(b) for b in blocks)
white_block = block_counts.most_common(1)[0][0]
# map: white block -> white, everything else -> black
# boom, ecb penguin
img = Image.new('L', (1024, 1024), 255)
pixels = img.load()
for idx in range(min(len(blocks), 256 * 1024)):
file_row = idx // 256
img_row = 1023 - file_row # bmp is bottom-to-top
col = (idx % 256) * 4
color = 255 if bytes(blocks[idx]) == white_block else 0
for px in range(4):
if col + px < 1024:
pixels[col + px, img_row] = color
img.save('middle_revealed.png')and just like that the encrypted image reveals: oCk_c1pH
flag
left + middle + right = BCCTF{BL + oCk_c1pH + 3r_Mod3}
BCCTF{BLoCk_c1pH3r_Mod3}
ngl this is the textbook example of why you never use ECB mode. the penguin lives on
smothy out ✌️