Buffer Overflow Lab [10 points]
These exercises are based heavily on those developed at Seed Labs.
Exercises
-
[2 points] Draw the stack frame for the following C function. Be sure label where index 0 and index 23 are in the buffer local variable.
int bufferoverflow(char *str) { char buffer[24]; strcpy(buffer,str); return 1; }
-
[4 points] Sometimes source code is not available and an adversary does not know the length of a buffer or if there are other local variables declared in a function that is vulnerable to a buffer overflow. In that case they must make some guesses in order to exploit a weakness. One method we discussed in class is called spraying where the return address is written to a number of locations on the stack so that one of those locations overwrites the real return address. In this problem you will implement a spraying attack.
You are given this compiled code stack_lab that reads 300 bytes from badfile and passes those 300 bytes to a function that does a vulnerable string copy like the code from class. This code was not compiled with the -g flag so you do not have debugging information available for gdb (but it was compiled with an executable stack and no stack guards).
Create a malicious badfile that when read by the compiled stack_lab code will result in a terminal running as root. You'll want to do the following:
- Turn off address randomization with sudo sysctl -w kernel.randomize_va_space=0 (turn it back on by setting value to 2)
- Run gdb against the compiled code
- Run a gdb command that will list all the function in stack_lab. Guess which one is vulnerable (you'll know it when you see it)
- Set a break point at that function and run up to the start of that function
- Print the address of the %ebp pointer with p $ebp
- Use the %ebp pointer's address to work out where the return address is on the stack and determine a good value to overwrite the return address so that when this function ends, execution will jump to your NOP sled and ultimately your malicious code
- Alter exploit.py from class to spray the value of the return address across multiple stack locations. Assume the vulnerable buffer was sized to hold a person's last name (but you do not know its exact size or location on the stack). You need not alter the shell code
- Run your altered exploit.py code to create a new badfile (hint: the vulnerable buffer might not be a multiple of 4 bytes, this adds a small level of complexity)
- Set the compiled stack_lab code provided above to be owned by root
- Set the compiled stack_lab code provided above to be a setUID program
- Run stack_lab and get a terminal with root privileges.
Note: due to memory virtualization, the address of %ebp will always be allocated on at the same virtual memory address on the stack whenever the stack_lab is executed.
Submit your updated exploit.py code and a screen shot of stack_lab resulting in a terminal with root privileges.
-
[4 points] Buffer overflows are not restricted to the stack, they can also occur on the heap. Consider the following code.
#include <stdlib.h> #include <string.h> #include <stdio.h> const int MAX_SIZE = 8; void main(int argc, char *argv[]) { //define user and admin variables char *user = (char *)malloc(sizeof(char)*MAX_SIZE); char *adminuser = (char *)malloc(sizeof(char)*MAX_SIZE); //set admin to root, user to command line arg or guest strcpy(adminuser, "root"); if (argc > 1) strcpy(user, argv[1]); else strcpy(user, "guest"); printf("User contains: %s\n", user); printf("Admin user contains: %s\n", adminuser); }
The variables user and adminuser are allocated on the heap using malloc. Use gdb to find an entry for arg[1] that will give the adminuser a value of <your last name>. You may compile this code with with debugging info to help you find any needed memory addresses.
Note: run this on the VM. It may be difficult to exploit an overflow on a Mac. Also, due to memory virtualization, user and adminuser will always be allocated on at the same virtual memory address on the heap. Finally, if you get a segfault, experiment with different input strings to see if you can avoid it while still writing your last name into adminuser.
Submit the string you would enter for arg[1] on the command line to write your last name into adminuser. Discuss how you arrived at this string and how to prevent this attack.
Submission Instructions
Create a single .pdf file with your answers to these exercises. Zip your code files together with your .pdf into a single file and submit that file via Canvas. In the text box on your Canvas submission, provide the names of your partners. Only one partner need submit.
Grading rubric
Exercise 1 [2 points]:
- 0.0: Nothing of substance
- 1.0: Your solution needs significant work
- 1.5: Mainly correct (small mistakes/errors)
- 2.0: Correct.
Exercise 2 [4 points]:
- 1 point: identify the correct location of return address on stack
- 1 point: spray the return address across portions of the stack
- 1 point: handle the case that the size of the buffer might not be a multiple of four bytes
- 1 point: calculate an address in the NOP sled to jump to when the vulnerable function terminates.
Exercise 3 [4 points]:
- 2 points: provide a string for user on the command line that will write your last name in adminuser
- 1 point: find a string that will write your last name in adminuser, but does not seg fault
- 1 point: give a method to prevent this attack.