Tuesday, July 29, 2014

Memory Hacks - Freeze and reload a C program - part II


"Here we come to the break"

Once in the previous post we have obtained a way to execute our program with "stable" addresses we can now enter in the real game.
In this post we are going to cover the heap part; before starting coding a quick (and incomplete) overview is (again) necessary.
What we have to know about the heap (or data segment) is that is simply a portion of memory that the operating system give us to store data dynamically.
Again using the picture above we can see where the heap is typically located in the present day. We can also observe that it grows upward.


Obviously we all know that "dynamically" means we don't know the amount of memory necessary for the execution of the program before the execution itself.
The linux kernel gives us this classical UNIX interface to tackle the problem.

#include <unistd.h>
int brk(void *addr);

void *sbrk(intptr_t increment);

A call to brk sets the new end of the data segment to the value specified in addr, and on success returns 0.
Calling sbrk is possible to increment (or to decrement) the size of the data sector of a certain value. This function returns the new pointer to the end of the data segment; if the increment is 0 it returns the current end of the heap.
For more info on this two functions obviously the man page will be more exhaustive.
It's time now for two observations:
1 the entire problem of the dynamic allocation is brilliantly solved at the interface with only two simple functions.
2 thinking on it we realize that not both are needed to solve the problem. Maybe for this reason none of the two is specified either in the C or POSIX standards but traditionally UNIX systems implement at least one. In fact  I'm just taking a look to the source of the UNIX Version 6 in the Lions' book and I find only trace of sbrk (at the time named sbreak). But the research provides me with another interesting/funny result in form of annotated comment:

/* break system call.
* -- bad planning: "break" is a dirty word in C.
*/

Luckily nobody's perfect...

Now that we have introduced the UNIX interface we can point out that in fact malloc is a function executed in user space by the standard library that effectively calls sbrk.
Instead of taking a look to the glibc implementation if you are interested in a simpler but working example of malloc implementation you can find it in the K&R. So now we have clear that all the allocators that we commonly use in the end pass trought either brk or sbrk calls. Working on the top of the operating system interface will make  our implementation agnostic on the kind of memory allocator that is used by the program (if any is used).

Ok let's go with the implementation!
First thing to do when we launch our program is to find and to store the heap address. It's very important to do this action before every allocation in the data segment. According to the interface previously this simply translate in:
heap_start = sbrk(0);
Now we need the function, that we will call before freezing our program, to save the content of the data segment to file. With our previous knowledge the implementation is pretty straightforward. 


StoreHeap simply  reads the current last address of the data segment and taking as argument the initial address, it stores the portion of memory between the two values directly onto a binary file named heap.data.

We now need the symmetric function that will load back the previously stored data.
This is a little bit more tricky... We are using fopen from stdio.h to keep our life as simple as possible, but fopen itself allocates some memory in the data segment.
We will have to:
  1. open the file
  2. store the new heap end
  3. allocate the necessary memory to load back our data
  4. write the data in memory (starting just after the portion allocated by fopen)
  5. close the file
  6. shift our heap content to the original position
  7. move the end of the data segment back in the original position.
This is basically what our load_heap is doing.


We are almost there and we miss only the main function.

Here is an example (written as simple as possible):


You will easily notice a couple of details:

#include <malloc.h>

mallopt(M_MMAP_MAX, 0);


This is because in fact the kernel linux provides a third way to allocate memory that is Anonymous Memory Mapping through mmap.

Because this is typically convenient for big portion of memory, malloc sometimes could also use that.

If (as I'm now assuming) we will be interested in using malloc, it's a good idea to instruct this not to use mmap with the code just showed.

Moreover you will have noticed that I stored the value of str directly in the code with:

str = (void*)0x602010;

I did this simply because reloading the program we will not have the correct value of the pointer in str.
Because this variable is in the stack we will learn in the next post how to restore that. For now I've simply discovered the pointer value reading the print in the first execution and I've hardcoded it in the code.

Do the same because depending on various factor this address probably will be different on your computer!
Here is the example on how to how our little library:

And here the output on my computer.



To prove that we are not doing something too illegal here is the valgrind output with no errors.


Next post stack time!

Thursday, July 10, 2014

Memory Hacks - Freeze and reload a C program - part I


Some years ago I was studying some memory topics, in summary that kind of stuff that make happy every C coder worthy of such a name...
As result I asked my self: is possible in a simple way to save "the state" of a generic C program?
It would be really nice to save the state of a program to the hard disk while it's running and reload it when needed to restart it from the saved state!
Even I think that the resulting solution is hardly  applicable in production, I  suppose it could be quite instructive for who is trying to enter in this kind of topics.
Because the main focus of this post is to build a simple example of a C program with freeze save and restart capabilities, we will only introduce some concepts in a real informal way. To the interested reader more research on these topics are left.
First we have to take a look to the classical memory layout of a C program.


Thanks to the virtual memory every program thinks to have all the memory for itself starting from address 0 to 2^64 (obviously talking about 64 bit systems).
We will see some more details later but we will focus on 3 main points:
  1. Stack: The history of the called function is in the stack (basically what you can see translated by gdb using the backtrace command while stopped in a break point). Also the values of local variables are contained there. As you can see the stack start from a really high address and "grows" downward going to the directions of the zero.
  2. Heap: In the heap (sometimes referred as data segment) is located all the memory dynamically allocated so typically the most part of our data.
  3. CPU registers: In the registers are located some values used during calculation by the processor. The register in which we are more interested in is the instruction pointer, also called program counter. In this register the address of the next instruction that the processor will execute is simply stored. Instructions (i.e. our program) are stored in the text segment area (see first figure). It's quite clear that the instruction pointer is a critical value to be saved for our purpose, because it basically holds the position of the execution of our program inside the code.
If you don't know nothing about these topics and you really want to understand what is going on your computer I strongly suggest this book ProgrammingGroundUp.
Last important point is that for simplicity we are now making the assumption to have a program without global variables (in fact, their use in general is not a good practice).
Before starting we face the first problem...
Try to compile and execute this example:


Here is a screenshot of the output on my computer.
First we can observe that, as expected, the stack variable has an address value really high. Also the main function address (that stay in the text sector) and of the memory allocated on the heap via malloc correspond to low values as expected.

But bad news!! The addresses of the memory allocated on heap and stack is always changing!
In fact only the address of the main function (that is stored in the text sector) stays stable.
The problem is pretty clear, if heap and stack do not start from the previous data addresses in memory when we will reload in memory all the data saved will have a new location shifted of a certain value. In this situation all the pointers will point to a wrong address and nothing will work.

But with bad news also good news are coming... In the lower buffer of the trusty emacs you can see the output of the same program running under gdb.
Good news is pretty evident, there the addresses are stable. Why?
The answer is Address Space Layout Randomization.
ASLR (for friends) is a technique  adopted to avoid buffer overflow attack, basically consists in randomly changing the initial address of stack and heap at every program run.
If this technique is good for security reason is not good for our purpose so we have first to disable ASLR in some way.
Luckily gdb disables ASLR to provide stable addresses during different debug sessions (a treatament that not all the debuggers will grant you...)
So to do the same has been only necessary to take a quick view to the gdb source code to extrapolate something like this:

We have now a tool that can child a process after having set the "personality" of the executable in the proper way. In this way the kernel will be informed not to adopt ASLR on the new process.

It works!
Next part following here.