views:

249

answers:

4

Hello. I would like to know how to retrieve the address of the function that called my function with inline assembly. My idea is to get the address to where the function that called mine will return and using the instruction before it (that is a call to the function that called mine) retrieving the address of the one that called mine adding to the offset given to that call, to the address of the next instruction (the address to where the function that called mine will return). So far I was able to make this but to get the address of mine. It is fairly simple and it works:

_asm
{
    mov eax, [ebp+4]
    mov returnTo,eax
}

long addressOfMine = (*((long*)(returnTo - sizeof(long)))) + returnTo)

This retrieves the address of mine just fine. (By knowing that [ebp+4] is the address to where mine will return)

To do the same but one step above I tried to get the old ebp and do the same. I saw in a site that [ebp+0] is the old ebp so I tried:

_asm
{ 
    mov eax, [ebp]
    mov ebx, [eax+4]
    mov returnTo,ebx
}

long addressOfCaller = (*((long*)(returnTo - sizeof(long)))) + returnTo)

But it doesn't work. So, my assumption is wrong or I'm doing something wrong so I would like to ask your help.

+2  A: 

Why don't just use the function provided by your OS? here are a pair of links http://stackoverflow.com/questions/105659/how-can-one-grab-a-stack-trace-in-c

You may try something more complicated http://www.yosefk.com/blog/getting-the-call-stack-without-a-frame-pointer.html

But you have to be aware that in x86 mode the calling conventions are not easier, it depends on some factors like your OS, your compiler, the calling convention used, etc.

Ismael
I don't want the name of the function that called mine to be displayed. I want to get its address so I can use it. I will check out your second link.
In order to get the name of the function you first need the address of it.
Ismael
Check the first link to understand what I said
+4  A: 

Ok, so as long as you know you are doing something non-portable. You know that right?

I mean, it's not like a dozen people haven't said it already...

so. for functions on x86 (but not X64) when frame pointer omission and other optimizations aren't enabled, this should work. doesn't work for all calling conventions, but it should work for standard C/C++ calling convention.

void ** puEBP = NULL;
__asm { mov puEBP, ebp };
void * pvReturn = puEBP[1]; // this is the caller of my function

puEBP = (void**)puEBP[0];    // walk back to the previous frame
void * pvReturn2 = puEBP[1]; // this is the caller's caller

edit: Ok I'm officially confused now. I looked again at your question, and as far as I can tell, the your first code fragment is functionally the same as what I just wrote. But you say that that code gives you the address of your function - but that shouldn't be true. that code fragment should be returning the address of the caller to your function.

edit2: added code to get the caller of the caller.

By the way this code that you show in your question

long addressOfCaller = (*((long*)(returnTo - sizeof(long)))) + returnTo)

won't work. It's based on the assumption that the only way to make a call is

call symbol

where symbol is a 4 byte absolute address of a function. But thats not the only way to make a call. it's also possible to call indirect

mov eax, symbol
call [eax]

or

call [ref_symbol]

And it also possible to call relative to the current instruction

call +12

But you don't need to do this, once you know any address within the calling function, you can use the Debug Help Library to find the address of the function that called you.

In order to use DebugHelp, you must have the debug symbols for the code. then just use SymFromAddr.

John Knoeller
Ok. that's clearer now. You want the caller of your caller. ok.
John Knoeller
Unknown: See my latest edit. I've verified this code in the debuffer this with compiler optimizations turned off.
John Knoeller
I understand the issue on what I'm assuming. Anyway i resorted to use os API to do what i want. In linux it was easy. In windows i'm still figuring out on how to use StackWalk64 function.
But your problem isn't walking the stack. Your problem is that there is no way to convert a return address into the address of the caller.
John Knoeller
I want to get the address of the caller. The "way to" doesn't matter.
and knowing an address _within_ the calling function is not good enough?
John Knoeller
no because I want to use that address as a function pointer (so I can call it or hook it)
+1  A: 

It's not easy to do. You must know how many arguments and local variables the caller has, which in most cases, is not trivial to figure out programmatically. If you make the possibly wrong assumption that the compiler keeps EBP as the stackframe holder and never alters it(as in, this wouldn't work with -O3/2/1 probably)

inside of the called function, you could do something like

mov ecx,ebp ;save our current stack frame
pop ebp ;get the old value of EBP that was there before our function got called
mov dword [_caller_address],dword [ebp+4] ;this isn't actually a valid opcode. you figure it out. 
mov ebp,ecx ;restore old state
push ebp 

This is very unsafe though. Optimizations on the compiler will probably break it. It will only work for x86-32, and depending on OS and compiler it may not work if it follows a different calling standard.

The way it works is this:

Functions in C look something like

_Sum:
        push    ebp             ; create stack frame
        mov     ebp, esp
        mov     eax, [ebp+8]    ; grab the first argument
        mov     ecx, [ebp+12]   ; grab the second argument
        add     eax, ecx        ; sum the arguments
        pop     ebp             ; restore the base pointer
        ret

So, if say you had _SumCall it'd look somethign like

_SumCall:
        push    ebp             ; create stack frame
        mov     ebp, esp
        mov     eax, [ebp+8]    ; grab the first argument
        mov     ecx, [ebp+12]   ; grab the second argument
        push ecx ;first argument for call
        push eax ;second argument for call
        call _Sum
        pop     ebp             ; restore the base pointer
        ret

So you see, it relies on the fact that the callee is responsible for stack frame preservation.

If you try it and it doesn't work, ensure both the caller and callee have at least 1 local variable/argument. Failing that, then well, your just screwed because the compiler made some optimization that broke this assumption.

Once again. This is very unsafe and is extremely not-portable

Reference: http://courses.ece.illinois.edu/ece390/books/labmanual/c-prog-mixing.html

Earlz
It didn't work for me with -O2 and I can't discard optimizations because the library where the caller is contained is not mine. In linux it was really easy. Just one call to "int backtrace (void **buffer, int size)". In windows I guess "StackWalk64" is my solution but haven't managed to make it work yet.
Even then it is not safe because how do you know what in the stack is a function call? What you are asking for is something that is not trivially solvable.
Earlz
A: 

I had an idea for you "unknown (google)". Retrieve the address of where your function will return to, patch that address to do "get to where it returns and call a function of yours passing you that value", return, and in your callback use the argument you receive and fix what you patched with the original values.

By the way, I'm hoping you are not using this to invade the Pentagon computers.