【发布时间】:2016-04-09 23:36:13
【问题描述】:
我正在尝试使用它的地址来挂钩一个函数,到目前为止它总体上工作得很好!
唯一的问题是当使用std::cout 并结合WinAPI 中的MessageBoxA 时,它会崩溃!奇怪的是,它只会在特定情况下崩溃,而不是与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,到达下一条语句时崩溃。
同样,它只是在它不起作用的情况下,所以使用这个:
__declspec(noinline) int testFunction(int i)
{
return i;
}
然后重用上面的代码并将MessageBoxA更改为testFunction(以及参数),现在所有4个语句都可以工作了!
底线,是否有人对特定情况下导致崩溃的原因和原因有任何想法?当其他情况完全正常时。
【问题讨论】:
-
在调试器中运行它,并向我们展示它崩溃时的 asm、寄存器和堆栈回溯。 MessageBoxA 使用什么调用约定?它应该从堆栈中弹出它的参数吗?如果是这样,调用代码将推送 args 并期望被调用函数清理堆栈(仅适用于 32 位代码,因为 win64 ABI 将前 4 个 args 放在 regs 中)。
-
std::cout << "Doesn't: " << (int)MessageBoxA(NULL, "Hello World", "Injector", MB_OK) << std::endl;工作吗? -
@AdamMartin 导致同样的错误。
标签: c++ winapi x86 hook inline-assembly