Format Strings

Format string attacks exploit badly-written printf(3) type statements. If the user can control the format string in the printf, she can read information from the program, and reset the value of variables.

Build-Up

First, disable ASLR. The easiest way to do this is to just turn it off for everything:

echo 0 > /proc/sys/kernel/randomize_va_space

You will need to do this as root. If you only want to do it for a specific program prog, running that program this way also works:

setarch linux32 -R ./prog

You do not need to be root, but you do need to run the program as above.

Now on to the format strings!

Basic Formatting

The first program, format_errors.c, lets you enter a format string as the first argument. Try “"Hello, world!""” and see what you get. Then try “""%08x"”, “"%08x."%08x"”, and so forth (with enough of them, you’ll eventually get a segmentation fault). With these, you will see what is on the stack.

The second program, format_n.c, shows you how %n works. This allows you to store numbers in variables so you can see how much you have printed. The program scanf_n.c prompts you for a number, and prints both the number and the number of digits you typed.

The fourth program, format_fun_num.c, shows you how different formatting strings affect the output. Of particular note is the way to control the width of the output.

Exploiting Format Strings

First, let’s look at printing things from the stack. The program format_stack.c. Use the “"%08x"” trick we used in the first program to print what is on the stack. When you see the cafefeed and deadbeef in the output, you will know the next one is the address of the string. You can then print it.

Next, let’ look at doing a jump to a routine — a return-to-libc style attack. For this, we’ll use format_overflow.c. Notice that the first sprintf in the function vuln cannot overflow. Although you can give it a str that is much longer than the size of buffer, the format string truncates it after 400 characters, and that plus the other text in the format string are less than the size of buffer.

But the second one can, and that is what you are to exploit. Proceed as in the exercise on buffer overflows to get the address of the function you want to call (bad or good, your choice). Then figure out where the return address is on the stack using the “"%08x"” trick we looked at in the first program here, and finally use a format string to overwrite it with the return address you want.

Finally, let’s alter a variable. Look at format_vuln.c. The key here is that we can control one of the arguments to the printf’s format string in the “Wrong” part. The variable of interest is “test_val”.


Here is a detailed script working through this. I strongly recommend doing it yourself, and using this only if you feel hopelessly stuck.

Credit: these are adapted from Unit 6, Format String Attacks, by Prof. Adam Aviv.


ECS 198, Preparation for Capture-the-Flag via Exploits
Fall Quarter 2018