13. 5. 2023

CTF - CyberGame2023 - AirGapped - VideoTape

CyberGame 2023, druhý ročník tejto súťaže s rébusmi z informačnej bezpečnosti organizovanej SK-CERT prebiehal 10 týždňov v termíne 1.marca - 10.mája 2023. Bol to môj prvý pokus, ak nerátam podobnú jednoduchšiu verziu kedysi organizovanú firmou ESET. Času veľmi nebolo, tak som robil len pre mňa jednoduchšie úlohy.

Zápisok z posledného riešeného hlavolamu..

Scenár Air Gapped

Naše dohľadové centrum (SOC) spĺňa tie najvyššie bezpečnostné štandardy. Dáta z monitorovaných systémov prúdia dnu dátovou diódou. Keďže prostredie je takto oddelené, bezpečnostné aktualizácie nie sú potrebné. Je predsa nemožné, aby došlo k akémukoľvek incidentu či úniku informácií. Že?

Dnes ráno sa však stalo niečo hrozné.

Reported Difficulty: 3


 úloha 2: VideoTape

Zdá sa, že zlé správy nekončia. Nejaké dáta predsa len unikli. To sme považovali za nemožné! Máme sabotéra? Keď sme preverili kamerový záznam, nikto za serverom nesedel. No veď posúďte sami… https://drive.google.com/file/d/.... Flag je v štandardnom formáte SK-CERT{xxx}.

Záznam bezpečnostnej kamery odhalil len blikanie LED klávesnice

Po prezretí 550MB 3,5min HD videa vo formáte MP4 som zistil, že únik dát prebiehal cez LED na klávesnici.

Na prvý pohľad ide o morzeovku, ako ju z videa dostať do textovej formy?

Najskôr orežem video pre jednoduchšie spracovanie, upravím na čiernobiele, aby farebnosť LED nespôsobovala problémy s detekciou svieti-nesvieti. V grafickom editore (gimp) zistím zo screenshotu približné súradnice - 1358, 775. Orežem teda video na obdĺžnik 20x10 pixelov okolo nich.

ffmpeg -i video.mp4 -vf crop=20:10:1352:770 video2.mp4
ffmpeg -i video2.mp4 -vf format=gray video3.mp4
Výstupné video3.mp4 má len 170KB.


Pre spracovanie videa po pixeloch radí google najčastejšie Python s knižnicou OpenCV (CV2). Nájdem príklad pre cyklus spracúvajúci video po snímkoch (frame), doň vložím kód pre zisťovanie farby pixelu (súradnice 5,5 v orezanom videu, knižnica numpy pre spracovanie polí čísel / matíc).

import cv2
import numpy as np
input_video = cv2.VideoCapture('video3.mp4')

# Metadata from the input video
frames_per_second = int(input_video.get(cv2.CAP_PROP_FPS))
frame_width = int(input_video.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(input_video.get(cv2.CAP_PROP_FRAME_HEIGHT))
no_of_frames = 0;

# A counter to keep track of the number of frames processed
count = 1

# Loop through all the frames in the video
while (count != no_of_frames):
  # Read the video to retrieve individual frames. 'frame' will reference the inidivdual frames read from the video.
  ret, frame = input_video.read()

  # Check the 'ret' (return value) to see if we have read all the frames in the video to exit the loop
  if not ret:
    print('Processed all frames')
    break

  # Convert the image (frame) to RGB format as by default Open CV uses BGR format.
  # This conversion is done as face_recognition and other libraries usually use RGB format.
  if np.any(frame[5, 5] < 40):
    print("   ")
  if np.any(frame[5, 5] > 40):
    print("---")

  count += 1

# Release to close all the resources that we have opened for reading and writing video
input_video.release()
cv2.destroyAllWindows()

Spustím ako "python3 pokus.py > snimky.txt"
Výstup po spracovaní videa je v textovej forme. Pre svietiacu led na aktuálnom snímku vypíše tri pomlčky na riadok, inak tri medzery na riadok.

Pozriem si výstupný súbor a spočítam, že čas medzi blikaniami je vždy konštantných 4-5 snímkov (riadkov s medzerami), zato čas blikania je v dvoch verziách, ako pri morzeovke. Kratší blik (bodka) je dĺžky väčšinou 6 snímkov, dlhší blik (čiarka) je okolo 11 snímkov.

Rozhodol som sa preto všetko pod 8 snímkov dekódovať ako bodku, nad 8 snímkov ako čiarku. Použijem svoj obľúbený jazyk - shell.
poc=0
IFS=" " for x in `cat snimky.txt`; do let poc=poc+1 if [[ "$x" == " " ]]; then if [[ $poc -gt 1 ]]; then if [[ $poc -lt 8 ]]; then echo -n "."; fi if [[ $poc -gt 8 ]]; then echo -n "-"; fi fi poc=0; fi done
.-.-..--.-..-.--..-.--.-.-....--.-...-.-.-.-..-..-.-.-...----.--..--..--..--.-...---.--...--..--..--.-.-.-.-----.--..-...---..-...--.....---.....---......--...-.--.---..--..---.-----.-..-......--.--...--..-.-.--....-.--.-.--.--.-..-.--.---..--..---..-......--.-..-.--.---..--..--..--.----.---..-..--.--.-.--....-.----...--.-..-.--.----.--.---..---..-

Výstup vyzerá zaujímavo. Problém je, že pre dekódovanie morzeovky je potrebné poznať medzery medzi písmenami, inak je ťažké uhádnuť kde písmeno končí, nie je to jednoznačné.

Tu prišlo na rad trochu premýšľania a pátrania či existujú brute-force dekodéry. Nakoniec mi to došlo. Dve hodnoty (bodka, čiarka) bez potreby oddeľovačov predsa používa binárny kód.

Stačí v shell dekodéri zameniť bodku za 0 a čiarku za 1.
Výstup vložiť do CyberChef stránky a nájsť správnu funkciu (from Binary). Hurá, vlajka.

CyberChef, užitočná stránka pre dekódovanie


Zaujímavosti:
  • https://arxiv.org/pdf/1907.05851.pdf  - článok pojednáva o vynášaní informácií z air-gapped počítačov pomocou LED na klávesniciach, kde dosahujú rýchlosti 15 - 130 bitov/sekundu, za použitia väčšieho počtu FPS kamery, troch LED a kódovania kde rozsvietená LED je 1 a nerozsvietená 0
  • CyberChef dekodér beží bez potreby servera v prehliadači pomocou javascriptu, bol vyvinutý a vypustený ako open source britskou vládnou spravodajskou a špionážnou službou GCHQ
  • OpenCV je multiplatformová open source knižnica funkcií pre spracovanie obrazu, prvý krát vydaná Intelom v roku 2000 pre prácu s grafikou, je tu teda 23 rokov
  • súpis riešení hráća z minulého ročníka možno nájsť aj na gite

Žiadne komentáre:

Zverejnenie komentára