3

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

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

使用 Procmon 检测 LoadLibrary

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

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

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


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

4

2 回答 2

1

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

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

实际上只有一种可靠的方法可以实现这一目标,而且它真的不适合胆小的人。

我可以使用 Sysinternals Process Monitor (ProcMon) 手动完成此操作。

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


DLL 注入

在计算机编程中,DLL 注入是一种通过强制加载动态链接库来在另一个进程的地址空间内运行代码的技术。1 DLL 注入经常被外部程序用来影响另一个程序的行为,其作者没有预料到或不打算这样做。1 [2][3] 例如,注入的代码可以挂接系统函数调用,[4][5] 或读取密码文本框的内容,这是通常无法做到的。 [6] 用于将任意代码注入任意进程的程序称为 DLL 注入器。

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

基本上,您需要将 DLL 注入程序地址空间。最著名和最常用的方法是“导入表补丁”。每个 win32 模块(应用程序/DLL)都有一个所谓的“导入表”,它基本上是该模块调用的所有 API 的列表。修补此导入表是一项非常容易的工作,并且效果很好。

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

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

这是非常激烈的事情,但它比你想象的更常见。有编写的库使用在内核模式下工作的驱动程序,这些驱动程序适用于 64 位和 32 位应用程序,这些应用程序可以完成所有艰苦的工作,你基本上只是给它一个作用域一个 dll 和你想要挂钩的 api 的签名并编写一个代理人。它会照顾其余的。那时,您可以在任何您喜欢的地方对结果进行 IPC。

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

这里唯一的缺点是它必须使用传统的 DLL 而不是在 .net 中完成

总之祝你好运

于 2018-10-02T01:12:02.423 回答
-1

我只能假设你甚至没有尝试过。我已经做了

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 等)并尝试创建此文件夹中的文件,它仍然会被捕获。

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

于 2018-10-02T02:02:02.517 回答