Buffer Overflow Lab [10 points]

These exercises are based heavily on those developed at Seed Labs.

Exercises

  1. [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;
    }

  2. [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.

  3. [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

Total of 10 points.

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.