Miguel.G
Miguel.G

Reputation: 387

Address space layout randomization and structures in C

I have this structure:

struct Books {
 char  title[50];
 char  author[50];
};

Let's say that I know that if I pass arg1 to the program, in some part of the code, it adds some chars in the direction $title+52, so the author value is overwritten (buffer overflow).

Now I add ASLR to my binary. By this way, some directions are random, so I think the buffer overflow that I described before could not be possible.

Is this true? Or even if I add ASLR the directions of struct members are together and buffer overflow could be possible?

Upvotes: 3

Views: 1634

Answers (3)

Marco Bonelli
Marco Bonelli

Reputation: 69276

I think you are misunderstanding the effects of ASLR (Address Space Layout Randomization): ASLR randomly arranges the positions of different virtual memory areas of a process (executable, stack, heap, data, libraries, etc) to be different in every execution. It does not change the relative position of elements in the same virtual memory area.


Take for example the following simple program:

int main(void) {
    struct {
        char a[10];
        char b[10];
    } myvar;

    printf("a: %p\n", &myvar.a);
    printf("b: %p\n", &myvar.b);

    return 0;
}

Here's the program's virtual memory with ASLR disabled:

0x555555554000     0x555555555000 r-xp     1000 0      /home/marco/test/test [executable segment]
0x555555754000     0x555555755000 r--p     1000 0      /home/marco/test/test [read only data]
0x555555755000     0x555555756000 rw-p     1000 1000   /home/marco/test/test [bss (global variables)]
0x7ffffffde000     0x7ffffffff000 rw-p    21000 0      [stack] <-- myvar is here

Output (ASLR disabled):

$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a

And here's the same program with ASLR enabled:

0x559fefcbe000     0x559fefcbf000 r-xp     1000 0      /home/marco/test/test [executable segment]
0x559fefebe000     0x559fefebf000 r--p     1000 0      /home/marco/test/test [read only data]
0x559fefebf000     0x559fefec0000 rw-p     1000 1000   /home/marco/test/test [bss (global variables)]
0x7ffe3bb5e000     0x7ffe3bb7f000 rw-p    21000 0      [stack] <-- myvar is here

Output (ASLR enabled):

$ ./test
a: 0x7ffe3bb5e080
b: 0x7ffe3bb5e08a
$ ./test 
a: 0x7ff4abdeea80
b: 0x7ff4abdeea8a
$ ./test 
a: 0x7efa6b8fa080
b: 0x7efa6b8fa08a

Your variable is still going to be inside a certain contiguous block of virtual memory, and the relative position of the fields will not change at all. Contiguous arrays will still be contiguous using ASLR: they will just start at a different position in memory.

Since struct fields are by standard contiguous in memory (and follow their declaration order), this means that buffer overflow will still be a potential problem, even when using ASLR.

Upvotes: 2

dbush
dbush

Reputation: 223689

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.

Upvotes: 5

ASLR does not affect stuff that is compile-time. The compiler chooses the layout of the structure at the time of compilation and this is hardcoded in the resulting object code.

Furthermore, the C standard requires that successive struct members are laid out in memory in the order they appear in the struct definition (with unspecified padding in between members, but this too is fixed at the compilation time)

Upvotes: 2

Related Questions