CS 202 - Homework 8 - 11/5/07
Due: Monday, 11/12/07, in class (or by 2pm the latest)
This homework has two parts and covers caches and assembly
programming. You have to do part 1 by yourself, but on part 2
you may work in groups of two (or by yourself if you
prefer). I only need one submission per group on part 2.
On your submissions for each part, please write down how much time it took
you.
Part 1: Cache memory
(To be done individually.)
Read BO, Sections 6.2-6.4.
- Do practice problem 6.9 on page 501.
- Do practice problem 6.10 on page 502.
- Repeat practice problem 6.10 for address 0x016A.
- Repeat practice problem 6.10 for address 0x1491.
- Repeat practice problem 6.10 for address 0x0707.
- For the cache in practice problem 6.9, list all of the hex
memory addresses that will hit in set 6.
Part 2: Buffer overflow attack
(Adapted from BO homework problem 3.38 - can be done in groups of 2.)
Update:
My code in the main() method for stabilizing the stack doesn't seem to work on
the new lab machines. Therefore, please log into basin (aka bj) to do your work,
using "ssh -X basin".
In this problem, you will mount a buffer overflow attack on your own
program. Start by reading BO, Section 3.13 (3.12 will be useful too).
Copy the program bufbomb.c from
~schar/cs202/hw8/ into your own account, and compile it using
gcc -m32 -g -O2 -Os -o bufbomb bufbomb.c
Please type the command exactly as shown, otherwise this problem will
be more difficult. In particular, option "-Os" optimizes the code for size
which avoids unnecessary space being allocated on the stack.
In bufbomb.c, you will find the following two functions:
int getbuf()
{
char buf[16];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
The function getxs (also in bufbomb.c) is similar to
the library function gets, except that it reads characters
encoded as pairs of hex digits. For example, to give it the string
"ABC", the user would type in the string "41 42 43"
(the ASCII code for 'A' is 0x41). The function ignores blank
characters, and stores the byte sequence entered by the user
(terminated by 0) at the address passed in as argument.
A typical execution of the program is as follows:
% ./bufbomb
Type Hex string: 41 42 43
getbuf returned 0x1
Looking at the code for the getbuf function, it seems that it
will return value 1 whenever it is called. It appears as if the call
to getxs has no effect. Your task is to make getbuf
return 0xdeadbeef, simply by typing an appropriate
hexadecimal string to the prompt.
To do this, you will have to mount a "buffer overflow attack" as
discussed in class. In particular, you'll have to write some "exploit
code" that makes getbuf return the desired value, and change
the return address on the stack so that your exploit code is run after
getbuf returns. All this can be accomplished by supplying
more than 16 bytes, and thus overflowing the buffer and overwriting
part of the stack frame.
Here are some ideas that will help you solve the problem:
-
Use the command "objdump -d bufbomb" to disassemble the
program, and study the function getbuf. Make sure you
understand how its stack frame is organized, and what effect
overflowing the buffer will have. (Note that you may see a command like
"subl $0x10, %esp", which has to do with gcc's
attempt to keep stack frames aligned. You can safely ignore it as long
as you can figure out where the array "buf" is located relative to the
base pointer.)
-
Run the program in the debugger using the command "ddd
bufbomb". Set a breakpoint in getbuf, run your
program to this point, and open the machine code and register
windows. Determine the important parameters, e.g, the value of
%ebp and the values on the stack that would get overwritten
by a buffer overflow. To look at memory contents, select Memory
from the Data menu. Then, in the memory window, select "hex",
"words" (or "bytes"), and type an address in the "from" field. (You
can also give a register name in the "from" field but you have to
use a "$" instead of the "%", e.g., "$ebp".
-
Before trying to execute any exploit code, make sure you have the
correct values of the portion of the stack that gets overwritten.
To do this, run the program and give it enough (more than 16) bytes
of input to make sure a buffer overflow occurs. Usually, this will
result in a segmentation fault. However, if you overwrite the stack
with the values that were there already, the program should
terminate normally. Hint: remember that the IA-32 is little endian.
-
Next you'll have to figure out what exploit code to use. Once you
have an idea, you can get the byte encoding of your code by first
assembling it using gcc and then disassembling it using
objdump. For example, if your assembly instructions are in
a file "exploit.s", use the command "gcc -c
exploit.s" followed by the command "objdump -d
exploit.o". To test your code, use "ddd bufbomb"
again and set a breakpoint on the line right after the call to
getxs. Click on Run, and enter your string in the bottom
window when asked. Then, use "Stepi" and observe in the machine
code window whether your exploit code is executed correctly.
Keep in mind that your attack is very machine and compiler specific.
You may need to alter your string when running on a different machine
or with a different version of gcc.
Note: You can find a similar assignment (at Harvey Mudd College)
here.
You may want to read the problem description for additional hints
and details. Unlike this assignment, the one at HMC proceeds in stages.
Our assignments corresponds to stage 3 (Dynamite).
What to hand in:
Once you find a solution, print a sample session from a terminal
window that shows the string you entered and that it produces the
correct answer (you can copy and paste it into a text file). In
addition, hand in a detailed explanation of how your code works (about
1 page). Include the important values and addresses that your program
uses as well as your disassembled exploit code.
If you cannot figure out how to solve this problem, I will help
you by giving you a sequence of hints, with a 10% grade penalty per
hint. However, even with these penalties you will likely get a higher
grade than if you can't solve the problem at all. Therefore, get
started early, so you have the option of coming to office hours for help!