x86_64 Get Stack Pointer (RSP)

IDK why, but getting a simple source code for this was actually quite difficult. I mean I figured google would immediately spit out some simple snippet, but NO. There are stack overflow posts with difficult solutions and I was thinking to myself “OMG it’s not that hard geeze I’ll just common sense it out.” And that’s what I did. I don’t do x64 asm at all but I know the general idea. So:

get_rsp.c

#include

unsigned long long getrsp()
{
  __asm__ ("movq %rsp, %rax");
}

int main()
{
  printf("%llx\n", getrsp());
  return 0;
}


I wanted to experiment observing if what I did was in fact correct (print stack pointer). Most kernels have Address space layout randomization (ASLR). So my plan was first to just run the program a few times:

[bazz@users ~]$ ./getrsp
7fff937aec30
[bazz@users ~]$ ./getrsp
7fff07448a50
[bazz@users ~]$ ./getrsp
7fffbdb0e470
[bazz@users ~]$ ./getrsp
7fff0fe2e950
[bazz@users ~]$ ./getrsp
7fffb2289ec0

So far so good. ASLR is enabled via /proc/sys/kernel/randomize_va_space, so I wanted to disable it and see the effect:

[root@users ~]# cat /proc/sys/kernel/randomize_va_space
2
[root@users ~]# echo 0 > /proc/sys/kernel/randomize_va_space

[bazz@users ~]$ ./getrsp
7fffffffe5d0
[bazz@users ~]$ ./getrsp
7fffffffe5d0
[bazz@users ~]$ ./getrsp
7fffffffe5d0
[bazz@users ~]$ ./getrsp
7fffffffe5d0

Then for fun, I wanted to see if compiling the executable as static would affect anything:

[bazz@users ~]$ gcc getrsp.c -static -o getrsp
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status

[root@users ~]# yum install glibc-static  # CentOS

[bazz@users ~]$ gcc getrsp.c -static -o getrsp
[bazz@users ~]$ ./getrsp
7fffffffe5e0
[bazz@users ~]$ ./getrsp
7fffffffe5e0
[bazz@users ~]$ ./getrsp
7fffffffe5e0

If you noticed, the statically compiled binary with ASLR disabled, produced a stack pointer (SP) 0x10 bytes “lighter” — I guess dynamic lib referencing needs more weight on the stack??

“Lighter” explanation — stack grows downward — meaning lower stack addresses means more stuff is on the stack: I proved this by modifying the assembly call with:

__asm__ ("pushq %rax\n\tmovq %rsp, %rax");
[bazz@users ~]$ gcc getrsp.c -static -o getrsp
[bazz@users ~]$ ./getrsp
7fffffffe5d8

I pushed a 64-bit/8-byte value to the stack, and we see the stack grew / smaller address is in the stack pointer :)

Cool, that was fun.

Finally, I re-enabled ASLR and checked to see if the static binary performed any differently from the dynamic one:

###
### Then, after re-enabling ASLR and still testing with static binary
[bazz@users ~]$ ./getrsp
7fffcd83acb0
[bazz@users ~]$ ./getrsp
7fff2d628260
[bazz@users ~]$ ./getrsp
7fff503cdb50
[bazz@users ~]$ ./getrsp
7fff23717d50
[bazz@users ~]$ ./getrsp
7fffaaa6fd10

Leave a Reply

Your email address will not be published. Required fields are marked *

*