465 words
2 minutes
ApoorvCTF 2026 - The Rite of the Blessings - AI Writeup

Category: AI Flag: apoorvctf{1_40_35}

Challenge Description#

Glen’s Enigmatic Module stands sealed behind a sacred gate, permitting passage only to the blessed ones who can perform the ritual of the gate upon the grid-formed relics that govern the chromatic layers within Glen’s image-recognition rite.

Analysis#

The challenge shipped with a zip and hinted at a “gate” ritual over “grid-formed relics” and “chromatic layers,” so the first move was to inspect exactly what files were provided.

unzip -l files.zip
Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  03-04-2026 13:35   files/
        0  03-04-2026 13:27   files/images/
    52960  03-04-2026 12:13   files/images/flower.jpg
  4396544  03-04-2026 13:27   files/images/flower_processed.npy
    18849  03-04-2026 13:27   files/images/flower_processed.jpg
     2358  03-05-2026 11:10   files/retrieve_kernel.py
      578  03-04-2026 13:15   files/process_scalars.py

That file list was a huge hint by itself: one script to recover kernels and another to print a flag from three scalar values. Extracting the archive confirmed the structure and made it clear this was a matrix operation puzzle, not model training or anything heavyweight.

unzip -o files.zip -d rite_blessings
Archive:  files.zip
   creating: rite_blessings/files/
   creating: rite_blessings/files/images/
  inflating: rite_blessings/files/images/flower.jpg
  inflating: rite_blessings/files/images/flower_processed.npy
  inflating: rite_blessings/files/images/flower_processed.jpg
  inflating: rite_blessings/files/retrieve_kernel.py
  inflating: rite_blessings/files/process_scalars.py

Running the recovery script produced a 3×3 kernel for each RGB channel. This directly matched the description’s “grid” + “chromatic layers,” and the “gate” wording strongly suggested determinant notation (|A|) for each matrix.

smile

python retrieve_kernel.py flower flower_processed
Kernel for the Red layer:

[[ 1 -1  0]
 [-1  5 -1]
 [ 2 -1  0]]

Kernel for the Green layer:

[[ 1  2  1]
 [-1  8 -1]
 [-3 -1  1]]

Kernel for the Blue layer:

[[-1 -4  1]
 [ 1  4  4]
 [-1  3  1]]

With those matrices in hand, the next question was what scalar to feed into process_scalars.py. Determinants fit both the clue and the data shape perfectly, so I computed the determinant of each recovered kernel and got (1, 40, 35).

import numpy as np

kr = np.array([[1, -1, 0], [-1, 5, -1], [2, -1, 0]], dtype=float)
kg = np.array([[1, 2, 1], [-1, 8, -1], [-3, -1, 1]], dtype=float)
kb = np.array([[-1, -4, 1], [1, 4, 4], [-1, 3, 1]], dtype=float)

print("det", round(np.linalg.det(kr)), round(np.linalg.det(kg)), round(np.linalg.det(kb)))
print("trace", np.trace(kr), np.trace(kg), np.trace(kb))
print("sum", kr.sum(), kg.sum(), kb.sum())
det 1 40 35
trace 6.0 10.0 4.0
sum 4.0 7.0 8.0

Feeding those three determinant scalars into the formatter script produced the flag immediately.

python process_scalars.py 1 40 35
apoorvctf{1_40_35}

Solution#

python retrieve_kernel.py flower flower_processed
Kernel for the Red layer:
[[ 1 -1  0]
 [-1  5 -1]
 [ 2 -1  0]]

Kernel for the Green layer:
[[ 1  2  1]
 [-1  8 -1]
 [-3 -1  1]]

Kernel for the Blue layer:
[[-1 -4  1]
 [ 1  4  4]
 [-1  3  1]]
import numpy as np

kr = np.array([[1, -1, 0], [-1, 5, -1], [2, -1, 0]], dtype=float)
kg = np.array([[1, 2, 1], [-1, 8, -1], [-3, -1, 1]], dtype=float)
kb = np.array([[-1, -4, 1], [1, 4, 4], [-1, 3, 1]], dtype=float)

print(round(np.linalg.det(kr)), round(np.linalg.det(kg)), round(np.linalg.det(kb)))
1 40 35
python process_scalars.py 1 40 35
apoorvctf{1_40_35}
ApoorvCTF 2026 - The Rite of the Blessings - AI Writeup
https://blog.rei.my.id/posts/92/apoorvctf-2026-the-rite-of-the-blessings-ai-writeup/
Author
Reidho Satria
Published at
2026-03-10
License
CC BY-NC-SA 4.0