Lösen eines Jobs mit pwnable.kr 17 - memcpy. Datenausrichtung

Bild

In diesem Artikel werden wir uns mit der Datenausrichtung befassen und auch die 17. Aufgabe von der Site pwnable.kr lösen .

Organisationsinformationen
Speziell für diejenigen, die etwas Neues lernen und sich in einem der Bereiche Informations- und Computersicherheit entwickeln möchten, werde ich über die folgenden Kategorien schreiben und sprechen:

  • PWN;
  • Kryptographie (Krypto);
  • Netzwerktechnologien (Netzwerk);
  • Reverse (Reverse Engineering);
  • Steganographie (Stegano);
  • Suche und Ausnutzung von WEB-Schwachstellen.

Darüber hinaus werde ich meine Erfahrungen in den Bereichen Computerforensik, Analyse von Malware und Firmware, Angriffe auf drahtlose Netzwerke und lokale Netzwerke, Durchführung von Pentests und Schreiben von Exploits teilen.

Damit Sie sich über neue Artikel, Software und andere Informationen informieren können, habe ich in Telegram einen Kanal und eine Gruppe eingerichtet, um alle Probleme im Bereich ICD zu diskutieren . Außerdem werde ich Ihre persönlichen Anfragen, Fragen, Vorschläge und Empfehlungen persönlich prüfen und alle beantworten .

Alle Informationen werden nur zu Bildungszwecken bereitgestellt. Der Autor dieses Dokuments übernimmt keine Verantwortung für Schäden, die jemandem durch die Verwendung von Kenntnissen und Methoden entstehen, die durch das Studium dieses Dokuments erworben wurden.

Datenausrichtung


Das Ausrichten von Daten im Direktzugriffsspeicher des Computers ist eine spezielle Anordnung von Daten im Speicher für einen schnelleren Zugriff. Bei der Arbeit mit dem Speicher verwenden Prozesse das Maschinenwort als Haupteinheit. Verschiedene Arten von Prozessoren können unterschiedliche Größen haben: eins, zwei, vier, acht usw. Bytes. Beim Speichern von Objekten im Speicher kann es vorkommen, dass ein Feld diese Wortgrenzen überschreitet. Einige Prozessoren können länger mit nicht ausgerichteten Daten arbeiten als mit ausgerichteten Daten. Und nicht hoch entwickelte Prozessoren können im Allgemeinen nicht mit nicht ausgerichteten Daten arbeiten.

Um sich ein Modell ausgerichteter und nicht ausgerichteter Daten besser vorstellen zu können, betrachten Sie ein Beispiel für das folgende Objekt - die Datenstruktur.

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

Da die Größe einer int-Variablen in x32- und x64-Prozessoren nicht 4 Byte beträgt und der Wert einer void * -Variable 4 bzw. 8 Byte beträgt, wird diese Struktur für x32- und x64-Prozessoren wie folgt im Speicher dargestellt.

Bild

X64-Prozessoren mit einer solchen Struktur funktionieren nicht, da die Daten nicht ausgerichtet sind. Für die Datenausrichtung muss der Struktur ein weiteres 4-Byte-Feld hinzugefügt werden.

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

Somit werden die Datenstrukturdaten für x64-Prozessoren im Speicher ausgerichtet.

Bild

Memcpy Joblösung


Wir klicken auf das memcpy-Signatursymbol und erfahren, dass wir uns über SSH mit dem Passwort-Gast verbinden müssen.

Sie bieten auch Quellcode.
 // 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; } 


Bild

Wenn verbunden, sehen wir das entsprechende Banner.

Bild

Lassen Sie uns herausfinden, welche Dateien sich auf dem Server befinden und welche Rechte wir haben.

Bild

Wir haben eine Readme-Datei. Nach dem Lesen erfahren wir, dass das Programm auf Port 9022 ausgeführt wird.

Bild

Stellen Sie eine Verbindung zu Port 9022 her. Wir erhalten ein Experiment - vergleichen Sie die langsame und schnelle Version von memcpy. Dann gibt das Programm in einem bestimmten Intervall eine Zahl ein und gibt einen Bericht über den Vergleich der langsamen und schnellen Versionen der Funktion aus. Es gibt eine Sache: Experimente 10 und Berichte - 5.

Bild

Lassen Sie uns aufräumen, warum. Suchen Sie die Stelle im Code, um die Ergebnisse zu vergleichen.

Bild

Alles ist einfach, zuerst wird slow_memcpy aufgerufen, dann fast_memcpy. Im Programmbericht gibt es jedoch eine Schlussfolgerung über die langsame Freigabe der Funktion, und wenn die schnelle Implementierung aufgerufen wird, stürzt das Programm ab. Sehen wir uns den schnellen Implementierungscode an.

Bild

Das Kopieren erfolgt mit Assembler-Funktionen. Wir bestimmen durch Befehle, dass dies SSE2 ist. Wie hier gesagt: SSE2 verwendet acht 128-Bit-Register (xmm0 bis xmm7), die in der x86-Architektur mit der Einführung der SSE-Erweiterung enthalten sind, von denen jedes als zwei aufeinanderfolgende Gleitkommawerte mit doppelter Genauigkeit behandelt wird. Darüber hinaus arbeitet dieser Code mit ausgerichteten Daten.

Bild

Bild

Wenn Sie mit nicht ausgerichteten Daten arbeiten, kann das Programm abstürzen. Die Ausrichtung erfolgt mit 128 Bits, dh jeweils 16 Bytes, was bedeutet, dass die Blöcke gleich 16 sein müssen. Wir müssen herausfinden, wie viele Bytes sich bereits im ersten Block auf dem Heap befinden (sei X), dann müssen wir dem Programm jeweils so viele Bytes (sei Y) übertragen, dass ( X + Y)% 16 war 0.

Da alle Operationen Heap-Blöcke belegen, die ein Vielfaches von zwei sind, iterieren Sie über X als 2, 4, 8 usw. bis 16.

Bild

Bild

Wie Sie sehen, wird das Programm mit X = 4 erfolgreich ausgeführt.

Bild

Wir bekommen die Muschel, lesen die Flagge, bekommen 10 Punkte.

Bild

Sie können sich uns per Telegramm anschließen . Das nächste Mal werden wir uns mit dem Heap-Überlauf befassen.

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


All Articles