问题目前仅涉及 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
但所有这些都需要:
- 深入了解 PE 文件格式
- 大多数这些方法都不是调试器友好的。
我检查过的 - 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 是通过以下函数调用发生的:
NtOpenFile
,NtQueryAttributesFile
,NtCreateSection
/NtOpenSection
,NtMapViewOfSection
(*)
(更多信息可以在
https://github.com/Hagrid29/PELoader
https://gist.github.com/bats3c/59932dfa1f5bb23dd36071119b91af0f
我也在考虑是否可以覆盖 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:
- 不使用文件系统(不将 .dll 存储在临时文件夹中)
- 不涉及自定义驱动程序(如 Dokan)?
- 如此加载的 .dll 仍然对调试器友好吗?
- 不与 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/