In the last couple of posts, We are already talking about how to develop buffer overflow and format string exploit to take control of the program execution. Those two attacks are really great to explore and both of them still persist in today's modern software
https://blog.zimperium.com/whatsapp-buffer-overflow-vulnerability-reportedly-exploited-wild/
https://www.forbes.com/sites/daveywinder/2020/02/05/cisco-confirms-5-serious-security-threats-to-tens-of-millions-of-network-devices/
BUT! what if I told you that there is another even more powerful memory corruption attack in the world of software security
Interested?
Enter the realm of the Heap Exploitation
PUN intended :)
Before getting into heap exploitation, let's talk about what is heap and when is it used?
(Keep in mind: When I'm talking about heap I'm not referring to a heap in the data structure algorithm but heap in memory allocation in OS)Basically, Heap is just a part of memory inside the program that can be allocated dynamically at runtime.
Heap is really useful for a programmer when they try to design their program but don't know how much memory they have to reserved and rather than guessing by trial and error on how much memory they need to acquire, they can just use Heap that will managed how much memory that they need in real-time
Pretty cool right? :)
But, heap doesn't have a size restriction on a variable that's why the writing and reading process is a little bit slower compared to the heap and once you allocated the memory you have the responsibility to free the memory again.
more detail can be read from this link: https://gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html
How Heap can be exploited by an attacker?
Similar to stack you need to be wise on how much memory you can be allocated in your program and because there is no size limitation when working heap, it is hard to keep track on each entry and if the programmer is not enforcing size limitation of each entry it might able to overflow other heap section (Just like buffer overflow)Also As I mentioned before once you are done with memory block that you have just reserved earlier you need to immediately free the region or it could cause a memory leak
Time to nut up or shut up
OK, I think that's enough with theory let's move on to the practical side to get more clear understanding. For this post, we are going to do Heap exploitation on heap0 and heap1 from the protostar challengeHEAP 0:

take a look at the main function, here is an example of how program can reserve heap memory. we can use malloc() function and the parameter is how big the size of the data that we want to store
d=malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
these two snipped basically tell the computer "please reserve memory for me with the size of data structure and fp structure" you can see the definition of struct of both variable at the beginning of the program
more detail on struct: https://www.studytonight.com/c/structures-in-c.php
pay attention to the next snipped code:
f -> fp = nowinner;
basically, the program assigns a value its member with the address of nowinner function and at the end of the main function, it will call this member again to call the function.
our job is to hijack the memory that was originally pointed to nowinner to winner function
lets put a breakpoint at the two malloc functions so we know how the program manage heap memory under the hood

run the program and once you hit the first breakpoint try to move on to the next instruction so the program will execute malloc and type "info proc mappings"
this will give you a list of the memory allocation in the program and from the result, we can see there is a section called heap and this where our heap data is stored
if you want to know where the location of heap memory store you can just look at the eax register using "i r" command

let's go to the memory location and see how heap managed the data

This is how the heap managed to store our data, it always separate into two side. Left side basically just told us how big is the memory we want used and the right side is the actual content of the memory. As we can see from the figure above the compiler give us 73(0x49) bytes of offset to store our memory
now let's try to find out how the second malloc is assigned into the heap memory

we can see that at the second malloc, the program first allocate memory for struct fp and then it assigned its member which is fp to hold the address of nowinner()
once you get to the second breakpoint try to step through the execution several time and look at the heap memory again

as you can see the result is still consistent with the first malloc. The left side is the size of the heap and the right is the content of the heap which is in this case is the location of nowinner() function.
as you know that the program uses an unsafe function of the infamous strcpy since the function don't have a size limitation on it we can overflow the second malloc that contains nowinner function location and change it to point to the winner() function location
cool! so know we can craft our payload
one neat trick from liveoverflow is how we can input hex value of the address to the program using bash shell
(gdb) r "`/bin/echo -ne "<68 randomstring for padding> + \x64\x84\x04\x08"`"
before we run the above command lets try to put another breakpoint at strcpy so we know for sure we got the right payload and we will define a function that each every breakpoint it will show the heap memory content
run the command that executes payload and as you can see that at the third breakpoint we are successfully take control of memory execution

you can also do this outside of the gdb

HEAP 1:

on the second challenge, we can see that the program need to be provided with two-parameter
the two-parameter use the same structure which contains variable priority and pointer name that assign with another malloc function, this eventually will store the location of the dynamic memory to the pointer name
at the end of the program, two values that we provided will be assigned using strcpy to each of the structs.
if we put a breakpoint at the end of two mallocs we can see here how the heap is managed by the program

we can see from the figure above each of the entries of the heap have the first value stored with priority variable and the second value stored the memory address that store string for *name.
if we try to overflow the value of the variable we can see that we managed to change the destination address of the second strcpy function to do that we need 20 bytes offsets

so we can deduce that first parameter is the address that we want to overwrite and the second parameter is the value that we want to assign to the destination address.
so what address we want to overwrite in the program to take control of the execution?
there is a puts function after the two strcpy function we can overwrite the GOT entry of the function and point it to the winner function

from this information, we can write our payload to be like this

there you go we successfully change the execution flow and redirect it to another function.
also, you can do it outside of the program

I make the explanation for this challenge to be concise since I want you guys to try it by yourself and the overall idea of this challenge is the same as the previous challenge
ok cheers :)
Hope you enjoy it see you next time
references:
https://www.youtube.com/watch?v=TfJrU95q1J4&t=251s
Comments
Post a Comment