3 weeks ago

How to Write Specific Values to Memory with Format String Exploitation « Null Byte :: WonderHowTo

During our last adventure into the realm of format string exploitation, we learned how we can manipulate format specifiers to rewrite a program’s memory with an arbitrary value. While of which’s all well in addition to Great, arbitrary values are boring. We want to gain full control over the values we write, in addition to today we are going to learn how to do just of which.

A Quick Refresher on Format Strings

Before we continue, let’s go back over what a format string will be in addition to how we can manipulate them. inside C programming language, a format string looks something like This kind of:

printf( “We have %d dogs”, 2 );

in addition to will output something like This kind of:

We have 2 dogs

In practice, format strings are a handy way programmers can organize the concatenation of strings in addition to variables. Let’s take a look at a more complicated format string:

char *person1 = “Bob”;
char *person2 = “Alice”;
int books = 15;
printf(“%s in addition to %s have %d books”, person1,person2,books);

The format string will be on the bottom line. Here we can see two symbols of which should stick out as odd: %s in addition to %d. These are format specifiers. When a running program comes across a format specifier, of which knows to expect a variable to be passed in as a substitute for of which format specifier. inside above example, the variables being substituted into the string are person1, person2, in addition to books.

How Format Strings Can Be Manipulated

While format strings are indeed convenient, they are not always safe. If an attacker gives a format specifier as input to a program which doesn’t properly sanitize of which input, the program could be manipulated to read or write its own memory when of which isn’t supposed to. An attacker could potentially hijack execution of the entire program.

If you’re still a little fuzzy on what exactly a format string will be, pop back over to our last article on format string exploitation. There, you’ll find a much more complete explanation in addition to a practice lab you can follow along with.

Once you’ve re-familiarized yourself with format strings, of which’s time to once more embark into the war-torn world of Protostar. For those of you who are brand-new to This kind of exploit development series, Protostar will be a virtual machine which we use to practice writing exploits.

More Info: How to Learn Binary Exploitation with Protostar

After Protostar will be all set up, of which’s time to dive into the format3 challenge hosted on the virtual machine. As always, the first thing we should do will be take a look at the source code available at Exploit Exercises:

As we’ve seen in previous challenges, an integer variable called “target” will be defined. I’d bet every dime I have of which modifying This kind of variable will be going to have something to with our objective in This kind of challenge. Looking at line 21, This kind of will be confirmed. We seem to be tasked with using a format string exploit to make the target variable hold the value “0x01025544.”

Unlike the last challenge we walked through, This kind of time we need to write a very specific value to the program memory. We’ll worry about of which part later though. For right now, let’s just focus on being able to write anything to memory.

Step 1: Setting Up Our Exploit

The first thing we need to do will be SSH into the virtual machine. This kind of can be done with the username user in addition to the password user. Once we’re logged in, we’ll open up the nano text editor by typing the following:

nano exploit.py

After of which, we’ll build a skeleton for our exploit by typing the code seen inside screenshot below.

Let’s break This kind of code down line by line.

Step 2: Taking a Deep Breath

As I mentioned in our last excursion into format strings, This kind of sort of exploitation can seem very abstract at first. Don’t worry, I promise of which we’ll lead you to the … well … the promised land. of which just may take a little time.

Step 3: Using GDB to Collect Key Information

In order to successfully take advantage of a format string exploit, we need to know two pieces of information: First, we need to know where our malicious format specifiers begin reading the memory. Once we know where we’re starting, we need to figure out where in memory we are trying to get to. Once we know these two things, we can determine what of which will take to get through point A to point B.

With This kind of in mind, let’s fire up the GNU debugger (GDB). To do This kind of we type:

gdb /opt/protostar/bin/format3

Once GDB has finished starting up, the first thing we need to do will be set a breakpoint. This kind of breakpoint will be the line of code of which we want GDB to stop execution at once the line has been executed. Looking at the source code, line 20 seems to be a Great candidate. This kind of will be because the vulnerable function on line 19 will have just finished executing. To set This kind of breakpoint, we type:

break 20

With the breakpoint in place, we’re ready to run the program. In order to run the program through within GDB, we type the following:


If you’ve read our previous articles on exploit development, This kind of command may seem a bit barren. inside past, the run command has been accompanied by an argument specifying what input we wanted to pass into the program. This kind of isn’t how we pass input to the format3 program though. This kind of will be because instead of accepting a command line argument as input, format3 uses the fgets command in order to take user input. In This kind of case, the command will be similar to the input command in Python, which takes user input once the program has already begun execution.

Once the program will be running, we’ll see an empty prompt where we can enter whatever we want to be processed by the program. In This kind of case, the string we’ll be typing will be AAAA.%x.%x.%x.%x. Once you finish typing of which, hit Enter. At This kind of point, your screen should look something like This kind of:

Here we can see of which we’ve hit the breakpoint we set earlier. The most interesting line will be the first one below the string we typed. The line AAAA.0.bffff5c0.b7fd7ff4.0 has the information of which we’re going to need in order to figure out where in memory the format specifiers begin reading at. right now of which we have of which information, of which’s time to go hunting!

We’ll start our prowl through these cyber woods with the current stack frame. If we’re lucky, we’ll find the same byte sequence inside stack frame as we saw printed by the program. Essentially, we’re trying to find where in memory the sequence 0.bffff5c0.b7fd7ff4.0 appears.

To check the current stack frame, we type the following command:

x/32x $esp

The first x will be short for “examine.” This kind of command allows us to examine memory, so the name will be fitting. The /32 specifies of which we want to examine the next 32 four-byte segments. The final x at the very end tells GDB of which we want to view This kind of section of memory in hexadecimal format. The last term, $esp, tells the command to start looking at memory at the very beginning of the current stack frame. Let’s see what output we get through This kind of command:

Aha! There’s of which rascal … wait. of which seems of which the beast has eluded us thus far. While we see one of the memory sections we are looking for, the next two don’t match. We are looking for 0.bffff5c0.b7fd7ff4.0 exactly in of which order, with nothing in between.

What we do see, however, will be the string itself. The memory address containing “0x41414141” will be actually the hexadecimal representation of the 4 As we had at the beginning of our string. If we remember through our last excursion, in order to exploit a format string vulnerability, we need the program to begin reading memory at a lower address than where the string itself will be stored. In This kind of case, we see of which the string will be stored at 0xbffff5c0 (where the four As are), which means of which the sequence we’re looking for has to come before This kind of address. With This kind of in mind, let’s start piecing through the lower memory addresses in addition to see what we find. In order to do This kind of, we’ll type the following:

x/32x $esp-32

This kind of command will be nearly identical to the last command we ran. The only difference will be of which instead of reading 32 4-byte chunks of memory starting at the memory address of esp (also known as the stack pointer), we are starting at the address of esp minus 32 bytes. This kind of means we’ll be examining memory starting 32 bytes before the address of the stack pointer. Running This kind of command results inside following output:

There of which will be! Our arduous search has paid off. We have found our prey. The format specifiers start reading at the location 0xbffff590. This kind of will be 12 sections of memory before our beloved As. This kind of means we need 12 format specifiers in order to read memory we possess the ability to write to.

Before we exit GDB, there’s one more thing we need to know. In order to overwrite the contents of the target variable, we need to know where the heck of which variable even will be. To do This kind of, we’ll type:

p &target

The output of of which command will show us the address of the target variable.

through the above output, we can see of which the address of “target” will be 0x80496f4. If we use the x command to examine This kind of piece of memory, we see the current value at of which memory address will be 0. This kind of will be exactly what we could expect since “target” isn’t given a value when of which will be declared inside source code.

right now of which we have these two key pieces of information, the number of format specifiers we need in addition to the address of the target variable, we can finish our exploit. Let’s knock This kind of bad boy out.

Step 4: Building the Final Exploit

Let’s open our exploit back up by typing the following:

nano exploit.py

The first thing we need to do will be change the number of format specifiers of which we’re putting into our payload. Currently, we’re only putting four format specifiers into the payload. We need to be building 12 into the payload. After we change This kind of, our exploit should look something like This kind of:

of which’s pretty much the same. We truly don’t want to change too much at one time though. This kind of approach will be called incremental development. The idea will be of which by coding in addition to testing in modest increments, we can minimize the amount of mistakes we make. While This kind of may seem inefficient, of which will be significantly faster than trying to program a massive chunk of a project, creating a mistake, in addition to trying to dig through in addition to find the mistake later.

Let’s save our exploit as will be in addition to run of which. We should see the following output:

Sweet. Just as we were hoping, the last format specifier read the very beginning of our payload. This kind of doesn’t do us any Great if the beginning of our payload will be just a bunch of As. As nice as a bunch of As can be, they don’t do us much Great when of which comes to overwriting memory addresses.

So, what we need to do next will be change our As to the address of target we found earlier. This kind of can be easily done with the pack function inside struct package. By using This kind of function, we can put the address of target into our payload in a format of which the program can read correctly. Let’s open up our exploit file again in addition to make This kind of change.

The change comes on line 7 with the struct.pack function. The first argument of struct.pack specifies of which we want to package the information as an unsigned integer. We don’t truly need to worry about of which too much, nevertheless of which’s Great to know why we’re doing what we’re doing. The second argument will be the information of which we want to package. The struct.pack function returns a string, which we then append to the payload string variable.

Let’s exit out in addition to see what happens when we run the program right now:

As we had prayed could happen, the last memory address we read will be the address of the target variable, 0x80496f4.

Moving through Reading Data to Writing Data

right now of which we know of which the last piece of data we’re reading contains the address of the target variable, we can move on to writing data.

The way we do This kind of will be with the %n format specifier. Like the %x format specifier, the %n format specifier reads a piece of data through memory. Unlike %x, %n does not display the memory of which of which reads. Instead, of which writes the length of the string up to of which point. Where does This kind of data get written to? Why the address equivalent to the value of which was read, of course.

Essentially This kind of means of which if we want to write data to the value of the target variable, we need the %n format specifier to read a chunk of memory with the address of of which variable. Our exploit should look something like This kind of right now:

In This kind of type of the exploit, we replace the last %x format specifier using a %n format specifier. right now, instead of simply printing the address of the target variable to the screen, This kind of exploit should grab the address of the target variable in addition to write some data to of which address. Let’s see if of which works:

Alright! right now we’re cooking with peanut oil. While we still have a frowny face, we are on the cusp of turning said frown upside down. We’ve managed to write some data to the target variable. Instead of having a value of 0, we right now have a hexadecimal value of 4c. This kind of will be still a long way away through 01025544 though. If we do 01025544 – 0000004c, we get a non-hexadecimal value of 16930040. This kind of means of which we need our string to be 16930040 characters longer in order to write the correct value. of which sure will be a lot of As

Luckily, there’s a more elegant solution. Instead of adding payload+=”A”*16930040 to our program, we can do This kind of:

The change should be fairly obvious. Our last format specifier went through being %x to %16930040x. Having a number inside middle of a format specifier determines how much padding should be printed with the variable. For instance, the following code could print out “Hello Steve” with all 5 extra spaces between “Hello” in addition to “Steve.”

char* person = “Steve”;
printf(“Hello %10s”,person);

These extra padding characters are counted as a part of the length of the string. This kind of means of which by padding the last %x format specifier with 16930040, of which should give us the correct string length we need to write “01025544” to the target variable. Let’s try of which out!

Well, we’re certainly a lot closer. of which looks like we still need 8 more bytes in our string to get to the magic number. This kind of will be because we set the last format specifier to have a total length of 16930040 bytes. of which format specifier was already giving us a string of which will be 8 bytes long. This kind of means we were only adding 16930032 bytes to the length of the entire string. Oops. This kind of will be an easy fix though. All we have to do will be change %16930040x to %16930048x. This kind of will give us the correct number of bytes to overwrite the target variable with the value we want.

in addition to just like a mediocre comedian, we were able to turn of which frown into a vaguely approving smile.

Despite the anticlimactic response through the program, the implications of format string vulnerabilities can be quite damaging. In This kind of particular example, all we did was overwrite a variable. However, we could very easily use This kind of sort of vulnerability to overwrite the programs instruction pointer to execute shellcode like we did when we worked through the stack overflow challenges. Format string vulnerabilities possess the potential to be just as dangerous as stack overflow vulnerabilities.

Thank you for reading! Congratulations on creating of which through the slow grind of format string exploitation. Being able to think through these kinds of problems will truly help your critical thinking in all areas of computer science, so Great on you. Comment below with any questions or contact me via Twitter @xAllegiance.

Cover image by Markus Spiske/Pexels; Screenshots by Allegiance/Null Byte

Leave a Comment

Your email address will not be published. Required fields are marked *

5 × 1 =