Приручение виртуальных машин

Любой из нас хотел бы писать стабильный код, дабы фатальный баг не сломал бы в час икс все копии нашего софта.

Чем меньше кода, тем меньше багов будет в финальной версии, по этой причине предпочтительней использовать сторонний код (winapi, как пример) вместо собственного. То что я собираюсь сказать и так давно известно, ибо мир прошел длинный путь от ассемблера до си-шарпа и джавы. Но не будем забегать вперёд!

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

На помощь спешит виртуализация или по простому говоря – использование интерпретаторов. Ваш код становится скриптом, исполняемым виртуальной машиной которая не даст вам убить себя обнулив регистр ESP или перейдя на нулевой адрес. Таким образом, даже если вам код – дерьмо, вы всегда сможете вернуть управление с деталями ошибки.

Варианты использования

Большинство скриптовых ЯП (даже python) можно собрать в embeded-версию, для работы из памяти, читай – без использования диска. Исполняя код в памяти (без установки интерпретатора) мы теряем ряд сигнатурных преимуществ.

Многие антивирусы хорошо обрабатывают нативный код и эмулируют часть системных структур\библиотек. Но что делать если вредоносный код написан на интерпретируемом языке? Писать эмуляторы для самых популярных или копить в базе сотни новых регулярок?

Приведу живой пример – py2exe сам по себе не является вредоносным проектом, но обернув им наш скрипт мы поставим эмулятор в неловкое положение. Эмулировать нативный код смысла мало – долго и на первых килобайтах трейса это будут общий для легальных (и не очень) приложений код.

Тоже самое касается инсталляторов типа InnoSetup – простые эвристики тут не работают, нужно писать распаковщик, чтобы понять что же там внутри. Так что использование легальных интерпретаторов сильно усложняет дятлам жизнь.

Плюсы и минусы

В обоих вариантах (embeded\installed) мы получаем:

  • защиту от падений
  • сокрытие импорта
  • увеличение размера тела на вес виртуальной машины и её библиотек
  • использование отлаженного и покрытого тестами (чужого) кода
  • возможность изменения логики приложения без перекомпиляции тела
  • сложность декомпиляции байткода конкретной вирт.машины

Итоги

Использование скриптовых движков – не новость. Без них невозможны были бы как забавные баги в играх, так и написание плагинов к nmap. К слову, luа можно встретить  как во Flame так и в антивирусе MSE. Нельзя не упомянуть и популярные атаки через макросы офисных документов.

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

Эмуляторы не могут покрыть все winapi, а число виртуальных машин растёт. Кто будет писать заглушки для всех си-шарп либ? С обоих сторон простор для творчества имеется. =)

Добавить комментарий