Aslr and Addresses

what is Address space layout randomization

ASLR is a technique designed to make various types of buffer overruns more difficult to exploit, by moving segments around a bit. The stack could be shifted a few bytes (or pages), the sections of your program (and even the libraries your code uses) can be loaded at different addresses, etc.

Buffer overflows usually work by tricking the CPU into running code at a certain address (often on the stack). ASLR complicates that by making the address harder to predict, since it can change each and every time the program runs. So often, instead of running arbitrary code, the program will just crash. This is obviously a bad thing, but not as bad as if some random joker were allowed to take control of your server.

A very simple, crude form of ASLR can actually be implemented without any help from the OS, by simply subtracting some small amount from the stack pointer. (It's a little tricky to do in higher-level languages, but somewhat simpler in C -- and downright trivial in ASM.) That'll only protect against overflows that use the stack, though. The OS is more helpful; it can change all sorts of stuff if it feels like. It depends on your OS as to how much it does, though.

ASLR and addresses

ASLR happens mostly at mmap(2) time. The stack segment of the main thread is allocated at execve(2) time (of your program) -but may be "randomly" located. The initial stack pointer of your main also depends on various factors (notably your environment - see environ(7)).

The stack pointer is set at execve time. It is passed to the crt0.o startup object file (which calls your main) by conventions defined in e.g. the x86-64 ABI specifications.

The address of main is fixed inside the ELF executable file. Unless your code is position independent code (i.e. compiled with -fPIE or -fPIC etc...), it cannot be moved (because that would require specific relocation). Use objdump -f badnack on your badnack executable to find out. Also pmap on your process. And PIC has a small cost (It uses more registers).

How ASLR randomizes address space in Linux

Fedora/CentOS/Redhat and presumably other distros are configured to build with -no-pie (Position Independent Executables) by default, which prevents ASLR of the executable itself.

You can explicitly enable it with -pie:

gcc -pie app.c -o app && ./app

Address space layout randomization and structures in C

The specific overflow you mentioned is still possible.

With the exception of bitfields, the fields of a structure follow one another in order in memory (with some possible padding in between). This is detailed in section 6.7.2.1p15 of the C standard:

Within a structure object, the non-bit-field members and the
units in which bit-fields reside have addresses that increase in
the order in which they are declared.
A pointer to a structure
object, suitably converted, points to its initial member (or
if that member is a bit-field, then to the unit in which it
resides), and vice versa. There may be unnamed padding within
a structure object, but not at its beginning.

So in this case the author field will always follow the title field, regardless of what specific address an object of type struct Books is located at. The only possible difference could be the amount of padding, but unless you add or remove fields in the struct this probably won't change.

Using ASLR To Get Random Anonmous Mapping Address

Using this slightly modified version of my test code above :

void main(int argc, char *argv[])                                                                      
{
if (argc < 2) return;
int iter = strtol(argv[1], NULL, 10);
for(int i = 0; i < iter; i++) {
char *x = (char *)mmap(0, 1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
printf("stack=%p mmap=%p\n", main, x);
munmap(x, 1000);
}
}

And running the test for 4 iterations I get the same address:

$ ./rndmap 3  
stack=0x5623b6ff3830 mmap=0x7fe8a29b7000
stack=0x5623b6ff3830 mmap=0x7fe8a29b7000
stack=0x5623b6ff3830 mmap=0x7fe8a29b7000

Which was my original question - Why are the mapping not at random addresses. I answered my own question by running the test several times with one iteration (./rndmap 1), here are the results:

stack=0x559714ce7830 mmap=0x7f6956ac9000    
stack=0x55b74b293830 mmap=0x7faafb7c0000
stack=0x564665b22830 mmap=0x7f56baf12000

One can thus conclude that ASLR in linux, in part, is responsible for randomizing the heap base address, not the individual memory maps. Which is why the address changes every time the binary is run, and for every mmap() we get the same randomized base address.



Related Topics



Leave a reply



Submit