所以我想分析我的应用程序,我特别想记录从程序开始到进入和退出程序内部调用的每个函数(忽略 DLL 中的函数)的时间,即我想要一个看起来像的简单表这个:
THREAD_ID FUNCTION_ADDRESS TIME EVENT_TYPE
5520 0xFF435360 0 ENTERED
5520 0xFF435ED3 25 ENTERED
5520 0xFF433550 40 ENTERED
5520 0xFF433550 50 EXITED
5520 0xFF433550 60 ENTERED
5520 0xFF433550 70 EXITED
5520 0xFF435ED3 82 EXITED
5520 0xFF435360 90 EXITED
对于一个看起来像这样忽略编译器优化的程序:
void test1(void)
{
int a = 0;
++a;
}
void test(void)
{
test1();
test1();
}
void main(void)
{
test();
}
我找不到任何现成的解决方案,我能找到的最接近的是微软的 VSPerfReport,但它只是输出在每个函数中花费了多长时间,而不是在输入和退出时。
所以我开始研究用一个简单的函数来挂钩我的所有函数,该函数产生一个缓冲区,我可以从中生成上表。为了做到这一点,我只是想创建一个在 main 开始时调用的函数,它可以通过整个 exe 修改 CALL 指令来调用我的钩子函数。
像 MinHook 等那里的库对我来说似乎有点 OTT 并且可能无法工作,因为它是一个 x64 应用程序,我不想挂钩 DLL 函数。
所以我想只修改每个 CALL 指令中的 JMP 指令,即这个程序:
void main(void)
{
...asm prologue
test();
002375C9 call test (235037h)
}
...asm epilogue
这里的调用转到 JMP 的表:
@ILT+40(__set_errno):
0023502D jmp _set_errno (243D80h)
@ILT+45(___crtGetEnvironmentStringsA):
00235032 jmp __crtGetEnvironmentStringsA (239B10h)
test:
00235037 jmp test (237170h)
@ILT+55(_wcstoul):
0023503C jmp wcstoul (27C5D0h)
@ILT+60(__vsnprintf_s_l):
我想通过这个表并将所有与我的应用程序 .exe 中的函数相关的 JMP 重新路由到包含计时代码的钩子函数,然后返回到调用函数。
那么 ILT 代表什么?
这可能吗?我听说过 IAT 挂钩,但在我看来,只有在挂钩 DLL 时才如此。同样在这里,我忽略了退出,尽管另一个 JMP 代替 RET 指令可能会有所帮助?
谢谢你的帮助