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

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

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

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

Объект данного класса содержит в себе указатели на объекты класса MethodEnv:

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

Данный класс представляет собой описание метода ActionScript и содержит указатель на тело функции в памяти по смещению $+4.


В объекте VTable по смещению $+D4 находится описание метода ByteArray::toString(). Имея возможность произвольно читать и писать в память, атакующий способен изменить указатель функции на тело функции (MethodEnv + 4) и благополучно перехватить поток исполнения приложения, выполнив ByteArray::toString().



Такое становится возможным по причине того, что метод данного класса будет вызываться из JIT-кода:

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

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



Данный метод обхода CFG был исправлен с выходом Adobe Flash Player версии 18.0.0.160 (KB3065820, Июнь 2015). Исправление заключается в следующем: если JIT-функция содержит неявный вызов, то JIT-компилятор вставит вызов процедуры проверки непосредственно перед неявным вызовом.


Любой адрес в пределах тела динамической функции является валидным


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


Исследователи Юрий Дроздов и Людмила Дроздова из Center of Vulnerability Research представили данный метод обхода CFG на конференции Defcon Russia.

Статья:

http://cvr-data.b*l*o*g*spot.ru/2015/07/advanced-cfg-bypass-on-adobe-flash.html


Их метод основан на том факте, что при выделении исполняемой памяти ядро выставляет единичный бит в битовой карте CFG для всей выделенной памяти. Посмотрим, к чему может привести такое поведение.

Предположим, что существует некая JIT-функция по адресу 0x69BC9080, в теле которой находится следующий код:

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

Что именно делает эта функция, нас не интересует, нужно лишь обратить внимание на 2 байта FF D0 инструкции по адресу 0x69BC90F0. Что будет, если начало функции вдруг сдвинется в середину данной инструкции? Вот что:

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

FF D0 — не что иное, как call eax! Вот так безобидная на первый взгляд функция превратилась в прекрасную цель для атакующего — неявный вызов без проверки Control Flow Guard. Нужно лишь разобраться с двумя вопросами: как добиться нужной последовательности байтов и как записать в регистр необходимый адрес.



Сгенерировать необходимую последовательность можно, просто экспериментируя с ActionScript-кодом. Стоит лишь учитывать тот факт, что Nanojit (JIT-компилятор AVM) обфусцирует генерируемый код, поэтому легкого пути не будет. Посмотрим, во что превратит Nanojit данную функцию:

public static function useless_func():uint

{


return 0xD5EC;


}

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

Совсем не то, что мы ожидали. Опытным путем можно прийти, например, к такому варианту кода:

public static function useless_func():void

{


useless_func2(0x11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26);


}



public static function useless_func2(arg1:uint, arg2:uint, arg3:uint, a, b, c, d, e, f, g, h, i, j, k, l, m, n, p, q, r, s, t, u, v, w, x, y, z):void


{


}

Тело первой функции будет содержать следующие инструкции:

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

Интересующие нас байты FF 11 являются инструкцией call [ecx]:

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

Неявный вызов получили, теперь нужно занести в регистр ecx контролируемый адрес. Выясним, что хранится в данном регистре в момент вызова функции useless_func().

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

В момент вызова функции, в регистре ecx находится объект класса MethodEnv. Первый DWORD данного класса является указателем на виртуальную таблицу функций (ту, которую генерирует компилятор C++). Эта таблица в момент вызова метода useless_func() не используется, поэтому ничего не мешает атакующему непосредственно перед вызовом метода заменить указатель на свой.

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

var class_addr:uint = read_addr(UselessClass);

var vtable:uint = read_dword(class_addr + 8);


var methodenv:uint = read_dword(vtable + 0x54); // $+54 = useless_func


var func_ptr:uint = read_dword(methodenv + 4);



write_dword(methodenv + 4, func_ptr + offset_to_call_ecx);


write_dword(methodenv, rop_gadget); // ecx <- pointer to rop gadgets



UselessClass.useless_func(); // call [ecx]

Таким образом, нам удалось перехватить поток исполнения приложения и перейти, в данном случае, к выполнению ROP-гаджета.


Этот метод обхода CFG был исправлен в версии 18.0.0.194 (KB3074219, Июнь 2015). Исправление заключается в использовании нового флага


PAGE_TARGETS_INVALID/PAGE_TARGETS_NO_UPDATE (0x40000000) для функций VirtualAlloc и VirtualProtect в связке с новой функцией WinAPI — SetProcessValidCallTargets.


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


Данное исправление можно наблюдать в функции AVMPI_makeCodeMemoryExecutable в исходном коде ядра AVM (AVMPI/MMgcPortWin.cpp):

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

Вызов функции SetProcessValidCallTargets реализован в AVMPI_makeTargetValid (AVMPI/MMgcPortWin.cpp):

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

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


VirtualAlloc(PAGE_READWRITE)

Запись кода в выделенный участок

VirtualProtect(PAGE_EXECUTE_READ | PAGE_TARGETS_NO_UPDATE)

SetProcessValidCallTargets()


И, конечно же, не стоит забывать про неявные вызовы внутри динамического кода.

Обход при помощи функций WinAPI

Проверка Control Flow Guard заключается в валидации вызываемого адреса, но валидными адресами являются не только начала пользовательских функций. Все функции WinAPI, как и любые другие функции из таблицы импорта, являются валидными адресатами для неявного вызова. Атакующему ничего не мешает перевести поток исполнения напрямую в библиотечную функцию, минуя тем самым выполнение шеллкода (shellcode) или ROP-гаджетов. Хорошим кандидатом для такой цели является WinAPI функция kernel32!WinExec.



Данная идея впервые была озвучена исследователем Yuki Chen из Qihoo 360 Vulcan Team на конференции SyScan (Сингапур, 2015) в презентации, посвященной эксплуатации уязвимости в Internet Explorer 11 с обходом новых механизмов защиты. Также на конференции BlackHat (США, 2015) исследователь Francisco Falcón описал реализацию данного метода применительно к Adobe Flash Player.


В своей реализации Francisco Falcón оперировал методом toString() объекта класса Vector, но мы попробуем реализовать данный метод, пользуясь наработками из предыдущего.


Основная сложность данного метода заключается в том, чтобы передать параметры WinExec через стек. Данная функция, согласно справке, принимает 2 параметра: LPCSTR lpCmdLine и UINT uCmdShow.


lpCmdLine — указатель на строку, которую нужно выполнить (должна заканчиваться нулевым байтом).

uCmdShow — режим отображения запускаемого приложения.


Обратимся к скриншоту из предыдущего метода:

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

В момент вызова нашей функции на стеке оказывается 3 параметра. Третий параметр нас не интересует. Со вторым все отлично, поскольку 0 = SW_HIDE (приложение запустится скрыто). Первым параметром является указатель на объект MethodEnv.

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

Как мы уже выяснили ранее, первые 4 байта данного объекта являются указателем на виртуальную таблицу функций, и в момент вызова ActionScript-метода она никак не задействуется. Следующие 4 байта указывают на тело функции, и именно их нужно изменить на указатель функции WinExec.

Поскольку порча указателя на тело функции не приведет ни к чему хорошему, в нашем распоряжении имеется лишь первые 4 байта. В данный размер можно, например, уместить строку cmd\0 (командная строка Windows). Данной командой, конечно, не добиться полной компрометации системы, но для демонстрации подойдет.


Модифицируем алгоритм из предыдущего метода и получим следующий код:

var class_addr:uint = read_addr(UselessClass);

var vtable:uint = read_dword(class_addr + 8);


var methodenv:uint = read_dword(vtable + 0x50); // $+50 = useless_func


var winexec:uint = get_proc_addr("kernel32.dll", "WinExec");


write_dword(methodenv + 4, winexec); // useless_func() --> WinExec()


write_dword(methodenv, 0x00646d63); // '\0', 'd', 'm', 'c'


UselessClass.useless_func();

Поиск WinAPI функции в условиях современных Flash-эксплоитов является тривиальной задачей. Данную реализацию мы опустим, но с ней можно всегда ознакомиться, изучив пакет Flash Exploiter из фреймворка Metasploit.

Выполнив приведенный выше алгоритм при эксплуатации уязвимости, можно убедиться в работоспособности данного метода:

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

Все современные Flash-эксплоиты так или иначе используют метод запуска полезной нагрузки (payload) из утекших исходников эксплоитов компании HackingTeam. Автором данного метода является Виталий Торопов. Его метод основан на вызове WinAPI функции kernel32!VirtualProtect, благодаря чему достигается обход всех механизмов защиты и, в том числе, Control Flow Guard.

Целью данного метода является метод apply() класса Function (core/FunctionClass.cpp)

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

В исходном коде данного метода происходит нативный вызов core->exec->apply(get_callEnv(), thisArg, (ArrayObject*)AvmCore::atomToScriptObject(argArray));, который можно перехватить, оперируя объектами ActionScript.

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

Подробное описание данного метода требует отдельной статьи, но с реализацией можно ознакомиться на GitHub. Также есть хороший материал с разбором данного метода в условиях 64-битного Flash в блоге Metasploit.(https://community.rapid7.com/community/metasploit/blog/2015/...)

Заключение

Несмотря на свои недостатки, Control Flow Guard при должном внимании со стороны разработчиков является хорошим дополнением в арсенале борцов с эксплоитами в среде ОС Windows. Компании Microsoft удалось, пусть и не полностью, реализовать концепцию Control Flow Integrity, минимально повлияв на производительность приложений, и сохранив обратную совместимость. Данный механизм еще не достиг предела своих возможностей, и разработчики из Microsoft наверняка в ближайшем будущем смогут усилить защиту приложений.

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

Источники

https://habrahabr.ru/company/dsec/blog/305960/

http://sjc1-te-ftp.trendmicro.com/assets/wp/exploring-contro...

http://www.powerofcommunity.net/poc2014/mj0011.pdf

https://github.com/adobe/avmplus

https://www.blackhat.com/docs/eu-15/materials/eu-15-Falcon-E...

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

Автор, пили тему как деньжат с этой хрени поднять

Автор поста оценил этот комментарий
Почему pepper flash не страдает этим? Или страдает?