Я экспериментирую с модификацией адреса возврата функции. Я успешно сделал эту функцию, чтобы пропустить инструкцию, и ошибки не произошло, программа запустилась без ошибок.
Однако я создал другую функцию и попытался вручную контролировать выполнение программы: 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
от этой ошибки? И как я могу "вызвать" функцию, вернувшись в нее?