7

stackalloc の C# リファレンスから:

stackalloc を使用すると、共通言語ランタイム (CLR) のバッファー オーバーラン検出機能が自動的に有効になります。バッファ オーバーランが検出された場合、悪意のあるコードが実行される可能性を最小限に抑えるために、プロセスはできるだけ早く終了します。

具体的には、.NET にはどのような保護メカニズムが実装されていますか?
また、バッファ アンダーランも検出しますか? どの既知の攻撃に対する保護が弱いですか?


コンテキストについては、たとえば MS C++ コンパイラの場合、情報は次の場所で入手できます:
Windows ISV ソフトウェア セキュリティ防御:

スタック バッファ オーバーラン検出機能は、Visual Studio .NET 2002 で C/C++ コンパイラに導入され、その後のバージョンで更新されました。/GS は、関数のスタックに配置される乱数を生成およびチェックするために、スタートアップ コード、関数のエピローグおよびプロローグ コードを追加するようにコンパイラに指示するコンパイラ スイッチです。

Visual C++ 2005 (およびそれ以降) も、スタック上のデータを並べ替えて、そのデータが予測どおりに破損しにくくすることに注意してください。例 を以下に示します。
• バッファを非バッファよりも上位のメモリに移動する。この手順は、スタック上に存在する関数ポインターを保護するのに役立ちます。
• さまざまなバッファ オーバーラン攻撃を軽減するために、実行時にポインタとバッファ引数を下位メモリに移動します。

4

1 に答える 1

16

はい、.NET ジッターは、/GS コンパイラ オプションを使用して Microsoft C/C++ コンパイラによって生成されたネイティブ コードにも存在する一種のスタック カナリア チェックを生成します。基本的なスキームは、ランダムな 32 ビット値をスタックの一番上に格納し、メソッド エントリに書き込むことです。メソッドの終了時に、値がまだそこにあるかどうかをチェックします。値の変化は、マルウェアがプログラムを制御するために使用する種類のスタック バッファ オーバーフローの非常に高い予測因子です。

遊ぶためのいくつかのコード:

class Program {
    static void Main(string[] args) {
        Kaboom();
    }
    static unsafe void Kaboom() {
        byte* ptr = stackalloc byte[1];
        for (int ix = 0; ix < 42; ++ix) ptr[ix] = 0;
    }
}

このコードを実行すると、デバッガーが接続されていても、Windows エラー報告ダイアログがトリガーされます。[出力] ウィンドウでクラッシュの理由を確認できます。

プログラム '[3636] ConsoleApplication33.exe: Native' はコード -1073740791 (0xc0000409) で終了しました。

例外コードは、ntstatus.h SDK ヘッダー ファイルで定義されています。

//
// MessageId: STATUS_STACK_BUFFER_OVERRUN
//
// MessageText:
//
// The system detected an overrun of a stack-based buffer in this application. This overrun could 
// potentially allow a malicious user to gain control of this application.
//
#define STATUS_STACK_BUFFER_OVERRUN      ((NTSTATUS)0xC0000409L)    // winnt

Debug + Windows + Disassembly でこれを行うコードを確認できます。Kaboom の重要な部分:

00000000  push        ebp                               ; setup stack frame
00000001  mov         ebp,esp 
00000003  sub         esp,8                             ; stack space for local variables
00000006  xor         eax,eax 
00000008  mov         dword ptr [ebp-8],eax             ; zero-initialize local variables
0000000b  mov         dword ptr [ebp-4],eax 
0000000e  mov         dword ptr [ebp-4],esp
00000011  mov         dword ptr [ebp-8],0EDDB7EDFh      ; canary stored here

// For loop code omitted

0000002d  cmp         dword ptr [ebp-8],0EDDB7EDFh      ; check canary value
00000034  je          0000003B 
00000036  call        727767A8                          ; crash program
0000003b  lea         esp,[ebp]                         ; normal exit, pop stack frame
0000003e  pop         ebp 
0000003f  ret 

実際のカナリア値は、コードがジットされるたびに変化します。

于 2013-02-17T22:20:53.953 に答える