Я хочу сделать следующее:Мессинга со стеком в сборке и C++
У меня есть функция, которая не моя (это на самом деле здесь не имеет значения, а просто сказать, что у меня нет контроля над это) и что я хочу исправлять так, чтобы он вызывал мою функцию, сохраняя список аргументов (прыжок не является опцией).
То, что я пытаюсь сделать, заключается в том, чтобы поместить указатель стека, как это было до того, как эта функция вызывается, а затем вызвать мою (например, вернуться назад и повторить одно и то же, но с другой функцией). Это не работает прямо, потому что стек становится испорченным. Я считаю, что когда я делаю вызов, он заменяет обратный адрес. Итак, я сделал шаг, чтобы сохранить обратный адрес, сохраняя его в глобальной переменной, и он работает, но это не нормально, потому что я хочу, чтобы он сопротивлялся рекурсивию, и вы знаете, что я имею в виду. Во всяком случае, я новичок в сборке, поэтому я здесь.
Пожалуйста, не говорите мне о уже сделанных программах, чтобы сделать это, потому что я хочу сделать все по-своему.
Конечно, этот код должен быть независимым от компилятора и оптимизации.
Мой код (если он больше, чем то, что является приемлемым, пожалуйста, скажите мне, как разместить его):
// A function that is not mine but to which I have access and want to patch so that it calls a function of mine with its original arguments
void real(int a,int b,int c,int d)
{
}
// A function that I want to be called, receiving the original arguments
void receiver(int a,int b,int c,int d)
{
printf("Arguments %d %d %d %d\n",a,b,c,d);
}
long helper;
// A patch to apply in the "real" function and on which I will call "receiver" with the same arguments that "real" received.
__declspec(naked) void patch()
{
_asm
{
// This first two instructions save the return address in a global variable
// If I don't save and restore, the program won't work correctly.
// I want to do this without having to use a global variable
mov eax, [ebp+4]
mov helper,eax
push ebp
mov ebp, esp
// Make that the stack becomes as it were before the real function was called
add esp, 8
// Calls our receiver
call receiver
mov esp, ebp
pop ebp
// Restores the return address previously saved
mov eax, helper
mov [ebp+4],eax
ret
}
}
int _tmain(int argc, _TCHAR* argv[])
{
FlushInstructionCache(GetCurrentProcess(),&real,5);
DWORD oldProtection;
VirtualProtect(&real,5,PAGE_EXECUTE_READWRITE,&oldProtection);
// Patching the real function to go to my patch
((unsigned char*)real)[0] = 0xE9;
*((long*)((long)(real) + sizeof(unsigned char))) = (char*)patch - (char*)real - 5;
// calling real function (I'm just calling it with inline assembly because otherwise it seems to works as if it were un patched
// that is strange but irrelevant for this
_asm
{
push 666
push 1337
push 69
push 100
call real
add esp, 16
}
return 0;
}
распечаток (и должен):
Аргументы 100 69 1337 666
Edit:
Код я проверяю следующее Владом предложение (Sti LL не работает)
// A patch to apply in the real function and on which I will call receiver with the same arguments that "real" received.
__declspec(naked) void patch()
{
_asm
{
jmp start
mem:
nop
nop
nop
nop
start :
// This first two instructions save the return address in a global variable
// If I don't save and restore the program won't work correctly.
// I want to do this without having to use a global variable
mov eax, [ebp+4]
mov mem, eax
push ebp
mov ebp, esp
// Make that the stack becomes as it were before the real function was called
add esp, 8
// Calls our receiver
call receiver
mov esp, ebp
pop ebp
// Restores the return address previously saved
mov eax, mem
mov [ebp+4],eax
ret
}
}
без явного вызова в asm, ваша функция, скорее всего, встроена компилятором. поэтому его не называли. – Vlad
Спасибо за то, что заставили меня чувствовать себя плохо, не думая, что: D. Просто шучу. Спасибо, имеет смысл. – user246100
Ваша функция 'real' действительно пуста? если это так, оно может быть короче 5 байтов, поэтому ваш патч может перезаписать следующую функцию. – Vlad