2. Erklaerung der Funktion eines PC's nach dem Einschalten.

- Beispiel des Aufbaus eines Computers

    +-------+            +---------------+            +-------+
    |       |            |               |            |       |
    |       |A0-A15      |               |A0-A15      |       |
    |       |------------|               |------------|       |
    |       |            |               |            |       |
    |       |            |      CPU      |            |       |
    |       |D0-D7       |               |D0-D7       |       |
    |  ROM  |------------|               |------------|  RAM  |
    |       |            |               |            |       |
    |       |------------|               |------------|       |
    |       |CS          +---------------+CS          |       |
    |       |                                         |       |
    |       |                                         |       |
    |       |                                         |       |
    |       |                                         |       |
    |       |                                         |       |
    |       |                                         |       |
    +-------+                                         +-------+

- jeweils 64K Adressen --> 64Kbyte Speicher
- Selektion des Speichers via ChipSelect von der CPU gesteuert
- Programmstart aus dem ROM ab Adresse 0000H
- Beim PC auslesen des BIOS, initialisieren der Peripherie, ...
- hochzaehlen des Programmzaehlers in Abhaengigkeit der Laenge des Befehls
- abarbeiten der Befehle Adresse fuer Adresse



3. Erklaerung der Aufteilung des Speichers

- grob: bestehend aus 3 Speicherbereichen:
	- Text (Programmdaten, Read-Only)        lower memory addresses
	- Variablen (statisch und dynamisch)
	- Stack                                  higher memory addresses

                   +------------------+  lower
                   |                  |  memory
                   |       Text       |  addresses
                   |                  |
                   |------------------|
                   |   (Initialized)  |
                   |        Data      |
                   |  (Uninitialized) |
                   |------------------|
                   |                  |
                   |       Stack      |  higher
                   |                  |  memory
                   +------------------+  addresses

- Programmcode wird im Textspeicher-Bereich abgelegt
- Speicherung von Referenzen, ...
- Stack wird fuer Uebergabeparameter, Rueckgabeparameter und Ruecksprungadressen
  verwendet



4. Erklaerung der Funktionsweise des Stacks und StackCounters

- Beispielprogramm und Aufteilung im Stack

+--------------------------------------+
| void function(int a, int b, int c) { |
|    char buffer1[5];                  |
|    char buffer2[10];                 |
| }                                    |
|                                      |
| void main() {                        |
|   function(1,2,3);                   |
| }                                    |
+--------------------------------------+

bottom of                                                            top of
memory                                                               memory
           buffer2       buffer1   sfp   ret   a     b     c
<------   [            ][        ][    ][    ][    ][    ][    ]

top of                                                            bottom of
stack                                                                 stack


- im Stack erst die Uebergabeparameter, die Ruecksprungadresse, der
  FramePointer, dann die Buffer (lokalen Variablen)
- beim Aufruf (in Assembler) mit 'call', wird im Stackpointer immer
  die Ruecksprungadresse gespeichert
- Ruecksprungadresse ist die Adresse vom call-Aufruf + die Laenge des
  call-Befehls
- fuer den Buffer werden immer Words angelegt (4 Byte)
- Buffer1 benoetigt daher 8 Byte und Buffer2 benoetigt 12 Byte



5. Was passiert beim BufferOverflow?

+-----------------------------+
| void function(char *str) {  |
|    char buffer[16];         |
|                             |
|    strcpy(buffer,str);      |
| }                           |
|                             |
| void main() {               |
|   char large_string[256];   |
|   int i;                    |
|                             |
|   for( i = 0; i < 255; i++) |
|     large_string[i] = 'A';  |
|                             |
|   function(large_string);   |
| }                           |
+-----------------------------+

bottom of                                                            top of
memory                                                               memory
                  buffer            sfp   ret   *str
<------          [                ][    ][    ][    ]

top of                                                            bottom of
stack                                                                 stack

- *str beinhaltet 256 Byte Daten
- es wird versucht, die 256 Byte in ein Buffer zu schreiben der nur 16 Byte
  gross ist
- folge: der FramePointer und die Ruecksprungadresse werden ueberschrieben
- nun steht als Ruecksprungadresse '41414141' an der Speicherstelle der
  Ruecksprungadresse
- die Ruecksprungadresse ist somit falsch und springt an eine nicht definierte
  Stelle im Speicher --> BufferOverflow
- es wird so lange weiter A in den Speicher geschrieben, bis die Grenze des
  zugewiesenen Speicherbereichs erreicht wird, und das Betriebssystem dann die
  Notbremse zieht. --> Core-Dump
- dieses Szenario macht man sich zunutze, um einen Exploit zu realisieren

- primitiv Beispiel zum Ueberschreiben des 'Ret'

+--------------------------------------+
| void function(int a, int b, int c) { |
|    char buffer1[5];                  |
|    char buffer2[10];                 |
|    int *ret;                         |
|                                      |
|    ret = buffer1 + 12;               |
|    (*ret) += 8;                      |
| }                                    |
|                                      |
| void main() {                        |
|   int x;                             |
|                                      |
|   x = 0;                             |
|   function(1,2,3);                   |
|   x = 1;                             |
|   printf("%d\n",x);                  |
| }                                    |
+--------------------------------------+

- ausnutzen von Exploits
- Exploit = Bufferoverflow mit Ausfuehrung von eigenem Code (z.B. Shellcode)



bottom of  DDDDDDDDEEEEEEEEEEEE  EEEE  FFFF  FFFF  FFFF  FFFF     top of
memory     89ABCDEF0123456789AB  CDEF  0123  4567  89AB  CDEF     memory
           buffer                sfp   ret   a     b     c

<------   [SSSSSSSSSSSSSSSSSSSS][SSSS][0xD8][0x01][0x02][0x03]
           ^                            |
           |____________________________|
top of                                                            bottom of
stack                                                                 stack

- in den reservierten Speicher des Buffers wird der Shell-Code geladen
- an der Stelle der Ruecksprungadresse wird die Anfangsadresse des Shell-Codes
  eingetragen
- System-Aufruf zum Ausfuehren der Shell eintragen
- folge: Zugriff auf einen fremden Rechner ueber Shell
- genauere Erklaerung des Shell-Codes und Erstellung --> Andy

- Problem bei BufferOverloads und Exploits (Implementierung):
	- ermitteln des zur Verfuegung stehenden Speichers
	- nur wenig Speicher steht zur Verfuegung
	- herausfinden der benoetigten Ruecksprungadresse
	- herausfinden des Ortes der gespeicherten Ruecksprungadresse im Stack
	- Prozessorabhaengig, Betriebssystemabhaengig, Abhaengig von den verwendeten 
	  Libraries

--> Problem kann einfach durch sauberes/kompetentes Coden abgestellt werden
