调试内存映射文件

Debugging Memory Mapped Files

我正在开发一个 .NET 程序,该程序假设使用共享内存(内存映射文件)与同一台机器上的其他现有程序通信,现有程序本身包括一个本地 dll.NET 包装器/桥 dll 我可以使用它来与其他程序通信。

问题是另一个程序有很多错误,程序的源代码和 dll 早就不见了,所以我的目标是重新创建另一个程序。我可以反编译 .NET dll 但它直接 P/Invoke 原生 dll.

幸运的是,我能够使用 System.IO.MemoryMappedFiles.MemoryMappedFile 查看内存映射文件,但这就是我所得到的,我不知道 dll 在我调用时从内存映射文件读取数据的偏移量它的某些功能(大多数时候 dll 只读不写)

我也试过在C++程序中hook CreateFileMapping, OpenFileMapping and MapViewOfFile 并在native dll 中调用某些函数,但是那些hook 函数只在初始化期间调用一次并且在调用函数时没有触发 dll 假设从内存映射文件中读取数据。如果我敢猜的话,dll 一定有指向内存映射文件的指针。

所以我的问题是,是否可以设置断点或检测任何进程何时尝试读取/写入内存映射文件的特定区域?例如,我想知道在我的内存映射文件中是否有读取进程或指针指向偏移量 0xdeadbeef。我愿意接受其他选择,如果您有更好的主意,请告诉我

我不熟悉内存映射文件,但如果两个进程共享相同的内存,我相信它具有相同的物理地址,如果这是真的那么你可能可以在内核模式下使用 Cheat Engine

请记住,它可能会导致系统不稳定或崩溃,因此请确保在继续之前保存您的所有作品。您可以按照以下步骤操作:

  1. 首先打开其中一个程序,确保在进行下一步之前创建“共享内存”。
  2. 打开作弊引擎,确保在设置 -> 额外中为 OpenProcess 启用内核模式,并在设置 -> 调试器选项中启用内核调试器(否则你将无法观察访问指令记忆)
  3. 在Cheat Engine中打开进程,select第一步启动的程序
  4. 现在扫描作弊引擎中的内存,因为你提到你可以查看内存,取出一些你想监控的字节块,将值类型更改为字节数组并扫描这些字节
  5. 扫描结果将出现在左窗格中,您可能会找到多个结果,大多数情况下只有一个正确的地址,其余的与您扫描的值不小心匹配,右键单击并 select浏览此内存区域,确保周围的数据与您期望的相匹配
  6. 回到主window,双击正确的,它会出现在底部窗格中,右键单击它和select“DBVM找出什么写或访问这个地址”,一个对话框将出现(否则您的系统可能会崩溃),最重要的部分是确保那里的物理地址而不是出现在文本框
  7. Select 访问类型,您可以只观看写入或同时读取和写入并点击“开始观看”按钮
  8. 每次任何进程尝试访问或写入该内存区域时,新指令都会出现在列表中。

在我看来,这个题目已经接近于逆向工程了。既然你对建议持开放态度,这是我的另外两分钱:如果你有计划重新创建通过共享内存发出数据的现有程序并且你也在开发客户端,为什么不从头开始重新制作它们所以你不必处理这个?

如果知道具体的数据地址,可以使用windbg或x64dbg等调试器设置硬件数据断点。我不确定它与 C# 一起工作的效果如何,但绝对有可能。

你也可以尝试使用windbg中的时间旅行调试,它记录了程序的整个执行过程,可以在某个地址被写入时追溯查询。