Casser les enveloppes propriétaires

Gazette Linux n°079 — Juin 2002

Sébastien Marbrier

Adaptation française  

Prénom Nom du relecteur

Relecture de la version française  

Article paru dans le n°079 de la Gazette Linux de juin 2002.

Cet article est publié selon les termes de la Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.


Table des matières

Extraire le texte
Localiser les images
Afficher les images
Extraire chaque fichier image
Conclusion

Tout possesseur d'une adresse électronique est susceptible de recevoir des pièces jointes dans une grande variété formats. Malheureusement, certains de ces formats ne peuvent être lus par les logiciels libres. Ceci est particulièrement vrai si nos potes virtuels font toujours un usage discutable et risqué des logiciels privateurs en combinaison avec leurs logiciels de courriels.

De nombreux partisans du logiciel libre adoptent comme ligne de conduite d'ignorer les courriels contenant des pièces-jointes liées aux logiciels privateurs, choisissant d'expliquer à l'expéditeur l'importance des standards ouverts. D'autres peuvent ne pas apprécier de s'exclure du plaisir procuré par les pièces-jointes envoyées entre correspondants. Si vous avez déjà rencontré cette situation, les techniques mises en lumière dans cet article peuvent apporter une solution partielle.

Un utilisateur de Linux ne peut pas faire grand-chose si tout le contenu attaché est encodé par un algorithme jalousement tenu secret. Toutefois, il est très fréquent que le fichier problématique ne soit qu'une mince enveloppe propriétaire entourant un fatras de structures de données reposant sur des standards d’encodages connus. Par exemple, certains documents MS Word™ envoyés sur internet incorporent en leur sein des images ordinaires au format JPG ou PNG. Si nous trouvions le moyen de retirer l'enveloppe, la lecture de ces documents insérés serait très simple. Les sections suivantes décrivent comment y parvenir au moyen de quelques programmes en Python associés à quelques outils de visualisation et de manipulation d'image disponibles dans la plupart des distributions Linux.

Extraire le texte

Avant de s'attaquer au problème des images incorporées, nous pouvons facilement visualiser n'importe quel texte en clair grâce à l'utilitaire strings : strings fichier.proprio | less

Ceci produira en sortie toute chaîne de caractères ayant une longueur minimale de quatre octets, composée de caractères ASCII lisibles. Naturellement, il y aura en sortie bien d'autres choses que des phrases intelligibles. La plupart n'auront aucune utilité, mais le texte lisible est facilement repéré. Les outils strings récupéreront également les informations d'entête lisibles à l'intérieur même des images éventuellement présentes dans un fichier. Les fichiers JPEG contiennent la chaîne « JFIF » dans l'entête. Ceci nous donne la possibilité de vérifier rapidement quels sont les types d'images contenues dans un fichier ainsi que leur nombre. strings fichier.proprio | grep JFIF strings -n 3 fichier.proprio | grep PNG strings fichier.proprio | grep GIF8 L'option -n 3 nous permet de détecter les chaînes en clair de 3 caractères. Toutes les occurrences de JFIF ne correspondent pas nécessairement à une image JPEG car le document peut avoir JFIF dans une zone de texte. — bien que ce soit rarement le cas dans les pièces jointes les plus souvent envoyées.

Localiser les images

Il nous faut trouver où se trouve exactement chaque image dans le fichier. Un peu de Python nous aidera à trouver les images insérées et retourner leurs positions sous forme de décalage binaire :

from string import find

#lit dans les données propriétaires
fh = open( "fichier.proprio" )
dat = fh.read()
fh.close()

#cherche la chaîne JFIF
x = -1
while 1:
    x = find(dat,"JFIF",x+1)
    if x<0: break
    #Le début réel du fichier commence 6 octets plus haut
    print x - 6

Ceci nous donnera la position en octets de chaque fichier JPEG bien que toutes les positions ne soient pas garanties pour un fichier valide. On peut facilement l'étendre pour manipuler les images GIF et PNG : Programme 1

#!/usr/bin/python
from string import find
from sys import argv

entetes = [("GIF8",0), ("PNG",1), ("JFIF",6)]
fichier = "fichier.proprio"
if len(argv)>1: fichier = argv[1]

fh = open(fichier )
dat = fh.read()
fh.close()

for kw,off in entetes:
    x = 0
    while 1:
        x = find(dat,kw,x+1)
        if x<0: break
        print kw,"le fichier commence à la position",x - off

Notez que le fichier image commence quelques octets avant les chaînes « PNG » ou « JFIF ».

Afficher les images

Maintenant que nous sommes capables de localiser approximativement la position de chaque image, comment les afficher ? L'utilitaire d'affichage ImageMagick display peut nous y aider. Supposons que notre fichier propriétaire contienne une image JPEG commençant à l'octet 1000. Grâce à tail, on retire tous les octets qui précèdent et on envoie le reste à display. tail -c +1001 fichier.proprio | display -

Notez que tail -c commence le comptage des octets à 1. Dans le cas où il y aurait plusieurs dizaines d'images, nous pouvons adapter notre précédent programme Python pour automatiser le traitement. Programme 2

#!/usr/bin/python
from string import find
from sys import argv
from os import system

entetes = [("GIF8",0), ("PNG",1), ("JFIF",6)]
fichier = "fichier.proprio"
if len(argv)>1: fichier = argv[1]

fh = open(fichier )
dat = fh.read()
fh.close()

for kw,off in entetes:
    x = 0
    while 1:
        x = find(dat,kw,x+1)
        if x<0: break
        system("tail -c +%d %s | display -" % (x - off + 1, filepath))

Extraire chaque fichier image

ImageMagick rejette toutes les données reçues qui se trouvent au-delà de la fin du segment d'image. Si nous voulons complètement séparer les données de l'image pour les stocker sous forme de fichiers individuels, nous devons également trouver la fin de chaque image. L'utilisation d'une version modifiée de notre algorithme de découpe de trame binaire est un moyen d'y parvenir. Programme 3

#!/usr/bin/python
from string import find
from sys import argv
from commands import getstatusoutput

entetes = [("GIF8",0,"giftopnm","gif"), ("PNG",1,"pngtopnm","png"),
           ("JFIF",6,"djpeg","jpg")]
fichier = "fichier.proprio"
if len(argv)>1: fichier = argv[1]

fh = open(fichier )
dat = fh.read()
fh.close()

inum = 0
for kw,off,conv,ext in entetes:
    x = -1
    while 1:
        x = find(dat,kw,x+1)
        if x<0: break
        deb = x - dec
        #candidat image localisé -- cherche la fin par découpe binaire
        s1 = len(dat) - x
        s0 = 1
        sz = s1
        while s0<s1:
        (stat,output) = getstatusoutput("tail -c +%d %s | head -c %d | %s >/dev/null" % (deb + 1, fichier, sz, conv))
        if stat:
                #echec -- candidat probablement trop petit
                if sz == s1:
                    #echec -- candidat trop petit
                    print "Echec... pas d'image"
                    break
                elif sz == s0:
                    #longueur trouvée -- écriture de l'image
                    nomimage = "image%03d.%s" % (inum, ext)
                    print "écriture",nomimage
                    fh = open( nomimage, "w")
                    fh.write(dat[deb :deb+s1])
                    fh.close()
                    inum = inum + 1
                    break
                s0 = sz
            else:
                #semble trop gros -- essaie de réduire
                s1 = sz
            sz = int((s0+s1)/2)

On peut utiliser les utilitaires de décodage d'image giftopnm, djpeg et pngtopnm pour localiser la fin du fichier. Tout comme display ces outils rejettent les données d'entrées excédentaires après la fin du fichier image et se terminent sans erreur. Si toutefois, ils reçoivent une image tronquée ils retourneront une erreur et se termineront en échec. Le script Python envoie des données images de tailles variables à l'outil de décodage et son état d'exécution est utilisé pour viser la bonne taille du fichier demandé.

Conclusion

Cet article a montré comment écrire des scripts pour extraire de fichiers propriétaires les objets de données encodés par des standards ouverts et indépendants du matériel. Ce devrait être assez facile d'étendre ces scripts pour manipuler d'autres formats d'image et même d'autres types de données tels que les fichiers audio. Notez qu'il existe de nombreux formats de fichier qui contrarient les techniques décrites ici à cause d'une couche de chiffrement simple et/ou d'obscurcissement.

Même en ayant accès à l'application propriétaire adéquate pour lire unes pièce jointe spécifique, les scripts présentés plus haut peuvent être utiles pour éviter toute sorte de virus macro ou d'exploitation de faille de sécurité propres à cette application.

Et terminons sur une note d'avertissement. La législation dans certains pays est suffisamment vague pour être interprétée de telle sorte que ces scripts peuvent être considérés comme des techniques illégales de contournement du droit d'auteur. Ceci peut être pertinent ou non selon votre pays de résidence. C'est toujours le cas avec les systèmes mêlant les logiciels libres et propriétaires, votre position peut varier.

Note de l'Éditeur :

La Python Imaging Library (PIL) apporte la possibilité de travailler les images depuis un programme plus grand. Vous pouvez ouvrir une image et obtenir son type et ses dimensions, la transformer, créer des vignettes, etc. –Iron.

Adrian J Chung Lorsqu'il n'enseigne pas l'informatique à l'Université des Indes Orientales, à Trinidad, Adrian écrit des scripts système pour piloter un réseau d'ordinateurs sous Linux et mène des expériences en interfaçant divers environnements de script avec différents systèmes de rendu maison et des librairies de visualisations de données.

Adaptation française de la Gazette Linux

L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux.

Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site : http://www.traduc.org/Gazette_Linux.

Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.