Skip navigation.

devloop :: blog

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

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.

Deux critiques de mauvais filmsPNG Noise : convertir un fichier en une image

How to use Quote function:

  1. Select some text
  2. Click on the Quote link

Write a comment

Comment
(BBcode and HTML is turned off for anonymous user comments.)

If you can't read the words, press the small reload icon.


Smilies