【问题标题】:Application crashes when using hooked function with cout使用带有 cout 的挂钩函数时应用程序崩溃
【发布时间】: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 &lt;&lt; MessageBoxA(...) 之后崩溃。删除那条线,一切正常!

注意它成功打印32,到达下一条语句时崩溃。

同样,它只是在它不起作用的情况下,所以使用这个:

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

然后重用上面的代码并将MessageBoxA更改为testFunction(以及参数),现在所有4个语句都可以工作了!


底线,是否有人对特定情况下导致崩溃的原因和原因有任何想法?当其他情况完全正常时。

【问题讨论】:

  • 在调试器中运行它,并向我们展示它崩溃时的 asm、寄存器和堆栈回溯。 MessageBoxA 使用什么调用约定?它应该从堆栈中弹出它的参数吗?如果是这样,调用代码将推送 args 并期望被调用函数清理堆栈(仅适用于 32 位代码,因为 win64 ABI 将前 4 个 args 放在 regs 中)。
  • std::cout &lt;&lt; "Doesn't: " &lt;&lt; (int)MessageBoxA(NULL, "Hello World", "Injector", MB_OK) &lt;&lt; std::endl; 工作吗?
  • @AdamMartin 导致同样的错误。

标签: c++ winapi x86 hook inline-assembly


【解决方案1】:

我认为问题在于您正在破坏堆栈指针。尝试使用以下内容:

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

正如 Peter Cordes 所说,这会将 args 从堆栈中弹出。希望对您有所帮助。

【讨论】:

  • 虽然我理解@PeterCordes 的评论,但我无法想象如何解决它(我从不使用汇编)。但你的回答就行了!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
  • 2013-05-13
  • 1970-01-01
相关资源
最近更新 更多