Aller au contenu

Cryptoart : exécuter un programme Piet dissimulé dans un fichier PPM

Certains défis de stéganographie présentent un fichier image valide, affichable normalement, mais conçu pour être exécuté comme un programme. Le format PPM et le langage Piet permettent cette superposition : l’image est un programme, et l’exécuter produit une sortie cachée.

PPM (Portable Pixmap) est l’un des formats de la famille Netpbm. Il stocke des images couleur RGB sans compression, en texte (P3) ou en binaire (P6).

Fenêtre de terminal
file fichier.ppm
# fichier.ppm: Netpbm image data, size = 70 x 50, rawbits, pixmap

rawbits indique le format binaire P6. L’en-tête :

P6
<largeur> <hauteur>
<valeur_max>
[données RGB binaires : 3 octets par pixel, ordre R G B]

La taille du corps en octets est largeur × hauteur × 3. Pour 70 × 50 : 10 500 octets de données RGB suivent l’en-tête.

Fenêtre de terminal
# Lire les premières lignes de l'en-tête
head -3 fichier.ppm
# Vérifier la cohérence taille / dimensions
python3 -c "print(70 * 50 * 3)"
# 10500
ls -lh fichier.ppm
# taille totale = taille de l'en-tête + 10500 octets

Piet : un langage de programmation par les couleurs

Section intitulée « Piet : un langage de programmation par les couleurs »

Piet est un langage ésotérique créé par David Morgan-Mar, dont les programmes sont des images bitmap. Les couleurs encodent les instructions, le flux d’exécution se lit comme un tracé à travers les blocs colorés.

Piet utilise 20 couleurs : 6 teintes × 3 niveaux de luminosité, plus le noir et le blanc.

Teinte Clair Normal Foncé
Rouge #FFC0C0 #FF0000 #C00000
Jaune #FFFFC0 #FFFF00 #C0C000
Vert #C0FFC0 #00FF00 #00C000
Cyan #C0FFFF #00FFFF #00C0C0
Bleu #C0C0FF #0000FF #0000C0
Magenta #FFC0FF #FF00FF #C000C0
Noir #000000
Blanc #FFFFFF

L’interpréteur maintient un pointeur qui se déplace de bloc coloré en bloc coloré. Un bloc est un ensemble de pixels contigus de la même couleur. À chaque transition entre deux blocs, l’instruction exécutée dépend de deux paramètres :

  • La variation de teinte entre les deux blocs (0 à 5 pas dans le cycle rouge → jaune → vert → cyan → bleu → magenta)
  • La variation de luminosité (0 à 2 pas dans le cycle clair → normal → foncé)

Ces 18 combinaisons produisent 18 opérations : push, pop, add, subtract, multiply, divide, mod, not, greater, pointer, switch, duplicate, roll, entrées/sorties char et int.

Le noir constitue des murs infranchissables. Le blanc laisse le pointeur traverser sans déclencher d’opération.

Un fichier PPM contenant un programme Piet présente des caractéristiques visuelles reconnaissables :

  • Des aplats de couleurs vives appartenant à la palette Piet (rouge, jaune, vert, cyan, bleu, magenta dans leurs trois luminosités)
  • Une composition géométrique en blocs, sans dégradés ni couleurs intermédiaires
  • Une taille souvent petite (quelques dizaines à quelques centaines de pixels)
Fenêtre de terminal
# Vérifier les couleurs présentes dans le fichier
python3 - <<'EOF'
with open("ch8.ppm", "rb") as f:
header = []
while len(header) < 3:
line = f.readline().decode('ascii').strip()
if not line.startswith('#'):
header.append(line)
w, h = map(int, header[1].split())
data = f.read()
colors = set()
for i in range(0, len(data), 3):
r, g, b = data[i], data[i+1], data[i+2]
colors.add((r, g, b))
print(f"Dimensions : {w}x{h}")
print(f"Nombre de couleurs distinctes : {len(colors)}")
for c in sorted(colors):
print(f" RGB{c} → #{c[0]:02X}{c[1]:02X}{c[2]:02X}")
EOF

Un programme Piet typique contient peu de couleurs distinctes, toutes appartenant à la palette définie.

Fenêtre de terminal
sudo apt install npiet
# Exécuter le programme
npiet fichier.ppm
# Afficher la trace d'exécution pas à pas
npiet -t fichier.ppm
# Limiter le nombre d'étapes (évite les boucles infinies)
npiet -e 100000 fichier.ppm

L’exécuteur en ligne npiet accepte les fichiers PPM directement :

https://www.bertnase.de/npiet/npiet-execute.php

Uploader fichier.ppm et lancer l’exécution. La sortie standard s’affiche dans la page.

La sortie produite par le programme peut prendre plusieurs formes :

  • Texte lisible : le flag ou le message est directement accessible
  • Texte chiffré : la sortie nécessite un déchiffrement supplémentaire
  • Valeurs numériques : convertir en ASCII ou traiter selon le contexte
Fenêtre de terminal
# Capturer la sortie dans un fichier
npiet fichier.ppm > output.txt
# Vérifier si la sortie est de l'ASCII imprimable
file output.txt
strings output.txt
1. Identifier le fichier
file fichier.ppm
→ format PPM confirmé, dimensions notées
2. Inspecter l'en-tête
head -3 fichier.ppm
→ vérifier la cohérence entre taille du fichier et dimensions déclarées
3. Analyser les couleurs présentes
→ palette Piet reconnue → tenter l'exécution
4. Exécuter le programme Piet
npiet fichier.ppm
→ ou via https://www.bertnase.de/npiet/npiet-execute.php
5. Analyser la sortie
→ texte lisible → flag trouvé
→ texte chiffré → identifier le chiffrement et décoder

Un fichier PPM est une image valide et un programme Piet exécutable simultanément. L’aspect « art abstrait » d’une image aux aplats de couleurs vives appartenant à la palette Piet est le premier indicateur. npiet exécute le programme en une commande et produit la sortie sur stdout. Si cette sortie est chiffrée, le contexte du défi indique généralement le chiffrement à appliquer.