Защита от переполнения буфера для stackalloc в.Net

Из ссылки на C# для stackalloc:

использование stackalloc автоматически включает функции обнаружения переполнения буфера в общеязыковой среде выполнения (CLR). Если обнаружено переполнение буфера, процесс завершается как можно быстрее, чтобы минимизировать вероятность выполнения вредоносного кода.

В частности, какой механизм защиты реализован для.NET?
И это также обнаружит переполнение буфера? Против каких известных атак защита слабее?


Для контекста, например для компилятора MS C++, информация доступна здесь:
Защиты безопасности программного обеспечения Windows ISV:

Возможность обнаружения переполнения стекового буфера была представлена ​​компилятору C/C++ в Visual Studio .NET 2002 и была обновлена ​​в последующих версиях. /GS - это параметр компилятора, который инструктирует компилятору добавлять код запуска и функции epilog и prolog, чтобы генерировать и проверять случайное число, которое помещается в стек функции.

Обратите внимание, что Visual C++ 2005 (и более поздние версии) также переупорядочивает данные в стеке, чтобы затруднить предсказуемое повреждение этих данных. Примеры включают в себя:
• Перемещение буферов в более высокую память, чем небуферы. Этот шаг может помочь защитить указатели функций, которые находятся в стеке.
• Перемещение аргументов указателя и буфера для уменьшения объема памяти во время выполнения, чтобы смягчить различные атаки переполнения буфера.

1 ответ

Решение

Да, джиттер.NET генерирует тот тип проверки стека, который также существует в собственном коде, сгенерированном компилятором Microsoft C/C++ с параметром компилятора /GS. Основная схема заключается в хранении случайного 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).

Код исключения определен в заголовочном файле SDK ntstatus.h:

//
// 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 

Фактическое значение канарейки изменяется каждый раз, когда код вставляется.

Другие вопросы по тегам