- PVSM.RU - https://www.pvsm.ru -

Как я убедил виртуальную машину, что у неё есть кулер

Как я убедил виртуальную машину, что у неё есть кулер - 1

Зачем вообще этим заморачиваться?

Некоторые образцы malware выполняют различные проверки, чтобы определить, запущены ли они в виртуальной машине. Один из самых частых способов — проверка наличия определённых аппаратных компонентов, обычно не эмулируемых в виртуальных средах. Один из таких компонентов — кулер процессора. Например, malware может проверять наличие кулера процессора, поискав в WMI класс Win32_Fan:

wmic path Win32_Fan get *

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

Зловредное ПО может определять, запущено ли оно в виртуальной машине, множеством разных способов. Есть различные классы WMI, позволяющие обнаружит присутствие виртуальной машины, например Win32_CacheMemory, Win32_VoltageProbe и множество других [1].

В этом посте я расскажу о кулере процессора. Мне просто понравилась идея убедить виртуальную машину, что он у неё есть. Однако такой же подход можно применить к другим аппаратным компонентам и классам WMI.

Как компьютер узнаёт, что в нём есть кулер процессора?

Компьютер узнаёт об этом, считывая данные SMBIOS.

Откуда я это знаю? Загуглил [2].

Экземпляры Win32_Fan предоставляются WindowsSystem32wbemcimwin32.dll. Если дизассемблировать библиотеку, можно увидеть, что для получения информации о кулере она считывает данные SMBIOS (в частности, записи с типом 27).

И в самом деле, если дизассемблировать cimwin32.dll, то именно это мы и увидим:

cimwin32.dll

cimwin32.dll

Возможно, первым делом вы бы решили воспользоваться хуками DLL и пропатчить cimwin32. Но надо мыслить масштабнее, чем мы и займёмся.

Тип 27

Тип 27 SMBIOS в System Management BIOS Reference Specification [3] определяется как Cooling Device:

Cooling Device (Type 27) structure

Структура Cooling Device (типа 27)

Можно получить дамп данных SMBIOS при помощи утилиты dmidecode:

root@host:/# dmidecode -t27 -u
# dmidecode 3.3
Getting SMBIOS data from sysfs.
SMBIOS 3.4 present.

Handle 0x1B00, DMI type 27, 15 bytes
        Header and Data:
                1B 0F 00 1B 00 1C 65 00 00 DD 00 00 E0 15 01
        Strings:
                43 50 55 20 46 61 6E 00
                CPU Fan

По умолчанию утилита dmidecode интерпретирует данные и отображает их в более удобном для чтения формате:

root@host:/# dmidecode -t27
# dmidecode 3.3
Getting SMBIOS data from sysfs.
SMBIOS 3.4 present.

Handle 0x1B00, DMI type 27, 15 bytes
Cooling Device
        Temperature Probe Handle: 0x1C00
        Type: Chip Fan
        Status: OK
        OEM-specific Information: 0x0000DD00
        Nominal Speed: 5600 rpm
        Description: CPU Fan

Задаём произвольные данные SMBIOS в Xen

На момент написания моей статьи единственным найденным мной источником о создании произвольных данных SMBIOS в Xen был пост mcnewton, которому уже почти десяток лет [4]. Рекомендую прочитать его, потому что в нём описываются как раз те мучения, которые испытывал я.

Если говорить вкратце, то можно задавать произвольные данные SMBIOS в Xen, присвоив опции smbios_firmware в файле конфигурации домена значение пути к файлу, содержащему данные SMBIOS.

Давайте создадим файл smbios.bin со следующим байтовым содержимым:

1B 0F 00 1B 00 1C 65 00 00 DD 00 00 E0 15 01 43
50 55 20 46 61 6E 00 00

Обратите внимание, что содержимое его такое же, как показанный выше вывод dmidecode -t27 -u, но с дополнительным байтом 00 в конце, потому что он требуется по спецификации SMBIOS.

В документации по файлу конфигурации домена Xen [5] можно также найти следующее:

Так как структуры SMBIOS не указывают свой общий размер, каждому элементу в файле должно предшествовать 32-битное целое число, определяющее размер последующей структуры.

Наша структура имеет длину 24 байт, поэтому перед содержимым нужно указать 18 00 00 00 (24 в формате little-endian):

18 00 00 00 1B 0F 00 1B 00 1C 65 00 00 DD 00 00
E0 15 01 43 50 55 20 46 61 6E 00 00

Теперь мы можем присвоить опции smbios_firmware в файле конфигурации домена Xen значение пути к этому файлу:

smbios_firmware = "/path/to/smbios.bin"

Сохраним файл конфигурации и запустим домен Windows.

root@host:/# xl create /path/to/windows/domain.cfg

Проверим теперь наличие кулера процессора в Windows VM:

PS C:> wmic path Win32_Fan get *
No Instance(s) Available.

Ой-ёй. Что-то пошло не так.

Предательство

Я упустил в документации одну важную подробность об опции smbios_firmware:

smbios_firmware=”STRING”

Указывает путь к файлу, содержащему дополнительную прошивку SMBIOS… Переопределению подлежат не все заранее заданные структуры, а только следующие типы: 0, 1, 2, 3, 11, 22, 39. Файл также может …

Если честно, на самом деле, я не упустил этот фрагмент, а просто надеялся, что мои действия не считаются «переопределением» заранее заданной структуры.

Потому что Xen (или, скорее, hvmloaderне определяет её [6].

Поэтому, прежде чем определять её самостоятельно, я попробовал узнать, возможно, какой-то бедняга пытался сделать то же самое до меня. К моему разочарованию, он нашёлся. Прямо в архиве патчей xen-devel.

Почему к разочарованию? Потому что после прочтения ответа на патч я ощутил раздражение автора. Но это уже другая история.

Как бы то ни было, патч отклонили, однако он маленький и простой, поэтому его легко можно самостоятельно применить к исходному коду Xen.

И тип 28 тоже

Применив патч и перекомпилировав Xen, я всё равно продолжал видеть ошибку No Instance(s) Available при попытках запросить класс Win32_Fan.

Мне это показалось совершенно нелогичным, поэтому я сдампил данные SMBIOS из VM, чтобы проверить наличие типа 27 (dmidecode есть и для Windows! [7]):

PS C:> .dmidecode -t27
# dmidecode 3.5
SMBIOS 2.4 present.

Handle 0x1B00, DMI type 27, 15 bytes
Cooling Device
        Temperature Probe Handle: 0x1C00
        Type: Chip Fan
        Status: OK
        OEM-specific Information: 0x0000DD00
        Nominal Speed: 5600 rpm
        Description: CPU Fan

Он там есть! Но почему он не отображается в WMI? Я заметил следующую строку:

        Temperature Probe Handle: 0x1C00

Она указывает на то, что охлаждающее устройство (CPU fan) связано с датчиком температуры, то есть другим типом SMBIOS (28). Однако датчик температуры не был определён в данных SMBIOS:

PS C:> .dmidecode -t28
# dmidecode 3.5
SMBIOS 2.4 present.

Вот и оно.

Нам нужно подделать ещё одну таблицу.

Отключим VM и сдампим данные типа 28 с хоста:

root@host:/# dmidecode -t28
# dmidecode 3.3
Getting SMBIOS data from sysfs.
SMBIOS 3.4 present.

Handle 0x1C00, DMI type 28, 22 bytes
Temperature Probe
        Description: CPU Thermal Probe
        Location: Processor
        Status: OK
        Maximum Value: 0.0 deg C
        Minimum Value: 0.0 deg C
        Resolution: 0.000 deg C
        Tolerance: 0.0 deg C
        Accuracy: 0.00%
        OEM-specific Information: 0x0000DC00
        Nominal Value: 0.0 deg C

И снова просмотрим их в байтовом представлении:

root@host:/# dmidecode -t28 -u
# dmidecode 3.3
Getting SMBIOS data from sysfs.
SMBIOS 3.4 present.

Handle 0x1C00, DMI type 28, 22 bytes
        Header and Data:
                1C 16 00 1C 01 63 00 00 00 00 00 00 00 00 00 00
                00 DC 00 00 00 00
        Strings:
                43 50 55 20 54 68 65 72 6D 61 6C 20 50 72 6F 62
                65 00
                CPU Thermal Probe

Следовательно, это содержимое нужно добавить в файл smbios.bin (снова не стоит забывать о дополнительном байте 00 в конце):

1C 16 00 1C 01 63 00 00 00 00 00 00 00 00 00 00
00 DC 00 00 00 00 43 50 55 20 54 68 65 72 6D 61
6C 20 50 72 6F 62 65 00 00

А, и ещё нам нужно указать перед ними размер структуры, на этот раз 41 байт (0x29 в шестнадцатеричном виде):

29 00 00 00 1C 16 00 1C 01 63 00 00 00 00 00 00
00 00 00 00 00 DC 00 00 00 00 43 50 55 20 54 68
65 72 6D 61 6C 20 50 72 6F 62 65 00 00

Итак, готовое содержимое файла smbios.bin должно выглядеть так:

18 00 00 00 1B 0F 00 1B 00 1C 65 00 00 DD 00 00
E0 15 01 43 50 55 20 46 61 6E 00 00 29 00 00 00
1C 16 00 1C 01 63 00 00 00 00 00 00 00 00 00 00
00 DC 00 00 00 00 43 50 55 20 54 68 65 72 6D 61
6C 20 50 72 6F 62 65 00 00

Закидываем невод в N-ный раз

Сохраним файл и снова запустим домен Windows:

root@host:/# xl create /path/to/windows/domain.cfg

Проверим, есть ли теперь кулер процессора в виртуальной машине Windows:

PS C:> wmic path Win32_Fan get Description,Status
Description     Status
Cooling Device  OK

Ура! Виртуалка теперь думает, что в ней есть кулер!

Если вы задаётесь вопросом, почему я не использовал * в команде wmic, то отвечу, что это вызвано тем, что класс Win32_Fan имеет множество свойств, а я хотел, чтобы вывод был коротким и удобным. Вполне бы также подошла команда wmic path Win32_Fan get *.

Задаём произвольные данные SMBIOS в QEMU/KVM

Если вместо Xen вы используете QEMU/KVM, то жизнь ваша будет намного проще, вам не нужно ничего патчить. Можно задавать произвольные данные SMBIOS при помощи опции -smbios:

qemu-system-x86_64 ... -smbios file=/path/to/smbios.bin

Или, если вы пользуетесь libvirt, то так:

  <qemu:commandline>
    <qemu:arg value='-smbios'/>
    <qemu:arg value='file=/path/to/smbios.bin'/>
  </qemu:commandline>

Однако вспомним о том, что Xen требовал 32-битных чисел, указывающих размеры структур. В QEMU они не требуются, поэтому можно просто использовать сырые данные, не указывая предварительно их размер:

1B 0F 00 1B 00 1C 65 00 00 DD 00 00 E0 15 01 43
50 55 20 46 61 6E 00 00 1C 16 00 1C 01 63 00 00
00 00 00 00 00 00 00 00 00 DC 00 00 00 00 43 50
55 20 54 68 65 72 6D 61 6C 20 50 72 6F 62 65 00
00

Вот и всё! QEMU автоматически обработает остальные важные записи SMBIOS.

Однако если вы задаётесь вопросом, можно ли просто взять данные SMBIOS хоста и использовать их в виртуальной машине, то да. Можете попробовать самостоятельно:

cat /sys/firmware/dmi/tables/DMI > /path/to/smbios.bin

Ссылки

Автор: PatientZero

Источник [11]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/xen/423978

Ссылки в тексте:

[1] множество других: https://github.com/zhaodice/qemu-anti-detection?tab=readme-ov-file#flaws-this-patch-does-not-fix-in-qemus-source

[2] Загуглил: https://stackoverflow.com/a/66605083/2011432

[3] System Management BIOS Reference Specification: https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.7.1.pdf

[4] пост mcnewton, которому уже почти десяток лет: https://notes.asd.me.uk/2015/12/04/setting-custom-smbios-data-in-xen-domus/

[5] документации по файлу конфигурации домена Xen: https://xenbits.xen.org/docs/unstable/man/xl.cfg.5.html#smbios_firmware-STRING

[6] не определяет её: https://github.com/xen-project/xen/blob/afbb876f1fe6f45ca5c3c425925d3d15101c7382/tools/firmware/hvmloader/smbios.c#L66-L98

[7] dmidecode есть и для Windows!: https://github.com/crystalidea/dmidecode-win

[8] https://xenbits.xen.org/docs/unstable/man/xl.cfg.5.html: https://xenbits.xen.org/docs/unstable/man/xl.cfg.5.html

[9] https://old-list-archives.xen.org/archives/html/xen-devel/2022-01/msg00725.html: https://old-list-archives.xen.org/archives/html/xen-devel/2022-01/msg00725.html

[10] https://github.com/zhaodice/qemu-anti-detection: https://github.com/zhaodice/qemu-anti-detection

[11] Источник: https://habr.com/ru/articles/923314/?utm_source=habrahabr&utm_medium=rss&utm_campaign=923314