Поделиться через


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

Параметр компилятора /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

  1. Откройте диалоговое окно Страницы свойств проекта. Подробнее см. в статье Настройка компилятора C++ и свойства сборки в Visual Studio.

  2. Перейдите на страницу свойств Свойства конфигурации>C/C++>Создание кода.

  3. Измените свойство "Проверка безопасности буфера".

Установка данного параметра компилятора программным способом

Пример

Этот пример перезапустит буфер. Это приводит к сбою приложения во время выполнения.

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