Search code examples
cpointerspass-by-referenceaslrchar-pointer

returned pointer address getting modified when ASLR turned on


I have this piece of C code running on development box with ASLR enabled. It is returning a char pointer (char *) to a function, but somehow few bytes in the returned pointer address are getting changed, printf output below:

kerb_selftkt_cache is 0x00007f0b8e7fc120
cache_str from get_self_ticket_cache 0xffffffff8e7fc120

The char pointer 0x00007f0b8e7fc120 is being returned to another function, which is getting modified as 0xffffffff8e7fc120 that differs from the original pointer address by one word (4-bytes) 0xffffffff instead of 0x00007f0b, the last four bytes (8e7fc120) being same. Any idea what might be going on? and how do I possibly fix this. The code is running on linux 64-bit architecture on Intel Xeon. This code is from an existing proprietary library, so I can't share the exact code, but the code logic looks something like this:

typedef struct mystr {
 int num;
 char addr[10];
}mystr;

static mystr m1;

char *get_addr() {
 return m1.addr;
}

void myprint() {
 printf("mystr m1 address %p\n",&m1);
 printf("mystr m1 addr %p\n",m1.addr);
}

int main (int argc, char *argv[]) {

char *retadd;
myprint();

retadd = get_addr();
printf("ret address %p\n",retadd);

return 0;
}

retadd and m1.addr are different when ASLR is turned on.


Solution

  • My guess is the func takes an int or something else only 4 bytes wide, then the argument gets casted to a pointer type which sign-extends it. Except the compiler (gcc?) should warn you even without flags like -Wall, but hey, maybe you have weird-ass macros or something which obfuscate it.

    Alternatively what you mean by passing is the fact that you return it (as opposed to passing as an argument). That could be easily explained by C defaulting to int as a return value if function declaration is missing. So in that case make sure you got stuff declared.