Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1

Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

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

Концепия Control Flow Integrity (целостность потока исполнения) была описана еще в 2005 году. И вот, 10 лет спустя, разработчики из компании Microsoft представили свою неполную реализацию данного концепта — Control Flow Guard.

Что такое Control Flow Guard

Control Flow Guard (Guard CF, CFG) — относительно новый механизм защиты Windows (exploit mitigation), нацеленный на то, чтобы усложнить процесс эксплуатации бинарных уязвимостей в пользовательских приложениях и приложениях режима ядра. Работа данного механизма заключается в валидации неявных вызовов (indirect calls), предотвращающей перехват потока исполнения злоумышленником (например, посредством перезаписи таблицы виртуальных функций). В сочетании с предыдущими механизмами защиты (SafeSEH, ASLR, DEP и т.д.) являет собой дополнительную головную боль для создателей эксплоитов.

Данная секьюрити фича доступна пользователям ОС Microsoft Windows 8.1 (Update 3, KB3000850) и Windows 10.


Компиляция программ с поддержкой CFG доступна в Microsoft Visual Studio 2015.

Как работает Control Flow Guard

Рассмотрим принцип работы CFG в пользовательском режиме. Данный механизм имеет два основных компонента: битовую карту адресов (управляется ядром) и процедуру проверки указателя вызываемой функции (используется пользовательскими приложениями).

Вся служебная информация CFG заносится в IMAGE_LOAD_CONFIG_DIRECTORY исполняемого файла во время компиляции:

Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

GuardCFCheckFunctionPointer — указатель на процедуру проверки

GuardCFFunctionTable — таблица валидных адресов функций (используется ядром для инициализации битовой карты)

GuardCFFunctionCount — количество функций в таблице

GuardFlags — флаги

В заголовок IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics заносится флаг IMAGE_DLLCHARACTERISTICS_GUARD_CF, показывающий, что данный исполняемый файл поддерживает механизм CFG.

Всю служебную информацию можно посмотреть при помощи инструмента dumpbin.exe из Microsoft Visual Studio 2015 (Microsoft Visual Studio 14.0\VC\bin\dumpbin.exe), запустив его с ключем /loadconfig.
Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты
GuardFlags
Заголовочный файл winnt.h для Windows 10 (1511) содержит следующие флаги CFG (последний является маской, а не флагом):

IMAGE_GUARD_CF_INSTRUMENTED (0x00000100) — Модуль производит проверки потока исполнения при поддержке системы


IMAGE_GUARD_CFW_INSTRUMENTED (0x00000200) — Модуль производит проверки целостности потока исполнения и записи


IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT (0x00000400) — Модуль содержит таблицу валидных функций


IMAGE_GUARD_SECURITY_COOKIE_UNUSED (0x00000800) — Модуль не использует security cookie (/GS)


IMAGE_GUARD_PROTECT_DELAYLOAD_IAT (0x00001000) — Модуль поддерживает Delay Load Import Table, доступную только для чтения


IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION (0x00002000) — Delay Load Import Table находится в своей собственной .didat секции


IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK (0xF0000000) — Шаг одного элемента таблицы валидных функций Guard CF кодируются в данных битах (дополнительное количество байтов для каждого элемента)

Стоит отметить, что это неполный список существующих флагов. Наиболее полный список можно получить из внутренностей файла link.exe (компоновщик):
Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

Также стоит обратить внимание на присутствие некоторых интересных флагов, официальной информации о которых нет. Разработчики Microsoft, по всей видимости, тестируют дополнительный механизм CFG для проверки адреса записи (IMAGE_GUARD_CFW_INSTRUMENTED).

Битовая карта

Во время загрузки ОС ядром (функция nt!MiInitializeCfg) создается битовая карта nt!MiCfgBitMapSection, которая является общей (shared) секцией для всех процессов. При запуске процесса, поддерживающего CFG, происходит отображение (mapping) битовой карты в адресное пространство процесса. После чего адрес и размер битовой карты заносятся в структуру ntdll!LdrSystemDllInitBlock.

Сопоставлением адресов функций с битами в битовой карте занимается загрузчик исполняемых файлов (функция nt!MiParseImageCfgBits). Каждый бит в битовой карте отвечает за 8 байт пользовательского адресного пространства процесса. Адреса начала всех валидных функций соотносятся с единичным битом по соответствующему смещению в битовой карте, а всё остальное — 0.

Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты
Процедура проверки указателя вызываемой функции

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

Для наглядности посмотрим на один и тот же код, скомпилированный без CFG и с ним.


Оригинальный код на C++:

class CSomeClass

{


public:


virtual void doSomething()


{


std::cout << "hello";


}


};



int main()


{


CSomeClass *someClass = new CSomeClass();


someClass->doSomething();



return 0;


}

ASM листинг (вырезка):

mov eax, [ecx] ; EAX = CSomeClass::vftable

call dword ptr [eax] ; [EAX] = CSomeClass::doSomething()


С ключем компиляции /guard:cf :

mov eax, [edi] ; EAX = CSomeClass::vftable

mov esi, [eax] ; ESI = CSomeClass::doSomething()


mov ecx, esi


call ds:___guard_check_icall_fptr ; checks that ECX is valid function pointer


mov ecx, edi


call esi

В первом случае код подвержен атаке с использованием техники подмены таблицы виртуальных функций. Если атакующий при эксплуатации уязвимости способен перезаписать данные объекта, то он может подменить таблицу виртуальных функций таким образом, что вызов функции someClass->doSomething() приведет к выполнению контролируемого атакующим кода, тем самым перехватив поток исполнения приложения.

В случае же использования Control Flow Guard, адрес вызываемой функции предварительно будет сверен с битовой картой. Если соответствующий бит будет равен нулю, произойдет программное исключение.



При запуске данного приложения на ОС, которые поддерживают механизм Guard CF, загрузчик исполняемых файлов построит битовую карту и перенаправит адрес проверяющей процедуры на функциюntdll!LdrpValidateUserCallTarget.


Данная функция в ОС Windows 10 (build 1511) реализована следующим образом:

Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты
Изучим алгоритм данной функции на примере входного адреса 0x0B3385B0.
Проверяемый адрес данная функция получает через регистр ecx. В регистр edx заносится адрес битовой карты. В моем случае битовая карта расположилась по адресу 0x01430000.
Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты
Три байта (24 бита) старшего порядка (подчеркнуты) адреса соответствуют смещению в битовой карте. В данном случае смещение будет равно 0xB3385. Единица измерения битовой карты равна 4 байтам (32 бита), поэтому для получения нужной ячейки необходимо вычислить базовый адрес карты + смещение * 4. Для данного примера получаем 0x01430000 + 0xB3385 * 4 = 0x16FCE14. Значение ячейки битовой карты записывается в регистр edx.
Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

Целевую ячейку получили, теперь требуется определить номер интересующего нас бита. Номером является значение следующих 5 бит адреса (выделены жирным). Но нужно учитывать, что если проверяемый адрес не выравнен по границе 16 байт (address & 0xf != 0), то использоваться будет нечетный бит (offset | 0x1). В данном случае адрес выравнен и номер бита будет равен 10110(двоичная) = 22(десятичная).

Теперь остается только проверить значение бита, проведя bit test. Инструкция bt проверяет значение бита первого регистра, порядковый номер которого берется из 5 младших бит (по модулю 32) второго регистра. В случае, если бит равен 1, будет выставлен Carry Flag (CF) и программа продолжит свое выполнение в обычном режиме. 
Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты
В ином случае будет вызвана функция ntdll!RtlpHandleInvalidUserCallTarget и работа программы завершится 29-го прерывания с параметром 0xA на стеке, что означает nt!_KiRaiseSecurityCheckFailure(FAST_FAIL_GUARD_ICALL_CHECK_FAILURE).
Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

Проверив 22-ой бит, можно убедиться, что адрес вызываемой функции является валидным.


Реализация данного алгоритма на Python выглядит следующим образом:

def calculate_bitmap_offset(addr):

offset = (addr >> 8) * 4

bit = (addr >> 3) % 32

aligned = (addr & 0xF == 0)

if not aligned:

bit = bit | 1

print "addr = 0x%08x, offset = 0x%x, bit index = %u, aligned? %s" % (addr, offset, bit, "yes" if aligned else "no")


calculate_bitmap_offset(0x0B3385B0)

Результат работы скрипта:

addr = 0x0b3385b0, offset = 0x2cce14, bit index = 22, aligned? yes

Исключения

Не во всех случаях вызов невалидной функции будет заканчиваться 29-ым прерыванием. В функции ntdll!RtlpHandleInvalidUserCallTarget происходят следующие проверки:


Включен ли DEP для текущего процесса


Имеет ли целевой адрес необходимые права (PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE)


Разрешены ли "suppressed" вызовы — ntdll!RtlGuardAllowSuppressedCalls


Является ли целевой адрес "suppressed" — ntdll!RtlpGuardIsSuppressedAddress


Псевдокод данной функции выглядит следующим образом:

Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

Официальная информация про "suppressed" вызовы отсутствует. Можно лишь сказать, что данные вызовы требуют поддержку компилятора — должна быть установлена маска IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK во флагах GuardFlags и компилятор должен сгенерировать расширенную таблицу. В байтах, соответствующих данной маске, хранится значение дополнительного размера для элементов таблицы GuardCFFunctionTable. Если адрес функции является "suppressed", то байт, следующий за адресом, должен быть равен единице.

Разрешить "suppressed" вызовы можно, например, с помощью ветки реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\, установив параметр CFGOptions для требуемого приложения в значение 1.

Слабые места Control Flow Guard

Как и любой другой защитный механизм, CFG имеет некоторые слабые места:


Выключенный DEP процесса влечет за собой потерю смысла проверок CFG, поскольку функция ntdll!RtlpHandleInvalidUserCallTarget в таком случае будет всегда разрешать исполнение невалидного адреса.


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


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


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


За каждые 8 байт адресного пространства отвечает 1 бит, но, на самом деле, 1 выравненный адрес соотносится с одним четным битом, при этом следующий нечетный бит соотносится сразу с 15 байтами адресного пространства. Убедиться в этом можно, запустив приведенный выше Python скрипт в цикле и проанализировав результат:

addr = 0x08f38480, offset = 0x23ce10, bit index = 16, aligned? yes

addr = 0x08f38481, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38482, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38483, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38484, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38485, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38486, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38487, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38488, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38489, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f3848a, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f3848b, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f3848c, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f3848d, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f3848e, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f3848f, offset = 0x23ce10, bit index = 17, aligned? no

addr = 0x08f38490, offset = 0x23ce10, bit index = 18, aligned? yes

addr = 0x08f38491, offset = 0x23ce10, bit index = 19, aligned? no

addr = 0x08f38492, offset = 0x23ce10, bit index = 19, aligned? no

addr = 0x08f38493, offset = 0x23ce10, bit index = 19, aligned? no

addr = 0x08f38494, offset = 0x23ce10, bit index = 19, aligned? no

...

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



Динамически генерируемые функции (например, JIT-функции) требуют особого внимания от разработчиков, поскольку необходимо обеспечить проверки неявных вызовов на стадии генерирования функций. В добавок к этому, необходимо учитывать, что стандартное поведение функций ntdll!NtAllocVirtualMemory и ntdll!NtProtectVirtualMemory заключается в проставлении единичного бита для всего региона памяти в битовой карте Control Flow Guard, если память становится исполняемой (PAGE_EXECUTE_*).


CFG не способен предотвратить перехват потока исполнения при модификации атакующим адреса возврата функции.


Вызовы библиотечных функций (например, WinAPI) с точки зрения CFG являются валидными, но атакующему предстоит решить задачу наполнения стека/регистров необходимыми параметрами.

Реализация обхода Control Flow Guard на примере Adobe Flash Player

Начиная с Windows 8 плагин Adobe Flash Player интегрирован в Internet Explorer, а с Windows 8.1 (Update 3) он поставляется с поддержкой CFG. Существует несколько реализаций обхода Control Flow Guard в эксплоитах под Adobe Flash Player, некоторые из которых актуальны и по сей день.

Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

Обход при помощи динамического кода


В Adobe Flash Player активно используется JIT-компиляция, которая позволяет избегать выполнения такой ресурсоемкой операции, как интерпретация ActionScript кода. Но, как было сказано ранее, динамически генерируемые функции требуют дополнительного внимания со стороны разработчиков. Два метода обхода, описанные ниже, являются следствием упущения разработчиков в отношении работы с выделением памяти.


Отсутствие проверок неявных вызовов в динамическом коде


Данный метод был предложен и реализован исследователем Francisco Falcón из Core Security в своем анализе эксплоита для уязвимости CVE-2015-0311. Оригинальная статья довольно хорошо и подробно описывает процесс реализации обхода. Суть метода заключается в модификации внутренней таблицы виртуальных функций определенного ActionScript класса. После чего один из методов данного класса должен быть вызван из тела динамически сгенерированной функции. Для данной цели хорошо подходит класс ByteArray.


Структура объекта ByteArray:

Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты
По смещению $+8 находится указатель на объект класса VTable:
Control Flow Guard. Принцип работы и методы обхода на примере Adobe Flash Player. Часть 1 Длиннопост, Adobe flash player, Exploit, Cfg, Control Flow Guard, Обход защиты

Класс VTable является внутренним представлением виртуальной таблицы функций (то есть не той, которую генерирует C++) для классов ActionScript.


Часть2 http://pikabu.ru/story/control_flow_guard_printsip_rabotyi_i...


Источник: https://habrahabr.ru/company/dsec/blog/305960/

Информационная безопасность IT

1.4K постов25.5K подписчиков

Добавить пост

Правила сообщества

Обязательно к прочтению для авторов:

1. Если вы добавляете пост, утверждающий об утечке данных или наличии дыр в системе, предоставьте ссылку на источники или технически подкованное расследование. Посты из разряда "Какой-то банк слил данные, потому что мне звонили мошенники" будут выноситься в общую ленту.
2. Все вопросы "Как обезопасить сервер\приложение\устройство" - в лигу "Компьютер это просто".

Обязательно к прочтению для всех:

Добавление ссылки разрешено если она не содержит описание коммерческих (платных) продуктов и/или идентификаторов для отслеживания перехода и для доступа не нужен пароль или оплата в т.ч. интернет-ресурсы, каналы (от 3-х тематических видео), блоги, группы, сообщества, СМИ и т.д.


Запрещены политические holy wars.

По решению модератора или администратора сообщества пользователь будет забанен за:

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

2. Публикацию поста/комментария не соответствующего тематике сообщества, в том числе обсуждение администраторов и модераторов сообщества, для этого есть специальное сообщество.

3. За обвинение в киберпреступной деятельности.

4. За нарушение прочих Правил Пикабу.

2
Автор поста оценил этот комментарий

ТС, ты ебанулся? Ты бы еще статьи Криса Касперски сюда выложил =)) Не обиды ради, но не надо оно тут :)

Автор поста оценил этот комментарий
Вопрос только один - как отключить это решето в Windows 10?
раскрыть ветку
1
DELETED
Автор поста оценил этот комментарий
Автор! Ты не найдешь тут своего читателя
Автор поста оценил этот комментарий

Спасибо, майкрософт, но всё равно нет.