小智 16
那么......你怎么定义"纯.NET"?当我阅读"如何崩溃JVM"帖子时,我玩了CLR2/delegate/GCHandle /数组,并想出了类似这样的东西:
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( );
}
}
}
Run Code Online (Sandbox Code Playgroud)
它只知道在x86上使用带有CLR2的32位Windows XP; 并且还知道不能使用Vista和Windows 7等,默认情况下DEP + ASLR处于打开状态.
关于上面代码的有趣之处在于它没有明确使用不安全的代码(尽管GCHandle.Alloc(...,GCHandleType.Pinned)需要安全权限),但它设法将数组伪造成委托实例,并且调用数组中的x86机器代码.代码本身是纯C#,如果你不把嵌入式x86代码算作某种"外语";-)基本上它利用了CLR2代理对静态方法的内部实现,那么Delegate的一些私有成员实际上是内部的指针.我将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
Run Code Online (Sandbox Code Playgroud)
这不是CLI指定的行为,也不适用于其他CLI实现,如Mono.还有其他方法可以在Mono上运行类似的逻辑,已经在Ubuntu 9.04 w/Mono 2.4上尝试过了.
我在这里写了一篇关于它的博客文章:http://rednaxelafx.javaeye.com/blog/461787
它是中文的,但那里有很多代码可以解释我的所作所为.使用相同的技巧,在博客文章的最后,我展示了几个例子,你可以调整上面的代码来解决问题,例如获取SEHException.
| 归档时间: |
|
| 查看次数: |
3037 次 |
| 最近记录: |