3

ASLR randomizes the addresses of the process executable code, stack, heap and libraries. This is to make the life of an attacker difficult as they cannot hardcode addresses in the code across multiple instantiations.

But how does this help with system libraries? They are never unloaded. Every process uses libc, for example, and so the address of prinf never changes. How is this helping if I am hardcoding the address of printf? This does not change unless the machine reboots.

I do have ASLR enabled --

# cat /proc/sys/kernel/randomize_va_space 
2

Here is some sample code --

unsigned long getEBP ( void )
{
    asm("movl %ebp, %eax");
}

int main(void)
{
    int (*p)(const char*, ...) = &printf;
    printf("printf address = %p \n", p);
    (*p)("printf address = %p\n", &printf);
    printf ("EBP:%x\n" ,getEBP ());
}

And the output across multiple runs --

# ./a.out 
  printf address = 0x4003c0 
  printf address = 0x4003c0 
  EBP:6a71d300

# ./a.out 
  printf address = 0x4003c0 
  printf address = 0x4003c0 
  EBP:93e5c100

See the EBP is changing as it should but not the address of printf.

What am I missing?

EDIT: Compiling with -fPIC did not help on my RHEL VM.

# ./a.out 
  printf address = 0x3047a4f0f0 
  printf address = 0x3047a4f0f0 
  EBP:7aaac900

# ./a.out 
  printf address = 0x3047a4f0f0 
  printf address = 0x3047a4f0f0
  EBP:632eca20

If the libc calls are in fact randomized as the reply says below, how is it implemented? libc itself is not reloaded, so the actual address of printf is not changing, how can it be randomized?

2

Update:

see https://stackoverflow.com/questions/24984955/why-arent-glibcs-function-addresses-randomized-when-aslr-is-enabled

Compile the binary using -fPIE or -fPIC -pie -fPIE:

https://stackoverflow.com/questions/2463150/fpie-position-independent-executable-option-gcc-ld

Binary compiled with default flags:

user01@user01 ~/test $ ./test_ASLR 
printf address = 0x400420 
printf address = 0x400420
EBP:9af703c0
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x400420 
printf address = 0x400420
EBP:8411e900
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x400420 
printf address = 0x400420
EBP:28f8e50

Binary compiled with -pie -fPIE flags:

user01@user01 ~/test $ ./test_ASLR 
printf address = 0x7f8227963340 
printf address = 0x7f8227963340
EBP:19e01ad0
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x7fecb2baa340 
printf address = 0x7fecb2baa340
EBP:9c8148e0
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x7f5d00edb340 
printf address = 0x7f5d00edb340
EBP:32b3c6d0
  • That did not work on my VM. I get the same value every time. Also, why would the EBP change in case the -fPIC is not used? – stflow Jan 2 '18 at 20:32
  • Compile with -fPIE – julian Jan 2 '18 at 20:35
  • No difference. I see the same value as the one compiled with -fPIC – stflow Jan 2 '18 at 20:37
  • If the libc calls are in fact randomized, how is it implemented? libc itself is not reloaded, so the actual address of printf is not changing, how can it be randomized? – stflow Jan 2 '18 at 20:38
  • 1
    @stflow: each process has its own memory mapping. This means different processes can have the same memory page mapped at different addresses. In other words: the library can still be shared between the processes but each process knows the memory pages of the library at different addresses. – Steffen Ullrich Jan 2 '18 at 21:26
0

When you compile with default flags, most of the time .text segment stays at a constant addresses and GOT is filled up with a list of pointers for functions used in the program which are resolved as they are encountered. Now since in this case GOT was at a constant place it is directly put in call by the compiler. An example :

0x8048446 <main+35>    call   printf@plt                    <0x80482f0>

This does not mean that actual location of printf was not randomized. If this was the first call to printf in the program _dl_runtime_resolve will fill in the appropriate values. Otherwise it should look something like this

pwndbg> x/xi 0x80482f0
0x80482f0 <printf@plt>: jmp    DWORD PTR ds:0x804a00c
pwndbg> telescope 0x804a00c
00:0000│   0x804a00c (_GLOBAL_OFFSET_TABLE_+12) —▸ 0xf7e38670 (printf) ◂— call   0xf7f0eb09

This is the actual location of printf in libc. In normal cases &printf points actually to the printf@plt which is just a jumptable for actual printf in libc.

Now for -pie -fPIE the &printf points to the actual printf in libc. This flag only adds ASLR to the sections that were constant earlier. Libraries were loaded at random offsets in both the cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.