JIT spraying and mitigations
Аннотация
С открытием новых методов эксплуатации, механизмы защиты также необходимы. Смягчающие меры, такие как DEP (предотвращение выполнения данных) или ASLR (рандомизация адресного пространства) создала значительно более сложную среду для эксплуатации. Злоумышленники однако недавно исследовали новые методы эксплуатации, способные обходить защиты и использовать память операционной системы. JIT-Spraying это один из новейших и самых популярных методов эксплуатации, который позволяет обойти оба вышеупомянутые средства защиты.
В этой статье мы представим краткий обзор техники JIT-Spraying, а также новые методы защиты от этого инновационного класса атак. Библиотека Anti-JIT была создана как часть системы предотвращения выполнения Shell-кодов.
1. Введение
Microsoft реализовала механизмы смягчения эксплуатации, такие как DEP и ASLR. Предотвращение выполнения данных (DEP) - это механизм безопасности, который запрещает приложению выполнять код из области памяти помеченной как неисполняемой.
Чтобы эксплуатировать уязвимость, злоумышленник должен сначала найти исполняемую память, а затем сможет заполнить эту память необходимыми данными (то есть, инструкциями Shell-кода). Как правило для достижение этой цели с использованием старых методов эксплуатации значительно затрудняется с добавлением механизма DEP.
В результате злоумышленники усовершенствовали классический метод возврата в libc (ret2libc) и начали использовать Возвратно-ориентированное программирование (ROP) для обхода DEP.
Тем не менее, такие методы, как ROP, все еще полагаются на то, что злоумышленник понимает характеристики структуры памяти Microsoft для реализации ASLR (Рандомизации адресного пространства) в качестве контрмеры.
ASLR делает макет адресного пространства приложения менее предсказуемым, поскольку он перемещает базовые адреса исполняемых модулей и другие отображения памяти. Техника распыления JIT была введена для обхода ASLR и DEP одновременно. В этой статье мы представляем наши новые механизмы, которые созданы специально для предотвращения техники распространения JIT из успешного исполнения. Это исследование предназначалось для операционных систем Microsoft Windows с архитектурой процессора x86-32. Меры по смягчению последствий специально направлены на ActionScript (Объектно-ориентированный язык программирования). JIT-компилятор, который в настоящее время интенсивно используется для этого типа атаки.
2. JIT-Spaying
Есть две основные причины, по которым распыление JIT - это очень полезный метод эксплуатации. Во-первых, код, сгенерированный компилятором JIT, храниться в памяти, помечена как исполняемая. Это очевидно, потому что в противном случае JIT-компилятор не сможет корректно работать в системах, поставляемых с функциями DEP. Очевидно, если код злоумышленника генерируется двигателем JIT, он также будет находиться в исполняемой область. Другими словами, DEP не участвует в защите кода, испускаемого JIT компилятором. Это очень полезный метод, так как память не была помечена как исполняемая в предыдущих подходах, таких как обычное распыление кучи.
Причина, по которой распыление JIT является мощной, заключается в том, что местоположение кода может быть предсказано правильно, поэтому в этот момент ASLR также больше не представляет большой угрозы для атакующего. В этой статье мы сосредоточимся на обнаружении генерации JIT-кода, необходимого для обнаружения адресов, обсуждаемых в ссылочных цитатах. Читателю рекомендуется иметь полное понимание ссылочной работы.
2.1 Генерация кода JIT
Компиляция Just-In-Time (JIT) преобразует код во время выполнения; обычно из байт-кода в машинный код.
Благодаря этому значительно улучшается производительность интерпретируемой программы. JIT метод распыления «Заставляет» JIT-компилятор создавать множество исполняемых страниц со встроенным кодом злоумышленника для того, чтобы написать код в определенное место, JIT Компилятор должен сначала отметить целевую память как доступную для записи. Так как несколько сгенерированных кусков кода может находиться на той же странице памяти, компилятор JIT помечает всю страницу как RWX (Читаемый-записываемый-исполняемый файл). Эти разрешения необходимы, потому что другой кусок памяти находится на этой же странице и может выполняться асинхронно (например, другим потоком), приводя к нарушению доступа, если запрошенная страница памяти была не исполняемая в тот момент. После того как код помечает регион назначения как RX - читаемый и исполняемый, файл больше не доступен для записи.
Код 1: Примерный список изменений памяти, запрошенный компилятором JIT.
Чтобы заставить JIT-компилятор генерировать код, включая данные Shell-кода, злоумышленники должны использовать операторов ActionScript. Хотя ActionScript состоит из нескольких операторов, таких как: арифметический, сложно арифметический, присваиваемый, побитовый и т. д. В настоящее время используется только один известный Shell-код. Код 2 представляет сгенерированный код для нескольких, различных типов операторов (выражение используется: a OP b OP c OP d ...). В качестве тестового примера
Значения данных, которые мы использовали, взяты из одного из самых доступных JIT-кодов оболочки.
Код 2 показывает, что когда дело доходит до операторов ActionScript, то только XOR, кажется, производит желаемый результат. Например, с оператором XOR атакующий контролирует четыре байта каждого отдельного блока. В других случаях аргументы выражения не обеспечивают точного и предсказуемого контроля над испускаемыми блоками кода.
С помощью выражения можно изменить содержимое указанных блоков и сделать их более зависимыми от аргументов злоумышленника, но XOR оператор, кажется, лучший вариант для использования Shell-кода, и именно поэтому, вероятно, каждый известный JIT Shell-код использует этот оператор. Однажды злоумышленник может распылить контролируемый исполняемый файл инструкции в кучу, остальная часть процесса эксплуатации идет по стандартному маршруту. Главная идея здесь заключается в том, чтобы распылить память с инструкциями, которые включают полезную нагрузку злоумышленника, а затем смогут перенести исполнение туда (как, например, быть в состоянии указания инструкции (EIP) на адрес XOR EAX).
3. Методы предотвращения использования памяти
Чтобы остановить JIT-распыления, мы должны быть в состоянии решить, является ли код сгенерированным7 Движок Just-In-Time должен быть помечен как Shell-код или нет? Это не тривиальная задача, так как Shell-код детектор не должен сильно влиять на исходную производительность программы, и он также должен быть свободным от ложных срабатываний оповещений. На данный момент есть два основных подхода для реализации в детекторе Shell-кода:
• Подход обнаружения подписи (сканирование для NOP слайдов, кода GetPC, кода декодирования (дешифрования) и т. д.)
• Эвристический подход обнаружения.
Детекторы на основе сигнатур наиболее просто реализовать, но они также имеют тенденцию генерировать высокое количество ложных срабатываний. Обнаружение подписи часто недостаточно, так как злоумышленник может обойти его, построив код другим способом. Чтобы сделать процесс обнаружения более надежные и менее статичные, мы решили использовать эвристический подход обнаружения. Как показано в подразделе 2.1, перед выполнением кода, сгенерированного JIT, защиту памяти нужно изменить на RX (Читаемым). Для этого движок JIT выполняет функцию API VirtualProtect. Похоже, что сгенерированный JIT код всегда начинается с адреса памяти, указанного в качестве параметра VirtualProtect API. Это может быть серьезным преимуществом для целей обнаружения, поскольку на данный момент мы знаем выбранный адрес (аргумент API). Всегда действительная отправная точка (точка входа) для разбора. Второй очень полезный фактор здесь то, что сгенерированный код, который обычно содержит встроенный Shell-код генерируется в очень особенном стиле (см. код 2):
Наш эвристический метод обнаружения прост, но очень надёжен. Как показано в Коде 3, каждый Shell-код JIT в настоящее время генерирует доступные инструкции, которые используют 32-битные непосредственные значения в качестве исходного операнда и целевой операнд такой инструкции всегда является регистром, который был предварительно инициализирован другим 32-битным непосредственным значением. Инициализация, как правило, MOV Reg, IMM32 или в большинстве случаев MOV EAX, IMM32. Наш алгоритм обнаружения описывается следующим образом (алгоритм 1):
где:
• numinstr - представляет количество разобранных инструкций
• numbadinstr - представляет количество «плохих» инструкции, другими словами инструкции, которые используют 32-битные непосредственные операнды
• is_terminator - представляет функцию, которая проверяет, должна ли текущая дизассемблированная инструкция быть помечена как terminator (такие команды, как CALL, RET, JMP и т. д. должны считаться “терминаторами”)
• used_imm32_operands - представляет функцию, которая проверяет, использует ли текущая обработанная инструкция 32-битные непосредственные операнды
• MAXibadnum - представляет собой статическое число которое описывает максимальное количество "плохих" инструкции в разобранном блоке.
Наш алгоритм вычисляет количество неверных инструкций (инструкции, которые используют 32-битные непосредственные операнды как источник) начиная с инициализации инструкции. Этот алгоритм не предполагает конкретный регистр назначения (поэтому неважно, если EAX используется или любой другой регистр процессора x86-32). Кроме того, он продолжает считать количество плохих инструкций, даже если они разделены каким-то другим инструкциями, которые не используют 32-битные операнды (например, по какой-либо инструкции MMX / SIMD или любой другой, которая не использует 32-битный непосредственный операнд, если он не является терминатором блока). Также стоит добавить, что вся процедура сканирования происходит до того, как злоумышленник получит возможность использовать код, сгенерированный движком JIT. Так как мы постоянно отслеживаем все вновь созданные регионы, то кто то может возразить, что проще начать разборку с точки входа, чем искать для MOV Reg, IMM32. Однако это более дорогой подход, так как скорость этого метода будет напрямую зависеть от размера блока, генерируемого механизмом JIT - чем длиннее блок, тем медленнее алгоритм. Во-вторых, разборка всегда очень дорогостоящий процесс, когда дело доходит до производительности. В поисках MOV Reg, IMM32 и начиная с этого момента мы не должны выполнять разборку всего региона.
4.Контрмеры
Как мы уже описывали в подразделе 2.1, злоумышленник обычно контролирует 32-битный операнд. Это даёт ему возможность использовать 24 бита контролируемого значения для кодирования команд Shell-кода (поскольку один байт обычно уже используется, чтобы выполнить NOP (т.е. CMP AL)). Чтобы обойти нашу защиту, злоумышленник может попытаться создать свой Shell -код, создав несколько неких площадок, связывая их с короткими переходами JMP / JCC (так как они имеют длину всего 2 байта). Делая это, злоумышленник может уменьшить количество отправляемых инструкций, использующих 32-битные непосредственные операнды, и переместить их через разные области памяти. Тем не менее, мы уже создали рабочее смягчение для этого метода путем дополнительного сканирования непосредственного значения для кодов операций JMP / JCC.
Поскольку эти переходы всегда короткие, атакующий может прыгнуть только в область от -128 до +127 байт из инструкции перехода. Учитывая тот факт, что с помощью этого метода злоумышленник теряет дополнительное место для ценных инструкций шелл-кода, он должен генерировать относительно большое количество инструкций перехода. В нашем методе мы не только сканируем коды операций JMP / JCC внутри непосредственного значения, но также проверяем, указывает ли адрес назначения таких переходов на допустимое местоположение, которое также включает другую инструкцию перехода и так далее. Другими словами, мы пытаемся проверить потенциальную цепочку прыжков. Этот шаг необходим для того, чтобы избежать ложных срабатываний. Соединяя этот подход с ранее описанными в разделе 3, мы значительно усложнили смягчение последствий распыления JIT.
5. Отзывы
Испытания показали, что библиотека защиты от распыления JIT не генерирует ложных срабатываний при просмотре типичных сайтов, перегруженных ActionScript и флэш-анимацией. Сама библиотека не внесла каких-либо заметных изменений в производительность исходного приложения. Все тесты были выполнены на Flash версии 10с (в операционных системах Microsoft Windows Vista и XP).
6. Заключение
В этой статье мы представили основные концепции распыления памяти JIT. Этот метод является хорошей контрмерой против таких механизмов защиты, как DEP и ASLR, и, кроме того, он становится все более популярным. Чтобы предотвратить успешное использование атак методом распыления JIT, мы разработали надежные и быстрые методы смягчения последствий. Мы надеемся, что читатель нашел эту статью интересной.
Дополнительная литература
[1] Alexey Sintsov. Writing JIT Shellcode for fun and profit.
[2] Piotr Bania. Evading network-level emulation. Technical Report arXiv:0906.1963, Jun 2009. Comments: 7 pages.
[3] Dion Blazakis. Interpreter Exploitation: Pointer Inference and JIT Spraying. http:// www.semantiscope.com/research/BHDC2010/ BHDC-2010-Paper.pdf.
[4] Erik Buchanan, Ryan Roemer, Stefan Savage, Hovav Shacham. Return-oriented Programming: Exploitation without Code Injection. https://www.blackhat.com/presentations/ bh-usa-08/Shacham/BH_US_08_Shacham_ Return_Oriented_Programming.pdf.
[5] Yuri Gushin. NIDS polymorphic evasion - The End? http://www.milw0rm.com/papers/18.
[6] Samuel Patton, William Yurcik, and David Doss. An Achilles’ Heel in Signature-Based IDS: Squealing False Positives in SNORT. http:// www.scs.carleton.ca/~soma/id-2007w/ readings/patton_yurcik_doss_raid2001. pdf, 2001.
[7] Hovav Shacham. The geometry of innocent flesh on the bone: Return-into-libc without function calls (on the x86). In Sabrina De Capitani di Vimercati and Paul Syverson, editors, Proceedings of CCS 2007, pages 552–61. ACM Press, October 2007.
[8] CLET Team. Polymorphic shellcode engine using spectrum analysis. Phrack Magazine Issue #65, 2003.
Это был мой второй перевод статьей для XSS, а предложил мне её опять же weaver . И того более 2.200 слов в данной статье, которые я попытался перевести для вас.
Если вы хотите меня поддержать, то можете задонатить мне на QIWI кошелёк 79054863063 на поездку в Польшу с классом (Да, я ещё школьник) или же купить Nord VPN в моей теме: https://xss.pro/threads/30205/
Оригинальная статья: https://www.piotrbania.com/all/articles/pbania-jit-mitigations2010.pdf
Аннотация
С открытием новых методов эксплуатации, механизмы защиты также необходимы. Смягчающие меры, такие как DEP (предотвращение выполнения данных) или ASLR (рандомизация адресного пространства) создала значительно более сложную среду для эксплуатации. Злоумышленники однако недавно исследовали новые методы эксплуатации, способные обходить защиты и использовать память операционной системы. JIT-Spraying это один из новейших и самых популярных методов эксплуатации, который позволяет обойти оба вышеупомянутые средства защиты.
В этой статье мы представим краткий обзор техники JIT-Spraying, а также новые методы защиты от этого инновационного класса атак. Библиотека Anti-JIT была создана как часть системы предотвращения выполнения Shell-кодов.
1. Введение
Microsoft реализовала механизмы смягчения эксплуатации, такие как DEP и ASLR. Предотвращение выполнения данных (DEP) - это механизм безопасности, который запрещает приложению выполнять код из области памяти помеченной как неисполняемой.
Чтобы эксплуатировать уязвимость, злоумышленник должен сначала найти исполняемую память, а затем сможет заполнить эту память необходимыми данными (то есть, инструкциями Shell-кода). Как правило для достижение этой цели с использованием старых методов эксплуатации значительно затрудняется с добавлением механизма DEP.
В результате злоумышленники усовершенствовали классический метод возврата в libc (ret2libc) и начали использовать Возвратно-ориентированное программирование (ROP) для обхода DEP.
Тем не менее, такие методы, как ROP, все еще полагаются на то, что злоумышленник понимает характеристики структуры памяти Microsoft для реализации ASLR (Рандомизации адресного пространства) в качестве контрмеры.
ASLR делает макет адресного пространства приложения менее предсказуемым, поскольку он перемещает базовые адреса исполняемых модулей и другие отображения памяти. Техника распыления JIT была введена для обхода ASLR и DEP одновременно. В этой статье мы представляем наши новые механизмы, которые созданы специально для предотвращения техники распространения JIT из успешного исполнения. Это исследование предназначалось для операционных систем Microsoft Windows с архитектурой процессора x86-32. Меры по смягчению последствий специально направлены на ActionScript (Объектно-ориентированный язык программирования). JIT-компилятор, который в настоящее время интенсивно используется для этого типа атаки.
2. JIT-Spaying
Есть две основные причины, по которым распыление JIT - это очень полезный метод эксплуатации. Во-первых, код, сгенерированный компилятором JIT, храниться в памяти, помечена как исполняемая. Это очевидно, потому что в противном случае JIT-компилятор не сможет корректно работать в системах, поставляемых с функциями DEP. Очевидно, если код злоумышленника генерируется двигателем JIT, он также будет находиться в исполняемой область. Другими словами, DEP не участвует в защите кода, испускаемого JIT компилятором. Это очень полезный метод, так как память не была помечена как исполняемая в предыдущих подходах, таких как обычное распыление кучи.
Причина, по которой распыление JIT является мощной, заключается в том, что местоположение кода может быть предсказано правильно, поэтому в этот момент ASLR также больше не представляет большой угрозы для атакующего. В этой статье мы сосредоточимся на обнаружении генерации JIT-кода, необходимого для обнаружения адресов, обсуждаемых в ссылочных цитатах. Читателю рекомендуется иметь полное понимание ссылочной работы.
2.1 Генерация кода JIT
Компиляция Just-In-Time (JIT) преобразует код во время выполнения; обычно из байт-кода в машинный код.
Благодаря этому значительно улучшается производительность интерпретируемой программы. JIT метод распыления «Заставляет» JIT-компилятор создавать множество исполняемых страниц со встроенным кодом злоумышленника для того, чтобы написать код в определенное место, JIT Компилятор должен сначала отметить целевую память как доступную для записи. Так как несколько сгенерированных кусков кода может находиться на той же странице памяти, компилятор JIT помечает всю страницу как RWX (Читаемый-записываемый-исполняемый файл). Эти разрешения необходимы, потому что другой кусок памяти находится на этой же странице и может выполняться асинхронно (например, другим потоком), приводя к нарушению доступа, если запрошенная страница памяти была не исполняемая в тот момент. После того как код помечает регион назначения как RX - читаемый и исполняемый, файл больше не доступен для записи.
Код:
Requests :
MEM : 0 x057d0090 size =1 prot =RWX
MEM : 0 x057d0090 size =c prot =RX
Generated code :
0 x057d0090 mov edx ,[ esp +0 ch ]
0 x057d0094 mov ecx ,[ edx]
0 x057d0096 call 0 fdea9d1ah
0 x057d009b ret
Requests :
MEM : 0 x057d0170 size =1 prot=RWX
MEM : 0 x057d0170 size =1a prot=RX
Generated code :
0 x057d0170 mov edx ,[ esp +0 ch ]
0 x057d0174 push dword [edx +0 ch ]
0 x057d0177 push dword [edx +08 h]
0 x057d017a push dword [edx +04 h]
0 x057d017d mov ecx ,[ edx]
0 x057d017f call 0 fdea5601h
0 x057d0184 mov eax ,04 h
0 x057d0189 ret
Чтобы заставить JIT-компилятор генерировать код, включая данные Shell-кода, злоумышленники должны использовать операторов ActionScript. Хотя ActionScript состоит из нескольких операторов, таких как: арифметический, сложно арифметический, присваиваемый, побитовый и т. д. В настоящее время используется только один известный Shell-код. Код 2 представляет сгенерированный код для нескольких, различных типов операторов (выражение используется: a OP b OP c OP d ...). В качестве тестового примера
Значения данных, которые мы использовали, взяты из одного из самых доступных JIT-кодов оболочки.
Код 2 показывает, что когда дело доходит до операторов ActionScript, то только XOR, кажется, производит желаемый результат. Например, с оператором XOR атакующий контролирует четыре байта каждого отдельного блока. В других случаях аргументы выражения не обеспечивают точного и предсказуемого контроля над испускаемыми блоками кода.
Код:
Operator XOR (^):
[b8 90 90 90 3c ] mov eax ,03 c909090h
[35 90 90 90 3c ] xor eax ,03 c909090h
[35 90 90 90 3c ] xor eax ,03 c909090h
[35 90 90 90 3c ] xor eax ,03 c909090h
[35 90 90 90 3c ] xor eax ,03 c909090h
[35 90 90 90 3c ] xor eax ,03 c909090h
[35 90 90 90 3c ] xor eax ,03 c909090h
...entire block of xors...
[35 31 d2 58 3c ] xor eax ,03 c58d231h
[35 80 ca ff 3c ] xor eax ,03 cffca80h
...
Operator ADD (+):
[b8 90 90 90 3c ] mov eax ,03 c909090h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[66 0f 28 c8 ] movapd xmm1 , xmm0
[f2 0f 58 c8 ] addsd xmm1 , xmm0
[f2 0f 58 c8 ] addsd xmm1 , xmm0
...addsd...
[b8 31 d2 58 3c ] mov eax ,03 c58d231h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[f2 0f 58 c8 ] addsd xmm1 , xmm0
[b8 80 ca ff 3c ] mov eax ,03 cffca80h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[f2 0f 58 c8 ] addsd xmm1 , xmm0
...so on...
Operator MUL (*):
[b8 90 90 90 3c ] mov eax ,03 c909090h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[66 0f 28 c8 ] movapd xmm1 , xmm0
[f2 0f 59 c8 ] mulsd xmm1 , xmm0
[f2 0f 59 c8 ] mulsd xmm1 , xmm0
...mulsd...
[b8 31 d2 58 3c ] mov eax ,03 c58d231h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[f2 0f 59 c8 ] mulsd xmm1 , xmm0
[b8 80 ca ff 3c ] mov eax ,03 cffca80h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[f2 0f 59 c8 ] mulsd xmm1 , xmm0
...so on...
Operator DIV (/):
[b8 90 90 90 3c ] mov eax ,03 c909090h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[66 0f 28 c8 ] movapd xmm1 , xmm0
[f2 0f 5e c8 ] divsd xmm1 , xmm0
[f2 0f 5e c8 ] divsd xmm1 , xmm0
...divsd...
[b8 31 d2 58 3c ] mov eax ,03 c58d231h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[f2 0f 5e c8 ] divsd xmm1 , xmm0
[b8 80 ca ff 3c ] mov eax ,03 cffca80h
[f2 0f 2a c0 ] cvtsi2sd xmm0 , eax
[f2 0f 5e c8 ] divsd xmm1 , xmm0
...so on...
С помощью выражения можно изменить содержимое указанных блоков и сделать их более зависимыми от аргументов злоумышленника, но XOR оператор, кажется, лучший вариант для использования Shell-кода, и именно поэтому, вероятно, каждый известный JIT Shell-код использует этот оператор. Однажды злоумышленник может распылить контролируемый исполняемый файл инструкции в кучу, остальная часть процесса эксплуатации идет по стандартному маршруту. Главная идея здесь заключается в том, чтобы распылить память с инструкциями, которые включают полезную нагрузку злоумышленника, а затем смогут перенести исполнение туда (как, например, быть в состоянии указания инструкции (EIP) на адрес XOR EAX).
3. Методы предотвращения использования памяти
Чтобы остановить JIT-распыления, мы должны быть в состоянии решить, является ли код сгенерированным7 Движок Just-In-Time должен быть помечен как Shell-код или нет? Это не тривиальная задача, так как Shell-код детектор не должен сильно влиять на исходную производительность программы, и он также должен быть свободным от ложных срабатываний оповещений. На данный момент есть два основных подхода для реализации в детекторе Shell-кода:
• Подход обнаружения подписи (сканирование для NOP слайдов, кода GetPC, кода декодирования (дешифрования) и т. д.)
• Эвристический подход обнаружения.
Детекторы на основе сигнатур наиболее просто реализовать, но они также имеют тенденцию генерировать высокое количество ложных срабатываний. Обнаружение подписи часто недостаточно, так как злоумышленник может обойти его, построив код другим способом. Чтобы сделать процесс обнаружения более надежные и менее статичные, мы решили использовать эвристический подход обнаружения. Как показано в подразделе 2.1, перед выполнением кода, сгенерированного JIT, защиту памяти нужно изменить на RX (Читаемым). Для этого движок JIT выполняет функцию API VirtualProtect. Похоже, что сгенерированный JIT код всегда начинается с адреса памяти, указанного в качестве параметра VirtualProtect API. Это может быть серьезным преимуществом для целей обнаружения, поскольку на данный момент мы знаем выбранный адрес (аргумент API). Всегда действительная отправная точка (точка входа) для разбора. Второй очень полезный фактор здесь то, что сгенерированный код, который обычно содержит встроенный Shell-код генерируется в очень особенном стиле (см. код 2):
Код:
mov reg , IMM32
operation reg , IMM32
So in case of XOR operator :
mov eax , IMM32
xor eax , IMM32
xor eax , IMM32
...
Наш эвристический метод обнаружения прост, но очень надёжен. Как показано в Коде 3, каждый Shell-код JIT в настоящее время генерирует доступные инструкции, которые используют 32-битные непосредственные значения в качестве исходного операнда и целевой операнд такой инструкции всегда является регистром, который был предварительно инициализирован другим 32-битным непосредственным значением. Инициализация, как правило, MOV Reg, IMM32 или в большинстве случаев MOV EAX, IMM32. Наш алгоритм обнаружения описывается следующим образом (алгоритм 1):
Код:
Algorithm 1: JIT shellcode detection
input : region_addr, region_size
output: detection marker
begin
foreach found_mov_imm32 do
numinstr ←− 0;
numbadinstr ←− 0;
while numinstr < MAXinum do ;
instr ←− disasm_next_instr();
if !instr or is_terminator(instr)
then
break;
if uses_imm32_operands(instr)
then numbadinstr ←− numbadinstr + 1;
numinstr ←− numinstr + 1;
if numbadinstr > MAXibadnum then
report_shellcode();
где:
• numinstr - представляет количество разобранных инструкций
• numbadinstr - представляет количество «плохих» инструкции, другими словами инструкции, которые используют 32-битные непосредственные операнды
• is_terminator - представляет функцию, которая проверяет, должна ли текущая дизассемблированная инструкция быть помечена как terminator (такие команды, как CALL, RET, JMP и т. д. должны считаться “терминаторами”)
• used_imm32_operands - представляет функцию, которая проверяет, использует ли текущая обработанная инструкция 32-битные непосредственные операнды
• MAXibadnum - представляет собой статическое число которое описывает максимальное количество "плохих" инструкции в разобранном блоке.
Наш алгоритм вычисляет количество неверных инструкций (инструкции, которые используют 32-битные непосредственные операнды как источник) начиная с инициализации инструкции. Этот алгоритм не предполагает конкретный регистр назначения (поэтому неважно, если EAX используется или любой другой регистр процессора x86-32). Кроме того, он продолжает считать количество плохих инструкций, даже если они разделены каким-то другим инструкциями, которые не используют 32-битные операнды (например, по какой-либо инструкции MMX / SIMD или любой другой, которая не использует 32-битный непосредственный операнд, если он не является терминатором блока). Также стоит добавить, что вся процедура сканирования происходит до того, как злоумышленник получит возможность использовать код, сгенерированный движком JIT. Так как мы постоянно отслеживаем все вновь созданные регионы, то кто то может возразить, что проще начать разборку с точки входа, чем искать для MOV Reg, IMM32. Однако это более дорогой подход, так как скорость этого метода будет напрямую зависеть от размера блока, генерируемого механизмом JIT - чем длиннее блок, тем медленнее алгоритм. Во-вторых, разборка всегда очень дорогостоящий процесс, когда дело доходит до производительности. В поисках MOV Reg, IMM32 и начиная с этого момента мы не должны выполнять разборку всего региона.
4.Контрмеры
Как мы уже описывали в подразделе 2.1, злоумышленник обычно контролирует 32-битный операнд. Это даёт ему возможность использовать 24 бита контролируемого значения для кодирования команд Shell-кода (поскольку один байт обычно уже используется, чтобы выполнить NOP (т.е. CMP AL)). Чтобы обойти нашу защиту, злоумышленник может попытаться создать свой Shell -код, создав несколько неких площадок, связывая их с короткими переходами JMP / JCC (так как они имеют длину всего 2 байта). Делая это, злоумышленник может уменьшить количество отправляемых инструкций, использующих 32-битные непосредственные операнды, и переместить их через разные области памяти. Тем не менее, мы уже создали рабочее смягчение для этого метода путем дополнительного сканирования непосредственного значения для кодов операций JMP / JCC.
Поскольку эти переходы всегда короткие, атакующий может прыгнуть только в область от -128 до +127 байт из инструкции перехода. Учитывая тот факт, что с помощью этого метода злоумышленник теряет дополнительное место для ценных инструкций шелл-кода, он должен генерировать относительно большое количество инструкций перехода. В нашем методе мы не только сканируем коды операций JMP / JCC внутри непосредственного значения, но также проверяем, указывает ли адрес назначения таких переходов на допустимое местоположение, которое также включает другую инструкцию перехода и так далее. Другими словами, мы пытаемся проверить потенциальную цепочку прыжков. Этот шаг необходим для того, чтобы избежать ложных срабатываний. Соединяя этот подход с ранее описанными в разделе 3, мы значительно усложнили смягчение последствий распыления JIT.
5. Отзывы
Испытания показали, что библиотека защиты от распыления JIT не генерирует ложных срабатываний при просмотре типичных сайтов, перегруженных ActionScript и флэш-анимацией. Сама библиотека не внесла каких-либо заметных изменений в производительность исходного приложения. Все тесты были выполнены на Flash версии 10с (в операционных системах Microsoft Windows Vista и XP).
6. Заключение
В этой статье мы представили основные концепции распыления памяти JIT. Этот метод является хорошей контрмерой против таких механизмов защиты, как DEP и ASLR, и, кроме того, он становится все более популярным. Чтобы предотвратить успешное использование атак методом распыления JIT, мы разработали надежные и быстрые методы смягчения последствий. Мы надеемся, что читатель нашел эту статью интересной.
Дополнительная литература
[1] Alexey Sintsov. Writing JIT Shellcode for fun and profit.
[2] Piotr Bania. Evading network-level emulation. Technical Report arXiv:0906.1963, Jun 2009. Comments: 7 pages.
[3] Dion Blazakis. Interpreter Exploitation: Pointer Inference and JIT Spraying. http:// www.semantiscope.com/research/BHDC2010/ BHDC-2010-Paper.pdf.
[4] Erik Buchanan, Ryan Roemer, Stefan Savage, Hovav Shacham. Return-oriented Programming: Exploitation without Code Injection. https://www.blackhat.com/presentations/ bh-usa-08/Shacham/BH_US_08_Shacham_ Return_Oriented_Programming.pdf.
[5] Yuri Gushin. NIDS polymorphic evasion - The End? http://www.milw0rm.com/papers/18.
[6] Samuel Patton, William Yurcik, and David Doss. An Achilles’ Heel in Signature-Based IDS: Squealing False Positives in SNORT. http:// www.scs.carleton.ca/~soma/id-2007w/ readings/patton_yurcik_doss_raid2001. pdf, 2001.
[7] Hovav Shacham. The geometry of innocent flesh on the bone: Return-into-libc without function calls (on the x86). In Sabrina De Capitani di Vimercati and Paul Syverson, editors, Proceedings of CCS 2007, pages 552–61. ACM Press, October 2007.
[8] CLET Team. Polymorphic shellcode engine using spectrum analysis. Phrack Magazine Issue #65, 2003.
Это был мой второй перевод статьей для XSS, а предложил мне её опять же weaver . И того более 2.200 слов в данной статье, которые я попытался перевести для вас.
Если вы хотите меня поддержать, то можете задонатить мне на QIWI кошелёк 79054863063 на поездку в Польшу с классом (Да, я ещё школьник) или же купить Nord VPN в моей теме: https://xss.pro/threads/30205/
Оригинальная статья: https://www.piotrbania.com/all/articles/pbania-jit-mitigations2010.pdf
Последнее редактирование модератором: