在'Any CPU'.NET程序集上强制使用x86 CLR

jef*_*ora 56 c# clr 64-bit code-injection

在.NET中,"Platform Target:Any CPU"编译器选项允许.NET程序集在x64计算机上以64位运行,在x86计算机上以32位运行.也可以使用"Platform Target:x86"编译器选项强制程序集在x64计算机上以x86身份运行.

是否可以使用"Any CPU"标志运行程序集,但是确定它是否应该在x86或x64 CLR中运行?通常,这个决定是由CLR/OS Loader(根据我的理解)基于底层系统的位数做出的.

我正在尝试编写一个可以与其他正在运行的进程交互(读取:注入代码)的C#.NET应用程序.x64进程只能注入其他x64进程,与x86相同.理想情况下,我想利用JIT编译和Any CPU选项,允许使用单个应用程序注入x64或x86进程(在x64机器上).

这个想法是应用程序将编译为任何CPU.在x64机器上,它将以x64运行.如果目标进程是x86,它应该重新启动它,强制CLR将其作为x86运行.这可能吗?

Oha*_*esh 60

您可以使用CorFlags应用程序找到应用程序的运行方式并静态更改它.要了解应用程序的运行方式,请使用:

corflags <PathToExe>
Run Code Online (Sandbox Code Playgroud)

要更改应用程序的运行方式,请使用:

corflags /32bit+  <PathToExe>
Run Code Online (Sandbox Code Playgroud)

这将使EXE文件作为32位进程运行.有关程序集应如何运行的信息存储在PE头中.请参阅堆栈溢出问题如何查找本机DLL文件是否编译为x64或x86?.

如果要在运行时注入代码,则必须在C++/COM中编写.NET分析器.有关更多详细信息,请参阅.NET Internals:Profiling APIProfiling(非托管API参考).

您需要实现JitCompilationStarted回调并在那里完成工作.如果您正朝着这个方向前进,那么您必须将注入DLL文件构建为x86和x64.一旦设置了以下环境变量,CLR将加载本机DLL文件:

Cor_Enable_Profiling=0x1
COR_PROFILER={CLSID-of-your-native-DLL-file}
Run Code Online (Sandbox Code Playgroud)

如果你设置正确,那么64位版本将"看到"64位进程,而32位版本将"看到"32位进程.

  • 我并不是希望进程在运行时更改它的上下文,而是说我将程序集a.exe编译为AnyCPU.它在x64机器上运行为64位.如果它需要注入32位,我希望它启动一个新的实例(Process.Start("a.exe"))并强制该新实例作为x86启动 (9认同)

jno*_*oss 9

我尝试过这段时间已经有一段时间了,但我相信调用程序集的进程的位数决定了它是否会被jit为x86或x64.

因此,如果您编写一个小型控制台应用程序并将其构建为x86,另一个编译为x64,则运行其中一个将导致加载到该进程中的其他程序集以32位或64位运行.当然,这假设您运行的是64位计算机.

  • 是的,我知道你可以通过将它包装在x86启动器程序集中来强制它,但我想知道你是否可以动态强制它为'任何CPU'编译的程序集.无论如何,如果我找不到其他任何东西,可能会回复到此.会投票但不足够的代表. (4认同)

Gra*_*ton 6

我不确定我是否可以帮助你.但这是我的经历.

我有一个主机应用程序,A.exe(编译为x86),我有一个客户端应用程序,B.exe(编译为ANY CPU),来自主机应用程序.我使用System.Diagnostic.ProcessB.exe从中启动.A.exe

现在的问题是,如果我将两者放在x64机器上,那么A.exe将以x86运行,B.exe将以x64运行.

但是如果A.exe调用程序集c(c.dll编译为Any CPU),并且B.exe还调用c.dll,则c.dll将跟随调用它的应用程序.换句话说,在A.exe调用它的64位机器中,它将表现得像x86dll,而当B.exe调用它时,它会表现得像x64.


Kar*_*rlW 6

我通过创建两个(实际上是三个)二进制文件做了类似的事情.我有一个检测我尝试注入的进程是32位还是64位.然后,此过程将启动注入二进制文件的32位或64位版本(而不是像您提到的那样重新启动自身).

这听起来很混乱,但您可以在构建时使用生成后事件轻松实现此功能,该事件生成输出二进制文件的副本并使用CorFlags实用程序强制复制以32位运行.这样您就不必在应用程序中部署CorFlags实用程序,这可能因某种原因而不合法.

我认为这与您最初的想法非常相似,除了两行构建事件外,实际上不需要更多工作.