Pull to refresh

Comments 27

К сожалению, ваш 1 уровень (да и последующие, к сожалению) — совершенно бесполезный детект, без обид. Эти строковые константы у vmWare / VirtualBox (про Hyper-V не встречал) патчатся на ура и есть готовые решения, недавно совсем натыкался на совсем уж киддиса, который в лоб смог забить почти все детекты, вот, почитайте на досуге: https://exelab.ru/f/index.php?action=vthread&forum=5&topic=24207
И там Клерк объявился с интересным предложением (ядро Win 8+, встроенный механизм детекта виртуальной среды по таймингам), скину сюда, т.к. ссылки не могу нормально вставлять:
ExpDetectHypervisorCr3Heuristic()
NTSTATUS
NtQueryLicenseValue (
    PUNICODE_STRING "Kernel-VMDetection-Private",
    NULL,
    PBOOL Result,
    ULONG 4,
    PULONG ResultLength);
Так что, отставить строковые константы оборудования и cpuid (с ним давно уже покончено), надо смотреть в сторону того, что нет эмуляции TLB и всяких хитрых таймингов
Ни в одном ядре не нашел. Он сам её так назвал? Дайте пруфов плз.
Нашёл на 7 x64.
Детекты забавные.
В 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».
PSPS Таки-да, если в вмваре исправить cpuid, то данный детект не работает ввиду хреновой статистики ;)
данный
ExpDetectHypervisorVarianceHeuristic? В итоге все MS-варианты оказались провальны, так?
Я лишь говорю о том, что грамотно настроенный гипер детектить достаточно сложно.
Приветствую!

Во-первых огромное спасибо за ссылку — одна из целей публикации это сбор дополнительной информации касательно особенностей детектирования ВМ.

А насчёт бесполезности — мне кажется вы рано клеймите этим словом последующие уровни. У первого уровня задача по сути обозначить проблему. На втором уровне добавляется детектирования через инструкцию 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++. Тогда нужно выносить сами алгоритмы, которые вы хотите скрыть от посторонних. Но и тут может случиться забавная ситуация, когда вашу библиотеку будут просто использовать в своей программе.
С точки зрения защиты кода Вы 100% правы. Защита должна быть построена таким образом, чтобы её нельзя было бы пропатчить 1 байтом, сам не раз сталкивался с таким. Поэтому предлагаемое в статье решение может (и должно) использоваться только как один из компонентов многослойной защиты. Themida отличный пример (хоть и не managed-code).

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

Вообще, параноикам имеет смысл прописать эти константы вручную в своей ОС — всякая малварь первым делом детектит виртуальную машину, и просто не запускается, чтобы избежать отладки.


А серьёзному софту плевать на виртуализацию.

Отчасти соглашусь, но иногда бывает так, что защита "серьёзного" софта точно так же реагирует на присутствие ВМ и не позволяет ему запускаться.

А что за софт такой серьёзный, что его нельзя запускать в ВМ?

Или вы про игры?

Пример серьезного софта, меняющего свое поведение при установке его на ВМ = Windows. Фишка в том, что в MS требуют отдельную лицензию на каждую ВМ (одной на всю физическую машину им мало). Предположу, что именно поэтому на ВМ при клонировании может слететь активация.

Сталкивался с таким поведением различных платных библиотек обработки аудио от крупных производителей.

Добавлю свои закладки:
1) Attacks on Virtual Machine Emulators
2) On the Cutting Edge: Thwarting Virtual Machine Detection
Большое спасибо! Обязательно просмотрю.

Эти темы по WMI уже столько изъездили! Думал хоть на хабре этого не будет!!!
Ан нет, WMI это круто, Написали бы лучше прогу инвентаризации и выложили в Opensource !

Спасибо за статью, очень интересно!

Добавлю от себя, что можно эту информацию также выдернуть из реестра Windows. Кстати малварь в основном так и делает.
Первая часть такая обстоятельная :)
ИМХО, постановка должна включать в себя два варианта — детект виртуалки, которая не скрывается и детект виртуалки которая пытается скрыться.
Первая часть очевидно разрешима, что вы и показали.
А вторая — настолько же очевидная разновидность задачи «брони-снаряда» — кому нужнее, тот и победит в краткосрочном периоде.
Еще для Hyper-V содержимое секции реестра:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters
Sign up to leave a comment.

Articles