If we must choose a particularly damaging vulnerability, it would most likely be arbitrary code execution, and even more so if it can be exploited remotely. In the previous blog entry we introduced the issues that can be caused by a poorly managed memory. Now we are going to see concrete examples.
Double Free: A Basic Example
This issue occurs when we free the same block of reserved memory twice. Let’s take a look at a program that does it “properly”:
We reserve two blocks, copy a string into them and free them as we no longer need them (note the calls for ‘free’). Let’s see the execution:
All right, now we are going to deliberately make a slip. We are going to free the block that we had already freed. This does not prove the vulnerability itself (which is more complex to exploit) but allow us to check out what happens when we get it wrong in the dynamic memory structures of the heap.
Let’s run and see what happens:
As we can see, the second string was not printed on the terminal, as it was in the previous program. What happened?
By freeing a block of heap, this space has been left free. We have required another space for the variable p2 and we have been assigned another block. But remember that even though p1 has been freed, it still points to its original block, now belonging to p2.
Since we are freeing p a second time, what we are actually doing is freeing memory that is using another pointer not related to the p object. The use of p2 becomes unstable since we are using a region of memory already freed. Let’s see how the memory addresses were made:
As we can see, p2 takes the address of the block that already had p, but this one has been freed. Let’s see the same situation, but freeing the two blocks at the end of the function:
If the situation is well managed, both point to different blocks, resources are not freed at the wrong time and everything goes as planned.
Again: Manual memory management is complex, very complex. Attention must be paid to the order of operations, where resources are obtained and where we stop using them in order to free them in good condition.
In the next entry we will talk about dangling pointers.
Don’t miss the first part of this post here: