【问题标题】:How to catch file creation and the responsible caller如何捕获文件创建和负责的调用者
【发布时间】:2009-05-26 12:37:08
【问题描述】:

我们正在使用第三方库来渲染 3d。在这个库中,有一个“内存跟踪器”功能,可以跟踪库在执行期间分配和释放的所有内存。这是一个很好的功能,因为它有助于确定例如内存泄漏。

通过调用该库中的某个函数,会在进程的当前工作目录中生成一个日志文件。最近我注意到这个文件出现在几个不同的地方,所以我的第一个想法当然是总是将当前工作目录设置为我希望显示日志的文件夹,这很好。

然而,事实证明,这个文件仍然是在不同的地方创建的,而没有被程序调用过上述函数。因此,该文件必须在未经我同意的情况下由库以某种方式创建。这个库的创建者说引擎从不在内部调用这个方法。

所以,为了证明他是错的(或者证明自己是愚蠢的(虽然这不是第一次)),我需要一种方法来准确地捕捉这个文件的创建时间。 FindFirstChangeNotification() 不会这样做,因为这只会向我提供某些文件夹中发生的事情的信息。理想情况下,我想(在进程内或进程外)在发生这种情况时进行拦截并以某种方式注入进程异常(例如让 WinDbg 捕获这个),所以我通过调用堆栈获取我想要的信息。

欢迎提出任何建议。

干杯!

【问题讨论】:

    标签: c++ winapi file debugging creation


    【解决方案1】:

    你可以试试:

    1. 使用FileMonProcess Explorer 之类的工具,它们可能足以追踪到它。
    2. 使用挂钩库并用您自己的函数替换 CreateFile(或更多函数,如果需要)。我对Detours 有很好的体验,它有一些非常好的示例,您可以直接使用。

    【讨论】:

      【解决方案2】:

      您需要使用自定义 CreateFile 创建注入 DLL,如下所示:

      /** We'll create a custom version of the CreateFile (WinAPI).
        *
        *
        */
      HANDLE WINAPI __CreateFile(LPCWSTR fileName,
                                 DWORD desiredAccess,
                                 DWORD shareMode,
                                 LPSECURITY_ATTRIBUTES securityAttributes,
                                 DWORD createDisp,
                                 DWORD flags,
                                 HANDLE tmp)
      {
              // At very first, we shall call the original CreateFile.
      
              HANDLE file = Real_CreateFile(fileName,
                                            desiredAccess,
                                            shareMode,
                                            securityAttributes,
                                            createDisp,
                                            flags,
                                            tmp);
      
              /** Here, you can do whatever you wish with fileName and the handle, file.
                *
                * ...
                */
      
              return file;
      }

      但是,这还不够。您还需要从 Detours 中受益:

      BOOL APIENTRY DllMain(HANDLE module, DWORD reasonForCall, LPVOID reserved)
      {
              switch (reasonForCall) {
                      case DLL_PROCESS_ATTACH: {
                              if (::GetModuleHandle(L"blablabla.exe") == NULL) {
                                      DetourTransactionBegin();
                                      DetourUpdateThread(GetCurrentThread());
                                      DetourAttach(&(PVOID &)Real_CreateFile, __CreateFile);
                                      DetourTransactionCommit();
                      }
      
                      break;
      
                      case DLL_THREAD_ATTACH: {
                      }
      
                      break;
      
                      case DLL_THREAD_DETACH: {
                      }
      
                      break;
      
                      case DLL_PROCESS_DETACH: {
                              if (::GetModuleHandle(L"blablabla.exe") == NULL) {
                                      DetourTransactionBegin();
                                      DetourUpdateThread(GetCurrentThread());
                                      DetourDetach(&(PVOID&)Real_CreateFile, __CreateFile);
                                      DetourTransactionCommit();
                              }
                      }
          }
      
          return TRUE;
      }

      剩下的留给你练习吧。这只是一个方向。您还需要找到合适的 IPC 方法来进行数据传输。

      【讨论】:

        猜你喜欢
        • 2018-08-16
        • 2021-07-29
        • 1970-01-01
        • 2012-08-20
        • 2019-10-05
        • 1970-01-01
        • 1970-01-01
        • 2018-03-14
        • 2015-01-06
        相关资源
        最近更新 更多