问题描述
我正在开发一个 .NET
程序,它假设使用共享内存(内存映射文件)与同一台机器上的其他现有程序进行通信,现有程序本身包括一个本机 dll
和 {{ 1}} 包装器/桥接 .NET
,我可以使用它与其他程序通信。
问题是另一个程序有很多错误,程序和 dll
的源代码早已不复存在,所以我的目标是重新创建另一个程序。我可以反编译 dll
.NET
但它只是直接 dll
原生 P/Invoke
。
幸运的是,我能够使用 System.IO.MemoryMappedFiles.MemoryMappedFile
查看内存映射文件,但这就是我所得到的,我不知道 dll
在调用某些函数时从内存映射文件读取数据的偏移量从它(大部分时间dll
只做读不写)
我还尝试在 C++ 程序中挂钩 CreateFileMapping
、OpenFileMapping
和 MapViewOfFile
并调用本机 dll
中的某些函数,但这些挂钩函数仅在初始化期间调用一次并且在 dll
中调用函数时没有触发,假设从内存映射文件中读取数据。如果我敢猜测,dll
必须具有指向内存映射文件的指针。
所以我的问题是,是否可以放置断点或检测任何进程何时尝试读取/写入内存映射文件的某个区域?例如,我想知道在我的内存映射文件中是否有读取进程或指向偏移量 dll
的指针。我愿意接受其他选择,所以如果您有更好的主意,请告诉我
解决方法
我不熟悉内存映射文件,但如果两个进程共享相同的内存,我相信它具有相同的物理地址,如果这是真的,那么您可能可以在内核模式下使用 Cheat Engine。
请记住,它可能会导致系统不稳定或崩溃,因此请确保在继续之前保存所有工作。您可以按照以下步骤操作:
- 首先打开其中一个程序,确保在继续下一步之前创建了“共享内存”。
- 打开 Cheat Engine,确保在 Settings -> Extra 中为
OpenProcess
启用内核模式并在 Settings -> Debugger Options 中启用内核调试器(否则您将无法观察访问内存的指令) - 在 Cheat Engine 中打开进程,选择您在第一步中启动的程序
- 现在扫描作弊引擎内部的内存,因为你提到你可以查看内存,取出一些你想要监控的字节块,将值类型更改为字节数组并扫描这些字节
- 扫描结果会出现在左侧窗格中,您可能会发现多个结果,大多数情况下只有一个正确的地址,其余的与您扫描的值意外匹配,右键单击并选择浏览此内存区域,使确保周围数据符合您的预期
- 返回主窗口,双击正确的,它会出现在底部窗格中,右键单击它并选择“DBVM找出写入或访问此地址的内容”,将出现一个对话框(否则您的系统可能会崩溃) ,最重要的部分是确保那里的物理地址而不是出现在文本框
- 选择访问类型,您可以只看写或读和写,然后点击“开始看”按钮
- 每次任何进程尝试访问或写入该内存区域时,新指令都会出现在列表中。
在我看来,这个话题接近逆向工程。由于您愿意接受建议,这是我的另外两分钱:如果您计划重新创建通过共享内存发出数据的现有程序并且您也在开发客户端,为什么不从头开始重新制作它们所以你不必处理这个?
,如果知道具体的数据地址,可以使用windbg或x64dbg等调试器设置硬件数据断点。我不确定它与 C# 一起工作的效果如何,但绝对有可能。
您也可以尝试在windbg中使用时间旅行调试,它会记录程序的整个执行过程,并允许您在写入地址时进行追溯查询。