Stéganographie APNG : données cachées dans les frames d'une image animée
Le format APNG (Animated PNG) étend PNG pour stocker des animations. Sa particularité : l’image affichée par une visionneuse PNG classique (non animée) peut être entièrement différente du contenu animé. Ce mécanisme permet d’embarquer des données dans les frames d’animation sans qu’elles soient visibles à l’ouverture ordinaire du fichier.
Structure d’un fichier APNG
Section intitulée « Structure d’un fichier APNG »Un fichier APNG est un PNG valide avec des chunks supplémentaires. Les visionneuses qui ne comprennent pas l’APNG ignorent ces chunks et affichent uniquement l’image principale stockée dans les chunks IDAT standard.
PNG Signature (8 octets)IHDR — dimensions du canvas, profondeur de couleuracTL — Animation Control : nombre de frames, nombre de bouclesfcTL — Frame Control : dimensions, position, timing, mode de fusion (par frame)IDAT — image par défaut (affichée par les visionneuses PNG classiques)fdAT — Frame Data : données de chaque frame animée (hors première si IDAT la couvre)...IEND — fin du fichierLe chunk acTL
Section intitulée « Le chunk acTL »Le chunk acTL signale qu’un PNG est en réalité un APNG. Il contient deux champs :
| Champ | Taille | Description |
|---|---|---|
num_frames |
4 octets | Nombre total de frames de l’animation |
num_plays |
4 octets | Nombre de boucles (0 = boucle infinie) |
Sa présence est le marqueur distinguant un APNG d’un PNG ordinaire.
Le chunk fcTL
Section intitulée « Le chunk fcTL »Chaque frame possède un chunk fcTL qui précède ses données. Il définit :
| Champ | Taille | Description |
|---|---|---|
sequence_number |
4 octets | Numéro de séquence (ordre des chunks fdAT et fcTL) |
width / height |
4 octets chacun | Dimensions de la frame |
x_offset / y_offset |
4 octets chacun | Position dans le canvas |
delay_num / delay_den |
2 octets chacun | Durée d’affichage (fraction) |
dispose_op |
1 octet | Comportement après affichage (effacer, conserver, restaurer) |
blend_op |
1 octet | Mode de fusion avec le canvas existant |
L’image par défaut et la dissociation des contenus
Section intitulée « L’image par défaut et la dissociation des contenus »La spec APNG autorise deux cas :
Cas 1 — le fcTL de la première frame précède les IDAT : l’image principale fait partie de l’animation. PNG et APNG affichent le même contenu.
Cas 2 — les IDAT précèdent le premier fcTL : l’image principale est indépendante de l’animation. Une visionneuse PNG classique affiche le contenu des IDAT. Une visionneuse APNG affiche l’animation stockée dans les fdAT, potentiellement complètement différente.
C’est ce second cas qui rend le format intéressant en stéganographie.
Détecter un APNG
Section intitulée « Détecter un APNG »Avec exiftool
Section intitulée « Avec exiftool »exiftool fichier.apngUn APNG produit des champs supplémentaires absents d’un PNG ordinaire :
File Type : APNGAnimation Iterations : 0Frame Count : 5L’absence de Frame Count dans la sortie d’un fichier .apng indique soit un PNG mal nommé, soit une visionneuse qui ne parse pas les chunks animés.
En inspectant les chunks bruts
Section intitulée « En inspectant les chunks bruts »Les chunks APNG ont des signatures reconnaissables en hexadécimal :
hexdump -C fichier.apng | grep -E "acTL|fcTL|fdAT"Signatures en hexadécimal :
61 63 54 4C → acTL (Animation Control)66 63 54 4C → fcTL (Frame Control)66 64 41 54 → fdAT (Frame Data)La présence de acTL confirme un fichier APNG. L’absence de fcTL avant les IDAT indique que l’image par défaut est distincte des frames animées.
Décomposer les frames avec apngdis
Section intitulée « Décomposer les frames avec apngdis »apngdis décompose un APNG en frames individuelles et produit un fichier texte avec les paramètres de chaque frame.
Installation
Section intitulée « Installation »sudo apt install apngdisExtraction des frames
Section intitulée « Extraction des frames »apngdis fichier.apngapngdis génère :
fichier_N.pngpour chaque frame (numérotées à partir de 1)fichier.txtcontenant le timing et les paramètres de chaque frame
Exemple de sortie du fichier texte généré :
num_frames=5num_plays=0frame1=fichier_1.png delay=100/1000 x=0 y=0 w=800 h=600 blend=None dispose=Noneframe2=fichier_2.png delay=100/1000 x=0 y=0 w=800 h=600 blend=None dispose=None...Analyser les frames extraites
Section intitulée « Analyser les frames extraites »Une fois les frames extraites, les inspecter comme n’importe quelle image PNG :
# Vérifier les métadonnées de chaque frameexiftool fichier_*.png
# Chercher des données textuelles dans les framesstrings fichier_*.png | grep -v "^.\{1\}$"
# Comparer les tailles des frames (une frame anormalement lourde mérite attention)ls -lh fichier_*.png
# Vérifier si une frame contient des données après son IENDexiftool fichier_2.png | grep "Warning"Chercher du texte encodé dans les noms de chunks personnalisés
Section intitulée « Chercher du texte encodé dans les noms de chunks personnalisés »Le format PNG autorise des chunks privés (dont le nom commence par une lettre minuscule). Un APNG peut embarquer des chunks non standard portant des données arbitraires :
python3 - <<'EOF'import struct
with open("fichier.apng", "rb") as f: data = f.read()
i = 8while i < len(data): length = struct.unpack(">I", data[i:i+4])[0] chunk_type = data[i+4:i+8].decode('ascii', errors='replace') chunk_data = data[i+8:i+8+length]
# Les chunks dont le nom commence en minuscule sont privés/non standard if chunk_type[0].islower(): print(f"Chunk privé : {chunk_type} ({length} octets)") print(f" Contenu : {chunk_data[:64]}")
i += 12 + lengthEOFWorkflow en pratique
Section intitulée « Workflow en pratique »Face à un fichier APNG suspect :
1. Vérifier le type de fichier exiftool fichier.apng → Frame Count présent ? Nombre de frames > ce que l'on attend ?
2. Inspecter les chunks bruts hexdump -C fichier.apng | grep -E "acTL|fcTL|fdAT" → Les IDAT précèdent-ils le premier fcTL ?
3. Décomposer les frames apngdis fichier.apng → Combien de frames ? Contenu différent de l'image affichée ?
4. Comparer l'image par défaut et la première frame → Une différence indique un contenu intentionnellement dissocié
5. Inspecter chaque frame individuellement exiftool fichier_*.png strings fichier_*.png → Données cachées dans les métadonnées ou en texte brut ?
6. Chercher les chunks non standard → Chunks dont le nom commence en minuscule → Données binaires inhabituelles
7. Analyser les paramètres de timing → Valeurs de delay anormales encodant potentiellement des donnéesÀ retenir
Section intitulée « À retenir »Un APNG affiché dans une visionneuse classique ne montre que l’image principale des chunks IDAT. Les frames animées stockées dans les fdAT restent invisibles sans un outil dédié. apngdis extrait l’ensemble des frames en une commande. Comparer l’image par défaut et les frames animées est la première vérification à effectuer sur tout APNG suspect.