2016-04-09 5 views
2

Я пытаюсь подключить функцию, используя ее адрес, и пока она отлично работает!Сбой приложения при использовании функции hooked с cout

Единственная проблема при использовании std::cout в сочетании с наличием MessageBoxA с WinAPI, а затем сбой! Странная вещь, он выходит из строя только в этом конкретном случае, а не если она вызывается в сочетании с printf или просто int i = MessageBoxA(...);

Для тестирования, я сделал так, что инструкции на адрес функции непосредственно возвращает 32. Не знаю, что я знаю, но это просто для тестирования.

// mov eax, 32 
// ret 
const DWORD instructionCount = 6; 
BYTE instructions[instructionCount] = { 0xB8, 0x20, 0x00, 0x00, 0x00, 0xC3 }; 

Кроме того, чтобы изменить защиту на области с VirtualProtect(), то теперь я в основном просто сделать

memcpy(MessageBoxA, instructions, instructionCount); 

Теперь тестирования с помощью этого:

int i = MessageBoxA(NULL, "Hello World", "Injector", MB_OK); 

printf("Works: %d\n", i); 
printf("Works: %d\n", MessageBoxA(NULL, "Hello World", "Injector", MB_OK)); 

std::cout << "Works: " << i << std::endl; 
std::cout << "Doesn't: " << MessageBoxA(NULL, "Hello World", "Injector", MB_OK) << std::endl; 

printf("Hello World\n"); 

Затем он выходит из строя только после std::cout << MessageBoxA(...). Удаление этой линии, и все работает!

Обратите внимание, что он успешно печатает 32, он падает при достижении следующего утверждения.

Application Crash

Опять же это только в том случае, когда он не работает, так что с помощью этого:

__declspec(noinline) int testFunction(int i) 
{ 
    return i; 
} 

Затем повторно использовать код выше и изменения MessageBoxA к testFunction (а также аргументы), и теперь все 4 заявления работают!

Подводя итог, есть ли у кого-нибудь идеи, почему и что вызывает крушение в этом конкретном случае? Когда другие дела работают отлично.

+1

запустите его в отладчике и покажите нам asm, register и stack backtrace в точке, где он сбой. Какая конвенция вызова используется MessageBoxA? Предполагается ли, что он выталкивает свои аргументы из стека? Если это так, вызывающий код будет толкать args и ожидать, что вызываемая функция очистит стек (применима только к 32-битовому коду, поскольку win64 ABI помещает первые 4 аргумента в regs). –

+0

«std :: cout <<» Не делает: «<< (int) MessageBoxA (NULL,« Hello World »,« Injector », MB_OK) << std :: endl;' Work? –

+0

@AdamMartin приводит к той же ошибке. – Vallentin

ответ

2

Я думаю, проблема в том, что вы развращаете указатель стека. Попробуйте следующее:

const DWORD instructionCount = 8; BYTE instructions[instructionCount] = { 0xB8, 0x20, 0x00, 0x00, 0x00, 0xC2, 0x10, 0x0 };

Это будет поп арг из стека, как указано Питер Кордес. Надеюсь, это поможет.

+0

Хотя я понял комментарий @PeterCordes, я не мог представить, как его исправить (я никогда не работаю с сборкой). Но ты отвечаешь, трюк! Большое спасибо! – Vallentin