Управление Flow Guard для обеспечения безопасности платформы

Что такое Control Flow Guard?

Управление Flow Guard (CFG) — это оптимизированная функция безопасности платформы, которая была создана для борьбы с уязвимостями в повреждении памяти. Устанавливая жесткие ограничения на то, откуда приложение может выполнять код, это делает его гораздо труднее для эксплойтов выполнять произвольный код с помощью таких уязвимостей, как переполнение буфера. CFG расширяет предыдущие технологии устранения эксплойтов, такие как /GS, DEP и ASLR.

  • Предотвращение повреждения памяти и атак программ-шантажистов.
  • Ограничьте возможности сервера любым необходимым в определенный момент времени для уменьшения уязвимой зоны.
  • Усложните использование произвольного кода с помощью таких уязвимостей, как переполнение буфера.

Эта функция доступна в Microsoft Visual Studio 2015 г. и работает в версиях CFG-Aware Windows — выпусках x86 и x64 для настольных компьютеров и серверов Windows 10 и Windows 8.1 с обновлением (KB3000850).

Мы настоятельно рекомендуем разработчикам включить CFG для своих приложений. Вам не нужно включать CFG для каждой части кода, так как сочетание cfg enabled и non-CFG включаемого кода будет выполняться нормально. Но не удалось включить CFG для всего кода, может открыть пробелы в защите. Кроме того, код с поддержкой CFG хорошо работает в версиях Windows, не имеющих значения CFG, и поэтому полностью совместим с ними.

Как включить CFG?

В большинстве случаев изменять исходный код не требуется. Все, что нужно сделать, — добавить параметр в проект Visual Studio 2015, а компилятор и компоновщик включите CFG.

Самый простой метод — перейти к Project | | свойств Свойства конфигурации | | C/C++ Создание кода и выбор значения "Да" (/guard:cf) для элемента управления Flow Guard.

cfg property in visual studio

Кроме того, добавьте /guard:cf в Project | | свойств Свойства конфигурации | | C/C++ | командной строки Дополнительные параметры (для компилятора) и /guard:cf для Project | | свойств Свойства конфигурации | Компоновщик | | командной строки Дополнительные параметры (для компоновщика).

cfg property for compilercfg property for linker

Дополнительные сведения см. в разделе /guard (включение элемента управления Flow Guard).

При создании проекта из командной строки можно добавить те же параметры. Например, если вы компилируете проект с именем test.cpp, используйте cl /guard:cf test.cpp /link /guard:cf.

Кроме того, вы можете динамически управлять набором целевых адресов, которые считаются допустимыми CFG с помощью SetProcessValidCallTargets из API управления памятью. Тот же API можно использовать для указания того, являются ли страницы недопустимыми или допустимыми целевыми объектами для CFG. Функции VirtualProtect и VirtualAlloc по умолчанию рассматривают указанный регион исполняемых и зафиксированных страниц как допустимые целевые объекты косвенного вызова. Это поведение можно переопределить, например при реализации JIT-компилятора, указав PAGE_TARGETS_INVALID при вызове VirtualAlloc или PAGE_TARGETS_NO_UPDATE при вызове VirtualProtect , как описано в разделе "Константы защиты памяти".

Как сказать, что двоичный файл находится под контролем Flow Guard?

Запустите средство dumpbin (включенного в установку Visual Studio 2015) из командной строки Visual Studio с параметрами /headers и /loadconfig: dumpbin /headers /loadconfig test.exe. Выходные данные двоичного файла в CFG должны показать, что значения заголовков включают "Guard", а значения конфигурации загрузки включают "CF Instrumented" и "FID table present".

output from dumpbin /headers

output from dumpbin /loadconfig

Как CFG действительно работает?

Уязвимости программного обеспечения часто используются путем предоставления маловероятных, необычных или экстремальных данных работающей программе. Например, злоумышленник может воспользоваться уязвимостью переполнения буфера, предоставив программе больше входных данных, чем ожидалось, тем самым перезапустив область, зарезервированную программой для хранения ответа. Это может привести к повреждению соседней памяти, которая может содержать указатель функции. Когда программа вызывает эту функцию, она может перейти в непреднамеренное расположение, указанное злоумышленником.

Однако мощное сочетание поддержки времени компиляции и выполнения из CFG реализует целостность потока управления, которая жестко ограничивает, где могут выполняться инструкции непрямого вызова.

Компилятор выполняет следующие действия.

  1. Добавляет упрощенные проверки безопасности в скомпилированный код.
  2. Определяет набор функций в приложении, которые являются допустимыми целевыми объектами для косвенных вызовов.

Поддержка среды выполнения, предоставляемая ядром Windows:

  1. Эффективно поддерживает состояние, определяющее допустимые целевые объекты непрямого вызова.
  2. Реализует логику, которая проверяет допустимость целевого объекта косвенного вызова.

Чтобы проиллюстрировать:

cfg pseudocode

Если проверка CFG завершается сбоем во время выполнения, Windows немедленно завершает программу, тем самым нарушая любой эксплойт, который пытается косвенно вызвать недопустимый адрес.