Вірус на асемблері
З глави ви дізнаєтеся, як помістити вірус тимчасово в пам'ять, як передати йому управління, як намагатися знайти файл.
Ми будемо заражати ТІЛЬКИ * .COM-файли! Якщо буде час і бажання у вас, то можемо написати вірус, що заражає і * .EXE-файли.
- Як вірус "прикріплюється" до файлу, не порушуючи його працездатності?
- Що повинен зробити вірус в першу чергу?
- Як передати управління вірусу з чужої програми?
Виходить приблизно так:
Програма після зараження:
Важкувато? Порівняйте два шматка коду: незараженной програми і зараженої. Повинно бути все зрозуміло.
Зараз будемо практикуватися.
Перший рядок - .286 - вказує Асемблеру, що будемо використовувати інструкції (команди, оператори) 286 процесора. Тобто на 8086 комп'ютері наш вірус вже працювати не буде!
З першого ж байта перейдемо на мітку Init (ініціалізації нашого вірусу).
Відразу ж виникає проблема: при пошуку файлу функцією DOS ми затираємо DTA "програми-жертви".
І тут же виникає друга проблема, точніше, питання: що таке DTA і для чого воно потрібне? Це ми розглянемо пізніше.
afd.exe format c: / s / u
До чого все це? Та до того, що коли ми спробуємо шукати перший файл, то, знайшовши його, ми затріть командний рядок (L_c: / s / u). Виходить, що "програма-жертва", до якої ми "підчепити" не зможе прочитати ті параметри, які їй передав користувач. В даному випадку - це L_ / s / u.
Є два способи обійти це.
1. Зберегти PSP програми перед пошуком файлу. А потім, як наш вірус відпрацював, відновити його.
2. Встановити DTA на іншу область пам'яті, а потім відновити його. Це дозволяє зробити функція 1Ah переривання 21h:
Ми виберемо другий шлях.
mov dx, offset String
Асемблер занесе в DX зсув рядка String в пам'яті. Фактично - після ассемблирования - це буде виглядати так:
Тисячу двісті тридцять чотири: 0200h mov dx, 400h --- 200h тому, що 100h байт займає "файл-жертва", а ми в "хвості" у нього.
.
Тисячу двісті тридцять чотири: 0400h --- все, що завгодно, але тільки не наша рядок.
.
Тисячу двісті тридцять чотири: 0500h 'Рядок' --- ось, де вона буде!
Можна, звичайно, перед зараженням отримати довжину "файлу-жертви" і потім замінити mov dx, 400h на mov dx, 500h. Але що робити, якщо таких посилань багато? Уявляєте, до яких розмірів розростеться наш вірус ?!
Ми вчинимо інакше: просто візьмемо і перенесемо вірус (і тільки вірус!) З "хвоста" "файлу-жертви" у вільний сегмент зі зміщення 100h. Ось, що вийде:
Тисячу двісті тридцять чотири: 0200h mov dx, 400h --- ми в хвості програми
.
Тисячу двісті тридцять чотири: 0500h 'Рядок'
5678: 0100h mov dx, 400h --- перекинули себе в сегмент 5678h, щодо зміщення 0100h
.
5678: 0400h 'Рядок' --- рядок стала на своє місце (зсув).
Ще питання: де гарантія того, що в даному сегменті нікого немає, і ми не затріть код який-небудь програми?
0B800 - нульова
0B900 - перша
0BA00 - друга
0BB00 - третя
0BC00 - четверта
0BD00 - п'ята
0BE00 - шоста
0BF00 - сьома
Давайте порахуємо розмір однієї сторінки. Чи вистачить нам місця для того, щоб розмістити на ній код вірусу? Наш вірус буде займати не більше 300-400 байт.
Візьмемо відомий вам режим 3: в одному рядку 80 символів, рядків на екрані 25. Один символ займає два байти (атрибут / зміщення). Отримуємо: 80 x 25 x 2 = 4000 байт. Чи вистачить нам цього? Звичайно вистачить! Навіть, якщо б не вистачало, ти ми могли б використовувати дві, три, чотири сторінки.
Думаю, що вам не важко буде розібратися в новому операторі movs. Принцип його роботи повністю відповідає команді stos. Ось його опис:
При цьому DS: SI вказує на те, звідки брати дані, ES: DI куди їх копіювати, а CX - кількість пересилаються байт / слів.
mov cx, 10; кількість пересилаються байт
mov si, offset Str1; звідки братимемо
mov di, offset Str2; куди копіювати
rep movsb; Пересилаємо побайтно, тому що movsB. Тепер Str1 = Str2
.
Str1 db '0123456789'
Str2 db '9876543210'
mov cx, 5; кількість пересилаються слів (два байта)
mov si, offset Str1; звідки братимемо
mov di, offset Str2; куди копіювати
rep movsw; Пересилаємо пословно (по два байта), тому що movsW. Тепер Str1 = Str2
.
Str1 db '0123456789'
Str2 db '9876543210'
Отже, тепер наш вірус є в двох місцях в пам'яті: 1. відразу за "програмою-жертвою"; 2. в області 7-ої сторінки (0BF00: 0100h).
jmp dword ptr cs: [Off_move]
Тепер можна спробувати знайти перший * .com-файл в поточному каталозі. Для цього використовується функція 4Eh переривання 21h:
AH = 4Eh
CX - атрибути для пошуку файлу: у нас - 0 (звичайні, не read-only і hidden!)
DS: DX - маска для пошуку. Наприклад, *. *, * .exe, comm. c. c: \ *. asm і т.д.
CF = 1 - немає такого файлу
CF = 0: DTA заповнюється інформацією про знайдений файлі
CF - це прапор переносу. Якщо написано CF = 1, то це означає, що прапор перенесення встановлений (дорівнює 1), а якщо CF = 0, то скинутий (дорівнює 0). Прапор перенесення використовується DOS для індикації помилки функції або для інших цілей.
В даному випадку, якщо функція 4Eh встановила прапор переносу, то це означає, що файлів, що задовольняють умові (масці пошуку), не було знайдено.
Якщо прапор переносу скинутий (дорівнює нулю), то в DTA заноситься інформація про фото. Її ми розглянемо в наступних розділах.
Якщо CF = 0 (скинутий прапор переносу), то можна що-небудь зробити з знайденим файлом.
Для того, щоб знайти наступний файл, що задовольняє нашому умові (масці пошуку), необхідно скористатися функцією 4Fh переривання 21h:
AH = 4Fh
CX - атрибути для пошуку файлу: у нас - 0 (звичайні, не read-only і hidden!)
DS: DX - маска для пошуку (як у функції 4Eh).
CF = 1 - немає більше файлів, що задовольняють умові (масці пошуку)
CF = 0: DTA заповнюється інформацією про знайдений файлі
Все так само, як у функції 4Eh.
Хочу зауважити, що вірус у нас поки непрацездатний. Тобто він нічого не заражає взагалі! Можете спокійно його ассембліровать і запускати. Тільки мало що побачите на екрані. Краще це справа дивитися під отладчиком.
Далі все просто! Я думаю, що описів в програмі досить для того, щоб зрозуміти принцип роботи програми.