如何使用C 给出的地址覆盖汇编器堆栈的返回地址



我得到了一个函数switchContext(void*& from, void*& to)。它收到两个堆栈指针,并将改变过程的上下文。因此,如果我获得了Coroutine A并使用特定功能resume(),则Coroutine B将继续工作。目前,我很难完成代码工作。

我正在使用nasm&gcc用于编译。

汇编程序:( switchContext(void*& from, void*& to)(:

switchContext:
    ; epb = esp
    mov     ebp, esp
    ; save registers
    push    ebp
    push    ebx
    push    esi
    push    edi
    ; from <= returnadress
    ; eax <= returnadress
    mov     eax, [ebp+16] 
    mov     edx, ebp
    add     edx, 20 ; make edx point to 'from'
    ; overwrite 'from' with returnadress
    mov     [edx], eax
    ; what to do now: returnadress <= to
    ; eax <= to
    mov     eax, [ebp+24]
    mov     edx, ebp
    add     edx, 16 ; make edx point to returnadress
    ; overwrite returnadress with 'to'
    mov     [edx], eax
    pop     edi ; RSA = esp + 12
    pop     esi ; RSA = esp + 8
    pop     ebx ; RSA = esp + 4
    pop     ebp ; RSA = esp + 0
    ; use new returnadress to jump to 'to'
    ret     

这是相应的C 类:

extern "C" {
    void switchContext(void*& from, void*& to);
}
class Coroutine {
public:
    const char* name;
    Coroutine(void* tos = 0)
    {
        setup(tos);
    }
    void resume(Coroutine* next)
    {
        switchContext(this->sp, next->sp);
    }
    virtual void body() = 0;
    virtual void exit() = 0;
private:
    static void startup(Coroutine* obj) {
        obj->body();
        obj->exit();
    };
    void setup(void* tos) {
        if (tos == 0) {
            unsigned temp_stack[1024];
            this->sp = &temp_stack;
            return;
        }
        this->sp = &tos;
        return;
    };
    void* sp;
};

当前我的程序只是崩溃。但这仅是通过用" to"中的汇编器中的返回地址来做到这一点。

我在此过程中在哪里犯错?

您的mov ebp,esp位于错误的位置。它应该在保存寄存器后。

您不是说明参考文献。从汇编器的角度来看,C 参考只是指针,因此您的参数为void **。由于您要保存/加载返回地址到指向的返回地址,因此您需要一个额外的间接地址来将值保存到指向地址的指向。

与此问题无关:您使用edx的某些地址计算可以凝结成更少的说明。您也可以分配使用ebp并使用基于esp的偏移。

最新更新