Résoudre un problÚme avec pwnable.kr 17 - memcpy. Alignement des données

image

Dans cet article, nous traiterons de l'alignement des données et résoudrons également la 17e tùche à partir du site pwnable.kr .

Information organisationnelle
Surtout pour ceux qui veulent apprendre quelque chose de nouveau et se développer dans l'un des domaines de l'information et de la sécurité informatique, j'écrirai et parlerai des catégories suivantes:

  • PWN;
  • cryptographie (Crypto);
  • technologies de rĂ©seau (rĂ©seau);
  • reverse (Reverse Engineering);
  • stĂ©ganographie (Stegano);
  • recherche et exploitation des vulnĂ©rabilitĂ©s WEB.

En plus de cela, je partagerai mon expérience en criminalistique informatique, analyse de logiciels malveillants et micrologiciels, attaques sur les réseaux sans fil et les réseaux locaux, réalisation de pentests et écriture d'exploits.

Afin que vous puissiez vous renseigner sur les nouveaux articles, logiciels et autres informations, j'ai créé une chaßne dans Telegram et un groupe pour discuter de tout problÚme dans le domaine de l'ICD. Aussi, je considérerai personnellement vos demandes, questions, suggestions et recommandations personnelles et répondrai à tout le monde .

Toutes les informations sont fournies à des fins éducatives uniquement. L'auteur de ce document n'assume aucune responsabilité pour tout dommage causé à quelqu'un du fait de l'utilisation des connaissances et des méthodes obtenues à la suite de l'étude de ce document.

Alignement des données


L'alignement des données dans la mémoire à accÚs aléatoire de l'ordinateur est un arrangement spécial de données en mémoire pour un accÚs plus rapide. Lorsque vous travaillez avec de la mémoire, les processus utilisent le mot machine comme unité principale. Différents types de processeurs peuvent avoir différentes tailles: un, deux, quatre, huit, etc. octets. Lors de la sauvegarde d'objets en mémoire, il peut arriver que certains champs dépassent ces limites de mots. Certains processeurs peuvent travailler avec des données non alignées plus longtemps qu'avec des données alignées. Et les processeurs non sophistiqués ne peuvent généralement pas fonctionner avec des données non alignées.

Afin de mieux imaginer un modÚle de données alignées et non alignées, considérons un exemple sur l'objet suivant - la structure de données.

struct Data{ int var1; void* mas[4]; }; 

Étant donnĂ© que la taille d'une variable int dans les processeurs x32 et x64 n'est pas de 4 octets et que la valeur d'une variable void * est respectivement de 4 et 8 octets, cette structure pour les processeurs x32 et x64 sera reprĂ©sentĂ©e en mĂ©moire comme suit.

image

Les processeurs X64 avec une telle structure ne fonctionneront pas, car les données ne sont pas alignées. Pour l'alignement des données, il est nécessaire d'ajouter un autre champ de 4 octets à la structure.

 struct Data{ int var1; int addition; void* mas[4]; }; 

Ainsi, les données de structure de données pour les processeurs x64 seront alignées en mémoire.

image

Solution d'emploi Memcpy


Nous cliquons sur l'icĂŽne de signature memcpy et on nous dit que nous devons nous connecter via SSH avec le mot de passe guest.

Ils fournissent également du code source.
 // compiled with : gcc -o memcpy memcpy.c -m32 -lm #include <stdio.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <sys/mman.h> #include <math.h> unsigned long long rdtsc(){ asm("rdtsc"); } char* slow_memcpy(char* dest, const char* src, size_t len){ int i; for (i=0; i<len; i++) { dest[i] = src[i]; } return dest; } char* fast_memcpy(char* dest, const char* src, size_t len){ size_t i; // 64-byte block fast copy if(len >= 64){ i = len / 64; len &= (64-1); while(i-- > 0){ __asm__ __volatile__ ( "movdqa (%0), %%xmm0\n" "movdqa 16(%0), %%xmm1\n" "movdqa 32(%0), %%xmm2\n" "movdqa 48(%0), %%xmm3\n" "movntps %%xmm0, (%1)\n" "movntps %%xmm1, 16(%1)\n" "movntps %%xmm2, 32(%1)\n" "movntps %%xmm3, 48(%1)\n" ::"r"(src),"r"(dest):"memory"); dest += 64; src += 64; } } // byte-to-byte slow copy if(len) slow_memcpy(dest, src, len); return dest; } int main(void){ setvbuf(stdout, 0, _IONBF, 0); setvbuf(stdin, 0, _IOLBF, 0); printf("Hey, I have a boring assignment for CS class.. :(\n"); printf("The assignment is simple.\n"); printf("-----------------------------------------------------\n"); printf("- What is the best implementation of memcpy? -\n"); printf("- 1. implement your own slow/fast version of memcpy -\n"); printf("- 2. compare them with various size of data -\n"); printf("- 3. conclude your experiment and submit report -\n"); printf("-----------------------------------------------------\n"); printf("This time, just help me out with my experiment and get flag\n"); printf("No fancy hacking, I promise :D\n"); unsigned long long t1, t2; int e; char* src; char* dest; unsigned int low, high; unsigned int size; // allocate memory char* cache1 = mmap(0, 0x4000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); char* cache2 = mmap(0, 0x4000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); src = mmap(0, 0x2000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); size_t sizes[10]; int i=0; // setup experiment parameters for(e=4; e<14; e++){ // 2^13 = 8K low = pow(2,e-1); high = pow(2,e); printf("specify the memcpy amount between %d ~ %d : ", low, high); scanf("%d", &size); if( size < low || size > high ){ printf("don't mess with the experiment.\n"); exit(0); } sizes[i++] = size; } sleep(1); printf("ok, lets run the experiment with your configuration\n"); sleep(1); // run experiment for(i=0; i<10; i++){ size = sizes[i]; printf("experiment %d : memcpy with buffer size %d\n", i+1, size); dest = malloc( size ); memcpy(cache1, cache2, 0x4000); // to eliminate cache effect t1 = rdtsc(); slow_memcpy(dest, src, size); // byte-to-byte memcpy t2 = rdtsc(); printf("ellapsed CPU cycles for slow_memcpy : %llu\n", t2-t1); memcpy(cache1, cache2, 0x4000); // to eliminate cache effect t1 = rdtsc(); fast_memcpy(dest, src, size); // block-to-block memcpy t2 = rdtsc(); printf("ellapsed CPU cycles for fast_memcpy : %llu\n", t2-t1); printf("\n"); } printf("thanks for helping my experiment!\n"); printf("flag : ----- erased in this source code -----\n"); return 0; } 


image

Une fois connecté, nous voyons la banniÚre correspondante.

image

Voyons quels fichiers se trouvent sur le serveur, ainsi que les droits dont nous disposons.

image

Nous avons un fichier Lisez-moi. AprÚs l'avoir lu, nous apprenons que le programme s'exécute sur le port 9022.

image

Connectez-vous au port 9022. On nous propose une expérience - comparez la version lente et rapide de memcpy. Ensuite, le programme entrera un nombre dans un certain intervalle et émettra un rapport sur la comparaison des versions lente et rapide de la fonction. Il y a une chose: les expériences 10 et les rapports - 5.

image

Voyons pourquoi. Trouvez l'endroit dans le code pour comparer les résultats.

image

Tout est simple, d'abord slow_memcpy est appelĂ©, puis fast_memcpy. Mais dans le rapport du programme, il y a une conclusion sur la libĂ©ration lente de la fonction, et lorsque la mise en Ɠuvre rapide est appelĂ©e, le programme plante. Voyons le code d'implĂ©mentation rapide.

image

La copie se fait à l'aide des fonctions d'assembleur. Nous déterminons par des commandes qu'il s'agit de SSE2. Comme indiqué ici : SSE2 utilise huit registres 128 bits (xmm0 à xmm7) inclus dans l'architecture x86 avec l'introduction de l'extension SSE, chacun étant traité comme 2 valeurs à virgule flottante double précision consécutives. De plus, ce code fonctionne avec des données alignées.

image

image

Ainsi, en travaillant avec des donnĂ©es non alignĂ©es, le programme peut se bloquer. L'alignement est effectuĂ© sur 128 bits, soit 16 octets, donc les blocs doivent ĂȘtre Ă©gaux Ă  16. Nous devons savoir combien d'octets sont dĂ©jĂ  dans le premier bloc du tas (soit X), puis nous devons chacun transfĂ©rer le programme autant d'octets (soit Y) pour que ( X + Y)% 16 Ă©tait 0.

Étant donnĂ© que toutes les opĂ©rations occupent des blocs de tas qui sont des multiples de deux, itĂ©rez sur X comme 2, 4, 8, etc. jusqu'au 16.

image

image

Comme vous pouvez le voir, avec X = 4, le programme s'exécute correctement.

image

Nous obtenons la coquille, lisons le drapeau, obtenons 10 points.

image

Vous pouvez nous rejoindre sur Telegram . La prochaine fois, nous traiterons du débordement de tas.

Source: https://habr.com/ru/post/fr462895/


All Articles