Skip to content

Instantly share code, notes, and snippets.

@ufcpp
Last active December 21, 2017 13:14
Show Gist options
  • Save ufcpp/5ef97fc49eb9c0d2412377e9ef566b86 to your computer and use it in GitHub Desktop.
Save ufcpp/5ef97fc49eb9c0d2412377e9ef566b86 to your computer and use it in GitHub Desktop.
セキュリティホール作るのに unsafe なんて要らなかった
using System;
using System.Runtime.InteropServices;
class Base { }
class Derived : Base
{
// 1個や2個だと「たまたま0詰め」な領域を指すかもしれないので無駄にたくさんフィールド並べる
public long A { get; }
public long B { get; }
public long C { get; }
public long D { get; }
public (long, long, long, long) T => (A, B, C, D);
}
[StructLayout(LayoutKind.Explicit)]
struct Union
{
[FieldOffset(0)]
public Base Base;
[FieldOffset(0)]
public Derived Derived;
}
class Program
{
// 本来やってはいけないダウンキャスト
static Derived AsDerived(Base b)
{
var u = new Union();
u.Base = b;
return u.Derived;
}
static void Main()
{
var b = new Base();
// やってはいけないダウンキャストを強行
var d = AsDerived(b);
// Derived な変数に Base が入ってる
Console.WriteLine(d.GetType());
// Derived にしかないはずのメンバーを読み出し
// (0, 0, 140708363800272, 0) みたいな身に覚えのない値が取れる
// 読めるだけならいいけど書き換えもできるんでさらにまずい(GC クラッシュ & セキュリティ ホール)
Console.WriteLine(d.T);
}
}
using System;
using System.Runtime.InteropServices;
// 本来、こういう参照型と値型が混ざった Union は作れない
// これは、この型を使おうとした時点で TypeLoadException を起こすので実現不可
// (ならコンパイル エラーにしろよという話は置いておいて)
[StructLayout(LayoutKind.Explicit)]
struct InvalidUnion
{
[FieldOffset(0)]
public object Obj;
[FieldOffset(0)]
public IntPtr Ptr;
}
// が、こうやって1段クラスを挟めば…
class A { public object Obj; }
class B { public IntPtr Ptr; }
// 重ねても平気!
[StructLayout(LayoutKind.Explicit)]
struct ValidUnion
{
[FieldOffset(0)]
public A A;
[FieldOffset(0)]
public B B;
}
class Program
{
// 本来やってはいけない無関係な型へのキャスト
static B Cast(A a)
{
var u = new ValidUnion();
u.A = a;
return u.B;
}
static void Main()
{
var a = new A { Obj = "abc" };
// やってはいけないキャストを強行
var b = Cast(a);
// a.Obj のアドレスが取れる
// ちなみに、GC 管理下のメモリのアドレスを取るのとか、
// safe な範囲どころか、unsafe を使ってもなかなか取るの難しい邪悪な所業
// もちろん、書き換えたら GC クラッシュの原因
Console.WriteLine(b.Ptr);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment