Bueno ... ¿cómo definirías "pure .NET"? Jugué con Clr2/delegado/GCHandle/matriz cuando leí el post "¿Cómo bloqueo de JVM", y se acercó con algo como esto:
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace TestCLR2Crash {
static void Main(string[ ] args) {
// declare a delegate that refers to a static method,
// in this case it's a static method generated from the
// anonymous delegate.
Action action = delegate() { };
// "generate" code into an array of uint
var fakeDelegate = new uint[ ] {
// dummy values
0x00000000, 0x00000000,
// fake _methodPtrAux
0x00000000,
// native code/string
0x6AEC8B55, 0x2FD9B8F5, 0xD0FF7C81, 0x006A006A,
0x00E81F6A, 0x83000000, 0x50102404, 0x81CC5DBA,
0x8BD2FF7C, 0x47C35DE5, 0x74656572, 0x73676E69,
0x6F726620, 0x6567206D, 0x6172656E, 0x20646574,
0x65646F63, 0x00000A21
};
// fill in the fake _methodPtrAux,
// make it point to the code region in fakeDelegate
var handle = GCHandle.Alloc(fakeDelegate, GCHandleType.Pinned);
var addr = handle.AddrOfPinnedObject();
const int sizeOfUInt32 = sizeof(uint); // 4
const int indexOfCode = 3;
fakeDelegate[ 2 ] = Convert.ToUInt32(addr.ToInt32() + sizeOfUInt32 * indexOfCode);
var targetInfo = typeof(Action)
.GetField("_target", BindingFlags.NonPublic | BindingFlags.Instance);
targetInfo.SetValue(action, fakeDelegate);
action(); // Greetings from generated code!
Console.WriteLine("Greetings from managed code!");
handle.Free();
}
}
}
Sólo se sabe que funciona en 32 bits Windows XP con Clr2 en x86; y también se sabe que no funciona con Vista y Windows 7 y similares, donde DEP + ASLR está activado por defecto.
Lo divertido del código anterior es que no usaba explícitamente código no seguro (aunque GCHandle.Alloc (..., GCHandleType.Pinned) exige privilegios de seguridad), pero logra falsificar una matriz en una delegar instancia y llama al código máquina x86 dentro de la matriz. El código en sí es puro C#, si no cuenta el código x86 incrustado como un "idioma extranjero" ;-) Básicamente hace uso de la implementación interna de los delegados de CLR2 en métodos estáticos, que algunos miembros privados del Delegado son en realidad punteros internos Rellené el código x86 en una matriz, que se asigna en el montón administrado. Entonces, para que esto funcione, DEP no debe estar habilitado, o tendremos que buscar otra forma de obtener privilegios de ejecución en esa página de memoria.
código El 86 es la siguiente: (en la sintaxis de pseudo-MASM)
55 push ebp
8BEC mov ebp,esp
6A F5 push -0B ; /DevType = STD_OUTPUT_HANDLE
B8 D92F817C mov eax,KERNEL32.GetStdHandle ; |
FFD0 call eax ; \GetStdHandle
6A 00 push 0 ; /pReserved = NULL
6A 00 push 0 ; |pWritten = NULL
6A 1F push 1F ; |CharsToWrite = 1F (31.)
E8 00000000 call <&next_instruction> ; |
830424 10 add dword ptr ss:[esp],10 ; |Buffer
50 push eax ; |hConsole
BA 5DCC817C mov edx,KERNEL32.WriteConsoleA ; |
FFD2 call edx ; \WriteConsoleA
8BE5 mov esp,ebp
5D pop ebp
C3 ret
Esto no es un comportamiento especificado por el CLI y no funcionará en otras implementaciones de CLI como Mono. Hay otras formas de hacer que la lógica similar se ejecute en Mono, aunque ya lo intenté en Ubuntu 9.04 con Mono 2.4 y funcionó.
escribí un post sobre ello aquí: http://rednaxelafx.javaeye.com/blog/461787
Está en chino, pero hay un montón de código que hay que debe explicar lo que hice. Utilizando el mismo truco, al final de la publicación del blog, mostré un par de ejemplos de cómo podría modificar el código anterior para que las cosas salgan mal, como obtener una SEHException.
El punto de CLR .NET es abstraer lejos de la computadora, manteniendo los desbordamientos de pila y otros insectos en el interior de la CLR y no bloquear su ordenador física (incluso con un sistema operativo con errores) – Earlz
Si tal cosa es posible, ¿no cae en la categoría "error en la máquina virtual", por definición? –
Sí ... a menos que esté hablando de eliminar archivos importantes y cosas así desde el tiempo de ejecución de CLR – Earlz