WD My Cloud et ses secrets II

 druide

Des secrets, mais pas trop

Dans l'article précédent, on a pu voir que le NAS se rendait visible sur Internet sans nous demander notre avis. Et que fait-il d'autre ce NAS. Et bien il met en place une sorte de DNS Dynamique (DynDNS) en s'appuyant sur le serveur de WD présent à l'adresse 129.253.8.107. Pour réussir ce travail, il doit informer le serveur de sa présence sur Internet. C'est-à-dire, qu'il doit dire à WD qui il est et où (adresse ip s'entend) il est. Pour réussir à voir cet échange d'information, il faut faire un déchiffrage SSL. En effet, tous les échanges fait entre le NAS et le site de WD sont chiffrés. Le problème c'est que le NAS n'utilise pas un navigateur web comme Firefox pour faire son travail. Il va donc falloir creuser un peu plus...


Dans cet article, on va voir :

  1. Quel programme envoie les informations
  2. Comment il les envoie
  3. La mise en place d'outils de cross compilation
  4. Le tuning du programme chargé d'envoyer les informations pour en permettre le déchiffrage
Ça fait déjà beaucoup pour un article. Le déchiffrage « imself » sera abordé dans un prochain article !

Quel programme envoi les informations

Par une méthode un peu archaïque :), je détermine que le programme qui envoi les informations de mon NAS chez www.wd2go.com est le programme communicationma

root@nas:~# netstat -paon | grep 198.107.148.110 
PID/prg  -> communicationma


Et


root@nas:~# ps faux | grep communicationma
root     24786  0.0  2.0  21184  4800 ?        SNs  11:00   0:02 /usr/local/orion/communicationmanager/communicationmanager -f 120 -l 5


Les paramètres -f et -l correspondent à


-f nnn (seconds) or -check_frequency nnn (seconds)
-l or -enable_log nnn (log severity level)

Plus précisément

Quel partie du programme envoi ces informations et comment.

  1. Il faut déjà avoir téléchargé le firmware depuis le site de WD
  2. En extraire le fichier rootfs.img
  3. Et monter le système de fichier rootfs.img dans /mnt
Ensuite, un petit coup de strings nous le dira (déjà en partie).

ubuntu@bidouille:/mnt$ strings usr/local/orion/communicationmanager/communicationmanager

blablabla

OrionClient::getRestUrl - baseSSLServerUrl %s.
OrionClient::getRestUrl - Invalid http type %d. Use only the input urn.
OrionClient::getRestUrl - restURL %s.
OrionClient:httpGet - empty url
OrionClient::httpGet  Error: [%s]
** OrionClient::httpGet - Throw exception error. **
OrionClient::initialize() - failed to read DEVICEID, DEVICEAUTH from dynamic config file
OrionClient::initialize() - CURL initialization failed.
disabled
OrionClient::getInstance() - initialize() returned false, set Comm Status to [disabled]
OrionClient::pollServerForSleepTime - central server already polled. Sleep time is %d secs.

blablabla

Bon, on est pas mal là. Reste à savoir comment le programme fait une requête GET. Reste plus qu'à dé-assembler le binaire...




Comme on peut le voir ci-dessus, c'est cURL qui est utilisé dans la requête GET et plus précisément, curl avec un chiffrement SSLv3.


On peut traduire le code assembleur ci-dessus par le code C suivant (environ)


#include <stdio.h>
#include <curl/curl.h>

function(void *, size_t, size_t, void *)
{
	return 0;
}

int main(int argc, char **argv)
{
        /****************************
         *Le reste du programme
         ****************************/

	CURL *curl;
	int var = 0;
	char url[] = "www.wd2go.com";

	curl_global_init(CURL_GLOBAL_ALL);
	curl = curl_easy_init();
	
	curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 30000);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &var);
	curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
	curl_easy_setopt(curl, CURLOPT_URL, url);
	curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
	curl_easy_perform(curl);
	curl_easy_cleanup(curl);

        /****************************
         * Le reste du programme
         ****************************/
	
	return 0;
}


Pour connaître les valeurs échangées entre mon NAS et le site web, il faudra donc faire un peu de « tuning » du programme cURL :)

Cross-compilation

Pour compiler un programme pour le NAS, il serait simple d'installer toutes les librairies nécessaires avec le traditionnel apt-get install. Malheureusement c'est pas possible! Le NAS est un mélange d'une version debian wheezy et d'une debian jessie. De plus, la compilation des paquets a été réalisée avec un compilateur gcc-linearo patché par WD pour être aligné sur des pages mémoires de 64k.


Il va donc falloir suivre la méthode WD

WD-README

Prerequisites:
- x86 PC with 64-bit Ubuntu or Debian installed
- packages qemu-user-static and binfmt-support installed on host build system
- Modified binutils package with 64K page size support. A pre-built version is included in binutils directory. There is no need to re-build binutils, however, instructions are provided in the source package (see binutils/README-binutils-64K-pagesize.txt).

Mise en place des outils

Il faut commencer par créer une machine virtuelle Ubuntu x86 Desktop 10.04 et la démarrer. Ensuite, depuis la machine virtuelle, télécharger cette archive et extraire son contenu. Dans le contenu extrait, il faut se rendre dans packages/build_tools/compilers/ et à nouveau extraire le contenu de gcc-linaro-arm-linux-gnueabihf-4.7-64k-2013.01-20130116_linux.tar.bz2.


Voilà, on est prêt pour le build du compilateur. On va utiliser le script fournit par WD après avoir fait une mise-à-jour du système.

Prévoyez du temps, beaucoup de temps!

ubuntu@virtuelle:~$ sudo apt-get update
ubuntu@virtuelle:~$ sudo apt-get dist-upgrade

# reboot nécessaire car nouveau noyau

ubuntu@virtuelle:~$ cd Téléchargement/packages/build_tools/compilers/src/
ubuntu@virtuelle:~/Téléchargement/packages/build_tools/compilers/src/$ sudo ./build.sh

#blablabla

[EXTRA]    Extracting 'gcc-linaro-4.7-2013.01'
[EXTRA]    Patching 'gcc-linaro-4.7-2013.01'
[EXTRA]    Extracting 'precise-sysroot-armhf-1+bzr2433'
[EXTRA]    Patching 'prebuilt-precise-sysroot-armhf-1+bzr2433'
[EXTRA]    Extracting 'gdb-linaro-7.5-2012.12'
[EXTRA]    Patching 'gdb-linaro-7.5-2012.12'

# Ça semble bien se préparer :)

[INFO ]  Installing final compiler
[EXTRA]    Configuring final compiler
[EXTRA]    Building final compiler
[EXTRA]    Installing final compiler
[EXTRA]    Building the GCC manuals
[EXTRA]    Installing the GCC manuals

# Et quelques bières plus tard... On y croit ...

bzip2 -fk9 builds/arm-linux-gnueabihf-linux/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux.tar
xz -fk9 builds/arm-linux-gnueabihf-linux/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux.tar

#voyons ça

ubuntu@virtuelle:~/Téléchargements/packages/build_tools/compilers/src$ ls bin
gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux.tar.bz2
ubuntu@virtuelle:~/Téléchargements/packages/build_tools/compilers/src$ cd bin
ubuntu@virtuelle:~/Téléchargements/packages/build_tools/compilers/src/bin$ tar xvf gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux.tar.bz2
ubuntu@virtuelle:~/Téléchargements/packages/build_tools/compilers/src/bin$ ls gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux/bin/
arm-linux-gnueabihf-addr2line     arm-linux-gnueabihf-g++         arm-linux-gnueabihf-gfortran  arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-ar            arm-linux-gnueabihf-gcc         arm-linux-gnueabihf-gprof     arm-linux-gnueabihf-pkg-config
arm-linux-gnueabihf-as            arm-linux-gnueabihf-gcc-4.7.3   arm-linux-gnueabihf-ld        arm-linux-gnueabihf-pkg-config-real
arm-linux-gnueabihf-c++           arm-linux-gnueabihf-gcc-ar      arm-linux-gnueabihf-ld.bfd    arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-c++filt       arm-linux-gnueabihf-gcc-nm      arm-linux-gnueabihf-ldd       arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-cpp           arm-linux-gnueabihf-gcc-ranlib  arm-linux-gnueabihf-ld.gold   arm-linux-gnueabihf-size
arm-linux-gnueabihf-ct-ng.config  arm-linux-gnueabihf-gcov        arm-linux-gnueabihf-nm        arm-linux-gnueabihf-strings
arm-linux-gnueabihf-elfedit       arm-linux-gnueabihf-gdb         arm-linux-gnueabihf-objcopy   arm-linux-gnueabihf-strip


Yes! On a le compilateur :)

Quelques variables d'environnement pour la compilation

Il faut commencer par mettre à jour la variable PATH pour que le système trouve le compilateur fraîchement crée. ATTENTION à adapter ce chemin à votre installation!

ubuntu@virtuelle:~$ export PATH=$HOME/Bureau/WDMyCloud/toolchain/bin:$PATH


On crée ensuite une variable indiquant où on souhaite placer les fichiers crées (résultats des différentes compilations).


ubuntu@virtuelle:~$ export PREFIX=$HOME/Bureau/WDMyCloud/usr/local


Pour terminer, on crée deux variables utilisées comme paramètre pour les compilations. La première précise la cible (ARM) et la seconde combinée à la première, donne le nom du compilateur.


ubuntu@virtuelle:~$ export HOST=arm-linux-gnueabihf
ubuntu@virtuelle:~$ export CC=${HOST}-gcc


En résumé:


ubuntu@virtuelle:~$ echo $PATH
/home/ubuntu/Bureau/WDMyCloud/toolchain/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
ubuntu@virtuelle:~$ echo $PREFIX
/home/ubuntu/Bureau/WDMyCloud/usr/local
ubuntu@virtuelle:~$ echo $HOST
arm-linux-gnueabihf
ubuntu@virtuelle:~$ echo $CC
arm-linux-gnueabihf-gcc
Création du répertoire correspondant à $PREFIX et copie de l'archive crée à la compilation (packages/build_tools/compilers/src/bin/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux.tar.bz2).

ubuntu@virtuelle:~$ mkdir -p $HOME/Bureau/WDMyCloud/src
ubuntu@virtuelle:~$ cd $HOME/Bureau/WDMyCloud
ubuntu@virtuelle:~/Bureau/WDMyCloud$ mkdir toolchain
ubuntu@virtuelle:~/Bureau/WDMyCloud$ cp ~/Téléchargements/packages/build_tools/compilers/src/bin/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux.tar.bz2/ ./src


On peut maintenant aller chercher les sources nécessaires à la compilation de cURL et de ses libraires (en tout cas une partie, zlib et openssl).


ubuntu@virtuelle:~$ cd Bureau/WDMyCloud/src
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ sudo -s
root@virtuelle:~/Bureau/WDMyCloud/src# mv /etc/apt/sources.list /etc/apt/sources.list.orig
root@virtuelle:~/Bureau/WDMyCloud/src# echo ''deb http://ch.archive.ubuntu.com/ubuntu/ trusty main restricted universe 
> deb-src http://ch.archive.ubuntu.com/ubuntu/ trusty main restricted universe'' > /etc/apt/sources.list
root@virtuelle:~/Bureau/WDMyCloud/src# cat /etc/apt/sources.list
deb http://ch.archive.ubuntu.com/ubuntu/ trusty main restricted universe 
deb-src http://ch.archive.ubuntu.com/ubuntu/ trusty main restricted universe
root@virtuelle:~/Bureau/WDMyCloud/src# exit
exit
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ sudo apt-get update
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ apt-get -d source zlib openssl ssh curl
Lecture des listes de paquets... Fait
Construction de l''arbre des dépendances       
Lecture des informations d''état... Fait
Choix de « openssh » comme paquet source à la place de « ssh »
Note : la maintenance du paquet de « openssh » est réalisée dans le système de suivi de versions « Git » à l''adresse :
git://anonscm.debian.org/pkg-ssh/openssh.git
Note : la maintenance du paquet de « curl » est réalisée dans le système de suivi de versions « Git » à l''adresse :
git://anonscm.debian.org/collab-maint/curl.git
Nécessité de prendre 10.0Mo dans les sources.
Réception de : 1 http://ch.archive.ubuntu.com/ubuntu/ trusty/main zlib 1:1.2.8.dfsg-1ubuntu1 (dsc) [2''543B]
Réception de : 2 http://ch.archive.ubuntu.com/ubuntu/ trusty/main zlib 1:1.2.8.dfsg-1ubuntu1 (tar) [362kB]
Réception de : 3 http://ch.archive.ubuntu.com/ubuntu/ trusty/main zlib 1:1.2.8.dfsg-1ubuntu1 (diff) [17.4kB]
Réception de : 4 http://ch.archive.ubuntu.com/ubuntu/ trusty/main openssl 1.0.1f-1ubuntu2 (dsc) [2''358B]
Réception de : 5 http://ch.archive.ubuntu.com/ubuntu/ trusty/main openssl 1.0.1f-1ubuntu2 (tar) [4''509kB]
Réception de : 6 http://ch.archive.ubuntu.com/ubuntu/ trusty/main openssl 1.0.1f-1ubuntu2 (diff) [113kB]
Réception de : 7 http://ch.archive.ubuntu.com/ubuntu/ trusty/main openssh 1:6.6p1-2ubuntu1 (dsc) [2''665B]
Réception de : 8 http://ch.archive.ubuntu.com/ubuntu/ trusty/main openssh 1:6.6p1-2ubuntu1 (tar) [1''283kB]
Réception de : 9 http://ch.archive.ubuntu.com/ubuntu/ trusty/main openssh 1:6.6p1-2ubuntu1 (diff) [142kB]
Réception de : 10 http://ch.archive.ubuntu.com/ubuntu/ trusty/main curl 7.35.0-1ubuntu2 (dsc) [2''729B]
Réception de : 11 http://ch.archive.ubuntu.com/ubuntu/ trusty/main curl 7.35.0-1ubuntu2 (tar) [3''544kB]
Réception de : 12 http://ch.archive.ubuntu.com/ubuntu/ trusty/main curl 7.35.0-1ubuntu2 (diff) [36.4kB]                                                     
10.0Mo réceptionnés en 8s (1''237ko/s)                                                                                                                       
Téléchargement achevé et dans le mode téléchargement uniquement
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ ls
curl-7.35.0                                                        openssh_6.6p1-2ubuntu1.debian.tar.xz   openssl_1.0.1f.orig.tar.gz
curl_7.35.0-1ubuntu2.debian.tar.gz                                 openssh_6.6p1-2ubuntu1.dsc             zlib-1.2.8
curl_7.35.0-1ubuntu2.dsc                                           openssh_6.6p1.orig.tar.gz              zlib_1.2.8.dfsg-1ubuntu1.debian.tar.gz
curl_7.35.0.orig.tar.gz                                            openssl-1.0.1f                         zlib_1.2.8.dfsg-1ubuntu1.dsc
gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux.tar.bz2  openssl_1.0.1f-1ubuntu2.debian.tar.gz  zlib_1.2.8.dfsg.orig.tar.gz
openssh-6.6p1                                                      openssl_1.0.1f-1ubuntu2.dsc
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ for i in `ls *.tar.*|grep -v debian`;do tar xf $i;done;
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ mv -f gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130116_linux/* ../toolchain/
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ ls ../toolchain/
arm-linux-gnueabihf  bin  lib  libexec  share
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ sudo mv /etc/apt/sources.list.orig /etc/apt/sources.list
ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ sudo apt-get update


Voilà! On peut commencer les compilations:

zlib

ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ cd zlib-1.2.8/
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/zlib-1.2.8$ ./configure --prefix=$PREFIX
Checking for shared library support...
Building shared library libz.so.1.2.8 with arm-linux-gnueabihf-gcc.
Checking for off64_t... Yes.
Checking for fseeko... Yes.
Checking for strerror... Yes.
Checking for unistd.h... Yes.
Checking for stdarg.h... Yes.
Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
Checking for vsnprintf() in stdio.h... Yes.
Checking for return value of vsnprintf()... Yes.
Checking for attribute(visibility) support... Yes.
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/zlib-1.2.8$ make CC="${HOST}-gcc" AR="${HOST}-ar" RANLIB="${HOST}-ranlib"
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/zlib-1.2.8$ make install



openssl

ubuntu@virtuelle:~/Bureau/WDMyCloud/src$ cd openssl-1.0.1f/
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/openssl-1.0.1f$ ./Configure --prefix=$PREFIX zlib-dynamic -I$PREFIX/include linux-generic32 shared no-ssl2
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/openssl-1.0.1f$ make CC="${HOST}-gcc" AR="${HOST}-ar r" RANLIB="${HOST}-ranlib"
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/openssl-1.0.1f$ make install_sw
curl C'est ici que l'on va mettre en place le « tuning ». On va faire en sorte que cURL exporte à chaque fois la « master key » (voir article Decrypter du ssl)

Une fois le code mis en place, il ne reste plus qu'à compiler :)


ubuntu@virtuelle:~/Bureau/WDMyCloud/src/$ cd curl-7.35.0
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/curl-7.35.0$ ./configure --prefix=$PREFIX --host=$HOST --target=$HOST --with-ssl=$PREFIX/lib
    --with-zlib=$PREFIX --with-ca-bundle=/etc/ssl/certs/ca-certificates.crt
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/curl-7.35.0$ make CC="${HOST}-gcc" AR="${HOST}-ar" RANLIB="${HOST}-ranlib"
ubuntu@virtuelle:~/Bureau/WDMyCloud/src/curl-7.35.0$ make install

cURL « tuné » sur le NAS

Maintenant que notre cURL « tuné » est prêt, il faut le mettre sur le NAS. Pour ce faire, il suffit de se connecter en SSH sur le NAS et remplacer les fichiers :
  • libcurl.so.4.3.0
  • libcurl.so -> libcurl.so.4.3.0
  • libcurl.so.4 -> libcurl.so.4.3.0
  • curl


Une fois le travail de remplacement effectué, quand on demande la version de cURL dans le shell du NAS:

Version originale

root@nas$ curl  -V             
curl 7.32.0 (arm-unknown-linux-gnueabihf) libcurl/7.32.0 OpenSSL/1.0.1g zlib/1.2.7 libidn/1.25 libssh2/1.4.3 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smtp smtps telnet tftp 
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP 
Ma version (en changant seulement libcurl.so.4.3.0)


On peut voir que la version de la lib a changé.


root@nas$ curl  -V
curl 7.32.0 (arm-unknown-linux-gnueabihf) libcurl/7.35.0 OpenSSL/1.0.1g zlib/1.2.7
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smtp smtps telnet tftp 
Features: Largefile NTLM NTLM_WB SSL libz TLS-SRP
En changeant aussi /usr/bin/curl

root@nas$ curl  -V
curl 7.35.0 (arm-unknown-linux-gnueabihf) libcurl/7.35.0 OpenSSL/1.0.1g zlib/1.2.7
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smtp smtps telnet tftp 
Features: Largefile NTLM NTLM_WB SSL libz TLS-SRP 


Nous voilà prêt à déchiffrer les informations transitant entre le NAS et le site de WD. On verra tout ça dans un prochain article.

That's all folks

Référence utile à la compilation

Guide de compilation WD

  • 6 years 1 month before
  • |