c# - Forzar x86 CLR en un ensamblado.NET ''Any CPU''
64bit code-injection (4)
Ha pasado un tiempo desde que probé esto, pero creo que la fragilidad del proceso que llama al ensamblado determina si se JITeará como x86 o x64.
Entonces, si escribe una aplicación de consola pequeña y la construye como x86, y otra como x64, ejecutar una u otra hará que otros ensamblajes cargados en el proceso se ejecuten como 32 o 64 bits. Esto, por supuesto, asume que se está ejecutando en una máquina de 64 bits.
En .NET, la opción de compilación ''Plataforma objetivo: Cualquier CPU'' permite que un ensamblado .NET se ejecute como 64 bits en una máquina x64 y 32 bits en una máquina x86. También es posible obligar a un ensamblaje a ejecutarse como x86 en una máquina x64 utilizando la opción del compilador ''Plataforma objetivo: x86''.
¿Es posible ejecutar un ensamblado con el indicador "Cualquier CPU", pero determinar si se debe ejecutar en el CLR x86 o x64? Normalmente, esta decisión la toma CLR / OS Loader (según entiendo) basada en la bitidez del sistema subyacente.
Intento escribir una aplicación C .NET que pueda interactuar con (leer: inyectar código) otros procesos en ejecución. Los procesos x64 solo pueden inyectarse en otros procesos x64, y lo mismo con x86. Idealmente, me gustaría aprovechar la compilación JIT y la opción Cualquier CPU para permitir que una sola aplicación se use para inyectar en procesos x64 o x86 (en una máquina x64).
La idea es que la aplicación se compile como Cualquier CPU . En una máquina x64, se ejecutaría como x64. Si el proceso objetivo es x86, debe reiniciarse, lo que obliga al CLR a ejecutarlo como x86. es posible?
He hecho algo similar creando dos (realmente tres) binarios. Tuve uno para detectar si el proceso que estaba tratando de inyectar era de 32 o 64 bits. Este proceso lanzará la versión de 32 bits o de 64 bits de su inyección binaria (en lugar de reiniciarse como usted mencionó).
Suena complicado, pero puede lograrlo fácilmente en el momento de la compilación con un evento posterior a la compilación que hace una copia de su CorFlags binario de salida y utiliza la utilidad CorFlags para forzar la copia a ejecutarse como de 32 bits. De esta forma, no tiene que implementar la utilidad CorFlags con su aplicación, que probablemente no sea legal por algún motivo de todos modos.
Creo que esto es bastante similar a su idea inicial y realmente no requiere más trabajo a excepción de un evento de compilación de dos líneas.
No estoy seguro de si puedo ayudarte con esto. Pero esta es mi experiencia.
Tengo una aplicación host, A.exe
(compilada como x86), y tengo una aplicación cliente, B.exe
(compilada como ANY CPU
), desde la aplicación host. Y B.exe
desde A.exe
, utilizando la clase System.Diagnostic.Process .
El problema ahora es si pongo los dos en una máquina x64, entonces A.exe
se ejecutará como x86, mientras que B.exe
se ejecutará como x64 .
Pero si A.exe
llama a assembly c ( c.dll
, que se compila como Any CPU
), y B.exe
también llama a c.dll
, entonces c.dll seguirá la aplicación que lo llame. En otras palabras, en la máquina de 64 bits cuando A.exe
llama, se comportará como x86
dll, mientras que cuando B.exe
llame, se comportará como x64
.
Puede encontrar cómo se ejecutará la aplicación y cambiarla estáticamente utilizando la aplicación CorFlags . Para saber cómo se ejecutará la aplicación, use:
corflags <PathToExe>
Para cambiar cómo se ejecutará la aplicación, use:
corflags /32bit+ <PathToExe>
Esto hará que el archivo EXE se ejecute como un proceso de 32 bits. La información sobre cómo debe ejecutarse el ensamblaje se almacena en el encabezado PE. Consulte Pregunta de desbordamiento de pila ¿ Cómo encontrar si un archivo DLL nativo está compilado como x64 o x86? .
Si desea inyectar código en tiempo de ejecución, debe escribir un generador de perfiles .NET en C++ / COM. Consulte .NET Internals: Profiling API y Profiling (Referencia de la API no administrada) para obtener más detalles.
Tendrá que implementar la devolución de llamada JitCompilationStarted y hacer su trabajo allí. Si estás en esta dirección, tendrás que compilar el archivo DLL de inyección tanto como x86 como x64. Los archivos DLL nativos serán cargados por el CLR una vez que se establezcan las siguientes variables de entorno:
Cor_Enable_Profiling=0x1
COR_PROFILER={CLSID-of-your-native-DLL-file}
Si lo tiene configurado correctamente, entonces la versión de 64 bits ''verá'' los procesos de 64 bits y la versión de 32 bits ''verá'' los procesos de 32 bits.