在 .NET 中,“平台目标:任何 CPU”编译器选项允许 .NET 程序集在 x64 计算机上以 64 位运行,在 x86 计算机上以 32 位运行。还可以使用“平台目标:x86”编译器选项强制程序集在 x64 计算机上作为 x86 运行。
是否可以运行带有“任何 CPU”标志的程序集,但确定它应该在 x86 还是 x64 CLR 中运行?通常这个决定是由 CLR/OS 加载器(据我的理解)根据底层系统的位数做出的。
我正在尝试编写一个 C# .NET 应用程序,它可以与其他正在运行的进程交互(读取:将代码注入到其中)。 x64进程只能注入其他x64进程,x86也是如此。理想情况下,我想利用 JIT 编译和 Any CPU 选项来允许使用单个应用程序注入 x64 或 x86 进程(在 x64 计算机上)。
这个想法是应用程序将被编译为任何CPU。在 x64 机器上,它将作为 x64 运行。如果目标进程是 x86,它应该重新启动自身,强制 CLR 将其作为 x86 运行。这可能吗?
In .NET, the 'Platform Target: Any CPU' compiler option allows a .NET assembly to run as 64 bit on a x64 machine, and 32 bit on an x86 machine. It is also possible to force an assembly to run as x86 on an x64 machine using the 'Platform Target: x86' compiler option.
Is it possible to run an assembly with the 'Any CPU' flag, but determine whether it should be run in the x86 or x64 CLR? Normally this decision is made by the CLR/OS Loader (as is my understanding) based on the bitness of the underlying system.
I am trying to write a C# .NET application that can interact with (read: inject code into) other running processes. x64 processes can only inject into other x64 processes, and the same with x86. Ideally, I would like to take advantage of JIT compilation and the Any CPU option to allow a single application to be used to inject into either x64 or x86 processes (on an x64 machine).
The idea is that the application would be compiled as Any CPU. On an x64 machine, it would run as x64. If the target process is x86, it should relaunch itself, forcing the CLR to run it as x86. Is this possible?
发布评论
评论(4)
您可以使用 CorFlags 应用程序。要了解应用程序将如何运行,请使用:
要更改应用程序将如何运行,请使用:
这将使 EXE 文件作为 32 位进程运行。有关程序集如何运行的信息存储在 PE 标头中。请参阅 Stack Overflow 问题如何查找本机 DLL 文件是编译为 x64 还是 x86?。
如果你想在运行时注入代码,你必须编写一个 .NET 分析器C++/COM。
请参阅.NET 内部结构:分析 API< /em> 和分析(非托管 API 参考)< /em> 了解更多详细信息。
您需要实现 JitCompilationStarted 回调并在那里完成您的工作。如果您朝这个方向发展,则必须将注入 DLL 文件构建为 x86 和 x64。 ,CLR 将加载本机 DLL 文件:
设置以下环境变量后 如果设置正确,那么 64 位版本将“看到”64 位进程,32 位版本将“看到”32 位进程。
You can find out how an application will run and change it statically using the CorFlags application. To find out how the application will run, use:
To change how the application will run, use:
This will make the EXE file run as a 32-bit process. The information about how the assembly should run is stored in the PE header. See Stack Overflow question How to find if a native DLL file is compiled as x64 or x86?.
If you want to inject code at run time, you have to write a .NET profiler in C++/COM.
See .NET Internals: The Profiling API and Profiling (Unmanaged API Reference) for more details.
You'll need to implement the JitCompilationStarted callback and do your work there. If you go in this direction, you'll have to build the injecting DLL file both as x86 and x64. The native DLL files will be loaded by the CLR once the following environment variables will be set:
If you have it set correctly then the 64-bit version will 'see' the 64 bit processes and the 32-bit version will 'see' the 32-bit processes.
我尝试这个已经有一段时间了,但我相信调用程序集的进程的位数决定了它是否会被 JIT 为 x86 还是 x64。
因此,如果您编写一个小型控制台应用程序并将其构建为 x86,另一个构建为 x64,则运行其中一个或另一个将导致加载到进程中的其他程序集以 32 或 64 位运行。当然,这是假设您在 64 位计算机上运行。
It has been a while since I tried this, but I believe that the bitness of the process that calls the assembly determines whether it will be JITed as x86 or x64.
So if you write a small console application and build it as x86, and another as x64, running one or the other will cause other assemblies loaded into the process to run as 32 or 64 bit. This, of course, assumes you are running on a 64 bit machine.
我不确定我是否可以帮助你解决这个问题。但这是我的经验。
我有一个主机应用程序,
A.exe
(编译为 x86),还有一个客户端应用程序,B.exe
(编译为ANY CPU),来自主机应用程序。我使用 A.exe
启动B.exe
。 Diagnostics.process.aspx" rel="noreferrer">System.Diagnostic.Process 类。现在的问题是,如果我将两者放在 x64 计算机上,则
A.exe
将作为 x86 运行,而B.exe
将作为 x64 运行< /强>。但是,如果
A.exe
调用程序集 c(c.dll
,编译为Any CPU
),并且B.exe< /code> 也会调用
c.dll
,然后 c.dll 将跟随调用它的应用程序。换句话说,在64位机器上,当A.exe
调用它时,它的行为就像x86
dll,而当B.exe
调用它时,它的行为类似于 x64。I'm not sure whether I can help you with this. But this is my experience.
I have a host application,
A.exe
( compiled as x86), and I have a client application,B.exe
( compiled asANY CPU
), from the host application. And I launchB.exe
fromA.exe
, using the System.Diagnostic.Process class.The issue now is if I put the two on a x64 machine, then
A.exe
will run as x86, whereas theB.exe
will run as x64.But if
A.exe
calls assembly c (c.dll
, which is compiled asAny CPU
), andB.exe
also callsc.dll
, then c.dll will follow the application that calls it. In other words, in 64 bit machine whenA.exe
calls it, it will behave likex86
dll, whereas whenB.exe
calls it, it will behave likex64
.我通过创建两个(实际上是三个)二进制文件做了类似的事情。我检测了我尝试注入的进程是 32 位还是 64 位。然后,此过程将启动注入二进制文件的 32 位或 64 位版本(而不是像您提到的那样重新启动自身)。
这听起来很混乱,但您可以在构建时通过构建后事件轻松实现此目的,该事件会复制输出二进制文件并使用 CorFlags 实用程序强制副本以 32 位运行。这样,您就不必在应用程序中部署 CorFlags 实用程序,无论如何,这可能由于某种原因是不合法的。
我认为这与您最初的想法非常相似,除了两行构建事件之外,实际上不需要更多的工作。
I've done something similar by creating two (really three) binaries. I had one detect whether the process I was trying to inject into was 32 or 64-bit. This process will then launch either the 32-bit or 64-bit version of your injection binary (as opposed to relaunching itself like you mentioned).
It sounds messy, but you can easily achieve this at build time with a post-build event that makes a copy of your output binary and uses the CorFlags utility to force the copy to run as 32-bit. This way you don't have to deploy the CorFlags utility with your application, which probably isn't legal for some reason anyway.
I think this is quite similar to your initial idea and really doesn't require more work except for a two-line build event.