/* file: vulnerable.c ------------------ author: Ted Baker version: $Version$ last modified by: $Author: cop4610 $ on: $Date: 2002/08/21 19:28:41 $ purpose: illustrate buffer overflow vulnerability The use of strcpy() here, on a string whose length has not been checked first, makes this program vulnerable to buffer overflow. Such unchecked overflows can be exploited to force the process to execute a different program. This is the kind of vulnerability in system software that is exploited frequently by hackers. */ #include #include #include #include #include #include char const * arg; void sub () { char buf[10]; int i; strcpy (buf, arg); for (i = 0; i <= (94 / sizeof (int)) + 1; i++) fprintf (stderr, "%10x\n", *(int *) (buf + i*sizeof (int))); fprintf (stderr, "%s\n", buf); fprintf (stderr, "%10x\n", (int *) &buf[28]); } /* ebp = 0xbffffa28 sp = 0xbffffa00 Activation record size = 0x28 = 44 Bytes Occupied by 0xbffffa24 - 27 saved base pointer 0xbffffa20 - 23 (maybe padding?) 0xbffffa10 - 19 buf[0-9] 0xbffffa0c - 0f i 0xbffffa00 - 0b (maybe padding?) At instruction 080484f6 ("sub $0x8,%esp) the activation record size is 44 bytes, and buf[] is 16 bytes below the top of the stack. The return address is just below the activation record, 44 bytes below the top of the stack, and 28 bytes below the start of buf[]. (gdb) disassem Dump of assembler code for function sub: stack effect 0x80484f0 : push %ebp +4 = 4 (old base pointer) 0x80484f1 : mov %esp,%ebp 0x80484f3 : sub $0x28,%esp +40 = 44 0x80484f6 : sub $0x8,%esp +8 = 52 0x80484f9 : pushl 0x804978c +4 = 56 0x80484ff : lea 0xffffffe8(%ebp),%eax 0x8048502 : push %eax +4 = 60 0x8048503 : call 0x80483d8 0x8048508 : add $0x10,%esp -16 = 44 0x804850b : sub $0x4,%esp +4 = 48 0x804850e : lea 0xffffffe8(%ebp),%eax 0x8048511 : push %eax +4 = 52 0x8048512 : push $0x8048620 +4 = 56 0x8048517 : pushl 0x8049770 +4 = 60 0x804851d : call 0x8048388 0x8048522 : add $0x10,%esp -16 = 44 0x8048525 : sub $0x4,%esp +4 = 48 0x8048528 : movsbl 0x4(%ebp),%eax 0x804852c : push %eax +4 = 52 0x804852d : push $0x8048624 +4 = 56 0x8048532 : pushl 0x8049770 +4 = 60 0x8048538 : call 0x8048388 0x804853d : add $0x10,%esp -1 = 44 0x8048540 : leave 0x8048541 : ret End of assembler dump. */ int main (int argc, const char *argv[]) { if (argc != 2) { fprintf (stderr, "this program expects a single command-line argument\n"); exit (-1); } arg = argv[1]; kill (getpid(), SIGSTOP); sub (); return 0; } /* (gdb) disassem Dump of assembler code for function main: 0x8048544
: push %ebp 0x8048545 : mov %esp,%ebp 0x8048547 : sub $0x8,%esp 0x804854a : cmpl $0x2,0x8(%ebp) 0x804854e : je 0x8048570 0x8048550 : sub $0x8,%esp 0x8048553 : push $0x8048640 0x8048558 : pushl 0x8049770 0x804855e : call 0x8048388 0x8048563 : add $0x10,%esp 0x8048566 : sub $0xc,%esp 0x8048569 : push $0xffffffff 0x804856b : call 0x80483c8 0x8048570 : mov 0xc(%ebp),%eax 0x8048573 : add $0x4,%eax 0x8048576 : mov (%eax),%eax 0x8048578 : mov %eax,0x804978c 0x804857d : call 0x80484f0 0x8048582 : mov $0x0,%eax 0x8048587 : leave 0x8048588 : ret End of assembler dump. */