Лев Казаркин, Удивительные приключения регистров sse...

52
Click to edit Master title style Об удивительных приключениях регистров SSE и поиске одного бага Лев Казаркин Лаборатория Касперского Группа шифрования данных

Upload: sergey-platonov

Post on 16-Apr-2017

478 views

Category:

Software


0 download

TRANSCRIPT

Click to edit Master title style

Об удивительных приключениях

регистров SSE и поиске одного

бага

Лев Казаркин

Лаборатория Касперского

Группа шифрования данных

Click to edit Master title style

Стр. 2

Full Disk Encryption от Касперского

Сокращенно: FDE

Похоже на: TrueCrypt, Bitlocker, только лучше ;)

Шифруем мы весь диск целиком, а не только отдельные тома.

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

Решение централизованно управляется с единого сервера(Kaspersky Security Center).

Шифруем безопасно, быстро, недорого, без SMS... ;)

Click to edit Master title style

Стр. 3

Исторический экскурс

• Основано на реальных событиях.

• Время действия: Ноябрь 2013.

• Второй релиз технологии в продукте Kaspersky Endpoint Security (KES 10).

• Стадия высокой готовности к релизу - идет внутреннее развертывание продукта (IRO).

• Internal Rollout или dogfooding (как говорят в Microsoft) – "ешь еду своей собаки".

Click to edit Master title style

Стр. 4

Дальше по плану

1. Матчасть - как устроено FDE от Касперского.

2. Завязка истории. Затем, ее пошаговое развитие. Интерактив!

3. Разоблачение.

Не забываем, что у нас детектив, проявляем активность

Click to edit Master title style

Стр. 5

Архитектура FDE v.1 (endpoint)

Click to edit Master title style

Стр. 6

Агент предзагрузочной аутентификации выглядел так

Click to edit Master title style

Стр. 7

Метаданные

Click to edit Master title style

Стр. 8

Завязка

2013/11/1 от саппорта приходит внутренний баг с IRO.

Пользователь из далекой Великобритании пришел утром на работу и обнаружил, что его рабочий комп превратился в кирпич.

FDE радостно мигает текстовым курсором на черном экране и сообщает, что кто-то испортил метаданные FDE.

Click to edit Master title style

Стр. 9

Завязка

2013/11/1 от саппорта приходит внутренний баг с IRO.

Пользователь из далекой Великобритании пришел утром на работу и обнаружил, что его рабочий комп превратился в кирпич.

FDE радостно мигает текстовым курсором на черном экране и сообщает, что кто-то испортил метаданные FDE.

Click to edit Master title style

Стр. 10

"Развал" метаданных

Метаданные здорового человека:

Поврежденная копия:

Click to edit Master title style

Стр. 11

Первое впечатление

•Н у да, у нас есть какой-то неприятный баг. Может быть, в пребуте.

• Не страшно. Подумаешь, баг у одного пользователя!

• В целом качество продукта не вызывает сомнения.

• Продукт же прошел отдел тестирования, преодолел нагрузочное тестиорование на стендах, да и баг проявился только у одного пользователя.

• Багу был назначен невысокий, обычный приоритет.

НО!

Не понятно как его воспроизводить. Что является триггером?

Ни на виртуалках, ни на реальном железе не воспроизводится.

Как исправлять то, что не воспроизводится?

Click to edit Master title style

Стр. 12

Гипотеза 1

Включаем воображение!

Что может вызвать порчу данных?

•Аппаратный сбой – не интересно.

•Конфликт клиентов при одновременном доступе! Вот это уже что-то.

Click to edit Master title style

Стр. 13

Гипотеза 1

Включаем воображение!

Что может вызвать порчу данных?

•Аппаратный сбой – не интересно.

•Конфликт клиентов при одновременном доступе! Вот это уже что-то.

Click to edit Master title style

Стр. 14

Проверка

• Организовали тестирование.

• Два клиента в одном Продукте.

• Запуск двух экзампляров Продукта одновременно.

• ...

Click to edit Master title style

Стр. 15

Проверка

• Организовали тестирование.

• Два клиента в одном Продукте.

• Запуск двух экзампляров Продукта одновременно.

• ...

Синхронизация в user mode стойко вынесла все нападки.

Конфликта 2х продуктовых клиентов быть не может!

Click to edit Master title style

Стр. 16

Гипотеза 2. Конфликт Продукта с гибернацией?

Click to edit Master title style

Стр. 17

Гипотеза 2. Конфликт Продукта с гибернацией?

Теоретическая возможность этого обсуждалась уже давно.

Но вероятность этих событий в реальной жизни казалась (и была) очень малой.

Правильное решение было дорогим.

Воспроизвели с первого раза.

Ага, кажется, это то, что нужно.

Фикс получился очень сложный. Пришлось разработать новый механизм синхронизации доступа к метаданным.Изменить архитектуру, и это во время релиза :)

Синхронизация была сделана на основе драйвера

Пока шел доступ, гибернация в системе была заблокирована.

Click to edit Master title style

Стр. 18

2013/11/14, вечер.

• Исправления были закоммичены после тщательной проверки и ревью.

• Проблема исправлена.

• Команда торжествовала.

• Конфликт проверяли ручным тестом на разных машинах.

• Процесс 1: модифицирует метаданные в цикле.

• Процесс 2: вызывает гибернацию, циклически.

Click to edit Master title style

Стр. 19

2013/11/14, вечер.

Был оставлен на ночь Процесс 1, на всякий случай.

Click to edit Master title style

Стр. 20

2013/11/15, 11 часов дня. Пятница.

Что увидели разработчики?

Click to edit Master title style

Стр. 21

2013/11/15, 11 часов дня. Пятница.

ASSERTION FAILEDМетаданные изменены после или во время записи на диск.

Насчитанная контрольная сумма не совпадает с записанной.

Click to edit Master title style

Стр. 22

2013/11/15, 11 часов дня. Пятница.

ASSERTION FAILEDМетаданные изменены после или во время записи на диск.

Насчитанная контрольная сумма не совпадает с записанной.

Та-да-да-даам.• Один клиент• Никакой гибернации• Машина надежная (виртуальная)

Click to edit Master title style

Стр. 23

Пожар

• Замечательно исправили проблему, но не ту!

• Проблема никуда не делась!

• У нас есть воспроизведение!

• Совершенно не понятно что происходит.

Click to edit Master title style

Стр. 24

Пожар и сверхурочные

Команда мобилизована на воспроизведение.

• Проблема вопроизводится, воспроизвести сумели почти все, особенно дело хорошо шло на Windows XP.

• Есть условия, сильно улучшающие воспроизведение. Например, если диск активно шифруется, оно ускоряется в разы.

• Еще быстрее воспроизведение наступает, если создать сильную нагрузку на диск.

• Чемпионом стала однопроцессорная виртуалка с XP. Воспроизведение через минуту!

Да, в те годы мы еще поддерживали XP ;)

Click to edit Master title style

Стр. 25

Пожар и сверхурочные

Команда мобилизована на воспроизведение.

• Проблема вопроизводится, воспроизвести сумели почти все, особенно дело хорошо шло на Windows XP.

• Есть условия, сильно улучшающие воспроизведение. Например, если диск активно шифруется, оно ускоряется в разы.

• Еще быстрее воспроизведение наступает, если создать сильную нагрузку на диск.

• Чемпионом стала однопроцессорная виртуалка с XP. Воспроизведение через минуту!

Да, в те годы мы еще поддерживали XP ;)

Что происходит? Как это возможно?

Click to edit Master title style

Стр. 26

На самом деле

• Для воспроизведения проблемы модифицировать метаданные не нужно вовсе.

• Достаточно их просто читать.

• Чтение метаданных у нас идет через драйвер, через особый IOCTL. Почему?

• Т.к. весь диск зашифрован, и все что читает/пишет Windows, шифруется...

• Да-да, даже PAGEFILE, HIBERFIL, и даже "синие дампы" - вообще все.

• …Доступ к метаданным должен идти другим, нелегальным каналом. То есть, через драйвер.

Click to edit Master title style

Стр. 27

Тест на чтение метаданных через драйвер

Был сделан максимально простой тест.

Тест читал с диска через драйвер (тем самым волшебным IOCTL-ом).

Ничего лишнего - выделяем память, и читаем в нее с известного места на диске известные данные и сравниваем с образцом.

На волшебной виртуалке с XP – воспроизводилось хорошо. У других разработчиков показания разнятся.

• Буфер на стеке – нет проблемы.

• Холодный буфер через VirtualAlloc() – как из пушки.

Click to edit Master title style

Стр. 28

Тест на чтение метаданных через драйвер

Был сделан максимально простой тест.

Тест читал с диска через драйвер (тем самым волшебным IOCTL-ом).

Ничего лишнего - выделяем память, и читаем в нее с известного места на диске известные данные и сравниваем с образцом.

На волшебной виртуалке с XP – воспроизводилось хорошо. У других разработчиков показания разнятся.

• Буфер на стеке – нет проблемы.

• Холодный буфер через VirtualAlloc() – как из пушки.

Варианты:• виноват драйвер, который как-то странно работает с памятью буфера, тут как-то замешан PAGING,

• кто-то стреляет по памяти, внутри процесса, ну или из драйвера как вариант.

Click to edit Master title style

Стр. 29

Стресс-тест на драйвер с агрессивным пейджингом

• Система была еле жива под тяжестью теста.

• Но жива.

• Для чистоты эксперимента взяты свежие виртуалки, с современными OS.

• Windows 7 64,• Windows 8 64, • новейшая Windows 8.1 64,• разные конфигурации,

контроллеры диска...

Click to edit Master title style

Стр. 30

Стресс-тест на драйвер

• Система была еле жива под тяжестью теста.

• Но жива.• Для чистоты эксперимента

взяты свежие виртуалки, с современными OS...

НИЧЕГО

Click to edit Master title style

Стр. 31

Тем временем другие разработчики...

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

Click to edit Master title style

Стр. 32

What?

• Внезапно.

• Все происходит в юзер моде, без участия драйвера.

• Мы просто копируем данные в памяти.

В псевдокоде

copy(A, B);ASSERT(B == ETALON);ASSERT(A == ETALON); // <--- FAIL!

Click to edit Master title style

Стр. 33

What?

• Внезапно.

• Все происходит в юзер моде, без участия драйвера.

• Мы просто копируем данные в памяти.

В псевдокоде

copy(A, B);ASSERT(B == ETALON);ASSERT(A == ETALON); // <--- FAIL!

Click to edit Master title style

Стр. 34

Подозрительно! VEC_memcpy10221720 movdqa xmm0,xmmword ptr [esi]

10221724 movdqa xmm1,xmmword ptr [esi+10h]

10221729 movdqa xmm2,xmmword ptr [esi+20h]

1022172E movdqa xmm3,xmmword ptr [esi+30h]

10221733 movdqa xmmword ptr [edi],xmm0

10221737 movdqa xmmword ptr [edi+10h],xmm1

1022173C movdqa xmmword ptr [edi+20h],xmm2

10221741 movdqa xmmword ptr [edi+30h],xmm3

10221746 movdqa xmm4,xmmword ptr [esi+40h]

1022174B movdqa xmm5,xmmword ptr [esi+50h]

10221750 movdqa xmm6,xmmword ptr [esi+60h]

10221755 movdqa xmm7,xmmword ptr [esi+70h]

1022175A movdqa xmmword ptr [edi+40h],xmm4

1022175F movdqa xmmword ptr [edi+50h],xmm5

10221764 movdqa xmmword ptr [edi+60h],xmm6

10221769 movdqa xmmword ptr [edi+70h],xmm7

1022176E lea esi,[esi+80h]

10221774 lea edi,[edi+80h]

...

Click to edit Master title style

Стр. 35

На самом деле, ч.2

Единственной архитектурой, на которой воспроизводилась проблема, на самом деле была Intel IA32 (x86).

Все усилия поиска проблемы со стороны драйвериста были направлены на эту архитектуру AMD64 (тем более что IA32 уже занимаются другие люди ;))

Между архитектурами IA32 и AMD64 есть существенная разница в том, как они работают с плавающей точкой и регистрами SSE.

Windows реализует ленивое сохранение контекста FPU (SSE).

Экономия

Click to edit Master title style

Стр. 36

Ленивое сохранение FP контекста

Click to edit Master title style

Стр. 37

Ленивое сохранение FP контекста

Click to edit Master title style

Стр. 38

Ленивое сохранение FP контекста

Click to edit Master title style

Стр. 39

На самом деле, ч.2

Между архитектурами IA32 и AMD64 есть существенная разница в том, как они работают с плавающей точкой и регистрами SSE.

Windows реализует ленивое сохранение контекста FPU (SSE).

Экономия

Так вот...

• В ядре ОС на IA32 всякое сохранение контекста FPU/SSE должен явно делать программист.

• На AMD64 FPU/SSE входит в стандартный набор регистров, сохраняемый в KTRAP_FRAME, то есть, при любом переключении потоков, прерывании и т.д.

Click to edit Master title style

Стр. 40

Догадка, которая напрашивалась, была чудовищна

- Лев, похоже криптомодуль ядра портит конекст SSE.- Угу, но ты представляешь, что это значит? Это значит, что проблеме подвержены все потоки в системе. ВСЕ.Действительно, разве может система еще шевелиться, как ни в чем ни бывало? Это же ходячий труп.- ВСЕЕЕ. Да, это совершенно невероятно. Поэтому я не думаю, что моя гипотеза верна.

Click to edit Master title style

Стр. 41

2013/11/17, вечер.

• Деваться некуда.

• Но как конкретно драйвер портит регистры в чужих процессах?

• Почему усиление дисковой активности усиливает эффект.

• И при чем тут PAGING, почему проблема воспроизводится только при обращении к холодной памяти?

• Все входы и выходы в ядерный криптомодуль перекрыты.

• Вход в криптопримитив - сохранение (KeSaveFloatingPointState()).

• Выход из криптопримитива - восстановление (KeRestoreFloatingPointState()).

• Все это завернуто в такой плюсовый автоматический scoped guard, мышь не проползет.

• Однако, факты говорили другое.

Click to edit Master title style

Стр. 42

2013/11/17, вечер.

Было сделано 2 вещи:

• был собран криптомодуль без инструкций SSE/AES NI,

• и в драйвер-фильтр, перед каждым обращением к крипте, была добавлена собственная пара сохранение - восстановление контекста.

Оба подхода показали, что проблема уходит. Действительно уходит.

Печальный тимлид настраивал поставку криптомодуля без SSE/AES NI оптимизации.

Это был наш план Б.

А без SSE2 и AES NI шифрование работает в 4-5 раз медленнее.

Click to edit Master title style

Стр. 43

IDA Pro

Метод скрупулезного и тщательного вглядывания в ядерный криптомодуль принес нам это:

Click to edit Master title style

Стр. 44

IDA Pro

Это тело функции SymmetricContext::OSSL_Transform(), той самой, которая выполняет симметричное шифрование/расшифровывание блочным шифром.

Click to edit Master title style

Стр. 45

SymmetricContext::OSSL_Transform()

Вот так она выглядит в коде

Click to edit Master title style

Стр. 46

SymmetricContext::OSSL_Transform()

А ExecutionContext это структурка, которая как раз в среде ядра призвана сохранять FPU context.

Click to edit Master title style

Стр. 47

IDA Pro

Итак

Что это? SSE инструкции в коде конструктора?Зачем и откуда они там?

Click to edit Master title style

Стр. 48

Разоблачение

• Спасибо всем, кто помогал команде FDE найти баг ;)

• Кто-то за 2 месяца до этого включил SSE2 оптимизацию для всего проекта cm_km.sys, ядерного криптомодуля.

• Оптимизация благоприятно сказалась на скорости работы крипты :)

• Хотя алгоритмы блочного шифрования на SSE2 и AES-NI написаны на асме, и в оптимизации такого рода не нуждались.

• Оказался соптимизирован весь код, даже тот, который находится снаружи оберток KeSaveFloatingPointState()/KeRestoreFloatingPointState().

• Хотя его вроде бы и нет. Или есть?

• Зануление полей объекта в одном конструкторе, через memset(), заиспользовало только один раз регистр xmm0.

• И все

Click to edit Master title style

Стр. 49

Схема происшествия

Click to edit Master title style

Стр. 50

Happy end

Решение было простым - код крипты вынесли из драйвера в отдельную статическую библиотеку, и наступило щастье.

2013/11/19. Наш исправленный оптимизированный криптомодуль заработал.2013/11/22. После тщательнейшей проверки, мы сделали поставку и отчитались об исправлении бага.

Разработчики получили большие премии за сверхурочную работу.А радости менеджмента не было конца.

Вывод?

Click to edit Master title style

Стр. 51

Вывод, наша версия

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

Click to edit Master title style

Стр. 52

Конец

Спасибо за внимание!

[email protected]

[email protected]