In this video, we'll take on our first vulnerable binary and we're going to use it to learn how our first
heap exploitation technique known as the House of Force.
It was first documented in 2005 in a paper titled The Malloc Maleficarum, which was considered
the GLIBC heap exploitation bible for some time.
The author, who goes by the handle, Phantasmal Phantasmagoria, developed five generic heap exploitation
techniques that they named the houses of Prime, Mind, Force, Lore and Spirit.
Since then, many techniques have followed the same "house of" naming convention.
So let's dive straight into the House of Force.
If you're not still in the house_of_force directory, navigate back there now. Our first vulnerable binary
is the one named, fittingly, house_of_force.
It's a small CTF-style binary written in C. It has a heap bug against which we're going to leverage
the House of Force technique.
Whenever we encounter a vulnerable binary, we can learn about its security stance with the checksec feature
installed with pwntools. This binary is 64 bit, as are all of our vulnerable binaries.
It's compiled with Full RELRO, which again is the case with all these binaries, partial RELRO is an exploit
mitigation that changes a program's section, layout in memory and full RELRO also maps some of those
sections as read-only after initialization.
Since our exploitation attempts focus primarily on GLIBC rather than the individual binaries, this
won't be an issue for us. This binary was also compiled with NX, also known as DEP, amongst
other names.
This is the case for all our binaries except one. NX is another
exploit mitigation that enforces whether
pages of memory can be treated as executable code.
PIE stands for position independent executable, this binary is not position independent, which
means at runtime we'll know its address.
This is just so that we have a static location where we can target our arbitrary writes.
The binary's otherwise subject to ASLR or address space layout randomisation, meaning that its stack
and libraries will be loaded at random addresses.
The challenge binaries, however, are all position independent.
Lastly, a runpath value like this would normally be a security concern because it means that this binary
will go searching for important libraries like GLIBC in a directory that the user controls.
All our binaries have a modified run path because it's the easiest way to link them against different
versions of GLIBC.
A non-standard runpath is not something required for heap exploitation.
Let's familiarize ourselves with the vulnerable binary, loading it into GDB with the command 'gdb house_
of_force' will allow us to inspect the process's heap at runtime. We'll run the binary without setting
any breakpoints with the 'run' command.
The program displays its title followed by two addresses.
The first is the address of the puts() function within GLIBC, from which we can extrapolate GLIBC's load address.
The second is the start address of this process's first heap.
So much for ASLR.
Leaking both heap and GLIBC addresses is possible via heap corruption and rest assured that at least one
of our challenge binaries won't be so forthcoming.
However, when learning a new technique, the vulnerable binaries will leak any addresses we need so
that we can focus on the technique at hand.
Below the leaked addresses is a numbered menu. Option one allows us to request up to four chunks of heap memory
via the malloc() function. We're prompted for the amount of memory that we want.
I'm going to request 24 bytes.
Then we're asked for any data
we want to write into that memory.
I'll send some capital
Ys.
There's no pretense that these binaries are anything more than a direct interface with malloc.
It allows us to learn the techniques without getting bogged down by peripheral functionality.
Just remember that getting malloc to do exactly what we want is often not as simple in a production
environment.
Now that this process has a heap, let's take a look at what state it's in. You can break in GDB with
ctrl + c, then visualize the heap like we did before with the 'vis' command.
If you need a reminder about which pwndbg commands are available, you can type 'pwndbg' to list all
available commands or follow it with a search term.
We can see that this heap starts at address 0x603000. When a process is started under GDB
ASLR is disabled,
so this will always start here
when we debug like this. As expected, malloc has allocated a 0x20-sized chunk with 24
bytes of user data to fulfill our request for 24 bytes.
The same size chunk would have been allocated had I requested anywhere between zero and 24 bytes.
We can see that the program has written the data
we sent it into this chunk starting at the beginning of its user data, 4 capital Ys and a new line
represented by their character codes in hexadecimal here.
So this program lets us request arbitrarily sized chunks of heap memory and fill them with data.
Let's explore the rest of this binary by issuing the 'continue' command, which can be shortened to 'c'.
At this point, we can hit return and the program will print its menu again.
Option 2 prints the target, I mentioned that the first thing we would do after learning a heap exploitation
technique was turn it into an arbitrary write primitive.
And our objective is to use that primitive to overwrite the target data, which is a short string of
capital Xs that reside in this binary's data section.
You'll recall that this binary is non-position-independent
so we always know the address of the target data.
We can check on the target in memory by breaking with ctrl + c, then issuing the 'dq' or dump quad
word command, which shows us those capital X's represented by these 0x58 bytes at address
0x602010.
Option two is just a quick way to check if we've successfully overwritten the target.
If you're ever unsure of which mapping a specific address resides at the 'xinfo' command can help. Used
here to confirm that the target data is indeed part of this binary's data section.
'continue', followed by return, shows us that the third option just quits the binary.
So once this video ends, familiarize yourself with the vulnerable house_of_force binary and see if
you can find the bug.
There's no need to go digging through the assembly,
this is not a reverse engineering course.
You could try, for example, using option 1 to request some heap memory, then send the program
more data than it's expecting.
Once you're comfortable with how the binary works, join me in the next video where I'll explain this
program's bug, then we'll exploit it together.