음 ... "pure .NET"을 어떻게 정의 하시겠습니까? 본인은 "JVM을 충돌하는 방법"게시물을 읽을 때 CLR2/대표/GCHandle/배열을 연주하고,이 같은 내놓았다 :
단지 CLR2 32 비트 Windows XP에서 작동하도록 알려져
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();
}
}
}
x86에서; 또한 DEP + ASLR이 기본적으로 켜져있는 Vista 및 Windows 7 등에서는 작동하지 않는 것으로 알려져 있습니다.
위의 코드에 대한 재미있는 점은 GCHandle.Alloc (..., GCHandleType.Pinned)이 보안 권한을 요구하지만 안전하지 않은 코드를 명시 적으로 사용하지 않았지만 배열을 가짜로 관리한다는 것입니다. 인스턴스를 위임하고 배열 내의 x86 컴퓨터 코드로 호출합니다. 임베디드 x86 코드를 "외국어"로 계산하지 않으면 코드 자체는 순수한 C#입니다. 기본적으로 정적 메서드에 대한 CLR2의 대리자의 내부 구현을 사용하며 대리인의 일부 비공개 멤버가 실제로는 내부 포인터. 나는 x86 코드를 관리 힙에 할당 된 배열에 채웠다. 따라서 DEP를 작동시키지 않아야하며 그렇지 않으면 해당 메모리 페이지에 대한 실행 권한을 얻으려면 다른 방법을 찾아야합니다.
는 x86 코드는 다음과 같다 : (의사 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
이 CLI가 지정한 행동하지 않고, 같은 모노와 같은 다른 CLI 구현에서 작동하지 않습니다. 유사한 로직을 Mono에서 실행하게하는 다른 방법이 있습니다. 이미 우분투 9.04/Mono 2.4에서이를 시도하고 작동했습니다.
나는 여기에 대한 블로그 포스트를 작성했습니다 :
http://rednaxelafx.javaeye.com/blog/461787
그것은 중국어,하지만 내가 무슨 짓을했는지 설명해야이 코드가 많이있다. 같은 트릭을 사용하여 블로그 게시물의 끝에서 나는 SEHException을 얻는 것과 같은 일이 잘못되도록 위의 코드를 조정할 수있는 몇 가지 예제를 보여주었습니다.
닷넷 CLR의 요점은 그런 일 경우 – Earlz
CLR은 내부 스택 오버 플로우 및 기타 버그를 유지하고 (심지어 버그가 OS로) 실제 컴퓨터를 충돌하지, 컴퓨터에서 멀리 추상적이다 가능하다면, 정의 상 "VM 자체의 버그"범주에 해당하지 않습니까? –
네 .. CLR 런타임 내부에서 중요한 파일 등을 지우지 않는다면 – Earlz