Introduction To GNU Heap Exploitation¶
Dynamic Memory - An Overview¶
Why Use It?¶
Reasons and Advantage of allocating memory dynamically:
- When we do not know how much amount of memory would be needed for the program beforehand.
- We can allocate dynamic local variable but its scope limited to the function call. Memory allocated with Dynamic Allocation is global memory and is not limited to the function call.
- For dynamically growing data structure.
Using Dynamic Memory¶
In C, stdlib.h
provides with standard library functions to access, modify and manage dynamic memory. Commonly used functions include malloc
, free
and realloc
.
- Malloc
malloc(size_t n)
returns a pointer to a newly allocated chunk of at least nbytes
, or null if no space is available.
If n is zero, malloc returns a minimum-sized chunk. (The minimum size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit systems.).
There's a safer version of malloc which is calloc(size_t nmemb, size_t size)
, the only major difference between malloc and calloc is that calloc sets the memory zero
before returning the allocated chunk.
- Free
free(void* p)
Releases the chunk of memory pointed to by p, that had been previously allocated using malloc or a related routine such as realloc. It has no effect if p is null. It can have devastating effects if p has already been freed [Double Free].
- Realloc
realloc(void *ptr, size_t size)
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. Contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes.
- If the new size is larger than the old size,the added memory will not be initialized.
- If ptr is NULL, then the call is equivalent to
malloc(size)
. - For all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to
free(ptr)
.
Note - Internally, these functions(malloc,realloc and calloc) use two system calls sbrk
and mmap
to request and release heap memory from the operating system.
Behaviour of Free Chunks¶
When we free a chunk of size less than 0x80, glibc uses a singly linked list
to organize each of the freed chunks, and each bin adopts the LIFO
policy, and the recently released chunk will be allocated earlier.
Why The LIFO Policy¶
The LIFO policy is applied due to the fact that Access latency
can be avoided by reusing the data fetched previously. This reduction in access latency is what is termed as Locality Of Reference
which is a term for the phenomenon in which the same values, or related storage locations, are frequently, depending on the memory access pattern.
In case of small size chunks , the concept of Locality Of Reference is better re-enforced due to the fact that generally, programmers may repeated allocated and free fairly small amount of memory to work with, and when small size memory chunks are freed, they can cause External fragmentation
in case they are not handled properly.
Classes Of Heap Memory Bugs¶
Used And Abused: The Infamous Use After Free¶
Basically, UAF happens when the program tries to access a portion of memory after it has been freed that may force the program to crash and based on the flow of the program you might get arbitrary code execution.
Consider the following situations:
-
Memory block released -> pointer=NULL (safe) -> used again -> program crashes (why?).
-
Memory block released -> pointer!=NULL (unsafe) -> no code to modify the free block -> program is likely to work properly.
And now comes the important scenario.
- Memory block is released -> pointer!=NULL, but before it is used next time, there is code to modify the memory, then when the program tries to use the freed memory again, it can lead to serious Security breaches(how?).
Let us try to understand with a simple program how UAF can happen due to simple programming aberrations and how it can be leveraged to attacker's needs.
#include <stdio.h>
#include <stdlib.h>
typedef struct name {
char *myname;
void (*func)(char *str);
} NAME;
void myprint(char *str)
{
printf("%s\n", str);
}
void Malicious(char *str)
{
system(str);
}
int main() {
NAME *a;
a = (NAME *)malloc(sizeof(struct name));
a->func = myprint;
a->myname = "I can also use it";
a->func("this is my function");
// Free without Nulling out a
free(a);
a->func("I can also use it");
// free with modify
a->func = Malicious;
a->func("/bin/sh");
}
As you can see, in the above program, with the help of Use After Free, we could do 2 major things.
- We overwrote the function argument and thus we could leverage memory leaks.
- We overwrote a function pointer and made it point to
system('/bin/sh')
landing us to a bash shell which is devasting if we can get shell on server.
So, with UAF, you can leverage a lot of control over the functionality of a program -
- Pointer dereference leading to arbitrary
write-what-where
primitive. - Leaking memory to defeat memory address randomisation (ASLR).
- Overwrite pointer dereferences to functions as we saw above.
And... a lot more, only limited by creativity and imagination.
A Little More You Can Do¶
To get your hands dirty with exploiting UAF, you can play around with this code,
//test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *name = 0;
char *pass = 0;
while(1)
{
if(name) printf("name address: %x\nname: %s\n",name,name);
if(pass) printf("pass address: %x\npass: %s\n",pass,pass);
printf("1: Username\n");
printf("2: Password\n");
printf("3: Reset\n");
printf("4: Login\n");
printf("5: Exit\n");
printf("Selection? ");
int num = 0;
scanf("%d", &num);
switch(num)
{
case 1:
name = malloc(255*sizeof(char));
printf("Insert Username: ");
scanf("%254s", name);
if(strcmp(name,"root") == 0)
{
printf("root not allowed.\n");
strcpy(name,"");
}
break;
case 2:
pass = malloc(255*sizeof(char));
printf("Insert Password: ");
scanf("%254s", pass);
break;
case 3:
free(name);
free(pass);
break;
case 4:
if(strcmp(name,"root") == 0)
{
printf("You just used after free!\n");
exit(0);
}
break;
case 5:
exit(0);
}
}
}
Compile it with gcc -no-pie -o test test.c
.
Apart from this, you can also try out the challenge HackNote
from Pwnable.tw.