获取使用内联汇编调用我的函数的函数的地址

use*_*100 0 c++ inline-assembly

我想知道如何检索使用内联汇编调用我的函数的函数的地址.我的想法是将地址发送到调用我的函数将返回的位置并使用前面的指令(这是对调用我的函数的调用)检索调用我的函数的地址添加到给定的偏移量调用,到下一条指令的地址(调用我的函数将返回的地址).到目前为止,我能够做到这一点,但要获得我的地址.它非常简单,有效:

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

long addressOfMine = (*((long*)(returnTo - sizeof(long)))) + returnTo)
Run Code Online (Sandbox Code Playgroud)

这检索我的地址就好了.(通过知道[ebp + 4]是我将返回的地址)

为了做同样的但是上面一步,我试图获得旧的ebp并做同样的事情.我在一个网站上看到[ebp + 0]是旧的ebp所以我试过了:

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

long addressOfCaller = (*((long*)(returnTo - sizeof(long)))) + returnTo)
Run Code Online (Sandbox Code Playgroud)

但它不起作用.所以,我的假设是错误的,或者我做错了所以我想请求你的帮助.

Joh*_*ler 6

好吧,只要你知道你在做一些不便携的事情.你知道吗?

我的意思是,它不像十几个人还没说过......

所以.对于x86(但不是X64)上的函数,当帧指针遗漏和其他优化未启用时,这应该可行.不适用于所有调用约定,但它应该适用于标准C/C++调用约定.

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
Run Code Online (Sandbox Code Playgroud)

编辑:好的,我现在正式混淆了.我再次看了你的问题,据我所知,你的第一个代码片段在功能上与我刚写的相同.但是你说那段代码会给你你的函数地址 - 但这不应该是真的.该代码片段应该将调用者的地址返回给您的函数.

edit2:添加代码以获取调用者的调用者.

顺便提一句,您在问题中显示的代码

long addressOfCaller = (*((long*)(returnTo - sizeof(long)))) + returnTo)
Run Code Online (Sandbox Code Playgroud)

不行.它基于这样的假设,即打电话的唯一方法是

call symbol
Run Code Online (Sandbox Code Playgroud)

其中symbol是函数的4字节绝对地址.但这不是打电话的唯一方式.它也可以称为间接的

mov eax, symbol
call [eax]
Run Code Online (Sandbox Code Playgroud)

要么

call [ref_symbol]
Run Code Online (Sandbox Code Playgroud)

并且还可以相对于当前指令进行调用

call +12
Run Code Online (Sandbox Code Playgroud)

但是您不需要这样做,一旦您知道调用函数中的任何地址,您就可以使用Debug Help Library来查找调用您的函数的地址.

要使用DebugHelp,您必须具有代码的调试符号.然后只使用 SymFromAddr.