Enviando información oculta cerrando y abriendo la unidad de CD-ROM

Todas las noches cuando enciendo mi viejo portátil, recorro el panorama actual de noticias incesantes y no dejo de sorprenderme. Créanme, después de tantos años es imposible agotar la curiosidad ante tanto ingenio. Prueba de ello es CDitter, un método para exfiltrar datos mediante el movimiento de la bandeja de un lector de CD-ROM ¡por fin vamos a volver a poder usarlo para algo! XD

El lector de CD-ROM es monitorizado por una Raspberry Pi y una cámara que estará pendiente de la salida/entrada de la bandeja del lector para interpretar estos movimientos mediante una simple codificación Manchester.

Escala de grises y procesado de imágenes


Transmitiendo el texto 'Hello'

 
Url del video: https://youtu.be/GHQv9y5g9II

emit.py – script para transmitir datos a través de una unidad de CD-ROM

Hace uso de un retraso de 4 segundos, tanto para el estado de la unidad de CD cerrada como abierta. Podría usarse menos tiempo pero se intenta evitar daños en la unidad.

#!/usr/bin/python
import os
import time

# Start with CD tray closed
os.system("eject -t")
time.sleep(15)
os.system("eject -T")
time.sleep(15)
os.system("eject -t")
time.sleep(15)

prev = 0

def emit(str):
    global prev

    for b in str:
        for i in range(0,8):
            bit = (ord(b) >> i) & 1 
            
            if bit == 0:
                manc = [0,1]
            else:
                manc = [1,0]

            for bv in manc:            
                print(bv)
                if bv == 1:
                    if not prev == 1:
                        os.system("eject -T")
                    time.sleep(4)
                else:
                    os.system("eject -t")
                    time.sleep(4)
                prev = bv

emit("AZhello")

cditter.py – captura y decodifica la salida de la unidad de CD-ROM

#!/usr/bin/python
import math
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import cv2
import numpy as np 
from itertools import tee

def window(iterable, size):
    iters = tee(iterable, size)
    for i in range(1, size):
        for each in iters[i:]:
            next(each, None)
    return zip(*iters)


def emit(str):
    global prev
    out = []
    for b in str:
        for i in range(0,8):
            bit = (ord(b) >> i) & 1

            if bit == 0:
                out.append(0)
                out.append(1)
            else:
                out.append(1)
                out.append(0)
    return out

preamble = emit("AZ")

def process(x):
    m = [sum(y) / len(y) for y in zip(*x)][1]

    for i in range(0,len(x)):
        v1=x[i:len(x)]
        new = []
        for v in v1:
            if v[1] > m:
                new.append(v[0])
                new.append(v[0])
            else:
                new.append(v[0])
        if new[0:len(preamble)] == preamble:
            mdec = mancdec(new)
            print("Data: ",tobytes(mdec[0:len(mdec) - (len(mdec) % 8)]))
            break
def binary(arr):
    m = 0
    s = 0
    for o in arr:
        s = s +(o * (2**m))
        m = m + 1
    return s

def mancdec(arr):
    out = []
    for i in range(0,len(arr),2):
        if arr[i:i+2] == [0,1]:
            out.append(0)
        elif arr[i:i+2] == [1,0]:
            out.append(1)
    return out

def tobytes(arr):
    out = ""
    for i in range(0,len(arr),8):
        bits = arr[i:i+8]
        out += chr(binary(bits))
    return out

camera = PiCamera()
camera.resolution = (320, 240)
camera.framerate = 30
rawCapture = PiRGBArray(camera, size=camera.resolution)
 
# allow the camera to warmup
time.sleep(0.1)
 
bits = []

# from http://www.pyimagesearch.com/2014/09/15/python-compare-two-images/
def mse(imageA, imageB):
    # the 'Mean Squared Error' between the two images is the
    # sum of the squared difference between the two images;
    # NOTE: the two images must have the same dimension
    err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
    err /= float(imageA.shape[0] * imageA.shape[1])
    
    # return the MSE, the lower the error, the more "similar"
    # the two images are
    return err


def extract(data):
    out = []
    x = [0,0]
    c = 0
    old = None

    for d in data:
        c += 1
        x[d] += 1
        if (not old == None and not d == old) or c == len(data):
            if c == len(data):
                out.append((d,x[d]))
            else:
                out.append((d^1,x[d^1]))
                x[d^1] = 0
        old = d

    nout = []
    for o in out:
        if o[1] > 3:
            nout.append(o)


    return nout
    
old = None
trained = False

imgl = []
trainv = []

for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
    image = frame.array
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)

    if not old == None and trained == False:
        #print(chr(27) + "[2J")
        print("Training...")
        count = 0
        simid = -1
        simv = float("inf")

        for img in imgl:
            s = mse(gray,img[0])
            if s < simv:
                simid = count
                simv = s

            count += 1
        print("Similarity: ",simv)
        if simv > 2600:
            imgl.append([gray,1])
            simid = len(imgl)-1
        else:
            imgl[simid][1]+=1
            imgl[simid][0] = gray

        trainv = []
        for i in range(0,len(imgl)):
            if imgl[i][1] > 20:
                trainv.append([imgl[i][0],imgl[i][1]])
            if len(trainv) == 2:
                break

        if len(trainv) == 2:
            print("Trained...")
            trained = True        
     
    elif trained:
        simid = -1
        simv = float("inf")
        count = 0
        for img in trainv:
            s = mse(gray,img[0])
            if s < simv:
                simid = count
                simv = s
            count += 1

        trainv[simid][0] = gray
        trainv[simid][1] += 1
        print(chr(27) + "[2J")
        print("Current bit: ",simid)

        bits.append(simid)
        d = extract(bits)
        if len(d) > 8:
            process(d)
    else:
        imgl.append([gray,1])

    old = image        
    rawCapture.truncate(0)

Raspberry Pi

Se necesitan las siguientes librerías para poder ejecutar el programa:

sudo apt-get update
sudo apt-get install python-opencv
sudo apt-get install python-pip
sudo pip install picamera
sudo pip install numpy

Repositorio: https://github.com/anfractuosity/cditter/

Comentarios