代码之家  ›  专栏  ›  技术社区  ›  ralphtheninja

如何捕获文件创建和负责的调用方

  •  0
  • ralphtheninja  · 技术社区  · 15 年前

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

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

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

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

    欢迎提出任何建议。

    干杯!

    2 回复  |  直到 15 年前
        1
  •  3
  •   Idan K    15 年前

    你可以试试:

    1. 使用类似工具 FileMon Process Explorer 他们可能足够追踪它了。
    2. 使用一个钩住一个库,并用自己的函数替换createfile(或者更多的函数,如果需要的话)。我有很好的经验 Detours 它有一些非常好的例子,您可以直接使用开箱即用。
        2
  •  2
  •   nhaa123    15 年前

    您需要使用自定义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;
    }

    然而,这还不够。您还需要从迂回中获益:

    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方法来传输数据。