NET公共语言运行库

NET公共语言运行库

本文介绍了如何崩溃的.NET公共语言运行库(CLR)在纯.NET的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有针对 Java虚拟机了类似的问题,但我的天堂 t上找不到的。NET的问题(请关闭并标记为重复的,如果我失去了一些东西)。

There is a similar question targeting the Java VM but I haven't found a question for .net (please close and mark as duplicate if I was missing something).

所以 - 这可能不讨厌的非托管互操作?并与崩溃我的意思是一个真正的xxx.exe已停止工作不是一个StackOverflow-或OutOfMemoryException异常。

So - is it possible without nasty unmanaged interop? And with crashing I mean a real "xxx.exe has stopped working" not a StackOverflow- or OutOfMemoryException.

我认为这是不可能的,打在虚拟机本身的错误时除外。

I think it is not possible, except when hitting a bug in the VM itself.

推荐答案

嗯...你如何定义纯.NET?我打了CLR2 /代理/的GCHandle /阵列时,我读了如何崩溃JVM的帖子,并提出了这样的事情:

Well...how would you define "pure .NET"? I played with CLR2/delegate/GCHandle/array when I read the "how to crash JVM" post, and came up with something like this:

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工作在32位的Windows XP CLR2;也可称为不与Vista和Windows 7等,其中,DEP + ASLR是在默认情况下工作。

It's only known to work on 32-bit Windows XP with CLR2 on x86; and also known not to work with Vista and Windows 7 and the like, where DEP+ASLR is on by default.

有趣的关于code上面的一点是,它并没有明确使用不安全code(虽然GCHandle.Alloc(...,GCHandleType.Pinned)要求的安全权限),但它管理伪造一个数组委托实例,并调用数组中的x86机器code。 C本身的$ C $是纯C#,如果不计算嵌入式x86 code一些外语;-)基本上,它利用的CLR2的静态方法的委托内部实现,这代表了一些私有成员实际上是内部指针。我酿86 code到一个数组,被分配在托管堆上。因此,为了使这项工作,DEP不能启用,否则我们将不得不寻找其他方式来获得内存页的执行权限。

The point of fun about the code above is that it didn't explicitly use unsafe code (although GCHandle.Alloc(..., GCHandleType.Pinned) demands security privilege), yet it manages to fake an array into a delegate instance, and calls into the x86 machine code within the array. The code itself is pure C#, if you don't count the embedded x86 code as some "foreign language" ;-)Basically it makes use of internal implementation of CLR2's delegates on static methods, that a few private members of Delegate are actually internal pointers. I stuffed x86 code into an array, which is allocated on the managed heap. So in order for this to work, DEP must not be enabled, or we'll have to find some other way to get execution privilege on that memory page.

在86 code是这样的:(伪MASM语法)

The x86 code is like this: (in pseudo-MASM syntax)

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实施如单工作。还有其他的方法,使单上的类似的逻辑来看,虽然,已经尝试过,对Ubuntu的9.04 W /单声道2.4和工作。

This is NOT a behavior specified by CLI, and won't work on other CLI implementations such as Mono. There are other ways to make the similar logic run on Mono though, already tried that on Ubuntu 9.04 w/ Mono 2.4 and worked.

我在这里写了一篇博客吧: http://rednaxelafx.javaeye.com/blog/461787

I wrote a blog post about it here: http://rednaxelafx.javaeye.com/blog/461787

这是在中国,而且有足够的code有哪些应该解释我做了什么。使用同样的伎俩,在博客文章的最后,我表现出了几个例子你如何能调整上面的code键使出问题,如获取一个SEHException。

It's in Chinese, but there's plenty of code there which should explain what I did. Using the same trick, at the end of the blog post I showed a couple of examples how you could tweak the code above to make things go wrong, such as getting a SEHException.

这篇关于如何崩溃的.NET公共语言运行库(CLR)在纯.NET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 00:05