mercredi 26 janvier 2011

Injection de librairie sous Linux


Injection de librairie sous Linux

Injection de lib : à quoi ça sert et quand ?

Il arrive parfois que l'on ai besoin lors de debugging ou de reverse de savoir quels sont les arguments passés à une fonction, et pouvoir accéder facilement à certaines infos sans se farcir un tas de ligne d'ASM à la main. Il suffit souvent d'injecter une librairie dans le processus pour « détourner » la fonction en question en modifiant son contenu pour faire certaines opérations comme de l'affichage de variable.
Ca, c'est la bonne manière de l'utiliser. Mais on peut aussi très bien imaginer ajouter un bout de code malicieux dans une fonction appelée par un programme. Un appel system bien placé. Bien sûr en aucun cas je ne suis responsable de l'utilisation que vous ferez de cet article.

Il faut savoir avant tout que le programme doit être linké « dynamiquement », c'est-à-dire que les librairies soient chargés comme des fichiers autres que le programme principal (souvent en .so pour shared-object). Dans le cas où le code des fonctions est directement intégré dans le programme, c'est tout de suite plus difficile (et cela sort du cadre de cet article). La plupart du temps (et par défaut), les programmes sont compilés avec linkage dynamique. Ne serait-ce que pour réduire considérablement la taille du programme résultant.

Le code en question (exemple avec la fonction strcmp)

Voici le code en question qui permet de détourner une fonction (ici strcmp) d'un programme.

<code>
#define _GNU_SOURCE
#include <stdio.h>
#include <stlib.h>
#include <string.h>
#include <dlfcn.h>
static int (*next_strcmp)(const char *s1, const char *s2) = NULL;

int strcmp(const char *s1, const char *s2)
{
 printf(« String 1 = %s\n String 2 = %s\n », s1, s2) ;
 // Autre code
 if (next_strcmp == NULL) 
  next_strcmp = dlsym(RTLD_NEXT, « strcmp ») ;

 return next_strcmp(s1, s2) ;
}
</code>

On compile et on éxecute : 
<code>
gcc -shared libstrcmp.c -o libstrcmp.so
LD_PRELOAD=libstrcmp.so ./program
</code>

Explication pas à pas

<code>
#define _GNU_SOURCE
#include <dlfcn.h >
</code>
Le #define est nécessaire pour utiliser la fonction dlsym qui permet de charger la vraie fonction strcmp (histoire que même si on a détourné la fonction, on fasse croire au programme que rien ne s'est passé).
Le include permet d'appeler l'header pour la fonction dlsym.

<code>
#include <stdio.h>
#include <stlib.h>
#include <string.h>
</code>
On incluse les autres librairies dont on va avoir besoin. Pour strcmp, bien penser à string.h

<code>
static int (*next_strcmp)(const char *s1, const char *s2) = NULL;
</code>

Alors là c'est une partie un peu délicate. On déclare un pointeur de fonction qui nous permettra de stoquer l'adresse de notre réelle fonction strcmp. Int est le type de retour de la fonction, (*next_strmp) et le nom du pointeur et (const char *s1, const char *s2) sont les arguments utilisés par cette fonction. On initialise le pointeur à NULL (= NULL). Il faut savoir que l'on doit spécifier pour le pointeur exactement le même type de retour que la fonction à détourner (int) et les mêmes arguments ainsi que leurs types. Un man strcmp vous aidera.

<code>
int strcmp(const char *s1, const char *s2)
</code>

On déclare notre fonction. Ce bout de code doit être exactement le même que la fonction à détourner

<code>
printf(« String 1 = %s\n String 2 = %s\n », s1, s2) ;
// Autre code
</code>

Ici notre code ajouté, ce qui nous permet de reverse. On affiche simplement les deux strings passées à la fonction. Libre à vous de rajouter ce que vous voulez à la place du printf.


<code>
 if (next_strcmp == NULL) 
  next_strcmp = dlsym(RTLD_NEXT, « strcmp ») ;
</code>

Ici est peut-être les instructions les plus interessantes. Tout d'abord on vérifie que notre pointeur de fonction ne pointe pas déjà sur la bonne fonction.
Dans le cas contraire on utilise dlsym pour charger la vraie fonction. L'astuce est d'utiliser RTLD_NEXT qui permet de charger la fonction recherchée dans la prochaine librairie (.so) après la notre. Normalement c'est la vraie fonction. A moins que quelqu'un ai déjà injectée une autre librairie ;)

<code>
return next_strcmp(s1, s2) ;
</code>
On appele et retourne simplement le vrai strcmp via notre pointeur de fonction sur les chaines s1 et s2. Rien de bien compliqué.


<code>
gcc -shared libstrcmp.c -o libstrcmp.so
</code>

La commande de compilation pour gcc. -shared permet de dire que c'est une librairie dynamique. -o libstrcmp.so indique le fichier résultant et libstrcmp.c est notre code source.

<code>
LD_PRELOAD=libstrcmp.so ./program
</code>
Ici on appele notre programme ./program simplement. La différence est qu'on ajoute LD_PRELOAD avant. Cela permet de dire au programme qu'avant de charger les librairies nécessaires dans la mémoire du programme, on va ajouter la notre (libstrcmp.so) avant toutes les autres. Donc si la fonction strcmp est appelée par notre programme, on lui passera déjà celle dans notre librairie. On peut aussi utiliser export LD_PRELOAD=libstrcmp.so puis appeler notre programme ./program

Cas particuliers d'injections

Que faire si je veux détourner une fonction autre que strcmp ?

Alors quatre choses à changer : 
  • Vérifier qu'on a bien #include l'header correspondant à notre fonction à détourner
  • Modifier la définition de notre pointeur de fonction. C'est-à-dire modifier le type de retour, les arguments (et le nom du pointeur puis le modifier de partout).
  • Changer l'appel à dlsym. On change le nom de la fonction originel.
  • Le return, pour appeler notre fonction originel avec les bons arguments
Et si je veux cacher un peu plus l'appel à ma librairie (LD_PRELOAD)

Plusieurs astuces peuvent être utilisées. Vous pouvez utiliser un export LD_PRELOAD plus tôt avant que le programme soit exécuté. L'ajouter dans le bashrc par exemple.
Vous pouvez aussi créer un petit script bash du même nom que le programme (en ayant renommé le programme précedement) qui appel LD_PRELOAD dedans.
Faites preuve d'imagination.

Ma machine est une 64 bits mais mon programme est compilé en 32 bits

Dans ce cas là, utilisez l'option -m32 dans gcc pour compiler notre librairie modifiée en 32 bits.
<code>
gcc -m32 -shared libstrcmp.c -o libstrcmp.so
</code>

Puis-je injecter directement la librairie dans le programme lorsque celui-ci tourne déjà ?

Alors là, c'est tout de même rudement plus compliqué. Je vous laisse vous référer à cet article (qui propose même un outil pour automatiser le tout) : http://www.segmentationfault.fr/projets/injecso-injection-de-so-sous-linux/

Conclusion

Voilà cet article touche à sa fin.Je vous ai présenté une technique simple et rapide qui permet de modifier facilement le comportement d'un programme. Pour toutes suggestions ou autre, veuillez me contacter à l'adresse < k1wy.mail (at) gmail (dot) com> (remplacez at par @ et dot par .).

Bon détournement !

mardi 11 janvier 2011

Deezer Desktop et Images/Sons



Je suis en train de regarder un peu le fonctionnement de DeezerDesktop.
J'ai commencé doucement en voulant récupérer les images que le programme a téléchargé sur mon PC.


Il s'avère que seulement un header de 50 octets de long est rajouté avant une simple image jpg.
Ni une ni deux je sort ma console bash et je pond une commande permettant de récupérer l'ensemble des images, la voici :

find picture/ -type f -exec sh -c 'cat $0 | python -c "import sys; data = sys.stdin.readlines(); print \"\".join(data)[49:]" > $0.jpg' {} \;

Il suffit de se placer dans le dossier de cache de deezerDesktop (chez moi ~/dzCache/cache) et le tour est joué.
Je vais regarder pour d'autres infos à dénicher, même si mon but reste quand même les chansons.


Je mettrais à jour ce post sur mes avancements.


Edit 1 :
Après plusieurs recherches, il semble que les fichiers soient enregistrés dans ~dzData/cache/audio. Seulement la correspondance entre les fichiers (qui sont découpés par blocs de 1mo) est stockée dans une DB dans ~/.appdata/DeezerDesktopXXXXXXXXXXXXXXXXXXXXXXXX.1/Local Store/database/dz.db
La db est de type sqlite mais est encrypté. Il faut que je me renseigne sur le chiffrement d'adobe air des base sqlite.

Edit 2 :
En regardant un peu à droite à gauche, il s'avère que le mot de passe est stocké en claire dans le fichier ~/.appdata/DeezerDesktop.XXXXXXXXXXXXX.1/Local Store/#SharedObjects/Tatooine.swf/deezer_tatooine.sol
En somme un fichier intéressant à récupérer au cas où.

Edit 3:
Les fichiers audios sont juste splitter en bloc de 1mo, reste juste à trouver dans quel ordre ils faut les assembler et comment retrouver pour quel artiste quels infos. /!\ Après reconsitution, les fichiers sont modifiés, je ne sais pas encore comment, mais dans tous les cas la chansons n'est plus la même. Il va falloir que je trouve comment ils sont modifiés pour arranger les choses.
Après de longues analyses avec ltrace et strace, il s'avère qu'on peut retrouver les noms des fichiers dans l'ordre. Mais c'est un peu fastidieux et ca oblige à lire la chanson en même temps (du moins à la charger, ce qui ne prend que quelques secondes). Je vais sans doute faire un premier script en exploitant cela.
J'ai aussi fait de l'injection de lib via LD_PRELOAD. Je ferrais sans doute un petit article là dessus, c'est vraiment puissant et assez simple à faire.

Edit 4:
Après analyse avec un fichier uploader et simple, il s'avère que le fichier est chiffré (si je ne me suis pas trompé lorsque je l'ai assemblé, à vérifier). Après essaie d'analyse via audacity, je me suis penché sur le fait de récupérer les sources ActionScript des différents swf. J'ai pour cela utilisé http://www.flash-decompiler.com/fr/ en version démo et http://www.nirsoft.net/utils/sysexp.zip pour pouvoir copier/coller la source car le programme empêché de copier le contenu. SysExp est un tool super interessant pour récupérer plein d'info sur des fenêtres sous windows.
Les sources sont disponibles ici : http://www.2shared.com/file/MuiFeO2a/as_online.html
Je ne connais pas du tout l'ActionScript3 mais ca a l'air de bien ressemblé à du C++, je vais analyser le tout. Je récupèrerais sans doute le mot de passe de la db sqlite dz.db pour retrouver la correspondance chanson -> fichier. J'espère trouver la méthode de chiffrement utilisé sur les chansons. Si quelqu'un veut m'aider avec les source AS, qu'il n'hésite pas à se manifester dans les commentaires ;)

Edit 5:
Au temps pour moi, la base de donnée n'était pas chiffré mais je n'avais pas vu les permissions necessaire dessus. Les données interessantes sont dans la table SONGS_PART, avec SONG_ID l'id de la chanson (récupérable via http://www.deezer.com/listen-{SONGS_ID}) et URL l'emplacement du fichier concerné. NUM_PARTS permet aussi de voir dans quel ordre il faut prendre les morceaux. Il y a clairement une compression sur les bouts de chansons, puisque la taille standard annoncée (1024000) est différentes de la vraie taille des fichiers 409600. Reste à trouver quoi...
Apparement seul les fichiers en cache (donc les fichiers téléchargés sur le disque dur) sont compressés, ca devrait être plus facile pour récupérer les fichiers directement depuis Deezer.


Edit 6:
Le son est bien chiffré, tout à l'air de se passer dans
package dz.media.sound.synch // class SynchSoundDecrypter

lundi 3 janvier 2011

GnackTrack et driver BroadCom

Tout d'abord, je vous souhaites une bonne année 2011.
Que celle-ci soit remplie de bonheur et de (bonnes) surprises.



J'ai recement installé BackTrack en liveUsb mais je n'arrivais pas à me connecter à mon réseau wifi (SSID caché) et l'injection de paquet était alors impossible.

De plus, je ne suis pas un grand fan de KDE, mais je ne rentrerais pas dans les détails, le troll ca serra pour un autre jour.)

J'ai alors décidé de rechercher une autre distribution orienté sécurité mais cette fois ci basée sur Gnome. Et voilà que GnackTrack (http://gnacktrack.co.uk/) m'est apparue !

Je fais sa petite pub car je viens tout juste de l'installer sur mon PC (il me reste encore pas mal de tools à découvrir).

Pour ceux qui comme moi aurait du mal à se connecter en wifi avec une carte BroadCom BCM4313, voici ce qu'il faut faire :

sudo apt-get remove --purge bcmwl-modaliases b43-fwcutter bcm5700-source broadcom-sta-common broadcom-sta-source bcmwl-kernel-source broadcom-sta broadcom-firmware
sudo apt-get remove --purge linux-backports-modules-net-* linux-backports-modules-compat-*
sudo apt-get install bcmwl-kernel-source

Je sais, ca fais beaucoup de paquets supprimés, mais en réalité ils ne sont pas nécessaire. Pour ce qui est des linux-backports-(net|compat), ces derniers empêchés le driver wifi de se charger, il faut donc les supprimer (https://bugs.launchpad.net/ubuntu/+source/bcmwl/+bug/395630).

Ps : apparemment l'injection de paquet ne marche toujours pas. Je ne peux pas passer ma carte en mode monitor. Je vous tiendrais au courant si je trouve une alternative.

lundi 27 décembre 2010

Multiples distributions sur une clef USB

Le père Noël est passé, et il m'a apporté un beau ultra-portable, parfait pour les cours, et le pentest sauvage en pleine cambrousse.

Cependant, sur de nombreux ultra portables, le lecteur CD n'est pas inclu. Il n'est donc pas possible d'utiliser des Live CD.
J'ai donc décidé d'investir d'en une grosse clef USB pour pouvoir me balader partout avec SystemRescue et Backtrack.



Voici un petit logiciel bien sympatoche qui permet d'installer automatiquement plusieurs distributions sur un live CD. Ce logiciel implante aussi certains utilitaires classiques tels que Memtest ou Grub.

Plus d'informations ici : http://liveusb.info/dotclear/


su root
echo "## Depôt MultiSystem" >> /etc/apt/sources.list
echo "deb http://liveusb.info/multisystem/depot all main" >> /etc/apt/sources.list
wget -q http://liveusb.info/multisystem/depot/multisystem.asc -O- | apt-key add -
apt-get update
apt-get install multisystem 

Amusez-vous bien avec votre toute nouvelle super clef USB ;)

mercredi 22 décembre 2010

Injection SQL : contourner un système d'authentification

Premier article d'une série sur les injections SQL.
Je ne montrerais que des exemples sur des applications PHP avec MySQL comme système de base de données.
Ce que nous allons apprendre :
  • Outrepasser un système d'authentification simple en PHP
  • Forger une requête SQL correcte
  • Comment outrepasser des systèmes plus complexes

mardi 21 décembre 2010

Ouverture du blog

Voilà, cela faisait longtemps  que je pensais ouvrir un blog.
Maintenant cela est chose faite.

Sur ce blog je parlerais essentiellement de sécurité informatique, mais aussi des petites astuces surement sur linux ou en programmation.

Voilà, n'hésitez-pas à me contacter à k1wy.mail <at> gmail <point> com