Buffer overflows

Buffer overflows

char name[8];
gets(name);

Gute Idee?

  • Name: 'Friedrich'
  • Name: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'

Gefahren

  • Überschreiben von Variablen
  • Beieinflussung vom Programmablauf

Kurze Wiederholung Betriebsysteme/Systemprogrammierung

#Pseudocode
def print_hello(string name)
0x20  print "hallo " + name
0x21  return

def main()
0x10  string test = "Peter"
0x11  print "programmstart"
0x12  call print_hello(test)
0x13  print "erfolg"
0x14  call print_hello(test)
0x15  print "beende programm"

Was ist der Output des Programms?

Output:

programmstart
hallo Peter
erfolg
hallo Peter
beende programm

Aber warum?

  • Wie erhält print_hello den Namen der Ausgegeben werden soll?
  • Wieso springt print_hello an die richtige Stelle der Mainfunktion?

Aufbau des Stacks

Beispiel in C

#include <stdio.h>

void print_hello(const char *name, int times) {
        int counter;
        for(counter = 0;  counter < times; counter++) {
                printf("Hallo %s\n", name);
        }
}

int main(int argc, char **argv) {
        char name[] = "Peter";
        int counter = 3;
        printf("Programmstart\n");
        print_hello(name, counter);
        printf("Erfolg\n");
        print_hello(name, counter);
        printf("Programmende\n");

        return 0;
}

Kompilieren

1.c

gcc 1.c -o 1 -fno-stack-protector -g -zexecstack

Als root:

echo 0 > /proc/sys/kernel/randomize_va_space

Betrachten in GDB

Livedemo

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

void good() { printf("Hauptgewinn!\n"); }

void bad() { printf("Zonk\nZonk\nZonk\n"); }

int check_admin(const char* name) {
        int userRechte = 0;
        char userName[16];

        strcpy(userName, name);
        if (!strcmp(userName, "superadmin")) {
                userRechte = 1337;
        }
        return userRechte;
}

int main(int argc, char **argv) {
        if ( argc < 2 ) {
                printf("Passwort fehlt\n");
                return 1;
        }
        if ( check_admin(argv[1]) != 0 ) {
                good();
        } else {
                bad();
        }
        return 0;
}

Kompilieren

2.c

gcc 2.c -o 2 -fno-stack-protector -g -zexecstack

Als root:

echo 0 > /proc/sys/kernel/randomize_va_space

Betrachten in GDB

Livedemo

Generieren von Strings mit Perl

Wie erzeugt man ein Argument mit 50 'A's am anfang und 0xcafecafe am ende?

perl -e 'print "A"x50 . "\xca\xfe\xca\xfe";'

Wie Übergeben?

/a.out `perl -e 'print "A"x50 . "\xca\xfe\xca\xfe";'`
./2 `perl -e 'print "superadmin";'`

Aufgabe 3

  • 3.c
  • Userrechte muessen exakt stimmen

Aufgabe 4

4.c

          gcc -m32 4.c -o a4 -fno-stack-protector -g -zexecstack
          
          

Aufgabe 5

5.c

gcc -m32 5.c -o a5 -fno-stack-protector -g -zexecstack

Gegenmaßnahmen

  • Address Space Layout Randomization
  • No eXecute
  • Canaries

Address Space Layout Randomization

Zufälliger Adressraum

Variablen auf dem Stack bei jedem durchlauf an verschiedenen Addressen

Folge: Können nicht mehr gezielt angesprungen werden

No eXecute

Kein ausführbarer Stack

Vom Angreifer auf den Stack gebrachter Schadcode kann nicht ausgeführt werden

Kann mittels ROP umgangen werden

Canaries

Auf dem Stack werden zusätzliche Werte abgelegt

Wird eine Veränderung dieser festgestellt wird das Programm beendet

Hilfreiche Links

GDB Cheat Sheet

Infos zum Stack