Свой гипервизор ближе к телу! Аппаратная виртуализация на практикеr0064 (r0064@mail.ru) Ты, конечно, не раз слышал про такую штуку, как аппаратная виртуализация – технологию, позволяющую запускать несколько гостевых ОС на одной машине (так называемом хосте). Исторически первой была программная виртуализация, затем разработчики процессоров призадумались, что неплохо было бы обеспечить аппаратную поддержку этого дела. Итак, с 2006-го года в нашем распоряжении оказались процессоры Intel и AMD с возможностями виртуализации. И пошло-поехало... Надо сказать, что обзоров и статей, касающихся темы виртуализации, выходило за эти годы немало. Например, рекомендую к прочтению статью «Технологии аппаратной виртуализации», представляющую собой довольно основательный обзор сабжа: ixbt.com/cm/virtualization-h.shtml. Однако, ни одной статьи, выходящей за рамки аналитики, я так и не встретил. Пора закрыть этот пробел и сконцентрироваться, наконец, на деталях реализации гипервизора. Между тем, уже, наверное, каждому известно про «Голубую пилюлю» (Blue Pill) Рутковской, в которой возможности виртуализации успешно применяются, причем не в самых легитимных целях :). Пока кто-то создает экспериментальные руткиты на базе виртуализации, кто-то активно разрабатывает анти-руткиты. Так, Hypersight Rootkit Detector от North Security Labs – считай готовый анти-руткит для Windows. Для Linux тоже существует подобный проект – HookSafe, который был представлен на конференции ACM по компьютерной и сетевой безопасности (CCS 2009). Такой интерес к виртуализации далеко не случаен – ведь для хакера это уникальная возможность скрытия своего присутствия в системе (наряду с более сложными, но и не менее красивыми, атаками на SMM и AMT). Конечно, чтобы сделать руткит (даже на базе виртуализации) на 100% недетектируемым придется напрячься, но игра стоит свеч! В конце концов, мы получает возможность тотального контроля над системой. Заинтересовало? Тогда вперед, осваивать такую непростую штуку как программирование гипервизоров. Прежде чем зарываться в документацию, нужно обрисовать задачу более подробно. Вообще, аппаратная виртуализация в процессорах Intel (именуемая Intel VT) отличается от аналогичной у AMD (AMD-V). Отличается – значит, код гипервизора (aka VMM – Virtual Machine Monitor) для AMD не будет работать на платформе Intel. Поэтому мы начнем с AMD и продолжим о Intel в последующих статьях. Чтобы ты мог уточнить для себя какие-то вещи, тебе потребуется дока от амд (смотри врезку), также можно почитать краткий обзор AMD-V от производителя (amd64.ru/index.php?link=2&addr=6&page=8). Теоретические основыПеред тем, как приступать к написанию кода, необходимо получить минимальную теоретическую базу. Для начала определимся с терминами и аббревиатурами, которые будут использоваться далее по тексту.
ПодробностиТы - обладатель процессора AMD. Как узнать, есть ли в нем поддержка аппаратной виртуализации? О том, что мы имеем соответствующий функционал, рапортует функция 80000001h инструкции CPUID (второй бит от нуля в регистре ecx, именуемый SVM, должен быть установлен). Функция, возвращающая 0 или 1,если возможности виртуализации недоступны или доступны, соответственно.
Убедившись, что в нашем распоряжении подходящий процессор, можно приступать к дальнейшему описанию. Забегая вперед, скажу, что включение виртуализации, как и, в общем-то, весь код нашего гипервизора, будет находиться в драйвере и работать в ring-0. В процессе освоения кодинга гипервизора от тебя потребуется представление о программировании драйверов под Windows, знание с/с++ и 64-битного ассемблера на базовом уровне. Хотя я все равно постараюсь объяснить все максимально подробно. Инструкции управления виртуальными машинамиПо своей сути аппаратная виртуализации – это расширение архитектуры ЦП: набор инструкций + новый режим работы процессора. До того, как говорить о наборе команд, нужно разобраться с такой штукой, как VMCB. VMCB (Virtual Machine Control Block) – управляющий блок виртуальной машины. Это основная структура данных, с которой нам предстоит работать. VMCB описывает виртуальную машину, которую мы будем запускать. Сразу о технических деталях: VMCB занимает одну страницу (4 килобайта) в непрерывной физической памяти. VMCB состоит из 2-х частей – область флагов (control area) и область состояния (state-save area). Рассмотрим структуру VMCB подробнее. VMM, как уже упоминалось, перехватывает события, происходящие в госте. Какие это будут события – определяется в области флагов. Мы можем перехватывать:
Все вышеперечисленные события – это условия #VMEXIT – возвращения из гостевого режима в режим хоста. Каждая причина #VMEXIT имеет свой код, который записывается в поле exitcode области флагов VMCB. Вот некоторые из этих кодов:
Полную таблицу #VMEXIT-тов можно посмотреть в Appendix C. SVM Intercept Exit Codes в уже упоминаемом мной AMD64 Architecture Programmer's Manual Volume 2. Часть дефиниции cтруктуры VMCB (из сорцов Xen):
Все неиспользуемое пространство обязательно должно быть заполнено нулями. Вторая часть VMCB содержит состояние регистров гостя. Из этой области во время выполнения инструкции VMRUN (о ней скажу позже) загружается информация о состоянии гостя, а при выходе из гостевого режима она (информация о состоянии) сохраняется там же.
С VMCB кое-как разобрались. Теперь можно переходить к описанию инструкций. VMRUN (опкод команды - 0Fh, 01h, 0D8h) – инструкция запуска виртуальной машины. Это основная и самая важная команда в аппаратной виртуализации. VMRUN принимает в качестве аргумента в регистре rax физический адрес управляющего блока виртуальной машины (VMCB), который описывает состояние виртуальной машины. VMRUN доступна только с нулевого кольца (вообще, с третьего кольца из инструкций, составляющих сабжевое расширение архитектуры процессора, доступна только VMMCALL). Гипервизор настраивает структуру VMCB, устанавливает в ней перехватываемые инструкции, прерывания и т.д. Переход в режим гостя происходит посредством инструкции VMRUN. Состояние хоста сохраняется в области памяти, на которую указывает содержимое msr регистра VM_HSAVE_PA (PA – Physical Address, то есть здесь мы опять имеем дело с физическим адресом этого региона). В этой области памяти сохраняется минимальная информация, необходимая для возобновления работы хоста после выхода из гостя (регистры cs,rip, efer, cr0, cr3 …). Теперь, когда виртуальная машина успешно запущена, мы вернемся в режим хоста только при возникновении перехваченного гипервизором события (условия #VMEXIT). После #VMEXIT будет выполнена следующая за VMRUN инструкция в гипервизоре. Специально для тебя я сделал обобщающую схему вышеописанного (смотри картинку «Схема работы виртуализации AMD-V»). Две инструкции VMSAVE (0Fh, 01h, 0DBh) и VMLOAD (0Fh, 01h, 0DAh) дополняют VMRUN и служат для сохранения/загрузки части VMCB. Включение возможностей аппаратной виртуализацииВсе инструкции работы с аппаратной виртуализацией (за исключением SKINIT, там особый случай) требуют установки бита SVME (он 12-й) в регистре EFER (иначе мы получим исключение #UD – неверная инструкция). Что это за регистр – EFER? Расшифровывается аббревиатура как Extended Feature Enable Register – это msr, который отвечает за включение дополнительных возможностей проца (что видно из расшифровки), и он имеет адрес 0C0000080h. Приведенный ниже код включает возможности аппаратной виртуализации:
Кстати, установка бита SVME может быть заблокирована, поэтому после того, как мы записали msr, нужно снова прочитать его содержимое и проверить – установился ли заветный бит. За блокировку инструкций виртуализации отвечают msr-регистры – VM_CR и SVM_KEY (опционально). Бит SVMDIS, который четвертый в VM_CR, запрещает установку EFER.SVME, а LOCK (бит три) в том же регистре запрещает сброс SVMDIS и LOCK (получается, что LOCK – это защита для защиты). LOCK можно сбросить либо после перезагрузки, либо указать ключ в машинно-зависимом регистре SVM_KEY (если этот ключ был установлен перед блокированием виртуализации). Сама возможность блокировки, к слову, появилась в AMD-V не сразу, а только со второй ревизии (специально для параноиков:)). ЗаключениеПервый теоретический рубеж преодолен. Изложение получилось несколько сумбурным, но, я думаю, это тебе не помешало уловить суть. Осталось реализовать полученные знания на практике, что мы и сделаем в последующих статьях. Если у тебя есть какие-то замечания или вопросы – пиши мне на мыло, постараюсь ответить. WWWAMD64 Architecture Programmer's Manual Volume 2: System Programming:amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24593.pdf. Теме виртуализации в этом мануале посвящена глава 15, Secure Virtual Machine. Hypersight Rootkit Detector (для Windows) – анти-руткит на основе аппаратной виртуализации. Фраза на главной странице «Blue Pill перестал быть невидимым» – заставляет познакомиться с сабжем поближе: northsecuritylabs.com/ru. Проект Blue Pill Джоанны Рутковской – руткит, использующий аппаратную виртуализацию (опенсорс): bluepillproject.org. В качестве дополнительной литературы можно почитать также ман AMD, целиком и полностью посвященный CPUID. CPUID Specification: amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf. Проект Xen:xen.org/products/projects.html. HookSafe – не так давно появившийся анти-руткит на основе гипервизора (для Linux). Исследователи работают над версией для Windows: http://discovery.csc.ncsu.edu/pubs/ccs09-HookSafe.pdf. |