Fall 2000

Lab 12: Hackers R Us

CS61C

Purpose:

In this lab you will learn why it is necessary to protect memory access from malicious programmers.

Overview:

In C when you attempt to access memory you are not supposed to, a "segmentation fault" occurs. SPIM on the other hand does not provide this kind of protection. Therefore, we are going to take advantage of this and modify address spaces, which normally we would not have access to.

Prelab: Read
Smashing The Stack For Fun And Profit
and
Stackguard: Automatic Adaptive Detection and Prevention of Buffer-Overflow Attacks (pdf)
Smashing The Stack For Fun and Profit is arguably the definitive how-to on writing buffer overflow attacks. Stackguard presents a novel method for preventing them. Pay particular attention to section 2 of Stackguard as it provides a concise description of buffer overflow attacks in general. The two documents are quite lengthy and Smashing The Stack uses significant amounts of X86 assembly, so, once you've got the basic idea down, you may stop reading if you get bored or lost.
Have a working copy of the disassembler project ready to run when you come into lab. You may use your own disassembler, or, if necessary, you can grab the dissassembler solution at: ~cs61c/solutions/proj/dis-sol.c.
Answer the following question:

  1. Strictly speaking, a buffer overflow attack consists of two parts, one part is changing the return address of the procedure of the current stack frame. You will perform this step in this lab. What is the other step needed to perform a buffer overflow attack?

Assignment:

Task 1:

Copy the file "~cs61c/lab12/lab12.s" into your working directory. You should have a working copy of the disassembler project ready from the prelab.

Task 2:

Getting familiar with what has been given:
lab12.s: This MIPS program will echo to the CRT (monitor) what you have typed. Be careful!! The program allows only a limited amount of characters per entry. Also notice that this MIPS program will go into an infinite loop, so long as you enter appropriately sized words.

Task 3:

As you look over the MIPS file you may notice what you could potentially write over something, by entering too many characters per line; that's right where the return address of the function "test" is. Now normally this would be a BAD thing to do, however, this is just a lab so it's okay. We are going to change this return address so that the function will return not to the "j loop" instruction but to the instruction following it.

Just in case you don't believe us, try typing a lengthy line of text, and watch the code crash and burn.

You are to create an input file called "overflow" such that if you do "cat overflow | spim -file lab12.s", the file will cause a buffer overflow which will cause the program to print out "Hot Dog, we have a weiner!" and exit. Read on to find out how to go about doing this.

We all know by now that the ascii value of a number and the 2's complement value of the same number are two different animals. Your job is to write a C program that will print to a file the ascii character of the corresponding 2's complement value. This 2's complement value will correspond to the address where you would like the function "test" in lab12.s to return to. You should make an array of four characters and populate it with the integer value of the address in memory. For example if we wanted to see the corresponding ascii representation of address 0x00400000 the following would work:

char addr[4];
addr[0] = 0;
addr[1] = 0x40;
addr[2] = 0;
addr[3] = 0;
. . .
print to a file n times, where n is enough times to write over the return address.

And this would print to the file: ^@@^@^@ ( n times )
^@ = 0
@ = 0x40

To sum it up, the goal of this exercise is to locate the appropriate address to put into the array of characters defined in your lab12.c file. (Hint 1: think disassembler - and don't forget, you'll have to use spim to create a dump file from the given .s file.) (Hint 2:Pay attention to endianness) You will also need to figure out the number times you need to print this address to the file. For example a "for" loop should execute enough times to generate enough characters to write over the return address located on the stack. You should write the address to the file just enough times to write over the return address, no more and no less (i.e. do not write the address a million times and call it a day!).

Task 4:

Furthermore, to ensure your understanding of this lab you should also answer the following questions:
  • Is it possible to modify instructions within the text segment of memory? If so explain how you would do this.
  • Explain how Virtual Memory can protect against malicious programs.

Task 5:

If you have not done so already, name your C program "lab12.c", name the file with the overflow string "overflow", and put the answers to the above questions in a file named "lab12.txt". Submit these three files.

Final Remarks:

This lab shows the potential danger of what could happen if programs like the operating system don't protect against malicious programs from changing values in memory. You could think of someone changing the return address of some function to the address of a program containing the instruction "format c:" So how does the operating system protect you from this?
VIRTUAL MEMORY!

Feedback:

Thoughts, comments, flames, etc.? Did you think this lab was 1337? Did you think this lab sucked? Mail Dan.

Last updated: 11/8