Archives par mot-clé : base64

Encoder et encapsuler un code pour l’injecter

Les petits soucis que j’ai rencontrés dernièrement (cf. mon précédent billet), ont amené un de mes amis à me questionner sur la manière qu’un hacker peut « chiffrer » un code malveillant avant de l’injecter dans un script quelconque.

Tout d’abord, encoder un code source est une chose très répandue, qui est réalisée bien au-delà de la dissimulation d’un simple hack. Une grande partie des sites Internet étant programmés avec des langages interprétés tels que JavaScript, PHP ou ASP, souvent les éditeurs de sites Web utilisent cette méthode pour rendre illisible le code (ou du moins une partie) avant de livrer le produit à leur client. Par « illisible », il faut entendre que l’analyse du code par ce client nécessitera un travail de rétro-ingénierie très important, et aura par conséquent un coût non négligeable : c’est donc une façon pour l’éditeur de « fidéliser » sa clientèle, qui devra bien faire appel à lui pour dépatouiller le bordule… On aime ou on n’aime pas. Moi pas.

Puisque l’encodage d’un code exécutable est monnaie courante sur le Web, et notamment par les vilains petits pirates, pour ma démonstration je vais transposer ce mécanisme en Shell : ça n’a rien à voir, ça ne sert pas à grand chose (quoiqu’il doit bien y avoir un ou deux sites hébergés sur des serveurs en Shell), mais j’aime bien quand-même.

Dans mon exemple, la commande se chargera de récupérer la page « La Grande Question sur la vie, l’univers et le reste » et de l’enregistrer dans un fichier HTML. La commande correspondant à cela, et qui sera donc encodée, est comme ceci :

wget -q -O $HOME/42.html http://fr.wikipedia.org/wiki/
La_grande_question_sur_la_vie,_l%27univers_et_le_reste

Pour l’encoder, on peut par exemple utiliser la commande base64, un classique sur GNU/Linux. Cette commande convertit n’importe quoi en un code ASCII facilitant son inclusion dans un quelconque fichier texte. C’est d’ailleurs par cette méthode que les pièces jointes sont stockées dans les e-mails, ou bien encore que les images bitmap sont encapsulées dans les fichiers SVG. Ici, il suffit de soumettre à base64 la commande qui nous intéresse, en tant que vulgaire chaîne de caractères via un printf. Notez au passage, que le pour-cent (en rouge ci-dessous) a été doublé au préalable. La raison est très simple : la commande printf risque d’interpréter le %27 comme une succession de 27 espaces à écrire à la place.

printf 'wget -q -O $HOME/42.html http://fr.wikipedia.org/wiki/
La_grande_question_sur_la_vie,_l%%27univers_et_le_reste'
| base64 | tr -d 'n'

Ce qui va retourner cette chaîne ASCII totalement imbuvable :

d2dldCAtcSAtTyAkSE9NRS80Mi5odG1sIGh0dHA6Ly9mci53aWtpcGVkaWE
ub3JnL3dpa2kvTGFfZ3JhbmRlX3F1ZXN0aW9uX3N1cl9sYV92aWUsX2wlMj
d1bml2ZXJzX2V0X2xlX3Jlc3Rl

Cette chaîne sera celle à encapsuler dans les scripts Shell hôtes. Mais il n’est toutefois pas possible de l’injecter telle quelle, il est nécessaire de donner au script les moyens de décoder ce texte, puis de l’interpréter comme étant une commande exécutable. Tout d’abord, pour la décoder, il suffit de procéder de manière identique à son encodage, c’est-à-dire en utilisant la commande base64, mais cette fois-ci en y précisant l’argument « -d » (comme l’anglais « decode », CQFD).

printf 'd2dldCAtcSAtTyAkSE9NRS80Mi5odG1sIGh0dHA6Ly9mci53aWtpcGV
kaWEub3JnL3dpa2kvTGFfZ3JhbmRlX3F1ZXN0aW9uX3N1cl9sYV92aWUsX2wlMj
d1bml2ZXJzX2V0X2xlX3Jlc3Rl' | base64 -d

La commande base64 -d nous a permis de recouvrer la chaîne de caractères initiale. Il faut donc maintenant l’interpréter en tant que commande pour pouvoir l’exécuter. C’est le rôle de la commande eval, dans laquelle il suffit d’encapsuler le printf et le base64 -d.

eval `printf 'd2dldCAtcSAtTyAkSE9NRS80Mi5odG1sIGh0dHA6Ly9mci53aWtpcGV
kaWEub3JnL3dpa2kvTGFfZ3JhbmRlX3F1ZXN0aW9uX3N1cl9sYV92aWUsX2wlMj
d1bml2ZXJzX2V0X2xlX3Jlc3Rl' | base64 -d`

Cette fois c’est terminé. Cette ligne de code est directement utilisable dans n’importe quel script Shell. A l’exécution de ce script, le fichier 42.html sera alors enregistré à la racine du répertoire utilisateur courant.

Cette méthode est identique quel que soit le langage de programmation employé. Evidemment, l’écriture du code à injecter dépendra du programme visé, puisque pour un site Web en PHP, il faudra nécessairement injecter du code PHP exécutant du PHP (pour écrire du HTML et du JavaScript dans le cadre d’un piratage), et non du Shell exécutant du Shell.

Réaliser facilement un cadre pour Fotowall

Les quelques cadres proposés par défaut dans Fotowall ne suffisent pas toujours à rassasier la créativité débordante des utilisateurs. Fort heureusement, ce logiciel repose exclusivement sur des standards, notamment le SVG pour la réalisation des cadres. Il est donc relativement simple de créer de nouveaux cadres, moyennant… deux petites contraintes 😉 :

  • Réaliser un dessin au format SVG nécessite l’utilisation d’un logiciel de dessin vectoriel, ce qui n’est pas très compliqué, mais peut déjà en rebuter plus d’un.
  • Suivre un certain nombre d’indications, toujours au niveau du SVG, pour un affichage sans problème dans Fotowall… et là, j’ai déjà perdu la moitié de mon lectorat (ce qui doit à peu près représenter un bras ou un pied)…

Avant de proposer une solution qui permettra de s’affranchir de ces deux contraintes, et ainsi faciliter l’intégration d’un « simple dessin » comme cadre dans Fotowall, nous allons voir comment fonctionnent ces fameux cadres.

Comme dit plus haut, les cadres reposent sur des dessins vectoriels au format SVG. Pour qu’ils puissent être utilisés dans Fotowall, ceux-ci sont découpés en 9 morceaux, identifiés par une étiquette au sein du fichier. L’illustration ci-dessous représente ces 9 morceaux composant le cadre, la zone représentée en rose correspondant au positionnement d’une photo du pèle-mêle.

Les différentes parties du cadre SVG
Les différentes parties du cadre SVG

Les étiquettes affichées sur chaque morceau, telles que « topleft » ou « bottom », correspondent aux différents ID sur lesquels repose Fotowall. Sans ces ID, Fotowall ne sera pas en mesure d’utiliser le cadre, et le contour de la photo du petit neveu ou de Médor, restera désespérément vide. A ces 9 morceaux s’ajoutent 4 autres éléments, ci-dessus représentés par des flèches. Bien qu’apparaissant lors de l’édition du dessin vectoriel, ces éléments sont invisibles une fois dans Fotowall. Ils restent pour autant nécessaires. Ceux-ci, identifiés par des ID « hint-[…]-margin », permettent de définir l’épaisseur du contour qui doit être visible. Ainsi, si nous prenons pour exemple la flèche de gauche, voici son impact sur l’image de gauche :

  • Si l’objet « hint-left-margin » est de longueur égale à l’image « left », alors cette image apparaît dans toute sa largeur.
  • Si l’objet « hint-left-margin » est de longueur supérieure à l’image « left », alors un espace apparaît entre cette image et le bord de la photo. Cet espace est automatiquement comblé par l’image de fond « center », qui dépasse donc à gauche de la photo.
  • Si l’objet « hint-left-margin » est de longueur inférieure à l’image « left », alors elle est partiellement recouverte par la photo.

Mathématiquement, la distance de la zone d’espace, ou de la zone recouverte, est la différence de longueur entre l’élément « hint-[…]-margin » et chacune des images concernées (les 3 de gauche, les 3 de droite, les 3 du haut, ou les 3 du bas) : si le cadre fait 5 pixels et la marge 10 pixels, il y aura un écart de 5 pixels entre le cadre et la photo.

Un petit détail qui a son importance, les images « top », « left », « bottom » et « right » seront automatiquement étirées en fonction de la taille de la photo. A partir de là, on se rend malheureusement compte qu’il est difficile de proposer un cadre avec des motifs supportant difficilement d’être déformés… L’exemple ci-dessous illustre assez bien ce problème. Qu’à cela ne tienne ! Il est déjà possible de faire pas mal de trucs pour s’amuser, et ces quelques limitations finiront par être levées avec le temps.

Les bords étant étirés, les motifs sont inévitablement déformés
Les bords étant étirés, les motifs sont inévitablement déformés

Nous avons vu qu’un cadre se composait de 9 + 4 éléments graphiques dans un fichier SVG. Pour éviter de saisir les ID de ces éléments à la main dans le fichier SVG (qui est une bête structure XML), dans Inkscape il est possible de les saisir après un clic droit sur chacun de ces éléments, comme illustré ci-dessous.

Edition d'un ID dans Inkscape
Edition d'un ID dans Inkscape

Avec les quelques informations que nous venons de voir, nous pouvons nous rendre compte que produire un cadre peut être fait sans trop de difficulté, mais que cela peut aussi devenir fastidieux dès lors qu’on voudra multiplier ces cadres, par exemple pour les décliner en plusieurs couleurs. Hé puis nous l’avons déjà dit, tout le monde n’est pas forcément à l’aise avec le dessin vectoriel ! Dans ce cas, pourquoi ne pas produire un cadre directement en bitmap (JPG, PNG) à l’aide d’un logiciel de retouche photo comme Gimp, pour le convertir aussitôt après en cadre SVG prêt pour Fotowall ?

Nous l’avons très rapidement abordé plus haut, un fichier SVG est un fichier texte au format XML. Ca tombe bien, les outils en ligne de commande foisonnent sur nunux, et Bash (ou tout autre *sh, ne soyons pas –trop– sectaire) est la star quand il s’agit de produire automatiquement des fichiers !

La tentation de faire un tel programme était trop forte. Voici un script qui va nous permettre de nous affranchir du découpage d’une image et de sa conversion en SVG : fotowall_frame_compiler.zip

Une fois décompressé, le fonctionnement de ce script, quoique nécessitant un de ces écrans sombres et étranges qu’on appelle « terminaux« , est d’une grande simplicité d’utilisation. Regardez plutôt :

./fotowall_frame_compiler.sh image.png

Le script peut se contenter d’un seul et unique paramètre, à savoir l’image à convertir. Dans ce cas, les 9 parties du cadre seront autant que possible de hauteur et de largeur égales. Pour un meilleur rendu, attention à préférer des dimensions multiples de 3 dès le départ. En sortie du programme, le fichier SVG est créé, en reprenant le nom de l’image d’origine et en remplaçant l’extension par « .svg » (ce qui donne dans notre exemple image.png > image.svg).

Mais on peut aussi très bien avoir un contour de cadre de largeur ou de hauteur (ou les deux) différente de celle de l’emplacement réservé pour les photos. Pour reprendre l’exemple de la première illustration, on voit très bien que la hauteur de « top » et de « bottom » n’est pas identique à la hauteur de « center ». Dans ce cas, il va donc être nécessaire de connaître la taille exacte que l’on souhaite donner à « center » une fois transformé en SVG. Dans Gimp, il est par exemple possible de mesurer cette zone avec l’outil de sélection rectangulaire. Une fois la hauteur et la largeur connues, il suffit ensuite d’ajouter ces deux nouveaux paramètres au script :

./fotowall_frame_compiler.sh image.png 150 130

Le premier nombre correspondant à la largeur en pixels, et le second nombre correspondant à la hauteur (en pixels aussi, vous l’aurez deviné). En considérant que la zone « center » est parfaitement centrée, le script est alors en mesure de calculer la largeur et la hauteur de chacune des 9 parties, ainsi que les positionner dans l’image SVG. Bref, il n’y a plus rien à faire, le cadre étant immédiatement utilisable par Fotowall ! Si le rendu n’est pas impeccable (un écart d’un ou deux pixels est toujours possible), il suffit de jouer directement sur les deux valeurs dans la ligne de commande, puis rafraîchir le cadre dans Fotowall. Pour illustrer tout ceci, voici un exemple plus concret :

Exemples de découpages d'une image
Exemples de découpages d'une image

Ce script, requiert toutefois un ou deux logiciels, qui sont disponibles parmi les dépôts de toute bonne distribution GNU/Linux :

Attention. Le script crée temporairement 9 images PNG dans le dossier. Ce sont les 9 éléments ensuite stockés dans le fichier SVG, qui ont été découpés par ImageMagick et numérotés ainsi (en reprenant l’exemple ci-dessus) : image_0.png, image_1.png, … image_8.png. Veillez donc à ne pas avoir une image portant le même nom, sans quoi elle sera écrasée. A la fin d’exécution, ces 9 images temporaires sont automatiquement supprimées.

Après avoir abordé le fonctionnement des cadres SVG pour Fotowall, un script nous permet désormais de nous affranchir d’un certain nombre d’étapes peu amusantes (étiquetage, découpage…), et ainsi nous concentrer sur la réalisation purement graphique de l’image. Attention toutefois à préférer le format d’image PNG, qui est le seul à bénéficier à la fois des dégradés de couleur et de la transparence.

En guise de conclusion, on peut résumer ainsi les différents points abordés au sujet des cadres dans Fotowall :

  • Ils sont au format SVG, et peuvent être dessinés à l’aide des nombreux logiciels de dessin vectoriel, dont Inkscape fait partie.
  • Un cadre est composé de 9 éléments : les 4 coins, les 4 bords et le centre. A ces 9 éléments s’ajoutent 4 autres éléments pour la distance entre les bords du cadre et les bords de la photo.
  • Chacun des 9 + 4 éléments possède un ID précis au sein de l’image vectorielle.
  • Les bords étant étirés, les motifs sont déformés, ce qui limite les possibilités de création pour le moment.
  • Il est possible de s’affranchir de toute la partie SVG et de réaliser des cadres à partir d’images bitmap (de préférence PNG) à l’aide du script fotowall_frame_compiler.zip (nécessite GNU/Linux et une version récente d’ImageMagick).

Creative Commons License
Publié sous licence Creative Commons.