Steve Kemp ([info]skx) wrote in [info]shellcode,
get_esp()

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 function

I'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...


  • Post a new comment

    Error

  • 6 comments

[info]transgress

October 10 2005, 00:45:01 UTC 6 years ago

Hi.

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.

[info]transgress

October 10 2005, 00:48:38 UTC 6 years ago

i.e.

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;
}
          

[info]skx

October 10 2005, 00:57:57 UTC 6 years ago

1. Noted, and correct.

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 ..

[info]transgress

October 10 2005, 01:05:41 UTC 6 years ago

it probably won't break a lot, other than places that introduce local variables after the initially declared ones (i.e. alloca() or if { char *foo; ... } etc)

[info]anonymiseyaface

December 10 2007, 12:59:34 UTC 4 years ago

what about:
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 :/

[info]mkborg.myopenid.com

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;
}
Create an Account
Forgot your login or password?
Facebook Twitter More login options
English • Español • Deutsch • Русский…