【问题标题】:Is finding code's address in visual studio 2010 c++ using in-line assembly possible?是否可以使用内联汇编在 Visual Studio 2010 C++ 中查找代码地址?
【发布时间】:2012-10-22 12:30:40
【问题描述】:

假设我想在一个返回其返回地址的 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 运行的是虚拟机?

这是我在这里的第一篇文章,所以也许我没有把我的观点说得很清楚。如果我能解释清楚,请告诉我。

【问题讨论】:

  • 无论如何这在 64 位中是不可能的,因为没有内联汇编
  • 只需使用 _ReturnAddress 内在函数。
  • @RaymondChen 我喜欢这个只是为了评论。我什至不知道它的存在。谢谢!
  • 那么,生成自修改代码的问题#1 解决了,接下来是问题#2 ...??

标签: c++ visual-studio-2010 assembly stack


【解决方案1】:

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

__declspec(naked) 
void* get_RetAddr()
{
    _asm {
        mov eax, [esp]
        ret
    }
}

【讨论】:

    【解决方案2】:

    代码段仅用于 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;
        }
    }
    

    【讨论】:

    • 1.我相信您的第一个示例将返回您的getAddress 中的地址,而不是实际的调用者。 2. 在 64 位构建 AFAIK 内联汇编是不允许的
    • @valdo: re: 2) 他确实说过“如果你想手动执行,请说在非 VisualStudio 编译器上”。
    • @valdo:阅读MSDN's documentation:“_ReturnAddress 内在函数提供了调用函数中指令的地址,该指令将在控制权返回给调用者后执行。” IOW,_ReturnAddress() 返回当 CPU 的 CALL 指令执行调用 getAddress() 时压入调用堆栈的地址。
    • 段在 32 位模式下没有“消失”,但 Windows 使用平面内存模型,其中 csdsesss 都指向平面4GB 段,覆盖所有地址空间。它确实使用了特定于线程的fs 选择器,该选择器指向每个线程的不同内存。
    • @Remy Lebeau:你是对的。我只是虽然_ReturnAddress 是一个“假”内在函数,它只是告诉当前指令指针。我还了解到什么是“IOW”。也谢谢你:)
    猜你喜欢
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 2014-08-06
    相关资源
    最近更新 更多