Comments 27
ExpDetectHypervisorCr3Heuristic()
NTSTATUS
NtQueryLicenseValue (
PUNICODE_STRING "Kernel-VMDetection-Private",
NULL,
PBOOL Result,
ULONG 4,
PULONG ResultLength);
Так что, отставить строковые константы оборудования и cpuid (с ним давно уже покончено), надо смотреть в сторону того, что нет эмуляции TLB и всяких хитрых тайминговДетекты забавные.
В ExpIsVirtualMachinePrivate() набор детектов:
ExpDetectHyperVisorCpuid(), ExpIsViridian(), ExpIsViridianGuest() — детекты через cpuid. Вообще это даже в vmware правится через настройки, можно назначить, какой результат будет выдавать cpuid. Кстати, если гость является мсовской вм, то ядро не считает это виртуальной машиной, гы.
ExpDetectHyperVisorCr3Heuristic() — забавный детект. Сравнивается время выполнения «медленной» и «быстрой» инструкции. Причем за медленную инструкцию берется доступ к CR3. Прикол в том, что если гипервизор поддерживает EPT, то доступ к CR3 не приводит к выходу по умолчанию. Так что детект сработает только если гипервизор не поддерживает EPT или трапает CR3 вручную.
ExpDetectHypervisorVarianceHeuristic() — вот это да, головная боль. По трем листам cpuid считается статистика по времени выхода, причем время замеряется при помощи perf counter'а, источником коего может быть и tsc, и pm timer, и hpet. Запоминается 1000 значений (если до этого мы не вылезли слишком за таймаут), из которых потом высчитывается разброс во времени выполнения (дисперсия). Далее детект по значению разброса, который не должен превышать 5000. Здесь все упирается в качественную эмуляцию таймеров. Надо будет отпробовать vmware с галочкой «virtualize cpu performance counters».
Во-первых огромное спасибо за ссылку — одна из целей публикации это сбор дополнительной информации касательно особенностей детектирования ВМ.
А насчёт бесполезности — мне кажется вы рано клеймите этим словом последующие уровни. У первого уровня задача по сути обозначить проблему. На втором уровне добавляется детектирования через инструкцию CPUID (EAX=40000000h) и через бит hypervisor present (EAX = 1, смотрим 31-бит в ECX). Это поведение гипервизоров пропатчить чуть сложнее.
А на 3м уровне рассматриваются уже особенности реализации некоторых гипервизоров для определения.
Приведу конкретный пример: применительно к тому же VMWare — в ВМ чипсет компьютера детектируется как Intel 440BX (это socket 370, уровень Pentium II). Соответственно, увидев в системе указаный чипсет вкупе с процессором Intel Kaby Lake, да ещё и одноядерным — мы можем почти со 100% уверенностью утверждать что это виртуалка.
В теории — да. Но на практике для обеспечения приемлемой производительности гипервизор вынужден использовать аппаратные возможности виртуализации (типа Intel VT-x). И, завязавшись на особенности их использования, можно ещё больше увеличить вероятность определения ВМ.
Вкратце. Разработать полностью «прозрачную» виртуализацию с приемлемым уровнем производительности просто невозможно (пруф), а существующие ВМ оставляют нам множество артефактов, которые можно детектить.
Вот интересная статья на тему фаззинга инструкций ВМ (ссылка). Можно все не читать, просто обратите внимание на таблицу 2 на странице 10, они показывают количество инструкций, которые работают в этих виртуальных машинах по-другому, чем на нативной. И это они взяли относительно небольшое количество команд. Самое главное, что разработчики ВМ и не стремятся сделать ВМ «прозрачной» (зачем им тратить на это время и ресурсы?), им достаточно добиться совместимости.
Вот интересная статья на тему фаззинга инструкций ВМУ автора приложение на .NET'е, вы всерьез полагаете, что кто-то будет опускаться до уровня машинных кодов? Уверен, что если кому-то понадобится взломать эту защиту (привет, неуловимый Джо!), то все закончится максимум патчем .NET-рантайма. Можно взять за основу Mono, например.
Короче, не усложняйте. Не так давно мне надо было вытащить одну строку из Android-приложения. Для защиты авторы написали на Си разделяемую библиотеку и относительно неплохо ее обфусцировали. Они, вероятно, рассчитывали, что я месяцами буду дебажить эту либу в IDA, а я просто взял и запустил ее в нужном окружении (на создание которого ушло минут 10). Так что, как говорится, прочность цепи определяется прочностью ее самого слабого звена (в данном случае — .NET и «управляемый» (managed) код).
А насчёт спуска до уровня машинных кодов — не вижу причин не спускаться если это даст дополнительные данные. До инструкции CPUID мы уже спустились (через вызов unmanaged C++ библиотеки, заметка на хабр в процессе).
не следует в рамках заметки смешивать задачу определения запуска в окружении ВМ и обфускацию кодаС академической точки зрения — да, с практической — нет. Зачем месяцами разрабатывать проверки, которые потом обходятся патчем одного байта в программе?
через вызов unmanaged C++ библиотекиКонечно, не зная конкретной реализации, утверждать что-то очень сложно. Но подумайте еще раз над моими словами о слабом звене. Если библиотека банально возвращает true/false, то библиотеку можно подменить своей реализацией. Даже если проверяется подпись и т.д., то все-равно это делается из managed-кода, который пропатчить значительно легче, чем копаться в скопилированном C++. Тогда нужно выносить сами алгоритмы, которые вы хотите скрыть от посторонних. Но и тут может случиться забавная ситуация, когда вашу библиотеку будут просто использовать в своей программе.
Ну и не нужно забывать, что такие методы могут применяться и в малвари, полезно знать какие есть способы обнаружения песочницы.
Вообще, параноикам имеет смысл прописать эти константы вручную в своей ОС — всякая малварь первым делом детектит виртуальную машину, и просто не запускается, чтобы избежать отладки.
А серьёзному софту плевать на виртуализацию.
Отчасти соглашусь, но иногда бывает так, что защита "серьёзного" софта точно так же реагирует на присутствие ВМ и не позволяет ему запускаться.
Или вы про игры?
Пример серьезного софта, меняющего свое поведение при установке его на ВМ = Windows. Фишка в том, что в MS требуют отдельную лицензию на каждую ВМ (одной на всю физическую машину им мало). Предположу, что именно поэтому на ВМ при клонировании может слететь активация.
Сталкивался с таким поведением различных платных библиотек обработки аудио от крупных производителей.
1) Attacks on Virtual Machine Emulators
2) On the Cutting Edge: Thwarting Virtual Machine Detection
Эти темы по WMI уже столько изъездили! Думал хоть на хабре этого не будет!!!
Ан нет, WMI это круто, Написали бы лучше прогу инвентаризации и выложили в Opensource !
Добавлю от себя, что можно эту информацию также выдернуть из реестра Windows. Кстати малварь в основном так и делает.
ИМХО, постановка должна включать в себя два варианта — детект виртуалки, которая не скрывается и детект виртуалки которая пытается скрыться.
Первая часть очевидно разрешима, что вы и показали.
А вторая — настолько же очевидная разновидность задачи «брони-снаряда» — кому нужнее, тот и победит в краткосрочном периоде.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters
Детектим виртуальную машину на C#: 1 уровень