如何检测何时在目录中检查文件?

How to detect when a file is checked for in a directory?

我希望能够以编程方式 (C#) 检测程序何时试图从我 control/own 在 Windows 上的目录加载(或以其他方式访问)不存在的 DLL。

我可以使用 Sysinternals Process Monitor (ProcMon) 手动完成此操作。例如,使用下面显示的过滤器,我能够检测到 ClientPrj.exe 程序试图从我的目录加载 dll (GetEvenOdd.dll)控制 (C:\MyDirectory);

如何以编程方式完成类似的事情?

到目前为止,我的尝试涉及手动启用 Windows 对文件夹、运行 程序的审核,然后检查 Windows 事件日志中的任何审核条目,但没有新条目条目出现在与此文件夹相关的事件日志中。

请注意,我并不想完全复制 procmon,我只是想检测何时尝试从我控制的目录加载文件(在本例中为 DLL)。


旁注;我不清楚为什么 ProcMon 将加载 DLL 的尝试列为 "CreateFile" 操作,因为 "ClientPrj.exe" 程序只是试图加载 DLL(在 C++ 中,"ClientPrj.exe" 程序正在使用LoadLibrary 加载 DLL 的方法)。

我认为回答这个问题很安全,

I want to be able to programmatically (C#) detect when a program attempts to load (or otherwise access) a non-existent DLL from a directory that I control/own on Windows.

确实只有一种可靠的方法可以实现这一点,而且它真的不适合胆小者。

I can manually accomplish this using Sysinternals Process Monitor (ProcMon).

ProcMon 是一个非常复杂的应用程序,它利用内核模式中的各种黑魔法来实现它的功能


DLL injection

In computer programming, DLL injection is a technique used for running code within the address space of another process by forcing it to load a dynamic-link library.1 DLL injection is often used by external programs to influence the behavior of another program in a way its authors did not anticipate or intend.1[2][3] For example, the injected code could hook system function calls,[4][5] or read the contents of password textboxes, which cannot be done the usual way.[6] A program used to inject arbitrary code into arbitrary processes is called a DLL injector.

前提非常简单,而且它是一种很好用的技术来做各种事情。

基本上,你需要在程序地址space中注入一个DLL。最著名和最常用的方法是 "Import Table Patching"。每个 win32 模块 (application/DLL) 都有一个所谓的 "import table",它基本上是该模块调用的所有 API 的列表。修补这个 import table 是一项非常简单的工作,而且效果很好。

还有一个更健壮的方法是,你也可以直接在内存中操作API的二进制代码。最常用的方法是用 JMP 指令覆盖 API 代码的前 5 个字节,然后跳转到您的回调函数。

在你的情况下,你想在你的目标应用程序中找到 LoadLibrary,JMP 到一个代理,你可以在其中监视加载的库以及调用的结果,然后将结果传回给原始调用者。

这是非常激烈的事情,但它比你想象的更常见。有一些库使用在内核模式下工作的驱动程序编写,这些驱动程序适用于 64 位和 32 位应用程序,可以处理所有繁重的工作,你基本上只需给它一个范围,一个 dll 和你想要挂钩的 api 的签名,然后编写一个代理。它会处理剩下的事情。届时,您可以在任何您喜欢的地方对结果进行 IPC。

您的第一个问题是在加载目标库之前设置一个挂钩。然而,这一切都已经为你完成了。看看 http://help.madshi.net/madCodeHook.htm

onyl 的缺点是必须使用传统的 DLL 而不是在 .net 中完成

总之祝你好运

我只能假设你还没有尝试过。我刚刚做了

private FileSystemWatcher fsWatcher;

public void SetupWatcher()
{
   fsWatcher = new FileSystemWatcher();
   fsWatcher.Path = @"C:\SomePath\SomeSubFolder\";
   fsWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
            | NotifyFilters.FileName | NotifyFilters.DirectoryName;
   fsWatcher.Filter = "*.*";
   fsWatcher.Changed += FsWatcher_Changed;
   fsWatcher.EnableRaisingEvents = true;

   System.IO.File.WriteAllText(fsWatcher.Path + "MyFile.txt", "testing" );
}

private void FsWatcher_Changed(object sender, FileSystemEventArgs e)
{
   var msg = "Action " + e.ChangeType + "\r\n"
           + "FullPath " + e.FullPath + "\r\n"
           + "Just File Name " + e.Name;

   MessageBox.Show(msg);
}

因此,即使文件夹中不存在我的 "MyFile.txt",只要我尝试写入、创建等,就会调用 FsWatcher_Changed 事件处理程序。然后我可以检查更改类型、文件路径、文件名等。从中您可以检测并确认文件名是否符合您的预期(或不是)并根据需要采取行动。

来自评论的反馈...

根据另一个程序...如果我 运行 我的程序带有上面的示例 SystemFileWatcher 并且正在侦听有问题的整个文件夹.. 然后我转到另一个应用程序(甚至例如:Word , Excel, 随便) 并尝试在此文件夹中创建文件,它仍然会被捕获。

如果另一个程序试图打开一个不存在的文件,该程序无论如何都会失败。如果另一个程序无法验证要打开的不存在的文件,您为什么一定要关心。那是其他程序的问题?