3

假设我想在返回其返回地址的 c++ 代码中编写一个内联汇编函数。

因此,如果我从某个地址调用函数 returnAddress() 并且它需要在函数完成后返回地址 X,我希望 returnAddress() 返回值 X。

returnAddress() 的代码示例:

void* getAddress()
{
    __asm {
        pop ebx;     // moving return offset to ebx?
        push ebx;    // restoring stack state
        xor eax, eax;
        mov ax, cs;  // ax <- code segment
        mov ecx, 16;
        mul ecx;     // multiplying the code segment by 16
        add eax, ebx;// adding offset
    }
}

前面的代码不能正常工作,因为当我按下 alt+8 时,我可以清楚地看到我的代码地址与这个函数的返回值完全不同。

我想在内存中找到我的代码地址的原因是因为我想在代码本身运行时尝试更改它。如果有任何其他方法可以在不使用内联汇编的情况下找到我的代码地址(也许使用 Windows API?)请告诉我。

此外,我很确定我什至不能使用 Visual Studio 2010 使用 CS(代码段)值,所以也许这就是导致我出现问题的原因...... CS 总是等于 35。装配视图(alt+8)是否显示不正确地址,因为VS2010运行虚拟机?

这是我在这里的第一篇文章,所以也许我没有把我的观点说得很清楚。请让我知道我是否可以解释自己以使其更清楚。

4

2 回答 2

4

实际上,我很难理解您只是为了恢复返回地址而使用的奥秘。正如一些人建议的那样,您可以使用 intrinsic _ReturnAddress。不过,为了好玩,您可以使用这个简单的代码:

__declspec(naked) 
void* get_RetAddr()
{
    _asm {
        mov eax, [esp]
        ret
    }
}
于 2012-11-01T21:09:52.177 回答
4

代码段仅用于 16 位系统。随着 32 位的引入,代码段消失了。

您可以使用 VisualStudio 的内在_ReturnAddress()函数:

void * _ReturnAddress(void);
#pragma intrinsic(_ReturnAddress)

void* getAddress()
{
    return _ReturnAddress();
}

如果您想手动执行此操作,例如在非 VisualStudio 编译器上,则 32 位 x86 函数调用的调用堆栈包含完整的 32 位返回地址,因此您可以按原样返回它:

void* __declspec(naked) getAddress()
{
    asm
    {
        mov eax, [esp];
        ret;
    }
}

对于 x64 函数调用,您应该能够使用等效的 64 位寄存器:

void* __declspec(naked) getAddress()
{
    asm
    {
        mov rax, [rsp];
        ret;
    }
}
于 2012-11-01T21:20:33.273 回答