I'm sure we've all seen this function before:
unsigned long get_esp(void) { __asm__("movl %esp,%eax"); }It works, but it has the side-effect of generating an irritating compiler warning:
foo.c: In function `get_esp': foo.c:99: warning: control reaches end of non-void functionI've just come across a novel approach to to solving this problem and I figured I'll share.
/* A way to get the ESP without using assembly instructions */ int get_esp = (int)&get_esp;Stick it at the end of any local variables and it'll do the job. I can't decide if I like it or not, but it does fix my compiler warnings...
get_esp()
October 10 2005, 00:45:01 UTC 6 years ago
A couple thoughts:
1: int get_esp = (int)&get_esp; this should be an unsigned long.
2: Getting the stack pointer inside a function other than the one you are trying to get it in is kinda silly, all it only works _by accident_, and is implementation specific, even though you don't have any variables on the stack, some implementations *will* change the stack pointer on you.
3: just do this inside of whatever function you want to get the stack pointer from:
unsigned long stackptr; __asm__ __volatile__ ("movl %%esp, %0" : "=r" stackptr );4: While I personally wouldn't use your method as it can break in several ways, albeit non-standard, I do like it as it helps further demonstrate the how the stack works and a lot of people get caught thinking they understand when they really don't. This is also the reason I like aleph1's shellcode for someone just learning.
October 10 2005, 00:48:38 UTC 6 years ago
int main(int argc, char **argv) { [,,,] unsigned long stackptr; [...] for (i=0; i < siz; i++) egg[i] = 0x90; [...] __asm__ __volatile__("movl %%esp, %0" : "=r" stackptr); [...] execve(...); return 0; }October 10 2005, 00:57:57 UTC 6 years ago
2. This is certainly correct. Although I think it works out "most" of the time, certainly if you have a large enough NOP-sled then being out by a little bit won't make much difference. (Some people might consider buffer overflow attacks themselves to be implementation specific ;)
3. That's neat.
4. I'm in two minds about it. I see how it works, and I see that it isn't perfect .. The more I think about it the more I like it though!
For the moment I've updated the env-overflow and cmd-overflow tools to this technique, we'll see who complains and what breaks soon enough ..
October 10 2005, 01:05:41 UTC 6 years ago
December 10 2007, 12:59:34 UTC 4 years ago
void *get_esp() {
__asm__ {
mov %eax, %esp
ret
}
}
... I get no compiler when using this. Of course, I'm using MSVC though. I guess it could be different :/
January 15 2008, 12:18:43 UTC 4 years ago
get_esp()
The following two functions (checked with GCC) return value of ESP register. The first one is just a fix for mentioned warning. The second one is slightly better (the source code is shorter).unsigned long get_esp_1(void)
{
unsigned long register r_esp;
asm volatile ("movl esp,%0" : "=a" (r_esp) : : "cc" );
return r_esp;
}
unsigned long get_esp_2(void)
{
volatile unsigned long register r_esp asm("esp");
return r_esp;
}