UAF
Trying to pass CET-6 and get used to using English in daily life (Nu1l ‘s Write up looks so cool.)
If this make it inconvenient for you to read this article, please use translation tools of browsers.
Principle
The main cause of the vulnerability is free the pointer without setting it to NULL after being freed. This kind of memory pointer that was not set to NULL after being freed is often called dangling pointer.
Using dangling pointer will cause following 3 situations:
- Crash
- If the chunk it point to hasn’t been changed before it is used next time, then the program is likely to work properly.
- If the chunk it point to has been changed before it is used next time, then the program is likely to work weirdly.
Leak Main arena
We can see that if the length we enter is between 16 Bytes and 64 Bytes, the chunk will be sorted into fastbin at first after being freed. But the chunks of which size is bigger than max_fast
or free chunks in fastbin
will be sort into unsorted bin after being integrated. While the fastbin is empty, the pointer fd
and bk
of unsortedbin point to the itself and the bin is in the main arena so we can get the address of main arena. After UAF, we can get the real address of main_arena, to get the real address of the libc.
So what’s the relation of the address of unsorted bin and main arena?q
in 64-bit the offset is
0x58
in 32-bit the offset is
0x30
After getting the real address of main arena, we can get the real address of libc.
In 32-bit, main_arena equals __malloc_hook + 0x10
fd & bk in unsorted bin often points to <main_arena+88 >
In 32-bit, main_arena equals __malloc_hook + 0x18
fd & bk in unsorted bin often points to <main_arena+48 >
address of __malloc_hook can be find in libc(drag it into IDA Pro)
Example
Let’s take freenote
as an example.
As we are talking about UAF, we won’t solve the problem in this part. Instead, we will just try to leak the address of the Main Arena.
Reverse Analysis
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked.
libc: libc-2.23.so
1 | Arch: amd64-64-little |
Canary and NX are enabled.
Use IDA to decompile the file.
Main logical structure :
1 | while ( 1 ) |
1 | int New() |
start_note’s address is 0x006020A8, we can use gdb to see what’s in it.
We can see the structure of the start_note, it’s a table recording data of notes
1 | gdb-peda$ x/30wx *0x06020A8 |
So we can know that the struct of node_note is
1 | struct node_note |
Let’s take a look at the function Delete()
1 | int Delete() |
We can see that the pointer hasn’t been set as NULL after the content it points being freed, so it becomes a dangling pointer. Perhaps there exist double free vulnerability. (Of course it’s double free, after all we are talking about double free.)
Since the ‘\n’ take 1 byte, we can only enter (Length-1) characters.
GDB debugging
- Create 2 notes. In order to leak main arena, we’re supposed to ensure the length of note is small so that it will be sorted into fastbin at first and then integrated into unsortedbin.
1 | == 0ops Free Note == |
1 | gdb-peda$ x/wx 0x006020A8 |
0x00603010 is the real memory block storing the data of notes, so let’s take a look at it.
1 | gdb-peda$ x/30wx 0x00603010 |
We can resort it to make it easy for us to see the structure.
1 | 0x00000100 0x00000000 0x00000002 ;head of note |
1 | gdb-peda$ x/2wx 0x00604830 |
- Free the first note.
1 | Your choice: 4 |
1 | gdb-peda$ x/20wx 0x00603010 |
we can see that the number of notes has been changed to 1 and the if_active
and len
have been set to 0. However, the pointer still exist. Let’ see what is in it.
1 | gdb-peda$ x/4wx 0x604830 |
since its Arch is amd64-64-little, fd
is actually 0x7ffff7dd1b78
1 | gdb-peda$ x/10wx 0x7ffff7dd1b78 |
0x7ffff7dd1b78 - 0x58 == 0x7ffff7dd1b20
1 | gdb-peda$ x/16wx 0x7ffff7dd1b20-0x20 |
It works.
the address of __malloc_hook just work as a toolman: help us find the main_arena
In IDA we can see that the offset of main_arena is 0x003C2740
In IDA, we can see the offset of main_arena is 0x3C4B20
0x7ffff7dd1b20 - 0x3C4B20 == 0x7ffff7a0d000
It seems like we get the real address of the libc_base, let’s check it.
1 | gdb-peda$ vmmap |
That’ true! We get the real address of the libc base.