←
$ Forensics: Queen Roselia's Diamond
Flag: BITSCTF{qr_bu7_n07_7h47_qr}Constructed the flag from all the Visible parts from the Image

Source Data
Input file:
queen_roselias_diamond/challenge_stego.tif
Intermediate source images used by the SVD step:
queen_roselias_diamond/byte0.png…queen_roselias_diamond/byte7.png
These byte*.png planes represent byte-lanes extracted from the TIFF pixel payload (8 bytes per pixel for float64 storage).
Method Used
sved_comp7.png was created by performing SVD across the set of 8 byte-plane images.
Exact processing logic
- Load
byte0.png…byte7.pngas grayscale arrays. - Stack into matrix form:
- shape before flattening:
(8, H, W) - shape for SVD:
(8, H*W)
- shape before flattening:
- Mean-center each plane (subtract per-plane mean).
- Run SVD:
A = U * S * Vt
- Take component index
7(8th component), reshapeVt[7]back to(H, W). - Normalize to
[0,255]and save as:svd_comp7.png
- Also saved inverted companion image (
255 - component) as:svd_comp7_inv.png
Reproducible Program
import numpy as np
from PIL import Image
base = "/home/taklaman/Downloads/queen_roselias_diamond"
# 1) Load byte planes
imgs = []
for i in range(8):
p = f"{base}/byte{i}.png"
imgs.append(np.array(Image.open(p).convert("L"), dtype=np.float32))
# 2) Stack and flatten
X = np.stack(imgs, axis=0) # (8, H, W)
k, h, w = X.shape
A = X.reshape(k, -1) # (8, H*W)
# 3) Mean-center each plane
A = A - A.mean(axis=1, keepdims=True)
# 4) SVD
U, S, Vt = np.linalg.svd(A, full_matrices=False)
# 5) Component 7 -> image
comp7 = Vt[7].reshape(h, w)
# 6) Normalize to 8-bit
m = comp7 - comp7.min()
m = m / (m.max() + 1e-9)
out = (m * 255).astype(np.uint8)
# 7) Save
Image.fromarray(out).save(f"{base}/svd_comp7.png")
Image.fromarray(255 - out).save(f"{base}/svd_comp7_inv.png")
print("Saved:")
print(f"- {base}/svd_comp7.png")
print(f"- {base}/svd_comp7_inv.png")