c++ - 以调试器友好的方式从 RAM 加载 native C++ .dll

标签 c++ dll native

问题目前仅涉及 Windows - 其他操作系统目前不那么相关。

只需通过快速谷歌搜索 - 就可以从 RAM 加载 native .dll,例如以下库:

https://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/

=>

https://github.com/fancycode/MemoryModule

https://forum.nim-lang.org/t/7943

但所有这些都需要:

  1. 深入了解 PE 文件格式
  2. 大多数这些方法都不是调试器友好的。

我检查过的 - Windows 的 LoadLibraryA/LoadLibraryW 被定向到 ntdll.dll/LdrLoadDll - 最好的事情是如何工作的从这里找到:https://github.com/hlldz/RefleXXion

即便如此,我也没有 Windows 源代码 - 我已经检查了 Wine 的相同功能:

LdrLoadDll:https://source.winehq.org/source/dlls/ntdll/loader.c#3169

load_dll: https://source.winehq.org/source/dlls/ntdll/loader.c#3083

load_native_dll: https://source.winehq.org/source/dlls/ntdll/loader.c#2564

NtMapViewOfSection: https://source.winehq.org/source/dlls/ntdll/unix/virtual.c#4469

找到_dll_文件:https://source.winehq.org/source/dlls/ntdll/loader.c#3021

open_dll_file: https://source.winehq.org/source/dlls/ntdll/loader.c#2467

怀疑加载 dll 是通过以下函数调用发生的: NtOpenFileNtQueryAttributesFileNtCreateSection/NtOpenSectionNtMapViewOfSection (*)

(更多信息可以在

https://github.com/Hagrid29/PELoader

https://gist.github.com/bats3c/59932dfa1f5bb23dd36071119b91af0f

https://www.octawian.ro/fisiere/situri/asor/build/html/_downloads/122f95f9a032396603a837c53b125bb8/Russinovich_M_WinInternals_part1_7th_ed.pdf )

我也在考虑是否可以覆盖 NtOpenFile 并重定向打开的文件(在 https://github.com/SegaraRai/PathRedirector方式) 到不同的路径 - 但主要问题是存储文件的替代位置是什么?

我在想如果 NtOpenFile 甚至可以打开设备,那么也许只是替换文件 使用某种命名管道 ( https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-client ) - 但随后在 map 中说明这与 NtMapViewOfSection 的配合情况。

由于我无法找到此类 Hook 或操作的任何工作示例(例如 LoadLibary("\\.\pipe\mynamedpipe_as_dll"))- 此类组合始终存在风险不只是支持。

是否可以完全从 RAM 加载 native .dll:

  1. 不使用文件系统(不将 .dll 存储在临时文件夹中)
  2. 不涉及自定义驱动程序(如 Dokan)?
  3. 如此加载的 .dll 仍然对调试器友好吗?
  4. 不与 PE 文件格式结构紧密绑定(bind)(或尽可能少使用 PE 结构)

如果您错过了更多信息,请查看我自己的原生 dll 加载实验(也许可以提供一些解决问题的提示):

https://github.com/tapika/test_native_dll_loading https://github.com/tapika/test_native_dll_loading/discussions/2

最佳答案

区分调试用例和发布用例。在调试中,将 DLL 保存在临时文件中并使用 LoadLibrary 加载,这将启用调试。在发行版中,从内存运行,没有调试功能。

这是另一个想法,来自于考虑链接的 Guthub 问题。如果目的是让用户在构建 ReadyToRun 可执行文件时提供他们自己的压缩/解压缩逻辑,则让他们将其作为静态 库(对象)而不是 DLL 提供。更大的项目已经在将内容打包到单个可执行文件中,可能会在其中进行一些链接。

另一个想法是让用户以某种解释语言提供编解码器,并可选择插入支持调试的解释器。 Windows 带有一个内置的 JavaScript 解释器,查找事件脚本,调试它们是免费的奖励。不过,性能可能无法与 native 代码实现相提并论。

关于c++ - 以调试器友好的方式从 RAM 加载 native C++ .dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72248319/

相关文章:

reactjs - 更改 React-Native-Material-Design 模块中按钮的背景颜色

android - native Android-加载共享库时,即使先前加载的共享库包含定义,也无法找到未定义的方法

c++ - 我的运算符(operator)有什么问题 <?

c++ - 如何在不安装Windows SDK的情况下在客户端PC上使用编译好的DLL?

c++ - 在 DLL 中包装类的优点

windows - 如果加载它的 DLL 被卸载,DLL 是否会被删除?

.net - 在 C# dll 中缓存数据的最佳方法是什么?

c++ - 在 Node.js C++ 插件中,永远不会调用 SetWindowsHookEx 的回调

c++ - 如何使用 emplace with hint 和 map of maps?

c++ - 具有固定值枚举器的枚举的零初始化