Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #47, ОКТЯБРЬ 2004 г.

Зараза для никсов

Крис Касперски aka мыщъх

Спецвыпуск: Хакер, номер #047, стр. 047-054-2


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

Язык разработки

Настоящие хакеры признают только один, максимум, два языка – C и Ассемблер, причем последний из них стремительно утрачивает свои позиции, уступая место Бейсику, Delphi и прочей дряни, на которой элегантный вирус невозможно создать в принципе.

А что на счет Си? С эстетической точки зрения, это – чудовищный выбор, и вирусмэйкеры старой школы его не прощают (однако написать код на ассемблере сравнымый с тем, что выдают современные оптимизирующие C-компиляторы вроде Microsoft C Compiler, - дело для новичка не такое уж простое - прим. AvaLANche'а). С другой стороны, будучи низкоуровневым системно-ориентированным языком, Си неплохо походит для разработки вирусов, хотя от знания Ассемблера это все равно не освобождает.

Код, генерируемый компилятором, должен: быть полностью перемещаемым (то есть независимым от базового адреса загрузки), не модифицировать никакие ячейки памяти, за исключением стекового пространства, и не использовать стандартные механизмы импорта функций, либо подключая все необходимые библиотеки самостоятельно, либо обращаясь в native-API. Этим требованиям удовлетворяет подавляющее большинство компиляторов, однако от программиста тоже кое-что потребуется.

Нельзя объявлять главную функцию программы как main: встретив такую, линкер внедрит в файл start-up код, который вирусу не нужен. Нельзя использовать глобальные или статические переменные: компилятор принудительно размещает их в сегменте данных, но у вирусного кода не может быть сегмента данных! Даже если вирус захочет воспользоваться сегментом пораженной программы, он будет должен, во-первых, самостоятельно определить адрес его "хвоста", а, во-вторых, растянуть сегмент до необходимых размера. Все это тривиально реализуется на Ассемблере, но для компилятора оказывается чересчур сложной задачей. Кроме того, нужно хранить все данные только в локальных переменных, задавая строковые константы в числовом виде. Если написать char x[] = "hello, world", коварный компилятор сбросит "hello, world" в сегмент данных, а затем динамически скопирует его в локальную переменную x. Можно сделать так: x[0]='h', x[1]='e', x[2]='l'… или преобразовать char в int, осуществлять присвоение двойными словами, не забывая о том, что младший байт должен располагаться по наименьшему адресу, что разворачивает строку задом наперед.

Нельзя использовать никакие библиотечные функции, если только не уверен в том, что они полностью удовлетворяют всем вышеперечисленным требованиям. Системные функции обычно вызываются через интерфейс native-API, также известный под именем sys-call (в Linux-подобных системах за это отвечает прерывание INT 80h, другие системы обычно используют дальний вызов по селектору семь, смещение ноль). Поскольку системные вызовы варьируются от одной системы к другой, это ограничивает среду обитания вируса и при желании он может прибегнуть к внедрению в таблицу импорта.

Назад на стр. 047-054-1  Содержание  Вперед на стр. 047-054-3