Захист
програм від комп'ютерних вірусів h2>
Реферат по
інформатики учня 11 "А" класу школи № 776 Південно - Східного адміністративного
округу Афоніна Сергія Вікторовича p>
Передмова b>
p>
У розділі
аналізується механізм поширення та функціонування вірусів у
операційній системі MS-DOS
і на основі аналізу пропонуються досить ефективні способи боротьби з ними.
Приводяться описи трьох різних програм, що забезпечують виявлення та ліквідацію
вірусів. Модуль F_Anti може використовуватися для автоматичної
захисту розроблених нових Турбо Паскалевих програм. Програма AntiVir здійснює виявлення та ліквідацію
завантажувальних вірусів і контроль будь-яких виконуваних файлів на основі зіставлення
найбільш уразливих для вірусу частин файлів з їх еталонними копіями. Нарешті,
комплекс програм SetFag.exe і Fag, prg дасть Вам можливість встановити антивірусну програму-фаг
на будь-який вже створений ЕХЕ-файл: у момент запуску програми фаг перевірить її
стан, якщо програма уражена вірусом, повідомить про це і видалить вірус. p>
1. b>
Що таке комп'ютерні віруси b> p>
Якщо Ви маєте
досвід тривалої роботи з ПК, то, можливо, вже стикалися з комп'ютерними
вірусами або хоча б чули про них. Комп'ютерний вірус-це програма, що виконує у Вашому ПК дії, в яких Ви не
потребуєте і про які не підозрюєте. Головною її особливістю є
здатність до «розмноження», тобто до створення безлічі готових до подальшої
роботі екземплярів вірусу. Віруси «чіпляються» до звичайних виконуваним файлів типу
. ЕХЕ,. СОМ або до завантажувальним секторам фізичних носіїв інформації (дискет)
і таким чином потрапляють від одного ПК до іншого. p>
що були
спочатку цілком невинна розвагою нудьгуючих програмістів комп'ютерні
віруси сьогодні стали справжнім лихом для користувачів ПК: кількість і
типи таких програм ростуть із жахливою швидкістю, а самі віруси в ряді випадків
набули вельми неприємні властивості-деякі
з них здатні знищувати файлову структуру дисків з усіма катастрофічними
для користувача наслідками. У літературі
[14] описується безпрецедентний випадок, коли вірус на Три дні (з 2 по 4
Листопад 1988) вивів з ладу фактично
всю комп'ютерну мережу США. Були паралізовані комп'ютери Агентства національної
безпеки, Стратегічного командування ВПС США, локальні мережі всіх великих
університетів і дослідницьких центрів. Лише в останній момент вдалося
врятувати систему керування польотом космічних кораблів Шаттл. Положення було
настільки серйозним, що до розслідування негайно приступило ФБР. Винуватцем
катастрофи, причинили збитків більш ніж у 100
мільйонів доларів, виявився студент випускного курсу Корнеллського університету
Р. Морріс, що придумав досить хитру різновид вірусу. Він був виключений
з університету з правом поновлення через рік і засуджений судом до сплати
штрафу в 270 тисяч доларів і трьом
місяців тюремного ув'язнення. p>
Важко
пояснити, для чого програмісти витрачають сили і час на створення все більш
витончених типів вірусу, оскільки їх автори майже завжди залишаються або сподіваються
залишитися анонімними, так що природне для людини прагнення до популярності
тут виключено. Може бути що це невдалий жарт (цієї версії дотримувався
Р. Морріс), можливо це пов'язане з патологічними відхиленнями в психіці, а
може бути пояснення криється у прагненні заробити на створенні антивірусних
програм? Як би там не було, нам не можна не рахуватися з можливістю зараження
ПК комп'ютерним вірусом. P>
2. b>
Цикл функціонування вірусів b> p>
У циклі
існування будь-якого вірусу можна виділити три етапи. Спочатку вірус
знаходиться у неактивному стані. У цьому стані він впроваджений у тіло виконуваного
файлу або знаходиться в завантажувальному секторі диска і «чекає» свого часу. Саме в
неактивному стані віруси переносяться разом з програмами або дискетами від
одного ПК до іншого (обмін програмами між користувачами ПК-явище буденне, і Ви самі, читачу,
можливо копіювали любиться Вам гру або текстовий редактор, не
підозрюючи, що копіюєте ще й вірус). Зрозуміло, в неактивному стані
вірус нічого не може зробити. Для того щоб він почав свою роботу, необхідно
запустити виконуваний файл або завантажитися з зараженої дискети. У цей момент
активізується вірус, який або створює резидентну в пам'яті програму,
здатну породжувати копії або робити якісь руйнівні дії,
або негайно приступає до роботи. p>
Якщо вірус створив
резидентну програму, то її активізація здійснюється різними способами - все залежить від фантазії автора вірусу.
Зазвичай вірус перехоплює переривання $ 21,
що є ключовим для доступу до будь-яких операцій з MS-DOS. Таким чином, будь-яка спроба читання або запису інформації
на диск або звернення до клавіатури дисплея призводить до активізації резидентної
програми вірусу. Після одержання керування (або активізації резидентної
програми) вірус приступає до «розмноження»: він відшукує відповідний виконуваний
файл і впроваджує свій код в його тіло (див. нижче). Як правило, вірус заражає
лише один виконуваний файл за раз, щоб користувач не звернув уваги на
надмірне уповільнення в роботі програм: другий етап життєдіяльності вірусу - це етап активного розмноження, тому
вірусна програма прагне максимально приховати від користувача ПК результати
своєї діяльності. p>
Після того як
заражене досить багато файлів, може настати третій етап, пов'язаний з
зовнішніми проявами роботи вірусу. Ваш комп'ютер раптом почне поводитися
дивно: зазвучить чи музична фраза, або почнуть «сипатися» символи на екрані
дисплея-не суть важливо, головне, що
тільки в цей момент Ви з жахом згадайте, що на жорсткому диску перебувають
надзвичайно важливі для Вас дані або програми, які Ви не встигли або не
змогли скопіювати на дискети. На жаль! Деякі віруси до цього моменту можуть вже
безповоротно порушити файлову структуру. p>
Що робити при
виявлення вірусу? Насамперед не панікувати, адже далеко не всі віруси
відрізняються «кровожерністю». Слід вимкнути комп'ютер, вставити в привід
гнучкого диска заздалегідь припасений еталонну системну дискету (ніколи не
знімайте з неї захист!) і знову включити комп'ютер. Якщо на ПК є
спеціальна кнопка для перезавантаження (RESET або INIT), можна використовувати її і не виключати/включати комп'ютер, але під
всіх випадках не намагайтеся перезавантажитися за допомогою Ctrl-Alt-Del: від деяких типів вірусу Ви не позбудетеся таким чином. Потім
потрібно запустити яку-небудь програму-антивірус (наприклад, AIDSTEST Д. Н. Лозинського) і з її допомогою
локалізувати і видалити вірус. Якщо антивірусна програма не може виявити
вірус або у Вас під рукою немає такого роду програм, варто спробувати
звернутися до потрібного Вам жорсткого диска і, якщо це вдасться зробити,
скопіювати всі найбільш цінне (але тільки не виконувані файли!) на дискети.
Після цього заново переформатувати жорсткий диск, перенести на нього еталонну
копію ДЗГ та відновити з дискет те, що вдалося врятувати. p>
3. b>
«Вакцинація» програм b> p>
Що ж слід
зробити, щоб ця безрадісна картина не стала реальністю? Один відповідь
очевидний-періодично (і по можливості
частіше) зберігати життєво важливі для Вас результати роботи на дискетах. Ні
нічого простіше, ніж дати ця рада, набагато складніше змусити себе дотримуватися
йому: я сам, чесно кажучи, далеко не кожен день витрачаю час на архівування.
Друга відповідь менш очевидний. З його простий ідеєю я вперше познайомився в
прекрасної статті Ф. М. Шерстюк. p>
Ось ця ідея:
потрібно зробити «вакцинацію» виконуваних програм, тобто додати їм властивість
самодіагностики, що дозволяє провести контроль власного файлу та з'ясувати,
заражений він чи ні. Якщо факт зараження встановлено, програма може спробувати
відновити свій початковий вигляд, тобто видалити причепився до її файлу вірус.
Якщо цю ідею послідовно втілювати в життя, то більшість Ваших програм
придбає стійкий «імунітет» до вірусів, у всякому разі, вони зможуть
досить швидко повідомити Вам про факт зараження. p>
Переваги
цієї ідеї очевидні: на відміну від розробників численних антивірусних
програм, які борються з конкретними різновидами вірусів, Ви можете
зберегти у файлі програми деяку ключову інформацію про її незараженою
вигляді, і тому факт зараження будь-яким видом вірусу може бути легко встановлений у
момент запуску Вашої програми. p>
3.1. Заголовок виконуваних файлів b>
p>
Яку саме
інформацію про нзараженном файлі слід зберігати? Для відповіді на це питання
необхідно знати угоду ДОС про формат виконуваних файлів. Як відомо,
існують два формати: СОМ та ЕХЕ. Будь-яка програма, що обробляється системою
Турбо Паскаль версії 4.0 і вище, може
бути оттранслірована тільки в ЕХЕ-файл, тому всі подальші міркування
відносяться саме до цього формату. p>
На початку
ЕХЕ-файла розташовується заголовок, в якому міститься вся інформація,
необхідна для перетворення дискового файлу в готову до роботи програму.
Перші 28 байт заголовка відповідають
такій структурі даних: p>
Type p>
HeadExeType = record p>
Sign: Word; (Ознака ЕХЕ-файла) p>
PartPag: Word; (Частина неповного сектора в кінці файлу) p>
PageCnt: Word; (Кількість секторів, включаючи неповний) p>
ReloCnt: Word; (Кількість елементів у таблиці
переміщення) p>
HdrSize: Word; (Довжина заголовка в параграфах) p>
MinMem: Word; (Мінімальний розмір купи (в параграфах)) p>
Махмет:
Word; (Максимальний
розмір купи (в параграфах)) p>
ReloSS: Word; (Початкове значення сегмента стека SS) p>
ExeSP: Word;
(Початкове значення покажчика стека SP) p>
ChkSum: Word; (Контрольна сума всіх слів файла) p>
ExelP: Word;
(Зміщення точки запуску програми) p>
ReloCS: Word; (Початкове значення сегменту коду CS); p>
TabiOff: Word; (Зсув першого елемента таблиці
переміщення) p>
Overlay: Word; (Номер оверлея або 0 для основної програми) p>
end;
(HeadExe) p>
Інші елементи заголовка містять так
звану таблицю переміщення, призначену для налаштування адрес
завантаженої програми. Таблиця починається з байта TabiOff від початку файлу і містить ReloCnt четирехбайтних елементів такого вигляду: p>
Type p>
ReloTablltem = record p>
ItemSeg: Word; (Сегмент переміщуваного адреси) p>
IternOfs: Word; (Зсув переміщуваного адреси) p>
end; p>
Ознака
ЕХЕ-файла зберігається в полі Sign у вигляді символів «MZ» (код $ 5A4D) --
з цієї ознаки повинен починатися будь-який ЕХЕ-файл. Поле HdrSize містить довжину всього заголовка в параграфах (дільницях
пам'яті довжиною по 16 байт кожний). Поля PartPag і PageCnt визначають загальну довжину що завантажується в
пам'ять частини ЕХЕ-файла за такою формулою: p>
L =
(PageCnt-l) * 512 + PartPag - HdrSize * 16 p>
Решта
файлу (довжина ЕХЕ-файла може бути більше L + HdrSize * 16) під час завантаження програми не
враховується. Зазвичай в залишку файлу, створеного системою Турбо Паскаль, (якщо,
зрозуміло, є залишок) міститься інформація, яка використовується вбудованим
відладчиком, або оверлеї. p>
Переважна
більшість ЕХЕ-вірусів прістиковивает свою програму в кінець файлу, а для того
щоб ця програма була завантажена в пам'ять і їй було передано управління,
змінює поля PartPag, PageCnt, ReloCS,
ExelP (адреса точки,
куди передається керування після закінчення завантаження) і, можливо, деякі
інші поля. При такому способі впровадження загальна довжина що завантажується в пам'ять частини
файлу повинна становити p>
ExeSize =
FileSize + VirusSize, p>
де FileSize-повна довжина ЕХЕ-файла, а VirusSize-довжина програми вірусу. Так як в
залишок фала можуть зберігатися оверлеї (або архів для саморозвантажних архівних
програм), довжина ExeSize може виявитися над-мірно великий, так що програма не зможе завантажитися
в пам'ять або не зможе працювати нормальним чином. Деякі безграмотно
написані віруси не враховують цю обставину і швидко видають себе, тому що
заражені програми перестають працювати. p>
Інший спосіб
впровадження вірусу-припасування коду вірусу до
початку завантажується частини програми і одразу за заголовком файлу. L - завантажується в пам'ять частину файлу. P>
Такий спосіб
впровадження дозволяє не завантажувати в пам'ять весь ЕХЕ-файл, а довжина завантаженої
програми збільшується тільки на довжину коду вірусу. Незважаючи на удавану
перевага такого способу, він використовується досить рідко. Його реалізація
значно складніше, тому що перед передачею управління основній програмі
вірус повинен перенести 256 байт префікса
програмного сегмента (PSP) в кінець власного коду так, щоб вони безпосередньо
передували тіла програми-в іншому
випадку буде порушена важливий зв'язок програми з
PSP або відносна адресація в самій програмі. P>
Крім того, в
процесі зараження він повинен збільшити на величину VirusSize поле IternOfs кожного елементу таблиці переміщення і
абсолютної адреси, зазначених цим елементом. На відміну від стандартного
завантажувача ДОС вірусу доводиться коригувати не завантажену програму, а її
файловий образ. Так як в ЕХЕ-програмі середньої складності може бути кілька
сотень елементів таблиці переміщення, процес настройки таблиці вірусом призводить
до помітного збільшення часу запуску програми, що може виявитися
користувачем. На етапі розмноження віруси прагнуть по можливості приховати від
користувача результат своєї діяльності, тому ЕХЕ-файли рідко уражаються
вірусами, пристикованому в початок файлу. p>
Зрозуміло,
існує можливість впровадження вірусу безпосередньо в тіло виконується
програми. Однак на практиці це майже завжди означає руйнування логіки
роботи програми, тому такий вірус негайно виявляється. p>
Аналіз
сказаного дозволяє зробити важливий висновок: практично будь-який існуючий вірус
(або вірус, який ще тільки буде створено!), розрахований на поразку ЕХЕ-файла,
прістиковивает свій код в кінець файлу і змінює його заголовок. Отже,
для контролю факту зараження програми та ліквідації вірусу необхідно десь
зберегти заголовок файлу і його еталонну довжину і періодично зіставляти
дійсний заголовок і довжину з еталонними значеннями. При цьому слід
враховувати ту обставину, що деякі віруси контролюють будь-яке звернення
до дисковим секторах, в яких розташована їхня програма, і «підсовують»
Незарах-женние копії цих секторів. Такі віруси (їх називають віруси-невидимки)
навряд чи вдасться виявити за допомогою стандартного звернення до функцій ДОС. Для
боротьби з ними використовують пряме звернення до BIOS-переривання $ 13. p>
3.2. Захист знову створюваних програм b>
p>
Ключову інформацію
(будемо для стислості називати її ключ) про незараженою програмі можна зберігати в
окремому файлі, але в цьому випадку існує небезпека втратити додатковий
файл при копіюванні програми або помилково знищити його. Набагато надійніше
зберігати ключ в тілі самого захищається файлу. На жаль, його не можна подібно
вірусу при-стикувати в кінець файлу, тому що у разі зараження вірус змінить поля PartPag і PageCnt і ми ніколи не зможемо визначити те
місце у файлі, де він розташовується. Згадаймо, що всі константи (у тому числі і
типізовані) створюються на етапі компіляції програми, таким чином у файлі
обов'язково є область даних, що містить значення цих констант. Ця
область в Турбо Паскалевих програмах розташовується в самому кінці завантажується частини
файлу (см.ріс.6.2). p>
Отже,
ми повинні оголосити в програмі типізований констант, призначену для
зберігання ключа, а потім в область файлу, відведену для її розміщення,
помістити потрібну інформацію. p>
Яким чином
відшукати в ЕХЕ-файлі місце, займане ключем? Звичайно, можна перед ним у
програмі розмістити будь-яку типізований константу з характерним
значенням (наприклад, заздалегідь обумовлену текстовий рядок) і потім відшукувати
її у файлі. Однак таке рішення навряд чи можна визнати задовільним:
по-перше, завжди існує ймовірність того, що якийсь фрагмент кодів
програми містить ту ж ланцюжок байт, що і заголовок ключа, по-друге,
доведеться переглядати часом великий за обсягом ЕХЕ-файл у пошуках потрібної
константи. Значно витонченіше виглядає рішення, засноване на точному
обчисленні зміщення від початку файлу до ключа. p>
Для цього потрібно
визначити початок області даних у файлі. У заголовку файлу не передбачено
ніякої інформації про початковому значенні регістра DS, в якому зберігається сегмент даних. Перед
передачею управління програмою завантажувач устаноавлівает значення цього регістра
так, щоб він вказував на початок так званого префікса програмного сегменту
(PSP), а запущена
програма вже сама повинна встановити його належним чином. p>
Префікс
програмного сегмента має довжину 256
байт (16 параграфів) і розміщується
завантажувачем в оперативній пам'яті безпосередньо перед завантаженої програмою.
У PSP міститься різна службова
інформація, яка може бути досить важливою для ДОС і працюючої програми
(в PSP, наприклад, зберігаються параметри
звернення до програми), але в ньому немає вказівок на вміст регістра DS. Таким чином, знайти початок області даних
у файлі досить важко. Однак це неважко зробити в працюючій програмі-для цього передбачена стандартна функція DSeg, яка повертає сегмент даних. Якщо б
програма могла одержати також інформацію про сегмент PSP, з якого починається завантажена програма, можна було б
обчислити зсув у файлі від його початку до початку області даних. Така
можливість є-функція MS-DOS з номером $ 62
повертає в регістрі ВХ значення сегменту PSP.
Отже, програма повинна отримати значення обох сегментів, обчислити їх
різницю і таким чином визначити місце у файлі, з якого починається область
даних. p>
Залишається
остання проблема-як знайти потрібну
константу. Турбо Паскаль розміщує константи в області даних по мірі їх
оголошення в програмі. Знаючи розмір кожної константи і порядок їх оголошення,
можна вирахувати місце розміщення потрібної нам типізований константи. Однак
цей метод не годиться для універсальної програми захисту, тому що порядок
оголошення констант може мінятися від програми до програми. На щастя, ми
можемо використовувати операцію отримання адреси @. Результатом застосування цієї
(четирехбайтний адреса); зсув адреси, на яку він містить, і є потрібним
нам зсувом початку ключа щодо початку області даних. p>
3.3. b>
Модуль b> F b> _ b> Anti b> p>
У цьому
параграфі описується модуль F_Anti,
в якому здійснюються всі необхідні дії з установки ключа в знову
створюваний ЕХЕ-файл і наступній перевірці цього ключа при кожному завантаженні
програми. Повний текст модуля см. пріл.П7. P>
Як
ключа для контролю факту зараження ЕХЕ-файла в модулі F_Anti використовується типізований константа Head, що відповідає такій структурі даних: p>
Type p>
НТуре = record p>
НЕ: HeadExeType; (Еталонний заголовок файла) p>
HL: Longint; (Еталонна довжина файла) p>
HF: Boolean; (Прапор установки ключа) p>
Key:
Word; (Шифр для
захисту ключа) p>
end; p>
При створенні
цієї типізований константи компілятор в поле
HF поміщає значення False. Запущена програма аналізує це поле. При першому прогоні HF = False, в результаті чого програма викликає процедуру Save, в ході виконання якої у файлі
зберігаються еталонний заголовок і початкова довжина файлу. При цьому одночасно
у полі HF (у файлі програми!) поміщається
значення True,
тому при будь-якому наступному запуску програми замість Save буде викликана процедура CheckFile, яка здійснить потрібний контроль
файлу. Якщо в ході контролю виявляється хоч би щонайменше відміну заголовка
файлу від його еталона, що зберігається в Head, програма повідомляє про факт зараження і пропонує
відновити зіпсований заголовок і початкову довжину файлу. p>
При
відновлення зараженого файлу здійснюються наступні дії: p>
• заражений файл
копіюється у файл з розширенням VIR-це
дозволить Вам в разі невдалої спроби відновлення повторити її ще раз;
крім того, при бажанні Ви зможете передати розробникам антивірусних програм
копію вірусу для вироблення методів його виявлення і знищення; p>
• аналізується адреса
запуску зараженої програми: якщо відносне значення сегмента точки
запуску у зараженої програми менше, ніж в еталоні, то це означає, що
вірус розташовується на початку або в середині. p>
Якщо програма
запускається на вже зараженому ПК. не виключено, що заголовок файлу буде
зіпсований вірусом, і тоді система захисту буде ревно стежити за
збереженням вірусу! У цьому випадку програма попереджає користувача про
неможливості відновлення (якщо Вас зацікавив описуваний спосіб боротьби
з вірусами, спробуйте модифіковані програму захисту так, щоб вона працювала
і в цьому випадку); p>
• якщо вірус пристикований
в кінець файлу, то в відновлюваний файл переноситься еталонний заголовок і
незаражених частина, починаючи з байти TablOff + ReloCnt'4 від початку файлу і до байти FileSize-HL Відзначу таку обставину.
Описана система захисту дублює заголовок файлу в тіло програми. Ніщо не
заважає вірусу перевірити тіло програми на наявність дубліката та відповідним
чином змінити його. Я далекий від думки, що Ви,, шановний читачу, після
знайомства з цим розділом захочете створити власний вірус, що враховує це
обставина. Тим не менше я вважаю, що не зайво буде якась захист
самого ключа. Такий захист реалізується дуже просто: для цього достатньо всі 16-бітові поля еталона заголовка скласти за модулем 2 з випадковою константою Key, З цією метою в процедуру Save поміщений наступний фрагмент (див. текст
модуля в пріл.П7): p>
(Зашифрувати ключ:) Randomize;
Head.Key: = Random ($ FFFF); p>
with Head, p>
Head. HE do for k =
I to 14 do p>
Hem [k]: = HE.
Hem [k] xor Key; p>
(масив Hem суміщений в пам'яті з його записала у файлі
еталонним заголовком, а НЕ. Ні-з
заголовком файлу в момент першого запуску). p>
Ініціація
генератора випадкових чисел за допомогою процедури Randomize гарантує, що шифр Head.Key не буде повторюватися в різних програмах. У процедурі CheckFile за допомогою операторів p>
(дешифрувати ключ:
) p>
with Н, Н. НЕ do for k
: = I to 14 do Hem [k]: = Hem [k] xor Key; p>
відновлюється
початковий вигляд ключа. p>
Процедура CheckFile, що здійснює установку або контроль
ключа, викликається в ході виконання настановної частини модуля F_Anti, тому для використання описаного методу захисту
достатньо вказати ім'я модуля в пропозиції Uses. Зауважу, що у разі розробки
програми з оверлеями модуль F_Anti
можна оголосити оверлейной, якщо в настановної частини будь-якого неоверлейного
модуля ініціюється робота адміністратора оверлея. p>
У розпорядженні
програміста є глобальна змінна CheckVirasResult, що сигналізує про результати перевірки
програми. Значення цієї змінної інтерпретується наступним чином: p>
0; (Не знайдено факт
зараження) 1; (Перший запуск, у програмі
встановлена захист) p>
-1; (Вірус знешкоджено з
згоди користувача) p>
-2; (Вірус знешкоджено
автоматично). p>
-3; (Контроль пригнічений
ключем/NOANTI) p>
-4; (Вірус розташований в
початок програми) p>
Робота
процедури CheckFile може бути пригнічена, якщо програма за-пускається з ключем/NOANTI. Ключ/NOQUERY дозволяє автоматичне видалення виявленого вірусу без
дозволу користувача. p>
Ключ/NOALARM також дозволяє процедурі автоматично
видалити вірус, але забороняє видавати на екран попередження.
Нарешті, ключ/NOCOPY
забороняє створення резервної копії зараженого файлу (з розширенням VIR). p>
Наступна
проста програма ілюструє техніку використання модуля F-Anti. Якщо Ви скомпіліруете цю програму у файл testanti.exe, то після команди testanti на екрані з'явиться повідомлення p>
Встановлено
захист файлу TESTANII.EXE.
при першому запуску програми і В файлі TESTANTI.EXE вірус не виявлено. p>
при кожному
наступному запуску. Якщо запустити програму командою p>
testanti/noanti
на екран буде виведено повідомлення Контроль блокований ключем/NOANTI. p>
Uses FAnti; begin p>
case CheckVirusResuit of p>
0: WriteLn ( 'B файлі', ParamStr (0), 'вірус не виявлений .*); p>
1: WriteLn ( 'Встановлено захист файлу', aramStr (0) ,*.*); p>
-1: WriteLn ( 'Вірус видалений з дозволу
користувача .'); p>
-2: WriteLn ( 'Вірус видалено автоматично .'); p>
-3: WriteLn З Контроль блокований ключем/NOANTI .*); p>
-4: WriteLn З Вірус розташований на початку * + p>
'файлу - видалення неможливо .') p>
end p>
end. p>
4. b>
Захист існуючих ехе-файлів b> p>
Отже,
«Вакцинація» розроблених нових програм не представляє особливої складності. А
як захистити вже існуючу ЕХЕ-програму? Для цього існують дві
можливості: або використовувати окрему програму, яка зберігає ключову
інформацію і здійснює перевірку на вимогу користувача (така програма
обговорюється в наступному розділі), або пристикований до захищається програмі
невеликий код «вірусного фага»-тоді
перевірка буде здійснюватися автоматично при кожному запуску програми. У
цьому розділі ми обговоримо техніку створення і впровадження в захищається. програму
антивіруса-фага, тобто невеликий асемблерні програми, яка використовує той
же механізм перехоплення управління, що і звичайний вірус, але здійснює потрібну
захист програми. p>
Програма - фаг
встановлюється спеціальною програмою-установником і до моменту початку своєї
роботи вже повинна мати у своєму розпорядженні еталонний заголовок файлу. Отримавши
управління, фаг перевіряє заголовок відповідного файлу і, якщо виявлені
зміни, повідомляє про це користувачу і видаляє вірус. Після закінчення
роботи фаг передає управління захищається програмі. Оскільки фаг пишеться
цілком на асемблері, його робота протікає дуже швидко без помітного
уповільнення завантаження програми. Якщо Ви встановите такий фаг на більшу частину
часто використовуваних програм, Ваш комп'ютер буде захищений дуже надійно. p>
Щоб правильно
спроектувати фаг, потрібно добре уявляти собі механізм запуску
ЕХЕ-програм. Стандартний завантажувач ДОС реалізує наступну послідовність
дій при запуску програми. p>
1) Створюється префікс
програмного сегменту PSP. Зазвичай для цього використовується функція ДГЗ $ 26. P>
2) У деяку локальну
область пам'яті зчитуються початкові 28
байт заголовка ЕХЕ-файла, що відповідають структурі даних HeadExeType. p>
3) Визначається розмір
завантажується частини файлу за формулою p>
LengExe =
(PageCnt-l) * 512 + PartPag p>
4) Визначається файлове
зсув завантажується частини: p>
SeekExe = HdrSize * 16 p>
5) Вибирається сегментний
адреса StartSeg для
розміщення програми. p>
Зазвичай StartSeg = Segment (PSP) +16, тобто програма розміщується відразу за PSP, який має довжину 256 байт (16
параграфів). p>
6) Читається
завантажувана частина програми на безперервну область пам'яті довжиною LengExe, що починається за адресою StartSeg: 0000. p>
7) Покажчик файлу
встановлюється на початок таблиці переміщення TablOff, p>
8) Для кожного елемента
переміщення (цих елементів ReloCnt): p>
• прочитується елемент
як два 16-бітних слова IternOfs, ItemSeg; p>
• обчислюється ReloSeg === StartSeg + ltemOfs, тобто сегментна частину зсуву
абсолютної адреси переміщуваного посилання; p>
• витягується слово по
адресою ReloSeg: ltemOfs-сегментна частина переміщуваного посилання; p>
• до цього слова
додається StartSeg (здійснюється так звана прив'язка сегмента); p>
• результат поміщається
назад за адресою ReloSeg: ltemOfs. p>
9) Виділяється пам'ять за
кінцем програми у відповідності до значень p>
MinMem
і Махмет. p>
10) ініціює
регістри і запускається програма: p>
• регістри ES і DS отримують значення сегмента, у якому
розташовується PSP ', p>
• регістр АХ відображає
коректність ідентифікаторів дисків в командному рядку (при нормальному запуску
містить 0); p>
• SS = StartSeg + ReloSS; p>
• SP = ExeSP; p>
• CS == StartSeg ^ ReloCS; p>
• IP = Exelp; p>
• вміст інших
регістрів не має значення. Регістри сегменту коду CS і покажчика інструкцій IP звичайно ініціюються наступними трьома
командами: p>
PUSH StartSeg + ReloCs p>
PUSH Exelp p>
RETF p>
(команда RETF далекого повернення з підпрограми
витягує з стека два слова-зміщення і
сегмент адреси переходу-і поміщає їх
відповідно в IP і CS). p>
Таким чином,
відразу після отримання управління фаг має зберегти значення регістрів АХ і DS і помістити в DS значення власного сегменту даних. На
практиці сегмент даних в коротких асемблерних програмах зазвичай збігається з
сегментом коду, тобто програма і дані розміщуються в одному сегменті. Сегмент
стека SS можна не змінювати,
тому що програма-інсталятор фага повинна подбати про те, щоб стік НЕ
зруйнував код самого фага, і відповідним чином налаштувати ReloSS та/або ExelP. Зазвичай в ЕХЕ-програмі початкове
значення ReloSS
таке, що стек розміщується відразу за кінцем програми, тобто в тому місці, куди
програма-інсталятор поміщає "код фага. Довжина стека ExeSP як правило більш ніж достатня для
того, щоб робота фага зі стеком не призвела до руйнування коду фага, тому в
більшості випадків інсталятор залишає початкові значення ReloSS і ExeSP
без зміни. p>
4.1. b>
Опис програм
b> SetFag b> . b> pas b>
і b> Fag b> . b> asm b> p>
У цьому
параграфі описуються програми SetFag.pas
і Fag.asm, за допомогою яких реалізується описаний
вище механізм захисту. Програма SetFag (пріл.П8.1) здійснює установку фага, а програма Fag.asm (пріл.П8.2) містить сам фаг. Якщо Ви захочете
скористатися запропонованими програмами, відкомпілюйте Турбо асемблером
файл Fag.asm командою p>
tasm fag
/ L p>
У ході
компіляції на екран буде виведено 13
попереджень виду p>
Warning * Open procedure: XXXXXX а наприкінці відомості: p>
Error message: None Warning message: 13 Passes: I Remainig memory: XXXК p>
Якщо в рядку Error message замість None вказано число виявлених помилок,
перегляньте файл лістингу компіляції fag.lst, відшукайте в ньому • повідомлення компілятора про помилки та усуньте їх.
Потім перетворіть отриманий файл fag.obj в програму Fag.prg
командою p>
tiink fag, fag.prg p>
Компонувальник
повинен повідомити Warning: No stack p>
Зауважу, що
програма Fag.prg не може працювати самостійно без
попереднього налаштування установником SetFag.exe, тому в цілях обережності їй присвоюється
нестандартне розширення PRG. Для встановлення захисту на будь-який ЕХЕ-фаил слід дати команду p>
setfag NAME, p>
де NAME-ім'я захищається файлу. Іншими словами, ім'я
файла передається програмі установки фага SetFag.exe за допомогою параметрів запуску. В імені NAME можна опускати стандартне розширення ЕХЕ, а також
дозволяється вказати маршрут знайти файл, та/або символи-замінники ДОС «*» і «?» для визначення групового імені-в цьому випадку захист буде встановлена на
кожен файл, відповідний груповому імені. Наприклад, команда p>
setfag d: mydir * p>
означає
вимога встановити захист на всі ЕХЕ-файли з каталогу MYDIR на диску D. p>
Перед
установкою зашиті програма здійснює серію перевірок файлу. Вона перевіряє
заголовок файлу і блокує встановлення захисту, якщо перші два байти заголовка
не відповідають сигнатурі «MZ» (ознакою ЕХЕ-файла). Крім того, вона перевіряє «хвіст» файлу з
тим, щоб переконатися у відсутності коду фага, і блокує повторну установку
захисту на вже захищений файл. Далі, захист не устанвливается також у тому
випадку, якщо довжина завантажується частини файлу стане занадто великий (перевищить
доступну пам'ять). Якщо в кінці файлу виявлена незагружаемая частина, програма
інформує про це користувача і запитує в нього підтвердження на
установку за-щити. Після завершення всіх перевірок програма створює резервну
копію вихідного файлу з розширенням ВАК. Створення ВАК-файлу можна заборонити,
якщо команду виклику доповнити ключем/NOBAK, наприклад setfag myprog/nobak. Для захисту використовується ключ, відповідний
такій структурі даних: p>
Type p>
HeadType =
record p>
case Byte of p>
1: (Sign: Word; (Сигнатура 'MZ' =
$ 5MD) p>
PartPag: Word;
(Частина неповного сектора) p>
PageCnt: Word;
(Кількість секторів) p>
ReloCnt: Word;
(Кількість елементів у таблиці переміщення) p>
HdrSize: Word;
(Довжина заголовка в параграфах) p>
MinMem: Word; (Мінімальний розмір купи) p>
Махмет: Word); (Максимальний розмір купи) p>
end. p>
Зрозуміло, фаг
не можна встановлювати на файли, захищені засобами модуля F_Anti тому що в цьому випадку процедура CheckFile цього модуля виявить зміна
заголовка і видалить фаг. Крім того, фаг прістиковивается в кінець програми і,
отже, не може захищати великі програми. Остання обставина
контролюється установником SetFag. p>
ReloSS: Word; (Початкове значення сегмента стека SS) p>
ExeSP: Word; (Початкове значення покажчика стека SP) p>
ChkSum: Word; (Контрольна сума всіх слів файла) p>
ExelP: Word; (Зміщення точки запуску програми) p>
ReloCS: Word; (Початкове значення сегменту коду CS)); p>
2: (W: array [1 .. 12]
of Word) end; p>
TAVir = record p>
Head24:
HeadType; (24 байти еталонного заголовка) p>
Starts:
Word; (Відносний
сегмент) p>
StartO:
Word; (і зсув
точки запуску програми) Leng24: Longint; (Довжина незараженою програми мінус 24 байта) p>
Key: Word; (Ключ шифрування) p>
end; p>
Як бачимо, цей
ключ-дещо відрізняється від використаного в модулі F_Anti: зберігаються тільки 24
байти заголовка (навряд чи вірус змінить зсув таблиці TablOff і номер оверлея Overlay), виключено непотрібне тепер поле HFf додані поля StartS і StartO
для запам'ятовування відносного адреси точкизапуску захищається програми. Поле Key як і раніше містить шифр для захисту
ключа. Сумарна довжина ключа SizeOf (TAVir)
складає 34 байта. p>
Процес
установки захисту складається з наступних етапів. p>
1) У динамічну пам'ять
зчитується код фага з файлу FAG.PRG.
Ви можете створити свій варіант фага і змусити програму SetFag використовувати його, якщо в команду запуску
інсталятора додасте ключ/F: NameFag.Ext,
де NameFag, Ext-ім'я і розширення файлу, що містить розроблений
Вами фаг. У цьому випадку майте на увазі, що SetFag
поміщає 34-байтним ключ в самий початок
коду фага (див. лістинг FAG. ASM)
і тому при зчитуванні з файлу пропускає 34
байти від початку його завантажується частини. Виділення коду фага в окремий P ^ G-файл знадобилося мені на етапі розробки
і налагодження коду фага. Я вирішив зберегти можливість завантаження коду з зовнішнього
файлу для того, щоб Ви змогли при бажанні поекспериментувати з цим кодом. p>
2) У полі Head24 змінної НН типу TAVir зчитується заголовок ЕХЕ-файла і
здійснюється настройка ключа НН: у полях
StartS і StartO запам'ятовується
відносний адреса точки запуску захищається програми; обчислюється файлове
зсув LS в
параграфах, відповідне повній довжині файлу і вирівняне на кордон
параграфа - з цим зміщенням від початку
файлу в нього буде поміщений ключ і тіло фага (вирівнювання на кордон параграфа
необхідно для того, щоб забезпечити коректність внутрісегментной адресації
коду фага); в ReloCS
поміщається нове значення відносного сегмента точки запуску фага, а в ExelP-зміщення цієї точки; розраховується нове
значення довжини завантажується частини файлу з урахуванням ключа і тіла фага і
відповідним чином змінюються поля PageCnt і PartPag; перевіряються і при необхідності
коректуються поля MinMem
і ExeSP так, щоб стік
не зруйнував код фага. p>
3) На початок ЕХЕ-файла
записується новий заголовок HH.Head24,
потім здійснюється зсув файлового вказівника на 15 * 16 байт від початку файла і в нього записується зашифрований
ключ і тіло фага. Асемблерні програма FAG. ASM
працює таким чином. p>
Відразу після
отримання управління фаг зберігає в стеку регістр АХ, запам'ятовує у змінній PSP значення регістра сегмента даних DS (у цей момент він вказує на префікс
програмного сегмента) і поміщає в DS сегмент
коду CS (дані та код фага
розташовані в одному сегменті). Крім того, у змінній SPO запам'ятовується вершина стека, а в CSO-сегмент коду фага. Потім обчислюється
абсолютний сегмент точки запуску захищається програми (як уже говорилося, він
дорівнює PSP 16) і знайдене значення поміщається в StartS-таким чином готується запуск захищається
програм. p>
Вся основна
робота фага запрограмована у серії послідовно викликаються процедур (при
розробці фага використовувався метод спадного програмування). Спочатку з
допомогою процедури GetExeNome фаг визначає повне ім'я захищається ЕХЕ-файла. Для цього
використовується та обставина, що у версіях ДОС 3.0 і вище стандартний завантажувач поміщає повне ім'я завантаження
файлу в розширене оточення ДОС. Оточення ДОС
- Це область пам'яті довжиною до 32