/GS (проверка безопасности буфера)
Обнаруживает некоторые переполнения буфера, которые перезаписывают возвращаемый адрес функции, адрес обработчика исключений или определенные типы параметров. Причина переполнения буфера — это метод, используемый хакерами для использования кода, который не применяет ограничения размера буфера.
Синтаксис
/GS[-]
Замечания
/GS включен по умолчанию. Если приложение не будет подвержено безопасности, используйте /GS-. Дополнительные сведения о подавлении обнаружения переполнения буфера см. в разделе "Безопасные буфферы".
Проверки безопасности
В функциях, которые компилятор распознает как предмет проблем переполнения буфера, компилятор выделяет место в стеке перед возвращаемым адресом. При входе функции выделенное пространство загружается с помощью файла cookie безопасности, вычисляемого один раз при загрузке модуля. При выходе функции и во время очистки кадра в 64-разрядных операционных системах вызывается вспомогательной функцией, чтобы убедиться, что значение файла cookie по-прежнему совпадает. Другое значение означает, что возможно, произошла перезапись стека. Если обнаружено другое значение, процесс завершается.
Буферы GS
Проверка безопасности переполнения буфера выполняется в буфере GS. Буфер GS может быть одним из следующих:
Массив размером более 4 байтов, содержит более двух элементов и имеет тип элемента, который не является типом указателя.
Структура данных, размер которой превышает 8 байтов и не содержит указателей.
Буфер, выделенный с помощью функции _alloca .
Любой класс или структура, содержащая буфер GS.
Например, следующие инструкции объявляют буферы GS.
char buffer[20];
int buffer[20];
struct { int a; int b; int c; int d; } myStruct;
struct { int a; char buf[20]; };
Однако следующие инструкции не объявляют буферы GS. Первые два объявления содержат элементы типа указателя. Третий и четвертый операторы объявляют массивы, размер которых слишком мал. Пятая инструкция объявляет структуру, размер которой на платформе x86 составляет не более 8 байт.
char *pBuf[20];
void *pv[20];
char buf[4];
int buf[2];
struct { int a; int b; };
Инициализация файла cookie безопасности
Параметр компилятора /GS требует, чтобы файл cookie безопасности был инициализирован перед запуском любой функции, которая использует файл cookie. Файл cookie безопасности должен быть инициализирован немедленно при входе в EXE или DLL. Это происходит автоматически, если вы используете точки входа VCRuntime по умолчанию: mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup или _DllMainCRTStartup. При использовании альтернативной точки входа необходимо вручную инициализировать файл cookie безопасности, вызвав __security_init_cookie.
Что защищено
Параметр компилятора /GS защищает следующие элементы:
Возвращаемый адрес вызова функции.
Адрес обработчика исключений для функции.
Уязвимые параметры функции.
На всех платформах /GS пытается обнаружить переполнение буфера в возвращаемый адрес. Переполнение буферов проще использовать на таких платформах, как x86 и x64, которые используют соглашения о вызовах, которые хранят обратный адрес вызова функции в стеке.
Если функция использует обработчик исключений, компилятор внедряет файл cookie безопасности для защиты адреса обработчика исключений. Файл cookie проверяется во время очистки кадра.
/GS защищает уязвимые параметры , передаваемые в функцию. Уязвимый параметр — это указатель, ссылка на C++, тип C-структуры (тип POD C++), содержащий указатель или буфер GS.
Уязвимый параметр выделяется перед файлами cookie и локальными переменными. Переполнение буфера может перезаписать эти параметры. И код в функции, которая использует эти параметры, может вызвать атаку до возврата функции и проверки безопасности. Чтобы свести к минимуму эту опасность, компилятор создает копию уязвимых параметров во время пролога функции и помещает их под область хранения для всех буферов.
Компилятор не делает копии уязвимых параметров в следующих ситуациях:
Функции, не содержащие буфер GS.
Параметры оптимизации (/O) не включены.
Функции с списком аргументов переменной (...).
Функции, помеченные голыми.
Функции, содержащие встроенный код сборки в первой инструкции.
Параметр используется только способами, которые, скорее всего, будут использоваться в случае переполнения буфера.
Что не защищено
Параметр компилятора /GS не защищает от атак безопасности всех буферов. Например, если у вас есть буфер и vtable в объекте, переполнение буфера может повредить vtable.
Даже если вы используете /GS, всегда старайтесь писать безопасный код без переполнения буфера.
Установка параметра компилятора в Visual Studio
Откройте диалоговое окно Страницы свойств проекта. Подробнее см. в статье Настройка компилятора C++ и свойства сборки в Visual Studio.
Перейдите на страницу свойств Свойства конфигурации>C/C++>Создание кода.
Измените свойство "Проверка безопасности буфера".
Установка данного параметра компилятора программным способом
- См. раздел BufferSecurityCheck.
Пример
Этот пример перезапустит буфер. Это приводит к сбою приложения во время выполнения.
// compile with: /c /W1
#include <cstring>
#include <stdlib.h>
#pragma warning(disable : 4996) // for strcpy use
// Vulnerable function
void vulnerable(const char *str) {
char buffer[10];
strcpy(buffer, str); // overrun buffer !!!
// use a secure CRT function to help prevent buffer overruns
// truncate string to fit a 10 byte buffer
// strncpy_s(buffer, _countof(buffer), str, _TRUNCATE);
}
int main() {
// declare buffer that is bigger than expected
char large_buffer[] = "This string is longer than 10 characters!!";
vulnerable(large_buffer);
}
См. также
Параметры компилятора MSVC
Синтаксис командной строки компилятора MSVC