Защита от переполнения буфера для 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
Фактическое значение канарейки изменяется каждый раз, когда код вставляется.