【问题标题】:How to catch function call [closed]如何捕获函数调用[关闭]
【发布时间】:2018-10-01 23:15:01
【问题描述】:

注意:这个话题不是关于调试和 try,throw,catch,我不能直接在我的函数中放置任何东西,只有像 WINapi 这样的外部影响。

如果调用任何函数,我需要某种方式在我的 APP 中获取信息。它应该在运行时“捕获”函数调用,我无法为我的 APP 中存在的每个函数实现任何额外的代码。我想一些 WINAPI 应该可以工作,但我找不到合适的方法来处理来自进程的每个调用。因为信息最好有 3 件事:

  1. 刚刚被调用的函数的入口点(地址)。
  2. 最好定义这个函数的返回类型。
  3. 例如是 (int, char) 等参数。

附:很高兴知道我的(或其他)进程中当前正在执行多少功能。

【问题讨论】:

  • 这里有些人知道有关 Win32 的知识,我做梦也想不到,但我认为您不会得到太多满足。除了堆栈上的内容之外,C++ 不会在运行时跟踪此类内容。哎呀,编译后的函数调用可能甚至不存在。当作为优化编译器的代码混合器使用调试器信息文件或内存映射完成时,您可以对一些丢弃的信息进行逆向工程,但不容易,也不能使用我在运行时知道的任何工具(不包括调试器)。跨度>
  • 实际上没有什么能完全按照您的要求进行操作,但Detours 可能是您能找到的最接近的。或者查看仪器是如何完成的。无论哪种方式,您都会进入一个充满痛苦、限制和平台特定事物的世界。
  • @MikeVine tnx 以获得这样的答案。但是找不到此应用程序的桌面安装下载。首先在谷歌是微软的Detours,但甚至不能去那个页面。访问被拒绝(奇怪)。

标签: c++ windows winapi visual-c++ c++14


【解决方案1】:

要在调用应用程序中的函数时执行某些操作,您必须使用/Gh 命令行开关Enable _penter Hook Function 进行编译,也许还可以使用/GH Enable _pexit Hook Function。然后你可以定义_penter 函数(也许还有_pexit),它会在进入(离开)你的应用程序函数时被调用。

这些开关必须在项目属性 -> C/C++ -> 命令行中手动输入。

函数必须是naked:

extern "C" void __declspec(naked) _cdecl _penter( void ) {
    // Save registers.
    _asm {
        push eax
        push ebx
        push ecx
        push edx
        push ebp
        push edi
        push esi
    }  

    // Your code here.

    // Restore registers.
    _asm {
        pop esi
        pop edi
        pop ebp
        pop edx
        pop ecx
        pop ebx
        pop eax
        ret
    }
}

为明显的减速做好准备。

当您从_penter_pleave 调用您的函数时,您可能会遇到非常讨厌的重入问题和堆栈溢出。使用一些保护变量或只调用裸函数。

下一步是从PDB 文件中提取数据,但如果您能描述您想用这些信息做什么,将会有所帮助。您是否打算重新实施分析或功能覆盖测试?

我们不能使用__func__ 宏,因为我们在错误的函数中这样做。也许生成详细的地图文件就足够了。我们可以得到返回地址并在地图文件中查找。

其他链接:

【讨论】:

  • 这是一个很好的答案。正如我所看到的,我的这种要求不会是一件容易的事。想看看其他人在接下来的两天内可能会提出什么建议。如果没有更好的结果出现 - 这个答案将是最好的。
【解决方案2】:

不,你不能。

函数在运行时不存在,一般情况下不存在。他们没有名字。他们的类型只是位。好像调用本身就可以消除一样。

有很多事情与您所描述的有些接近。分析、检测、使用 DLL 作为代理等。我的意思是使用调试符号表(例如来自 MSVC 的 pdb),您可以每秒中断进程 10 次并对其进行分析。但没有一个符合您的要求,所以答案仍然是“否”。

【讨论】:

  • 为了帮助澄清一个令人困惑的句子,"as-if" 指的是 C++ 编译器的一条规则,它表示只要生成的代码符合要求,它们就可以进行任何代码转换好像它是原始的。这包括用它们的内联体替换函数调用。
【解决方案3】:

如果您的可执行文件有私有 pdb 符号文件,您可以编写一个简单的调试器来加载您的可执行文件并让您检查可执行文件。您可以在您感兴趣的功能上设置软件断点,它将中断您的调试器。根据它命中的断点,您可以使用 Microsoft Debug Interface Access SDK (DIA SDK) 获取有关该函数参数、返回值等的信息。查找 MinDBG,一个简单的 Win32 调试器,了解如何编写最简单的调试器.还可以查看 DIA SDK Api 的如何解密 exe。这只有在您的可执行文件有私有符号时才有效。

【讨论】:

    【解决方案4】:

    我没有得到确切的上下文,但也许你可以写一个其他 C++ 文件:

    • 重写函数

    • 记录参数、时间戳……

    • 调用被覆盖的函数

    类似的东西:

    void A::foo(a,b,c)
    {
      // log timestamp, parameters...
      B::foo(a,b,c);
      // log elapsed time, returned value...
    }
    

    【讨论】:

    • 我对这些事情没有意见。我在内存地址中找到该函数时遇到问题,它是基本参数,如返回类型和参数数量(如果可能的话,是他们的类型)
    猜你喜欢
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多