V Lecture 18 — buffer overflow
V what is a buffer overflow?
* void echo() {
char buf[8];
gets(buf);
puts(buf);
}
* gets does not do any bounds checking
* any input longer than 7 characters will write past the end of buf
V stack layout
V stack frame
V section of the stack set aside for each function call
* pushed on the stack when function is called, popped off when function returns
V contains:
* return address
* pointer to previous stack frame (i.e., the stack frame of the function that called this one)
* local variables
* arguments for next function call
* int bar(char *arg, char *out)
{
strcpy(out, arg);
return 0;
}

void foo(char *argv[])
{
char buf[256];
bar(argv[1], buf);
}

int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "target1: argc != 2\n");
exit(1);
}
foo(argv);
return 0;
}
* what does the stack look like after bar has been called?
V buffer overflow attack
V what do we need to have?
* attack code
* size of the buffer
* location of the buffer
V use gdb to verify stack layout
* examine location of args, frames, ebp, eip, sp
* sneak peek of assembly
* run with too long argument to verify it overwrites return address
* write exploit
* use gdb to find location of the buffer
V defenses against buffer overflow attacks
V avoid vulnerabilities
V use library functions that limit string lengths
* fgets instead of gets
* strncpy instead of strcpy
* %ns instead of %s in scanf
V system-level protections
V random stack offsets
* requires attacker to guess random offset correctly
* In Linux, controlled by code written to /proc/sys/kernel/randomize_va_size (0, 1, or 2)
* make stack non-executable
V have compiler insert “stack canaries”
* put a special value between buffer and return address
* check for corruption before leaving function