Aller au contenu

Stéganographie Whitespace : programme caché dans les espaces d'un fichier texte

Le langage Whitespace, créé par Edwin Brady et Chris Morris en 2003, ignore tous les caractères imprimables. Seuls trois caractères ont une signification : l’espace (0x20), la tabulation (0x09) et le saut de ligne (0x0A). Tout le reste est traité comme un commentaire.

Cette propriété permet d’embarquer un programme exécutable dans n’importe quel fichier texte. La prose visible masque un programme entièrement codé dans les espaces et tabulations intercalés entre les caractères lisibles.

Caractère Notation Valeur binaire
Espace [S] 0
Tabulation [T] 1
Saut de ligne [L] séparateur / terminateur

Les instructions sont regroupées par préfixe (IMP — Instruction Modification Parameter) :

Préfixe Catégorie
[S] Manipulation de pile
[T][S] Arithmétique
[T][T] Accès au tas
[L] Contrôle de flux
[T][L] Entrées / Sorties

Exemple, empiler la valeur 65 (A en ASCII) et l’afficher :

[S][S] → push
[S] → signe positif
[T][S][S][S][S][S][T] → 1000001 = 65 en binaire
[L] → fin du nombre
[T][L][S][S] → output char
[L][L][L] → exit

Les nombres sont encodés en binaire avec un bit de signe en tête :

  • [S] = positif
  • [T] = négatif

Les bits suivants : [S] = 0, [T] = 1, terminés par [L].

Un fichier texte ordinaire contient des tabulations et des espaces en quantités prévisibles. Un fichier portant un programme Whitespace présente souvent :

  • Des suites de tabulations là où aucune indentation n’est attendue
  • Des espaces en fin de ligne en nombre inhabituel
  • Un ratio espaces/tabulations qui ne correspond pas au contenu visible
Fenêtre de terminal
# Afficher les caractères spéciaux (^ = tab, $ = fin de ligne)
cat -A fichier.txt
# Compter les tabulations
cat fichier.txt | tr -cd '\t' | wc -c
# Compter les espaces
cat fichier.txt | tr -cd ' ' | wc -c
# Afficher les octets bruts
hexdump -C fichier.txt | head -30

Pour isoler le programme de son enveloppe textuelle :

Fenêtre de terminal
# Ne garder que les espaces, tabulations et sauts de ligne
cat fichier.txt | tr -cd ' \t\n' > programme.ws

Le fichier programme.ws ne contient plus que les caractères significatifs pour l’interpréteur.

with open("fichier.txt", "r") as f:
contenu = f.read()
for i, char in enumerate(contenu):
if char == ' ':
print(f"pos {i:4d} : ESPACE")
elif char == '\t':
print(f"pos {i:4d} : TAB")
elif char == '\n':
print(f"pos {i:4d} : NEWLINE")

Plusieurs interpréteurs en ligne acceptent les fichiers .ws :

https://www.tutorialspoint.com/execute_whitespace_online.php

Coller le contenu extrait (ou uploader le fichier .ws) et lancer l’exécution.

Fenêtre de terminal
pip install whitespace-python
Fenêtre de terminal
whitespace fichier.ws

Ou utiliser un interpréteur Python minimal :

whitespace_interp.py
import sys
def run(source):
# Filtrer uniquement les caractères Whitespace
prog = [c for c in source if c in (' ', '\t', '\n')]
stack = []
heap = {}
output = []
i = 0
def read_num():
nonlocal i
sign = 1 if prog[i] == ' ' else -1
i += 1
bits = []
while prog[i] != '\n':
bits.append('0' if prog[i] == ' ' else '1')
i += 1
i += 1
return sign * int(''.join(bits), 2) if bits else 0
while i < len(prog):
c = prog[i]; i += 1
if c == ' ':
nc = prog[i]; i += 1
if nc == ' ':
stack.append(read_num())
elif nc == '\n':
nnc = prog[i]; i += 1
if nnc == ' ':
stack.append(stack[-1])
elif nnc == '\t':
stack[-1], stack[-2] = stack[-2], stack[-1]
elif nnc == '\n':
stack.pop()
elif c == '\t':
nc = prog[i]; i += 1
if nc == '\n':
nnc = prog[i]; i += 1
if nnc == ' ':
nnnnc = prog[i]; i += 1
if nnnnc == ' ':
output.append(chr(stack.pop()))
elif nnnnc == '\t':
output.append(str(stack.pop()))
elif c == '\n':
nc = prog[i]; i += 1
if nc == '\n':
nnc = prog[i]; i += 1
if nnc == '\n':
break
return ''.join(output)
with open(sys.argv[1], 'r') as f:
print(run(f.read()))
Fenêtre de terminal
python3 whitespace_interp.py fichier.txt
1. Inspecter le fichier
cat -A fichier.txt
→ tabulations ou espaces en fin de ligne inhabituels ?
2. Quantifier les caractères Whitespace
cat fichier.txt | tr -cd '\t' | wc -c
cat fichier.txt | tr -cd ' ' | wc -c
→ un nombre élevé par rapport à la longueur du texte visible évoque un programme embarqué
3. Extraire le programme
cat fichier.txt | tr -cd ' \t\n' > programme.ws
4. Exécuter
→ interpréteur en ligne ou whitespace-python
5. Analyser la sortie
→ texte en clair → flag ou message
→ texte chiffré → identifier le chiffrement

Un programme Whitespace est invisible dans un éditeur de texte standard et dans tout affichage terminal normal. cat -A révèle les tabulations et les fins de ligne inhabituelles. Extraire les seuls caractères [S], [T] et [L] suffit à isoler le programme, que n’importe quel interpréteur Whitespace peut ensuite exécuter.