Video-frame-injectieaanvallen
Adversariële frames invoegen in video om videobegripmodellen te exploiteren: temporele injectie, keyframe-manipulatie, subliminale frame-aanvallen en detectie-ontwijking.
Videobegripmodellen verwerken video door frames te bemonsteren, features te extraheren en te redeneren over temporele sequenties. Ze zien niet elk frame. Dit bemonsteringsgedrag creëert een nauwkeurig aanvalsoppervlak: als een aanvaller weet (of kan raden) hoe een model frames bemonstert, kan hij adversariële content invoegen op posities die waarschijnlijk worden geselecteerd, terwijl de video visueel normaal blijft voor menselijke kijkers die deze op volledige framerate zien.
Hoe videomodellen frames bemonsteren
Het begrijpen van de bemonsteringsstrategie van het doelmodel is de basis van elke frame-injectieaanval.
Veelvoorkomende bemonsteringsstrategieën
| Strategie | Methode | Geselecteerde frames (uit video van 300 frames) | Kwetsbaarheid |
|---|---|---|---|
| Uniforme bemonstering | Selecteer N frames met gelijke intervallen | Frames 0, 37, 75, 112, ... | Voorspelbare posities |
| Keyframe-extractie | Gebruik I-frames uit videocodec | Codec-afhankelijk | Aanvaller bestuurt codec |
| Scènewisseldetectie | Bemonster frames op scènegrenzen | Variabel | Valse scènewisselingen injecteren |
| Willekeurige bemonstering | Selecteer N willekeurige frames | Onvoorspelbaar | Vereist verzadiging van meer frames |
| Temporele stride | Elk Kde frame | Frames 0, K, 2K, ... | Voorspelbaar als K bekend is |
import cv2
import numpy as np
def analyze_sampling_strategy(
model_fn: callable,
test_video_path: str,
num_unique_frames: int = 300
):
"""Bepaal welke frames een model daadwerkelijk verwerkt met unieke markeringen."""
# Maak een testvideo waarin elk frame een unieke identifier heeft
cap = cv2.VideoCapture(test_video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
cap.release()
# Genereer video met framenummer-watermerken
marked_path = "marked_test.mp4"
writer = cv2.VideoWriter(marked_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height))
for i in range(num_unique_frames):
frame = np.zeros((height, width, 3), dtype=np.uint8)
cv2.putText(frame, f"FRAME_{i:04d}", (50, height // 2),
cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 3)
writer.write(frame)
writer.release()
# Vraag het model welke framenummers het ziet
response = model_fn(marked_path, "List all FRAME_XXXX identifiers you can see.")
return responseSingle-frame-injectie
De eenvoudigste aanval: voeg één adversarieel frame in op een positie die het model waarschijnlijk bemonstert.
Gericht op uniforme bemonstering
Als het model uniform N frames bemonstert uit een video van T totale frames, liggen de bemonsterde posities ongeveer op de indices [0, T/N, 2T/N, ..., T-1]. De aanvaller vervangt het frame op een van deze posities.
def inject_single_frame(
video_path: str,
adversarial_frame: np.ndarray,
target_position: int,
output_path: str
):
"""Vervang één enkel frame in de video door een adversarieel frame."""
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
writer = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*'mp4v'),
fps, (width, height))
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_idx == target_position:
# Pas adversarieel frame aan op videodimensies
adv_resized = cv2.resize(adversarial_frame, (width, height))
writer.write(adv_resized)
else:
writer.write(frame)
frame_idx += 1
cap.release()
writer.release()
return output_pathGemengde injectie
In plaats van een frame volledig te vervangen (wat een visuele glitch creëert als het wordt opgemerkt), meng je de adversariële content met het originele frame.
def inject_blended_frame(
video_path: str,
adversarial_content: np.ndarray,
target_position: int,
blend_alpha: float = 0.3,
output_path: str = "blended_output.mp4"
):
"""Meng adversariële content in een frame in plaats van het te vervangen."""
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
writer = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*'mp4v'),
fps, (width, height))
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_idx == target_position:
adv_resized = cv2.resize(adversarial_content, (width, height))
blended = cv2.addWeighted(frame, 1 - blend_alpha, adv_resized, blend_alpha, 0)
writer.write(blended.astype(np.uint8))
else:
writer.write(frame)
frame_idx += 1
cap.release()
writer.release()
return output_pathStrategieën voor multi-frame-injectie
Single-frame-injectie is kwetsbaar -- als de bemonstering van het model het geïnjecteerde frame mist, faalt de aanval. Multi-frame-strategieën verhogen de betrouwbaarheid.
Verzadigingsinjectie
Voeg op regelmatige intervallen door de hele video adversariële frames in, zodat ongeacht de bemonsteringsstrategie ten minste één adversarieel frame wordt vastgelegd.
def inject_saturated(
video_path: str,
adversarial_frame: np.ndarray,
injection_interval: int = 10,
output_path: str = "saturated_output.mp4"
):
"""Voeg adversariële frames in op regelmatige intervallen."""
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
writer = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*'mp4v'),
fps, (width, height))
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_idx % injection_interval == 0:
adv_resized = cv2.resize(adversarial_frame, (width, height))
writer.write(adv_resized)
else:
writer.write(frame)
frame_idx += 1
cap.release()
writer.release()
injected_count = frame_idx // injection_interval
return output_path, injected_countTemporele gradiëntinjectie
Introduceer adversariële content geleidelijk over meerdere frames, waardoor de overgang minder detecteerbaar wordt voor temporele anomaliedetectoren.
def inject_temporal_gradient(
video_path: str,
adversarial_frame: np.ndarray,
center_position: int,
ramp_frames: int = 5,
output_path: str = "gradient_output.mp4"
):
"""Meng adversariële content geleidelijk in over meerdere frames."""
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
writer = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*'mp4v'),
fps, (width, height))
adv_resized = cv2.resize(adversarial_frame, (width, height))
start = center_position - ramp_frames
end = center_position + ramp_frames
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
if start <= frame_idx <= end:
# Bereken mengfactor -- piekt op center_position
distance = abs(frame_idx - center_position)
alpha = 1.0 - (distance / (ramp_frames + 1))
blended = cv2.addWeighted(frame, 1 - alpha, adv_resized, alpha, 0)
writer.write(blended.astype(np.uint8))
else:
writer.write(frame)
frame_idx += 1
cap.release()
writer.release()
return output_pathTypen content voor adversariële frames
De content van het geïnjecteerde frame bepaalt het doel van de aanval.
Typografische frame-injectie
Voeg een frame in met tekstinstructies. Dit combineert video-frame-injectie met typografische aanvallen -- het videomodel leest de tekst in het adversariële frame en volgt de instructies op.
def create_text_frame(
width: int,
height: int,
instruction: str,
background_color: tuple = (255, 255, 255),
text_color: tuple = (0, 0, 0)
):
"""Maak een frame met adversariële tekstinstructies."""
frame = np.full((height, width, 3), background_color, dtype=np.uint8)
# Splits de instructie in regels die in het frame passen
words = instruction.split()
lines = []
current_line = ""
max_chars = width // 15 # Geschat aantal tekens per regel
for word in words:
if len(current_line) + len(word) + 1 <= max_chars:
current_line += " " + word if current_line else word
else:
lines.append(current_line)
current_line = word
if current_line:
lines.append(current_line)
y_start = height // 2 - (len(lines) * 30) // 2
for i, line in enumerate(lines):
cv2.putText(frame, line, (20, y_start + i * 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, text_color, 2)
return frameAdversarieel beeldframe
Voeg een frame in dat een adversarieel beeld is, gemaakt om misclassificatie of gedragsverandering in de vision-encoder te veroorzaken. Dit vereist white-box-toegang om perturbaties te berekenen.
Contextmanipulerend frame
Voeg een frame in dat een andere scène toont en het begrip van het model van de context van de video verandert. Bijvoorbeeld: het invoegen van een frame van een medische setting in een kookvideo kan ervoor zorgen dat het model de video als medische content beschrijft.
Aanvallen op codecniveau
Videocodecs (H.264, H.265, VP9) gebruiken keyframes (I-frames) en delta-frames (P-frames, B-frames). Modellen die keyframes extraheren als bemonsteringsstrategie zijn kwetsbaar voor manipulatie op codecniveau.
Keyframe-plaatsing forceren
import subprocess
def encode_with_forced_keyframes(
input_path: str,
keyframe_positions: list,
output_path: str
):
"""Hercodeer video met keyframes op specifieke posities."""
# Bouw keyframe-expressie voor ffmpeg
kf_expr = "+".join(f"eq(n,{pos})" for pos in keyframe_positions)
cmd = [
"ffmpeg", "-i", input_path,
"-force_key_frames", f"expr:{kf_expr}",
"-c:v", "libx264",
"-y", output_path
]
subprocess.run(cmd, capture_output=True, check=True)
return output_pathDoor keyframes te forceren op posities waar adversariële frames zijn ingevoegd, zorgt de aanvaller ervoor dat op keyframes gebaseerde bemonstering de adversariële content selecteert.
Detectie en verdediging
Temporele consistentieanalyse
Adversariële frames verschillen doorgaans aanzienlijk van hun buren. Het meten van de gelijkenis van frame tot frame kan injecties identificeren.
def detect_frame_anomalies(
video_path: str,
threshold: float = 0.3
):
"""Detecteer afwijkende frames door temporele consistentie te meten."""
cap = cv2.VideoCapture(video_path)
prev_frame = None
anomalies = []
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if prev_frame is not None:
# Structurele gelijkenis tussen opeenvolgende frames
diff = cv2.absdiff(prev_frame, gray)
mean_diff = np.mean(diff) / 255.0
if mean_diff > threshold:
anomalies.append({
"frame": frame_idx,
"difference_score": float(mean_diff),
"type": "high_temporal_discontinuity"
})
prev_frame = gray
frame_idx += 1
cap.release()
return anomaliesMulti-sample-verificatie
Verwerk de video met meerdere verschillende bemonsteringsstrategieën. Als de resultaten consistent zijn, is de video waarschijnlijk schoon. Als verschillende bemonsteringsstrategieën verschillende beschrijvingen produceren, kunnen er adversariële frames aanwezig zijn.
Frame-deduplicatie
Identificeer en verwijder voorafgaand aan de verwerking bijna-identieke of afwijkende frames. Dit verdedigt tegen verzadigingsinjectie door het aantal adversariële frames dat het model bereikt te beperken.
Methodologie voor red team-assessment
Identificeer de videoverwerkingspipeline
Bepaal welk model de video verwerkt, hoe het frames bemonstert en welke output het produceert (classificatie, beschrijving, actieherkenning, contentmoderatie).
Onderzoek het bemonsteringsgedrag
Dien testvideo's in met framenummer-markeringen om de bemonsteringsstrategie van het model te bepalen. Dit onthult welke frameposities het meest waardevol zijn voor injectie.
Test single-frame-injectie
Voeg één duidelijk adversarieel frame in (bijv. met grote tekstinstructies) op een voorspelde bemonsteringspositie. Verifieer of het model het verwerkt.
Test heimelijke varianten
Ga verder met gemengde injectie, temporele gradiënt en content met lage zichtbaarheid. Meet de minimale injectiesterkte die de modeloutput nog steeds beïnvloedt.
Evalueer aanvallen op codecniveau
Als het model keyframe-extractie gebruikt, test dan of geforceerde keyframe-plaatsing op adversariële frames het aanvalssucces verhoogt.
Test detectie-bypass
Als het systeem frame-anomaliedetectie heeft, gebruik dan temporele gradiëntinjectie of contextconsistente adversariële frames om detectie te ontwijken terwijl je toch de modeloutput beïnvloedt.
Samenvatting
Video-frame-injectie exploiteert de fundamentele mismatch tussen hoe mensen en modellen video waarnemen. Door adversariële frames in te voegen op posities die het model bemonstert, kunnen aanvallers de outputs van videobegrip sturen zonder artefacten te creëren die zichtbaar zijn voor menselijke kijkers. Effectieve verdediging vereist temporele consistentieanalyse, multi-sample-verificatie en het behandelen van elk bemonsterd frame als potentieel adversariële input. Naarmate videobegripmodellen meer voorkomen in contentmoderatie, surveillance en media-analyse, vertegenwoordigen frame-injectieaanvallen een steeds belangrijker aanvalsoppervlak.