有没有办法让 Windows 64 位上的应用程序在 64 位和 32 位仿真层下执行代码?

Posted

技术标签:

【中文标题】有没有办法让 Windows 64 位上的应用程序在 64 位和 32 位仿真层下执行代码?【英文标题】:Is there a way for application on Windows 64 bit to execute code both under 64 bit and 32 bit emulation layer? 【发布时间】:2011-05-16 07:11:43 【问题描述】:

我很感兴趣是否可以编写一个应用程序,它能够在没有仿真层的情况下调用一些代码以及在 32 位仿真层内部调用一些代码。

主要原因是我需要使用 API SetWindowHook 并且我想为 64 位和 32 位应用程序设置挂钩。

当然,我可以创建 2 个应用程序(一个用于 32 位,另一个用于 64 位)并同时启动它们。但是,我需要更多代码来管理它们(启动、停止、升级等)。

所以,我正在研究是否有可能拥有一个应用程序。

我唯一的想法是拥有一个应用程序和 2 个 COM DLL(32 位和 64 位)并使用代理进程来运行 32 位代码。但是,它需要一些额外的 COM 包装器等等。

【问题讨论】:

【参考方案1】:

我不能提出更好的方法,但我可以为您提供一个简单的基于钩子的工具的源代码,它可以完成完全相同的事情。随意对你有用的位:

http://www.pretentiousname.com/NoBarTab/NoBarTab_poc3.zip

(如果此 URL 将来中断,只需上一级;可能是因为我已经完成了它并为该工具及其来源放置了一个真实页面。)

这是一个 VS2010 C++ 项目,但应该很容易在旧 IDE 中编译。 (写这篇文章实际上让我暂时不再使用 VS2010,呵呵。)

显然,如果您使用它,请重命名任何窗口类和二进制名称,以避免与我的工具冲突。 (名称中带有“NoBarTab”的任何内容。)

FWIW,这是我几周前开始编写但尚未完成的工具。不过,挂钩部分已经完成。它挂钩窗口创建,以便它可以针对特定进程从 Windows 7 任务栏中删除选项卡。 (我特别讨厌 VMware 使用该功能的方式。)无论如何,当我完成它时,我打算发布源代码......

32/64 位挂钩部分全部完成。我唯一没有想到的是添加一个配置 UI,以便您可以指定它应该关注哪些进程,但这对于您正在做的事情并不重要。

(我应该说,我从 Win7 任务栏中删除选项卡的方式是一种完全的 hack,并且可能会与未来版本的 Windows 中断。没有记录的方法可以做到这一点,所以我不得不解决一个讨厌的问题。实际的挂钩不过,您感兴趣的代码都是“正确的”。)

另外,我做到了几乎所有真正的逻辑都在主 64 位 exe 中。 32 位 EXE 仅用于安装 32 位钩子 DLL,32 位和 64 位钩子 DLL 都只是将消息发布到主 64 位 exe 的隐藏窗口。这是否适合你正在做的事情,我让你来决定,但我认为这可能符合你希望尽可能将所有东西都放在一个地方的愿望。

希望有用!

【讨论】:

知道了。非常感谢。我会为此付出很多。 @Leo:如果运行钩子的进程上下文在另一个特权级别运行,则发布到另一个窗口对于 Vista 及更高版本将失败,不是吗?不过,对于解决方案的总体方向的内容,+1。 @STATUS_ACCESS_DENIED:如果需要,该进程可以允许该窗口消息通过(在 Win7 上这样做的 API 比在 Vista 上更好,但两者都可以)。最初的帖子没有提到任何关于任何被提升的进程,特权/UI 隔离是一个广泛的问题,会影响任何旨在与混合 IL 中的其他进程交互的代码,所以我认为它并不具体对于这个问题或这个解决方案,但我同意人们可能需要牢记这一点。 @Leo: 是的,我什至发现自己也经常忘记它,因为这些规则被插入到带有 Vista 的 Win32 中,有时当你可以做任何事情时,人们会渴望“旧时代 (tm)”不考虑安全的过程边界;)【参考方案2】:

SetWinEventHook 是一个高级挂钩 API,它为您处理 32 位/64 位的东西。这出现在另一个question today 的答案中,我认为在这里值得一提,以防万一解决了您的问题。感谢@atzz 在那里的回答。

SetWinEventHook 是否像较低级别的SetWindowsHookEx 一样适合您将取决于您正在做什么。 (就我而言,我可能会在我的其他答案中重新编写 NoBarTab 代码以使用更简单的 API。不过,还没有详细查看。)

【讨论】:

【参考方案3】:

模拟层的最大原因是您的 64 位代码将拥有更大的地址空间。例如,假设您的数据地址为 0x12345678aa000000。如果将该指针直接传递给 32 位代码,它将被截断为 32 位地址空间。也就是说,高位 32 位被移除。因此,对于您的 32 位代码,您的数据地址看起来像 0x00000000aa000000。这显然是一个完全不同的领域,而不是您想要的。

是的,这是可能的。不,您不应该这样做,除非您对 x86 和 x64 程序集非常有经验,并且可以访问 32 位源代码以确保它知道它实际上是在 64 位空间中运行并且还可以访问 64-位代码,以确保它传递给 32 位代码的所有数据都只在 32 位地址范围内。

不,不希望在没有仿真层的情况下执行 32 位代码,除非您尝试制作 UBER UGLY hack。

【讨论】:

我想看一个具体的例子,因为我不相信这是可能的 我会告诉你什么 - 你给我几天,也许一两个星期,看看我从 waaaay 开始真正非常古老的项目,当时我在 C++ 中使用 x86 内联 asm 和手动加载代码模块,我会给你一个具体的例子,不保证稳定性。 你能成功调用 SetWindowHook,就好像你是一个使用它的 32 位应用程序一样?我原以为操作系统仍然会将您视为 64 位进程,并且只允许您安装 64 位挂钩,尽管我不知道 Wow64 是如何在如此低的级别上真正工作的。你当然仍然需要一个 32 位的钩子 DLL,所以最多你会减少对额外进程的需求(但如果技术可靠,那仍然是一个巨大的胜利;事实上,它是额外的运行进程比额外的 DLL 更烦人)。 如果您能找到并分享有关此主题的信息,我将不胜感激。我不认为我会使用它(基于你对这个黑客丑陋的赞扬)。但是,很高兴看到它是如何完成的。 @inetknght:你有大约。 52-53 周 ;) ...你要更新你的问题吗?我也很好奇。【参考方案4】:

我认为你唯一的希望是通过进程外 COM 之类的方法来实现,因为每个进程都必须是全部 32 位或全部 64 位。

【讨论】:

以上是关于有没有办法让 Windows 64 位上的应用程序在 64 位和 32 位仿真层下执行代码?的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Windows 10 上的 python 3.6 64 位上运行 pyqt5(没有 anaconda 没有 virtualenv)

Windows 7 64 位上的 streamlit 安装错误

Windows 7 64 位上的 MercurialEclipse:不安装“Mercurial 的 Windows 二进制文件”

Windows 64 位上的 Qt Jambi eclipse 集成错误

无法启用 CURL - Windows 7 64 位上的 WAMP - PHP 5.3.13 Apache 2.2.22

如何在 Windows 7 64 位上安装 PyOpenSSL?