Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 132, ДЕКАБРЬ 2009 г.

Прокачиваем виртуальную машину. Разбираем с API виртуалки и добавляем ей веб-интерфейс

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

Запускать на винде сомнительные тулзы, скачанные с «хакерских» сайтов, кейгены и прочую ерунду, происхождение которой под большим вопросом, сродни добровольной установке в систему трояна. Такие файлы я предпочитаю запускать исключительно под виртуальными машинами. Проблемы возникают, когда домашнего компьютера или хотя бы ноута нет под рукой.

Веб-консоль для управления

К счастью, для каждой виртуальной машины VirtualBox (www.virtualbox.org), на котором у меня вполне успешно уже год работают несколько виртуалок, позволяет назначить порт VRDP-сервера и работать с ними удаленно через любой RPD-клиент: например, mstsc под виндой или rdesktop под линуксом. В настройках роутера проброшены два порта: один — до виртуалки с виндой и другой — для openSUSE. При всей красоте такого подхода очень скоро вскрылись два серьезных минуса. Во-первых, во многих сетях и хотспотах беспощадно режется все, кроме нескольких стандартных портов, и подключиться по RPD никуда уже не удается. А во-вторых, для возможности коннекта виртуальную машину приходится держать включенной, потому как функций удаленного управления или, скажем, включения по входящему подключению нет. Я уже не говорю о том, чтобы изменить параметры виртуальной машины или даже создать новую.

Для всего этого напрашивалось вполне очевидное решение — организовать управление через веб, ведь 80 порт открыт практически везде. Изобретать велосипед не пришлось: Sun некогда позаботилась о пользователях, инициировав разработку VirtualBox Web Console (code.google.com/p/vboxweb) и пустив ее в свободное плавание OpenSource.

В результате, сейчас мы можем получить качественно написанный веб-демон, на котором будет крутиться AJAX-приложение для виртуальной машины. Тут все просто — это полная копия графического интерфейса виртуальной машины, только отображаемая в браузере. Вот тебе наглядный пример, какие интерфейсы можно создавать, используя всем доступные AJAX-фреймворки jQuery и его расширение jQuert UI. Создание новой виртуальной машины, запуск и ее остановка, сохранение состояния, изменения параметров гостевой ОС — все делается так, как если бы ты запустил VirtualBox на своей машине.

Возможность такой оболочки реализована через API VirtualBox'а — систему вызовов, позволяющую с помощью различных языков манипулировать виртуальными машинами. Серверные компоненты веб-оболочки написаны на Python и используют привязки для этого языка. Кстати говоря, VirtualBox Python API в текущий момент входит в состав VirtualBox по умолчанию: до этого момента приходилось скачивать VirtualBox SDK и устанавливать привязки для Python'а вручную. В качестве основы для демона разработчиками был выбран CherryPy (www.cherrypy.org) как легкий и мощный веб-сервер. В результате демон (исходник — VBoxWebSrv.py) общается с VirtualBox, используя API, и с клиентом — посредством HTTP. Все просто: сервер принимает запросы от браузера клиента, проверяет их и выполняет вызов соответствующей функции VirtualBox API. Данные передаются с использованием стандарта JSON, который очень легко парсится в AJAX-окружении.

Модуль на Python также регистрирует все события внутри VirtualBox'а (например, изменения состояния виртуальных машин) и передает их для отображения в веб-интерфейсе. Посмотрим, как это выглядит на практике.

Устанавливаем веб-консоль

Поскольку VirtualBox Web Console написана на Python'е, первое, что нужно сделать, — установить интерпретатор. Здесь и далее я буду описывать процесс для винды, но для других ОС все выполняется аналогично. Если не ищешь проблем, рекомендую взять Python версии 2.6 с python.org/download. Далее необходимо установить библиотеки расширения — так называемые Python Win32 Extensions, предварительно скачанные для используемой версии интерпретатора с репозитория sourceforge.net/projects/pywin32/files. Чтобы дальше все было окей, нужно проверить, чтобы путь к интерпретатору python.exe был прописан в переменной окружении PATH.

Следующий шаг — позаботиться о привязках. Вообще говоря, опцию Python API VirtualBox я выбирал во время установки, но... привязка почему-то не установилась (хотя файлы скопировались). Поэтому сразу объясню, как заинсталлить ее вручную. Для этого переходим в директорию с VirtualBox'ом (program filessunvirtualbox), находим папку sdkinstall и далее выполняем: python vboxapisetup.py install Еще один важный момент — под Windows Vista и W7 установку необходимо запускать из-под администратора. После этого можно было бы считать ее законченной и приступать к запуску веб-демона:

python VBoxWebSrv.py

Однако открыв в браузере http://localhost:8080 (официально поддерживается Internet Explore и Firefox), ты упрешься в тупик. Рабочая система запросит имя и пароль пользователя, которого мы еще банально не создали. Не вопрос! Опять же, из-под аккаунта администратора отдаем демону команду на создание нового пользователя: python VBoxWebSrv.py adduser myuser mypassword.
Теперь, залогинившись в систему, ты увидишь список виртуальных машин в левой панели, точно такой же, как и в самом интерфейсе VirtualBox. Если потребуется изменить порт или интерфейс, на котором нужно принимать подключения, достаточно указать нужные параметры в конфиге VBoxWeb.conf:

[global]
server.socket_host = "0.0.0.0"
server.socket_port = 8080

О том, что в VirtualBox вот-вот появится поддержка плагина на Flash, позволяющего управлять виртуальными машинами через браузер, мне рассказал один из разработчиков еще во время весенней конференции Sun Tech Days. Правда, в тот момент Sun ничего официально не объявлял, а пощупать все руками не вышло даже в самой последней бете. Такая возможность появилась с выходом VirtualBox Web Console, которая создавалась именно с целью предоставления доступа к VRDP-серверу через Flash. Разработанная технология называется Sun RPD Web Control. Последняя версия компонента закачивается во время установки веб-консоли, поэтому дополнительно настраивать ничего не нужно.

Просто переходишь во вкладку Console, нажимаешь кнопку Connect, и ты прямо в окне браузера получаешь полноценное RPD-подключение со всеми его возможностями. Только представь: из любой точки мира ты можешь открывать страничку вебинтерфейса, запускать виртуальную машину и работать с ней, как ни в чем не бывало, прямо из браузера! Респект разработчикам.

Осваиваем API

Пример веб-консоли показывает, насколько мощным инструментом является система API-вызовов, позволяющая управлять всеми аспектами конфигурации и запуска виртуальных машин. Освоив несложные привязки, можно вывести использование виртуальных машин на новый качественный уровень. В отличие от VMware, ты не можешь включить автозапуск гостевых систем в момент запуска гостевой машины. Но благодаря простенькому скрипту, запуск можно автоматизировать и влиять на любые его параметры. Вообще, есть несколько вариантов решения задачи, но попробуем реализовать это с помощью сценария, который будет отдавать команды на старт виртуалок с помощью VirtualBox API. Система встроенных вызовов такова, что использовать его можно из самых разных языков программирования: существуют привязки (т.е. специальные модули) для Java, Python и других языков. У нас уже установлено все, что нужно для работы c Python, поэтому это хороший вариант для старта. Скажу более — прямо с VirtuaBox'ом идет специальная обертка, в которой завуалированы многие кроссплатформенные аспекты, а потому написанные с ее помощью скрипты будут работать на разных платформах.
Любой скрипт с использованием привязки начинается с подключения нужного модуля и создания объекта virtualBoxManager:

import VirtualBoxManager
virtualBoxManager =
VirtualBoxManager(None, None)

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

vbox = virtualBoxManager.vbox
mgr = virtualBoxManager.mgr
print "Version is",vbox.version
name = "xp eng"
mach = machById(name)
if mach is None:
print "cannot find machine",name
else:
session = mgr.getSessionObject(vbox)
progress = vbox.openRemoteSession(
session, mach.id, "gui", "")
progress.waitForCompletion(-1)
session.close()

Для запуска виртуальной машины используется функция openRemoteSession(), при этом в качестве первых двух параметров передается сессия, идентификатор виртуальной машины. Поскольку мы позволяем пользователю использовать как идентификатор, что неудобно, так и имя виртуальной машины, то дополнительно определяем функцию machById. Задача функции — по имени виртуальной машины определить ее идентификатор:

def machById(id):
mach = None
for m in virtualBoxManager.
getArray(vbox, 'machines'):
if m.name == id or mach.id == id:
mach = m
break
return mach

Третий параметр, передаваемый функции openRemoteSession(), может принимать два значения: gui и vrdp. В первом случае открывается обычное окно виртуальной машины, в котором ты можешь работать с гостевой ОС. Во втором случае откроется консольное окно и предполагается, что работать с гостевой ОС ты сможешь, подключившись к виртуалке по RPD-протоколу.

Вот собственно и весь код. Оформив его в виде функции, можно повторно использовать код для включения нужного числа виртуальных машин, что нам как раз и нужно. В качестве еще одного примера рекомендую изучить скрипт для безболезненного импорта/экспорта виртуальных машин (gui-at.cendaweb.cz/2009/09/VBoxUtil.py). Без него процесс переноса виртуальной машины с одного хоста на другой превращается в некислый геморрой. С позиции обучения он интересен тем, что использует самые разные возможности API.

Продолжаем эксперименты

Вот тебе другая ситуация. Файл необходимо проверить несколькими антивирусами. Понятно, что на одной машине едва ли уживутся даже два антивируса — чего уж говорить, если их будет, скажем, десять? Верный путь решения проблемы — установить каждый антивирус на отдельную виртуальную машину, но не запускать же каждую с последующим сканированием файла вручную?

Можно взять и написать несложный сценарий, который через API запустит виртуальную машину и передаст антивирусу файл для проверки. Попробуем с этим разобраться. Я был уверен, что в API VirtualBox'а, помимо функций для управления виртуальными машинами, найдутся вызовы для манипулирования гостевыми системами. Например, в VMWare есть функции RunProgramInGuest для запуска приложения в гостевой системе и функции CopyFileFromGuestToHost для копирования файлов между гостевыми и хостовой системами. Не найдя аналогов в документации, пришлось обратиться к разработчикам VirtualBox, которые подтвердили: «такие функции пока только в планах» :(. Конечно, можно было бы обойтись и без них (например, добавив скрипт для проверки в автозагрузку системы, а файлы для проверки передавать через систему Shared Folders), но отказываться от возможности манипулировать гостевой системой не хотелось, поэтому было принято решение — в качестве технологии использовать продукты VMware.

К счастью, есть выбор: можно использовать платную WMware Workstation, с которой многие уже знакомы, или же бесплатный VMware Server. Оба дистрибутива весят под полгигабайта, но предоставляют в нашем случае равные возможности. Печальная новость состоит в том, что управление VMware Server, начиная с версии 2.0, полностью осуществляется через веб-интерфейс и, хотя работает он неплохо, нативный GUI-интерфейс Workstation использовать-таки удобнее. Но что делать... зато всю мощь виртуализации ты получаешь бесплатно, и в своих примерах я буду использовать именно его.

Вместе с тяжелым ядром и веб-сервером Tomcat, на котором хостится админка VMware Server, в систему устанавливается так называемая VMware VIX — собственная система API, позволяющая программировать виртуальные машины и управлять ими, в том числе, манипулировать гостевыми ОС во время выполнения. В качестве языка программирования очень хотелось использовать Python, но, увы, не вышло. Официальных привязок для этого языка компания не выпускает, а найденные на просторах Сети самоделки pyvix (sourceforge.net/projects/pyvix) и pyvmware (code.google.com/p/pyvmware) давно не обновлялись и заработали бы с новыми версиями VMware лишь после серьезной работы напильником, которой заниматься совсем не охота. Описание проекта vixpy (code.google.com/p/vixpy), указывающее, что это единственный обновляющийся проект, выглядело многообещающе, но все попытки найти файлы привязки, скачать их из репозитария svn или связаться с автором не увенчались успехом.

Впрочем, нашелся еще один проект — обертка Python'а для утилиты vmrun.exe, также входящей в набор VMware VIX и позволяющей как угодно манипулировать системой прямо из командной строки. Сама обертка, как водится, безнадежно устарела, зато открыла для меня vmrun.exe — совершенно чумовой консольный инструмент, реализующий всю мощь VMware API! Задача у нас несложная, а, значит, вполне должно хватить ее возможностей. Конечно, при таком положении вещей пришлось сразу попрощаться с объектной моделью и прочими красивостями, но способ построить прототип системы быстрее еще нужно поискать. К тому же, для большей универсальности и качества кода легко можно использовать возможности PowerShell. Впрочем, прежде чем приступать к программированию VMware, нужно заняться подготовкой самих виртуальных машин и установленных антивирусов.

Тестовая лаборатория

Как мы уже сказали, для каждого авера мы создаем по одной виртуальной машине. Пускай они будут работать на базе Windows XP. Для большей универсальности предлагаю сразу давать виртуальным машинам имена в соответствии с тем антивирусом, который на нем установлен: ClamAV, Nod32, Symantec, Kaspersky. Автоматизировать процесс сканирования через навороченные графические интерфейсы — лишнее изобретение велосипеда, потому как у любого вендора есть решение, работающее через командную строку. Возьмем для примера бесплатный антивирус ClamAV, с помощью которого и построим одну из виртуальных машин для тестирования. Я использовал Portable-версию антивируса (portableapps.com/apps/utilities/clamwin_portable), но это непринципиально.
Чтобы скрипты для работы были более-менее универсальны, на каждой виртуальной машине неплохо будет использовать одинаковую систему каталогов. Предлагаю создать папку для нашей тестовой лаборатории C:XLab с простой структурой:

C:XLab: QuarantineFiles — карантин, куда будут скачиваться файлы для анализа OutputFiles — папка для сохранения отчетов антивируса, которые далее будут передаваться на хостовую машину

Soft — папка с необходимым софтом: SoftWget — утилита для закачки файлов SoftClamWinPortable — наш антивирус Общая идея простая: специальный BATфайл сначала запускает консольную качалку wget (порт никсовой утилиты), закачивая указанный файл в папку-карантин, содержимое которого затем проверяется антивирусом. Отчет авера сохраняется в папку OutputFiles, откуда мы его забираем на хостовую машину. При всей простоте с настройкой антивирусов придется немного повозиться. Даже если взять ClamAV, для которого изначально предполагается использование из командной строки. При запуске консольной версии программы clamscan.exe упорно выдавалась ошибка об отсутствии антивирусных баз, хотя в GUI-версии антивируса все было окей. Долго не понимая, какой же ключ используется для обновления антивирусных баз, я нашел специально предназначенную для этого тулзу, которая лежала рядом — freshclam.exe. Но и она не запускалась, ссылаясь на отсутствие конфига!

DatabaseDirectory c:/XLab/Soft/ClamWinPortable/App/clamwin/bin
DatabaseMirror database.clamav.net

Эти две строки, сохраненные в freshclam.conf, наконец, заставили базы обновиться, а сам антивирус заработать. Чтобы указать путь для сканирования, пришлось создать текстовый файл toscan.txt с содержанием пути до карантина «C:XLabQuarantineFiles». В результате можно было собрать готовый doWork.bat, принимающий в качестве единственного параметра URL файла для проверки и выполняющий сканирование:

c:
del /Q /F c:XLabQuarantineFiles*.*
del c:XLabOutputFilesreport.txt
cd c:XLabSoftClamWinPortableAppclamwinbin
freshclam.exe
cd c:XLabSoftWget
wget --directory-prefix=c:XLabQuarantineFiles %1
cd c:XLabSoftClamWinPortableAppclamwinbin
clamscan.exe --file-list=toScan.txt --log=c:XLab
OutputFilesreport.txt

Дабы избежать проблем с парсингом URL, в момент вызова bat-файла его лучше взять в кавычки: doWork.bat "http://dvd.xakep.ru/test.exe".
Убедившись, что все работает, приступаем к следующей задаче — интеграции виртуалки в наш прототип системы для анализа файлов.

Тестовая лаборатория

Запустить виртуальную машину через vmrun.exe — проще простого. Используется ключ start и указывается путь до .vmx-файла — это XML-ка с описанием виртуальной машины, которую генерирует в момент создания виртуалки сама VMware: vmrun auth_param start "[standard] xp eng/xp eng.vmx"

Обрати внимание на переменную [standard], которая определяет стандартное хранилище виртуальных машин. Если указать полный путь до .vmx-файла (скажем, j:virtual machinesxp engxp eng.vmx), тулза выдаст сообщение об ошибке. Чтобы упростить пример, здесь и далее я намерено укоротил строку параметров для запуска vmrun, заменив опции для авторизации переменной auth_param. Что она собой представляет? С помощью ключа -T определяется продукт, который ты используешь — Workstation или Server — причем, в последнем случае указывается URL админки, а также логин и пароль для входа в хостовую машину (и, соответственно, админку VMware Server). Вместо auth_param в строке для запуска должно стоять:

Для VMware Workstation: — T ws
Для VMware Server: -T server -h https://localhost:8333/sdk -u xlablogin -p xlabpass m

После того, как виртуальная машина запущена, запустим нужное нам приложение. Название команды runProgramInGuest говорит само за себя. Составляем строку параметров, указывая логин и пароль для пользователя внутри гостевой (!) системы, а также полный путь до нашего doWork.bat-файла. Помимо этого, нужно передать в качестве параметра URL файла для проверки.

vmrun auth_param -gu xlab -gp xlab runProgramInGuest
"[standard] xp eng/xp eng.vmx" "c:XLabdoWork.bat" %1%

И тут нас постигает первый облом. После недолгого ковыряния в мануале оказывается, что для работы этой команды на виртуалке должны быть установлены VMware Tools, а в гостевой системе включена гостевая учетка. Один клик мыши — и в виртуалке уже смонтирован виртуальный диск с установщиком. Проверяем еще раз... работает!

Сценарий doWork.bat создал отчет в папке c:XLabOutputFiles — осталось его оттуда забрать. Для обмена файлами между хостовой и виртуальными машинами есть специальные команды copyFileFromHostToGuest и copyFileFromGuestToHost. Попробуем: vmrun auth_param -gu xlab -gp xlab copyFileFromGuestToHost "[standard] xp eng/xp eng. vmx" "c:XLabOutputFilesreport.txt" "c:XlabInput report.txt"

Результат проверки оказывается в папке c:XlabInput на хостовой машине. Проверка окончена — осталось охладить виртуалку, выключив ее. Но делать этого мы не будем :). Ведь на запуск уйдет куча времени, к тому же, в некоторых случаях придется заморачиваться с авторизацией нужного пользователя в гостевой системе. Поэтому вместо того чтобы виртуальную машину выключать, мы ее будем усыплять — с помощью команды suspend:

vmrun auth_param suspend "[standard] xp eng/xp eng.vmx"

Теперь добавляем в наш doWork.bat необходимые паузы (чтобы запуск программы не начинался до того, как загрузится система), и автоматизированный инструмент для тестирования файла в виртуальной машине готов. Не буду приводить здесь полную версию скриптов — все вместе ты найдешь на диске. Конечно, это лишь прототип полноценной системы. Но ничего не стоит добавить еще несколько виртуалок для других антивирусов и таким образом получать сводный отчет по одному и тому же файлу. Тот же файл реально скачивать единожды на хостовой машине и передавать на гостевые машины — можно делать все, что угодно. Главное, что ты знаешь, как манипулировать виртуальными машинами, а остальное уже дело техники.

Info

• Комплект разработчика для VirtualBox включает в себя примеры на Java, Python, Perl.
• В случае автоматизированного использования VirtualBox ее лучше запускать как сервис. Рекомендую тебе правильный мануал по этому поводу: thelivedevil.com/virtualbox/how-to-runvirtualboxas-serviceinwindows.

Содержание
ttfb: 28.73682975769 ms