【问题标题】:Debugging Memory Mapped Files调试内存映射文件
【发布时间】:2021-08-24 14:13:58
【问题描述】:

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

问题是其他程序有很多bug,程序的源代码和dll早已不复存在,所以我的目标是重新创建其他程序。我可以反编译.NETdll,但它只是直接P/Invoke本机dll

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

我还尝试在 C++ 程序中挂钩 CreateFileMappingOpenFileMappingMapViewOfFile 并在本机 dll 中调用某些函数,但这些挂钩函数仅在初始化期间调用一次,并且在调用函数时未触发dll 假设从内存映射文件中读取数据。如果我敢猜测,dll 肯定是指向内存映射文件的指针。

所以我的问题是,是否可以设置断点或检测任何进程何时尝试读取/写入内存映射文件的某些区域?例如,我想知道在我的内存映射文件中是否有读取进程或指针指向偏移量0xdeadbeef。我对替代方案持开放态度,所以如果您有更好的想法,请告诉我

【问题讨论】:

  • 一个文件映射对象被创建一次,通常只映射一次。从那时起,它就像其他任何东西一样只是记忆的垃圾。可以预料,文件映射 API 调用不超过一次。要了解内存区域何时发生变化,请使用您的调试器set a data breakpoint
  • @IInspectable 感谢您的回复,我更好地理解了为什么 API 只调用了一次。对于调试,您链接的页面显示“如果值已读取但未更改,则执行不会中断”,我需要跟踪读取的值,因为 dll 主要是读取操作。它还说它不适用于“内存位置在两个或多个进程之间共享”
  • 从内存中读取没有明显的副作用。我不知道有一种方法(使用调试器或其他方式)可以让您获得有关内存读取的通知。记录time-travel debugging 会话可能是您最好的选择,尽管我不确定查询内存读取操作有多难。

标签: c# c++ winapi shared-memory memory-mapped-files


【解决方案1】:

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

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

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

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

【讨论】:

  • 感谢您的回答,我尝试按照上述步骤进行操作,但是启用 OpenProcess 的额外设置以及内核调试器也是灰色的,我已经按下“使其成为可能”按钮并重新启动我的电脑,但它仍然是灰色的,有什么想法吗?至于你的建议,有多个现有客户端通过内存映射文件与其他程序通信,我不打算重写
  • 位搜索后,我需要禁用 Hyper V 才能让这个 DBVM 正常工作,谢谢!编辑:赞成,因为它帮助了我,有人反对这个答案
【解决方案2】:

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

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

【讨论】:

  • 您能否逐步添加我如何使用这些工具添加硬件断点?
猜你喜欢
  • 2016-02-23
  • 1970-01-01
  • 2010-11-01
  • 2011-05-14
  • 2016-12-08
  • 2010-09-26
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
相关资源
最近更新 更多