Stack Smashing and Heap Overflow
Objectives:
The purpose of this lab is to learn about stack smashing and heap overflow
attacks. You should understand exactly how they work and various approaches to
preventing them. In addition, you will gain hands-on experience with the
following:
- Using a debugger
- Analyzing user stack
processing during function calls
- Understanding assembly code
- Using a stack-protecting
compiler
You have probably learned about buffer overflows in earlier classes (like
CS 324). Feel free to use other textbooks or references you may have. You
should have already read the assigned paper that discusses StackGuard, and
other approaches to preventing buffer overflow attacks. Here are two classic
non-traditional papers that are worth reading:
Smashing The Stack For Fun
And Profit
w00w00 on Heap
Overflows
For this lab you
will need to download
the tar file of code. To receive credit for completing this lab,
you only need to turn in a written deliverable with your answers to the
questions asked throughout the lab. To receive full credit, you must express
your answer clearly; consider this an opportunity to demonstrate your writing
skills. No pass-off with the TAs
is required.
Part
1: Decoding the Stack
The program that we will be exploiting is "vulnerable.c" in the
tar ball. A make file is provided in the tar ball. The program accepts a
character string as an input parameter and echoes that value to the screen.
The program has a bug. You will need to use a debugger and analyze the
program. Both GDB and DDD are available in the labs. If
you are not familiar with debuggers, read these quick introductions:
GDB
DDD
Here are some helpful links to browse over to refresh your memory about the structure
of processes in memory:
Function
Call Conventions
Procedure
Stack Frames
Layout
of Heap in relation to Stack
Complete the following 3 items:
- Type the command "gcc
-v" and record what version of GCC you are using. Ex. "gcc
version 1.1.2 230434212 (Red Hat Linux 3.3.3-7)"
- After compiling
vulnerable.c, run the program in a debugger and pass in a short string
like "test" as the only parameter. View and analyze the
contents of the user stack during the function call to
"vulnerable":
- What
is the value of the stack pointer ($esp) and base pointer ($ebp) at the
exact moment that dummy1 is set to 7 in the main routine?
- What
is the value of the stack pointer and the base pointer at the exact
moment that dummy2 is set to 10 in the function "vulnerable"?
- Using
the two stack pointer ($esp) values as bounds, neatly draw (or type
out) the contents of the user stack generated for handling the function
call and precisely identify as many items on the stack as possible.
- Try running the program
once by supplying an input argument string of length five, such as
"cs465". Repeatedly run the program and increase the size of
the string by one during each invocation (i.e., cs465a, cs465ab,
cs465abc, . . .) until the program crashes.
- What
is the length of the shortest input string that results in a program
crash? (number of characters you typed)
- On
what line of source code did the program crash? (use the debugger)
- Explain
precisely why the program crashed. Your answer will be graded on detail
and clarity.
Part
2: Alter Program Execution Flow
Notice that the "exploited" function in "vulnerable"
is never invoked. In this section, you will cause the "exploited"
function to be executed using a carefully constructed input string to
"vulnerable."
The program "wrap" will help you build a string to overflow the
buffer "buf" in the "vulnerable" function in the
"vulnerable" program. "wrap" executes
"vulnerable" itself so you don't need to copy and paste. Use the
debugger to find the following about "vulnerable:"
- The distance in bytes from
the end of the buffer to the return address on the stack.
- The address of the
"exploited" function
"wrap" takes the distance in bytes from the end of the buffer to
the return address and the address of the exploited function and produces a
string that will overflow "buf" and cause the program to execute
"exploited."
Once you have successfully caused "vulnerable" to execute
"exploited," do the following:
- Explain what each section
of code in "wrap.c" labeled "Section X," where X is a
number, does.
- Diagram the string that
wrap creates with the data you give it.
- Is the ability to just
alter program flow a security problem? Why?
Part
3: Heap Overflow: A Simple Example
This part is an introduction to heap
overflows. Compile the program "simple_heap_overflow.c" (a make
file is provide). Run the program at the command prompt. Open up the file
"simple_heap_overflow.c" and think about what is happening. Answer
the following questions:
- What is a heap overflow?
- How does this program
demonstrate a heap overflow?
- Why doesn't the program
crash?
Part
4: Heap Overflow: Getting a Shell
In this part, we will work with the files
"vulnerable_heap.c" and "exploit_heap.c". Vulnerable_heap
is a program that takes two character strings as arguments. The first gets
stored in a buffer and the second is passed to the function
"goodfunc" in "vulnerable_heap" as an argument.
See how "vulnerable_heap" works by looking at the source code and
by running it. (Ex. "./vulnerable_heap blah test")
"exploit_heap" is a program that takes one argument--an integer.
Run the program "exploit_heap" and try passing in different numbers
(start with 70 and go up to 100) until you get a shell.
- How does the attack work?
(i.e. What does the exploit_heap program do and why?)
Part
5: Stack Protection
We have compiled a version of GCC with
stack protection using IBM's Propolice (based on StackGuard). To
use our version of GCC, copy and paste the following at the command prompt:
PATH=/users/ta/cs465ta/gcc_path/bin:$PATH
Now, type "gcc -v" and check to make sure you are using gcc
version 3.4.1. You should see the following:
[user]$ gcc -v
Reading specs from /users/user2/ta/cs465ta/gcc_path/bin/../lib/gcc/i686-pc-linux-gnu/3.4.1/specs
Configured with: ../configure --prefix=/users/ta/cs465ta/gcc_path
--enable-stack-protector
Thread model: posix
gcc version 3.4.1
Recompile the vulnerable programs in this lab with the new compiler and run
each of the corresponding exploits again (parts 1-4). This doesn't mean to
answer all the questions again--just see if each exploit still works.
Remember to first type "make clean" to remove all the files
previously compiled, before you type "make" to recompile with the
new version of GCC.
- For each vulnerable program
describe what happened with each corresponding exploit.
- Describe two ways that
Propolice protects the stack (see their website).
- If some of the exploits
still work, explain why they work even though Propolice is being used.
Conclusion
and Pass Off
To pass off the lab:
- Turn in answers your
answers to all the questions in parts 1-5.
- Also, turn in the answers
to the additional questions presented below:
Additional Questions:
- In parts 4 when you
executed shell code, did you really compromise the security of the
system you are working on? If not, under what circumstances does a
buffer overflow/heap overflow attack result in a security violation?
- How many hours did you spend
on lab 7?
- What did you like about lab
7?
- What did you dislike about
lab 7?
|