【发布时间】:2015-10-26 15:00:33
【问题描述】:
目前我们正在研究在 x64 平台上将 DLL 手动加载到较低 4Gbs 的进程虚拟地址空间中。之所以需要它,是因为 DLL 是在任何地方都明确使用 32 位类型编写的,并且无法重写。所以我们要在项目中使用这个特性,我们要确保 DLL 只使用较低的 4Gbs 来保持工作。
网上有一些实现手动加载 DLL 的链接,我们以此为基础:link
此变体有效。目前只检测到一些问题:
- 现在无法使用源进行调试,操作系统只是看不到此模块,它只是它的内存区域,没有其他内容,因此没有加载 PDB。
- 我们的项目是这样实现的,即 DLL 从一些有效负载所在的外部框架调用函数。然后在框架中引发异常(故意,而不是偶尔),这就是问题发生的地方。此异常仍未处理,但处理程序存在于框架的代码中。
当通过 x86 或 x64 上的 LoadLibrary 加载 DLL 时(我们很幸运,它加载到较低的 4Gbs 区域)一切正常。我们可以看到整个 SEH 链(例如在 WinDbg 中)并且异常处理得很好。
当手动加载 DLL 时,WinDbg 显示如下:
>!exchain
Frame 0x01: MSVCR120D!__ExceptionPtr::_RethrowException+0x1e1 (000007fe`d9cf4281)
ehandler MSVCR120D!__GSHandlerCheck (000007fe`d9e11eb0)
Frame 0x0b: error getting module for 000000000214daa1
Frame 0x0c: error getting module for 0000000000000003
Frame 0x0d: error getting module for 0000000100000000
Frame 0x0e: error getting module for 0000000002ffa420
Frame 0x0f: error getting module for 0000000100000000
Frame 0x10: error getting module for 0000000000000004
我们尝试关闭/SafeSEH 选项,但结果相同。我们这样做是因为一种猜测是操作系统可以拒绝处理不在受保护模块中的异常处理程序。
目前对为什么会发生这种情况的猜测是操作系统需要这么说内部可见的模块(在通过合法系统函数 LoadLibrary 加载 DLL 的过程中创建了一些内核对象)异常链可以通过。
您如何看待这个问题的可能解决方案?
编辑:在下面回答。
【问题讨论】:
-
我想知道这个问题的缺点的原因。是不是写的太复杂了?是哑巴吗?请随时分享您的想法,而不是简单的点击。
-
您尝试加载的 .dll 是否指定了图像库?我对在 64 位 Windows 上加载 32 位模块并不熟悉,但我猜你可以使用 rebase.exe SDK 工具为你的模块提供低于 4GB 的图像库,Windows 会尝试在那里加载它你。
-
您忘记通过RtlAddFunctionTable 添加展开表。
标签: c++ windows exception-handling 64-bit loadlibrary