labo secu (v2017.1.6) Programmation assembleur (ASM) Rick Wertenbroek / Magali Frölich / Daniel Rossier Sécurité sur x86 Jeudi 12 janvier 2017 Echéance: vendredi 27 janvier 2017, 23h59 Objectif du laboratoire Ce laboratoire propose deux exercices pratiques pour étudier les conventions ABI cdecl utilisées avec le jeu d’instructions x86. Le premier exercice se concentre sur l'algorithme de chiffrement AES-128 (128 bits). Nous utiliserons les instructions spécialisées fournies par l'extension AES-NI d'Intel. Le deuxième exercice propose de mettre en place une attaque de type buffer overflow. Consignes de laboratoire Le laboratoire est individuel et est évalué selon les conditions établies dans le document annexe qui vous a été distribué en début de semestre. Pour toutes les fonctions implémentées en assembleur x86 il sera demandé de respecter la convention ABI cdecl étudiée en cours. Etape no. 1 – Chiffrer un bloc de données avec l’algorithme AES L’algorithme de chiffrement AES-128 sert à chiffrer des blocs de données de 128 bits. C’est un chiffrement symétrique, ce qui veut dire qu’on utilisera la même clé pour chiffrer et déchiffrer les données. Les étapes permettant le chiffrement d'un bloc de données sont les suivantes : Générer les sous-clés depuis la clé initiale. Ronde initiale Rondes internes (Cette opération doit être répétée 8 fois) Ronde finale Les instructions principales utilisées dans le programme sont les suivantes : aeskeygenassist aesimc aesenc aesenclast aesdec aesdeclast imm8, %xmm1, %xmm1, %xmm1, %xmm1, %xmm1, %xmm1, %xmm2 %xmm2 %xmm2 %xmm2 %xmm2 %xmm1 Génération des sous-clés Transformation inverse mixColumns Chiffrement des rondes internes Chiffrement de la ronde finale Déchiffrement des rondes internes Déchiffrement de la ronde finale Les instructions AES-NI manipulent les registres 128-bits (%xmm0, %xmm1, %xmm2, …). a) Le ficher labo6/asm_x86/aes.S contient une implémentation de l’algorithme AES. Prenez connaissance du code contenu dans ce fichier. -1 - ASM – Programmation assembleur b) Editez le code assembleur de ce fichier de manière à pouvoir appeler les fonctions de chiffrement et de déchiffrement depuis l'application C qui se trouve dans le fichier labo6/c_x86/crypt.c. Les fonctions doivent respecter la convention ABI cdecl. Les prototypes sont les suivants : void aes_initialize(void) int aes_crypt(void *src, void *dst, void *key) void aes_decrypt(void *src, void *dst, void *key) c) Editez le code assembleur et vérifiez que la fonction de chiffrement est correcte en ajoutant le test suivant : dans la fonction de chiffrement assembleur, sauvez une copie du message à chiffrer dans une variable locale (en suivant les conventions de l'ABI). Puis après l’opération de chiffrement, appliquez un déchiffrement et vérifiez que la valeur obtenue corresponde bien à la valeur originale. Pour cela, utilisez/adaptez la fonction de comparaison. La fonction de chiffrement retournera 0 si la comparaison est correcte, -1 dans le cas contraire. Indications Attention à bien recompiler le code assembleur dans le répertoire asm_x86 lors de toute modification. Le Makefile dans le répertoire c_x86 ne régénère pas le code assembleur. Les détails sur ce jeu d'instructions et les impacts sur la sécurité au niveau du processeur sont disponibles ici : http://download-software.intel.com/sites/default/files/article/165683/aes-wp-2012-09-22-v01.pdf Une variable d’environnement est disponible pour charger et exécuter le programme crypt.bin. Une configuration de Debug a été ajoutée dans eclipse. -2- ASM – Programmation assembleur Etape no. 2 – Buffer overflow (débordement de tampon) Une société de location de films propose une petite application C pour louer un film et débiter le compte de l’utilisateur. Cette application est composée de trois fonctions : - void afficher_commande(const char *titre, int size) void debiter() void visionner_film() a) Examinez l’application contenue dans le fichier labo6/c_x86/location_films.c. Effectuez, si nécessaire, quelques recherches sur internet et décrivez comment utiliser une attaque de type buffer overflow pour modifier le déroulement du programme (sans en altérer le code source) et visionner un film sans que le compte de l’utilisateur ne soit débité. Le code de la fonction afficher_commande(…) est le suivant : void afficher_commande(const char *titre, int size) { char recu[20]; strcpy(recu, "Location: "); strncat(recu, titre, size); afficher_recu(recu); } b) Réalisez l’attaque que vous avez décrite et documentez votre démarche dans le fichier labo6/README.md U-Boot détectera votre attaque et un message vous indiquera que vous avez réussi l’exercice. Faites une capture et ajoutez-là à votre labo6/README.md Dessinez le contenu de la pile pour illustrer votre attaque. (Bonus) Proposez un exemple de contre-mesure ou de protection contre cette attaque autre que celui mis en place par U-Boot. Indications Il est possible de modifier l’adresse de retour d’une fonction avec une attaque de type buffer overflow Une variable d’environnement est disponible pour charger et exécuter le programme location_films.bin. Une configuration de Debug a été ajoutée dans eclipse. -3-