Well hidden message - Insignificant blue

Flag: HACKDAY{s73@M_$7@tion_4CcE5S}

Challenge

Description


On a USB key marked with the seal of the Black Mist, a mysterious film was discovered. This film, that you are watching from the EIGHTH ROW of seats in the Cogswell Halls cinema, shows apparently innocuous scènes. But according to rumors, it is not just a simple video. Data would have been compressed and hidden there…


Format: You need to find bytes of a zip archive containing the flag HACKDAY{FLAG} SHA256: f950cd9690cefea88deb08af718c8933ded7641758ed145724d7812ee79102d0

https://challenges.s3.rbx.io.cloud.ovh.net/challenges/well-hidden-message.avi

Solution

On parle de Insignificant blue. Il faut le comprendre comme LSB sur le channel bleu. Il y a également l'indice EIGHT ROW. Il faut faire un LSB sur le bleu sur les 8 premières lignes.

Maintenant, on n'a pas une image, mais une vidéo. Il suffit donc d'appliquer cette méthode pour chaque frame de la vidéo.

On sait que l'on doit récupérer un ZIP, il faut donc détecter la fin de celui-ci pour éviter de récupérer trop de données. Pour ça, un petit schéma de la structure s'impose :

Un fichier ZIP termine par la signature PK\x05\x06 puis par un commentaire de taille variable. Pour connaître cette taille, il faut que 16 bytes après la signature de fin. On peut donc analyse les données que l'on récupère pour détecter la fin du ZIP.

from io import BytesIO
import cv2
import numpy as np
import zipfile

pk_end = b'PK\x05\x06'    # Signature de fin
data = b''                # Données extraite

cap = cv2.VideoCapture('well-hidden-message.avi')
while True:
  ret, frame = cap.read() # Lecture de l'image suivante
  if not ret:
    break

  # Pour les 8 premières lignes, on récupére le LSB du bleu de chaque pixel
  blue_channel = 0
  data_bits = [frame[i, :, blue_channel] & 1 for i in range(8)]
  # Réassemblage des bits en octets
  new_data = bytes(np.packbits(data_bits))
  data += new_data
  # Si la signature de fin est détecté, on tronque les bytes en trop et on s'arrête
  if pk_end in new_data:
    i = data.index(pk_end)
    pk_comment_len = int.from_bytes(data[i+20:i+22], 'little')
    data = data[:i+22+pk_comment_len]
    break

# Sauvegarde du zip pour les challs suivants
with open('well-hidden.zip', 'wb') as f:
  f.write(data)
  
# Affichage du flag
z = zipfile.ZipFile(BytesIO(data), 'r')
print(z.read('flag.txt').decode())

Dernière mise à jour

Cet article vous a-t-il été utile ?