# Security Camera — Solution
We are given an hour-long[video](https://drive.google.com/file/d/1-IJrGdyG2trFLLIrIKZfSTd7eo9IMwlV/view)of an office workstation in which seemingly nothing interesting happens.
Looking at the video more carefully, you will notice that the brightness levelof the laptop screen seems to be changing from time to time. Could it be that somesecret data is getting exfiltrated through the screen brightness?
Turns out that is exactly what happens, and this challenge is all about carefulimplementation. The high-level approach we will take is as follows:  * Write a program that lets the user select a pixel on the video.  * Keep track of the brightness of that pixel for each frame.  * Hope that changes in the brightness level leak data.
Just by looking at the brightness level of some pixel, you'll see that italternates around two values — these represent binary zeroes and ones. Tofigure out the throughput of leaked bits, we will try to approximate theshortest amount of time one of those values is achieved. It turns out thisvalue is roughly $30$ frames, and since the video is shot at $30$ FPS, thiswould indicate that one bit gets leaked every second.
Armed with this knowledge, we can easily devise the following strategy:  * We will keep track of the brightness level of a particular bit across all    frames.  * At each frame, we will attempt to classify the brightness level into a $0$    bit or a $1$ bit.  * The length of each consecutive interval of same-valued bits should roughly be    a multiple of the frame rate, and we should be able to deduce the actual number    of same-valued bits being leaked.
This simple strategy is good enough to determine the leaked bits. Some details thatmight help increase precision are:  * Ignore obvious outliers in brightness values.  * When unsure how to classify a bit (e.g. it is somewhere between values for zero and    one), classify it as the last bit you were confident about.  * Do the same thing for multiple bits, consider the majority value as correct    classification.
Here is one ugly and barely-readable such implementation:
```pythonimport cv2import numpy as npimport matplotlib.pyplot as plt
from Crypto.Util.number import long_to_bytes
zero_b = 0one_b = 0
zs = []os = []
def bit(b_level):    global zero_b, one_b, zs, os    if one_b == 0:        if b_level >= zero_b + 3:            one_b = b_level            return 1        else:            return 0
    if (b_level - zero_b) / (one_b - zero_b) <= 0.35:        zs.append(b_level)        zero_b = min(zero_b, b_level)        return 0
    if (b_level - zero_b) / (one_b - zero_b) >= 0.65:        os.append(b_level)        one_b = max(one_b, b_level)        return 1
    return None
cap = cv2.VideoCapture('video.mp4')
clicked = Falsedef get_pixel(event, x, y, flags, param):    global clicked, pixel_x, pixel_y    if event == cv2.EVENT_LBUTTONDOWN:        pixel_x, pixel_y = x, y        clicked = True
cv2.namedWindow('frame')cv2.setMouseCallback('frame', get_pixel)
while not clicked:    ret, frame = cap.read()    if not ret:        break    cv2.imshow('frame', frame)    if cv2.waitKey(1) == ord('q'):        break
frame_count = 0
start = Falsedata = ""b_data = b""
bs = []curr = 0cnt = 0
while cap.isOpened():    ret, frame = cap.read()    if not ret:        break
    frame_count += 1
    if len(data) >= 8:        b_data += long_to_bytes(int(data[:8], 2))        data = data[8:]        print(b_data)
    if zero_b != 0 and one_b != 0:        brightness = frame[pixel_y, pixel_x].mean()        b = bit(brightness)        if b == curr or b == None:            cnt += 1        else:            for _ in range(round(cnt / 31.5)):                data += str(curr)            cnt = 1        if b != None: curr = b        continue
    brightness = frame[pixel_y, pixel_x].mean()    bs.append(brightness)
    if frame_count % ((cap.get(cv2.CAP_PROP_FPS) + 1) // 1) == 0:        bs.sort()        brightness = bs[len(bs) // 2]        bs = []        if zero_b == 0: zero_b = brightness        b = bit(brightness)
        if not start and b == 1:            data = "0"            start = True        if start:            data += str(b)
while len(data) >= 8:    b_data += long_to_bytes(int(data[:8], 2))    data = data[8:]    print(b_data)
cap.release()cv2.destroyAllWindows()```
Tracking pixel $(1133, 499)$ leaks the following data:
```b'Exfiltrating contents of current directory...\n\nDumping ./workspace/flag1.txt...\n\nTBTL{5an1t7y_ch3ck_pa55ed!_D0_y0u_h4v3_wh47_1t_74k35_f0r_p4r7_2?}\n\nDumping ./workspace/flag2.zip...\n\nPK\x03\x04\n\x00\t\x00\x00\x00\xbcb\xa3V9gW\xa7*\x00\x00\x00\x1e\x00\x00\x00\x08\x00\x1c\x00flag.txt\xd5T\t\x00\x03\xc35Rd\xaf5Rdux\x0b\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00\xe0\xf7\x02\xf6\xbbX\xadI.2\x0b\xb2y;G\xa9\xf4+\xe2\xde\x87^\xb9\xbd\xabU\xfb\xa2i\xcf\x1d\xbccv\x88\x04\x14\xe7z\x8a!\x8dPK\x07\x089gW\xa7*\x00\x00\x00\x1e\x00\x00\x00PK\x01\x02\x1e\x03\n\x00\t\x00\x00\x00\xbcb\xa3V9gW\xa7*\x00\x00\x00\x1e\x00\x00\x00\x08\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\x81\x00\x00\x00\x00flag.txtUP\x05\x00\x03\xc35Rdux\x0b\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00N\x00\x00\x00|\x00\x00\x00\x00\x00'```
The first flag is immediately visible:`TBTL{5an1t7y_ch3ck_pa55ed!_D0_y0u_h4v3_wh47_1t_74k35_f0r_p4r7_2?}`, and letsteams score points with less precise algorithms.
The second flag seems to be a `.zip` archive, but we need a password to extractit. The password is written on a post-it note in the video — `TBTLPWD123`.
The extracted file `flag.txt` contains the second flag:`TBTL{1_don7_m1nd_7h3_41r_g4p}`.
**Fun fact:** The challenge author got excited about turning this into alegitimate method for data exfiltration from air-gapped machines, but it turnsout this [has already been done](https://arxiv.org/pdf/2002.01078.pdf).