Изменение адреса возврата вызывает исключение из соглашения о вызовах - PullRequest
0 голосов
/ 09 февраля 2020

Я экспериментирую с модификацией адреса возврата функции. Я успешно сделал эту функцию, чтобы пропустить инструкцию, и ошибки не произошло, программа запустилась без ошибок.

Однако я создал другую функцию и попытался вручную контролировать выполнение программы: main-> f-> g -> главная. Это происходит, как и ожидалось, но после того, как программа достигает конца основной функции, происходит утверждение, которое говорит:

Ошибка проверки во время выполнения # 0 - значение ESP не было должным образом сохранено в вызов функции. Обычно это является результатом вызова функции, объявленной с одним соглашением о вызовах с указателем функции, объявленным с другим соглашением о вызовах. произошло

Мой код:

#include <iostream>

void g();
void f();

void* default_return_address = 0;
void* new_return_address = &g;


void g() {
    std::cout << "g ran\n";

    __asm {
        push edx  // push edx to stack because we don't want to modify it
        mov edx, default_return_address  // load default_return_address to edx
        mov [ebp + 0x04], edx  // replace current function's return address with edx
        pop edx  // restore edx
    };
}

void f() {
    __asm {
        push eax  // push eax to stack because we don't want to modify it
        push edx  // push edx to stack because we don't want to modify it

        lea eax, default_return_address  // load address of default_return_address variable to eax
        mov edx, [ebp + 0x04]  // load the return address of the current function to edx
        mov [eax], edx  // store the current function's return address in eax

        mov edx, new_return_address  // load new_return_address to edx
        mov [ebp + 0x04], edx  // replace current function's return address with edx

        pop edx  // restore edx
        pop eax  // restore eax
    };
}

int main() {
    int x = 0;
    f();
    std::cout << x;
    std::cin.get();
}

Если я не использую переменную new_return_address, но перенесу переменную default_return_address в EDX в функции f программа будет работать "как обычно", и я не получаю ошибки, поэтому проблема должна быть где-то в g.

Я пытался удалить cout, но результат был тот же. Я также попытался no to pu sh и вытолкнул стек. Регистр ESP имеет то же значение до того, как программа входит в блок asm в g и после его выхода.

Чем отличается g от этой ошибки? И как я могу "вызвать" функцию, вернувшись в нее?

...