For the past couple of months you guys see me doing lot of buffer overflow exploitation in Linux and Windows but buffer overflow itself is not the only approach in memory corruption attack. There are other techniques such as format string and heap overflow method
But today we are going to focus on Format String attack.
So what is it ?
Format string attack is an attack that are taking an advantage on how the print function work in C.
you guys already know some of them such as printf, sprintf and so on my point is any function from print family
typically you use print function like this:
void main(){
int a = 10;
printf("%d\n",a) ;
}
notice that we parse a string format which is %d, that represent an integer so this telling the program to show the output of the program from variable a.
But things to get little funny when we create program like this:
void main() {
char buffer[512];
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
}
so whats wrong with this snipped code? we reserve the buffer to be in the correct length, thus we just avoid buffer overflow and after that we print it to the console.
can you guess?
yes! the printf function is the problem we don't specify the format string and let user take control on what they want to print
printf work by using the format string as the reference to the variable that was passed so with this the printf itself know what value that need to be showed
but if we don't specify the format string in the function and let user take control of the input they can just supply another format string that will leaked the stack
like this
notice here there are bunch of hex characters and all of it actually coming from the stack.
cool! right? using Format string attack we are able to dump the stack value, but hold on dumping the stack will not do much of a exploitation right ?
I agree but there much more than meets the eye. The truth is format string can be leverage into RCE
how ?
we will cover this in the next chapter, this post used to show you some capability that how format string can be utilized to be more rather than just showing stack
Before you go further, I suggest you guys study the basic of format string exploitation from protostar or other blog since the next part demand you to have at least a little bit knowledge of format string exploitation.
Also to all of you who already been around in security might notice that format string is already long gone and might not be necessary to learn about it. But once again we should never close our eyes with every possibility since the exploitation might arise again.
https://www.helpnetsecurity.com/2019/07/22/cve-2019-1579-poc/
https://blogs.grammatech.com/tainted-data-and-format-string-attack-strike-again
So let's get into the interesting stuff:
note: you can get the code at protostar format 3 challenge
compile the following piece of code with this command:
~# gcc format_func.c -o format_func -m32 -no-pie
as you guys already know this following piece of code is contain vulnerable printf implementation we can pass some string format in the buffer and leaked according stack value to our input
in the first phase of format string attack we need to know the location of our input in the stack
use the following piece of code to determine at what location in the stack that our input is held on. The code itself is pretty straight forward, we loop until 30 iteration and enter a format string then see the result that fit our goal. Notice the symbol "$" before the "x" this is meant we are going to use direct parameter access so we don't have to type multiple "%x %x %x" every time
cool :) so our input is at the 15 iteration of the loop so by the information we can confirm it by doing it manually.
so what's next ?
as you guys know from the code, it is expect us to modify the variable target inside the binary with the value 0x01025544
we are going to use the capability of format string to edit the value in runtime.
How ?
we going to approach this task by using the format string "%n" this format let us to write an integer value of number of bytes written so far to the stack
but doing this task could take up your time if the value is too big. To be more effective we can utilizes what so called "short writes"(%hn) that allow us to write 2 bytes at a certain location
let me show you the example in this following code
part 1, first we assign some variable that hold important information to our exploitation. at the beginning we can see that there are two variable first is target_location and target_location_higher this is the location of target variable that we must change in the program. You can get it by typing:
~# p &target
now as I explained earlier that short write only able let us to write two bytes so we need to initialize the location of target variable along with the next two bytes so we can fully write the variable
then we set value of the offset we got earlier which is 15 and the value that we want to insert at the variable "target"
part 2, concatenate the two variable that contain target variable so when we hit the offset the "%hn" can reference the location at write it at the stack
part 3, here where get it get interesting
as I mentioned again that the short write only let us to write two bytes we need to divide the value 0x01025544 into two pieces.
you can do it by little bit of math, but I think this algorithm is more flexible
lower_addr = target_value & 0xFFFF
high_addr = target_value >> 16
so we divide 0x01025544 into two variable one is going to held the lower address which is 5544 and the high address which is 0102
once we got the two variable we are going to concatenate it with the buf variable
buf += "%" + str((lower_addr - len(buf)) & 0xFFFF ) + "p%" + str(offset) + "$hn"
buf += "%" + str((high_addr - lower_addr) & 0xFFFF) + "p%" + str(offset+1) + "$hn"
but before we can concatenate it with the buf variable we need to adjust the value since the buf variable already have value of location of "target" variable
so if we passed the value like this
buf += "%" + str(lower_addr ) + "p%" + str(offset) + "$hn"
it will be 0x0804c02c0804c02e%21828p%15$hn
this will write 21828 + 8 since the "%n" will write number of bytes written so far in order to make it right we need to subtract it with the buf variable length first and this concept also apply to the second short write that will contain the higher address we need to subtract it again with the lower address to adjust the write value.
the last is just invoke the binary and passed our payload to it.
run the following script with:
~# python exploit.py LOCAL DEBUG
cool so we just change the value of variable
hope you enjoy this and see you at the next post.
Comments
Post a Comment