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