Калашников.ru - Ассемблер? Это просто!.. (Выпуск № 013)
InterReklama Advertising
Доброго здоровья, дорогие мои!
Выпуск N 013
Там, дзе вечар на зямлю сыпле зор манiсты,
Я злаyлю, цябе злаyлю, выпуск наравiсты.
Праз палеткi i лясы, праз лугi, паляны,
Ты нясi, яго нясi, Iнэт незацугляны.
Ты нясi, яго нясi, Iнэт незацугляны.
Что у нас сегодня?
Ваши письма
Вирус
Ваши письма
Спасибо всем, кто посетил наш сайт и оставил в Гостевой книге информацию! Многие жалуются, что страница стала загружаться дольше. Что ж, я "ужал" все, что можно было.
Ко мне приходит много писем с просьбой подсказать где найти ту или иную информацию. Друзья мои! Ну не знаю я, где можно все найти. Могу подсказать два адреса (один из которых был опубликован в предыдущем выпуске):
http://win32asm.newmail.ru
http://www.chat.ru/~rusdoc
Надеюсь, там вы найдете то, что вам нужно.
Вот письмо (отрывок) от подписчика Сани, который в прошлом выпуске просил помощи по BIOS:
Если есть какая возможность и тебя это не затруднит, поблагодари всех, кто откликнулся на мою просьбу о помощи!!! С уважением, Саня.
Всем спасибо!
Вирус.
Сегодня рассылка небольшая, но информативная. Из нее вы узнаете, как поместить вирус временно в память, как передать ему управление, как пытаться найти файл...
Ну что, поехали писать вирус...
Мы будем заражать ТОЛЬКО *.COM-файлы! Если будет время и желание у вас, то можем написать вирус, заражающий и *.EXE-файлы.
Как вирус "прикрепляется" к файлу, не нарушая его работоспособности?
Что должен сделать вирус в первую очередь?
Как передать управление вирусу из чужой программы?
Как вы знаете, com-файл сразу начинается с кода, первый байт которого располагается в свободном сегменте по смещению 100h. Следовательно, нам нужно будет сохранить в теле нашего вируса первые три байта "файла-жертвы", записать наш вирус в "хвост" файла и вместо сохраненных трех байт установить команду jmp на начало нашего вируса (т.е. передать ему первому управление). После того, как вирус отработал свое, восстановить сохраненные три байта (записать их в памяти по адресу 100h) и передать им управление. На практике все будет понятней...
Получается примерно так:
Программа до заражения (следите за адресами):
________
1234:0100h mov ax,34 ; код программы до заражения, расположенный по адресу 100h
1234:0103h mov dx,15 ; здесь может быть все, что угодно... Но нам-то все равно...
1234:0106h add ax,bx
1234:0108h .... и т.д.
...
1234:0500h int 20h ; последний байт программы
1234:0502h --- здесь идет уже свободная память...
Программа после заражения:
___________
1234:0100h jmp 0502h ;прыгаем на начало нашего вируса (заменили мы байты здесь)
1234:0103h mov dx,15 ;а это байты "файла-жертвы"
1234:0106h add ax,bx
...
1234:0500h int 20h
1234:0502h --- а здесь уже начинается код нашего вируса.
... --- здесь тело вируса. Делаем, что хотим...
1234:0700h mov word ptr cs:[0100h], First_bytes_1 ;восстановим первые два байта "файла-жертвы"
1234:0705h mov byte ptr cs:[0102h], First_bytes_2 ;восстановим третий байт "файла-жертвы"...
; Теперь по адресу 100h первые два байта не jmp 502h, а mov ax,34 (т.е. оригинальный код программы)
; Вспоминаем из прошлых выпусков о том, что в Ассемблере можно менять код программы "на лету"...
; Все это меняется только в памяти, а не на диске!
1234:0709h jmp 0100h ; ...и перейдем по адресу 100h, т.е. передадим управление программе
___________
Сложновато? Сравните два куска кода: незараженной программы и зараженной. Должно быть все понятно...
Сейчас будем практиковаться...
Возьмите, пожалуйста, файл здесь: http://www.Kalashnikoff.ru/Assembler/Programs/Lessons/Virus13.rar
Если у вас нет выхода в Сеть, то напишите мне письмо с просьбой выслать. Я также включу ваш адрес в базу данных. Затем перед выходом очередной рассылки вы получите этот файл по почте.
Первая строка - .286 - указывает Ассемблеру, что будем использовать инструкции (команды, операторы) 286 процессора. Т.е. на 8086 компьютере наш вирус уже работать не будет!
С первого же байта перейдем на метку Init (инициализации нашего вируса).
Сразу же возникает проблема: при поиске файла функцией DOS мы затираем DTA "программы-жертвы".
И тут же возникает вторая проблема, точнее, вопрос: что такое DTA и для чего оно нужно? Полную информацию об этом можно найти в программе helpassm, которую я рекомендую скачать с нашего сайта. В этой рассылке мы рассмотрим только то, что нас интересует (пока!).
Как вы помните, все *.com-программы начинаются с адреса 100h (org 100h). Что же находится в памяти от 0 до 100h? Там расположен PSP (Program Segment Prefix - префикс программного сегмента). По адресу 80h находится по умолчанию DTA (Data Transfer Area - область переноса данных). В DTA записывается информация, когда функция поиска файла (4Eh и 4Fh) находит очередной файл. Все вроде бы и ничего, но проблема в том, что по этому адресу (80h) располагается изначально командная строка. Например:
format.com c:/s/u
По адресу CS:0080h будет находится: L_c:/s/u, где L - длина командной строки, а _ - символ пробела. Для того, чтобы удостовериться, запустите отладчик AFD так:
afd.exe format c:/s/u
Затем посмотрите, что будет находиться по адресу CS:0080h.
К чему все это? Да к тому, что когда мы попробуем искать первый файл, то, найдя его, мы затрем командную строку (L_c:/s/u). Получается, что "программа-жертва", к которой мы "подцепились" не сможет прочитать те параметры, которые ей передал пользователь. В данном случае - это L_/s/u.
Есть два способа обойти это.
1. Сохранить PSP программы перед поиском файла. А затем, как наш вирус отработал, восстановить его.
2. Установить DTA на другую область памяти, а затем восстановить его. Это позволяет сделать функция 1Ah прерывания 21h:
Вход: AH=1AhDS:DX - адрес DTA для установки
Выход: ничего Мы выберем второй путь.
Далее возникает еще одна проблема: мы теряемся в адресах. Т.е. мы занесем наш сассемблированный код в конец программы, при этом смещения все поменяются.
Например:
mov dx,offset String
Ассемблер занесет в DX смещение строки String в памяти. Фактически - после ассемблирования - это будет выглядеть так:
mov dx,125h --- какое именно число - не важно. Главное, что в DX будет находиться адрес (смещение) строки в памяти, отсчитывающееся от 0. Но мы-то запишем код нашего вируса в конец программы, включая все строки и прочие области данных! Получается, что строка в памяти будет находится по одному адресу, а в регистры будет загружаться совсем другой адрес!
Вот пример:
1234:0100h mov dx,400h --- в неассемблированном варианте это выглядит, как mov dx,offset String. Т.е. Ассемблер заменит offset String на адрес (смещение) этой строки в памяти, начиная от нуля.
...
1234:0400h 'Строка' --- а вот и строка, которая расположиться по такому адресу. Она может расположиться и по любому другому (надеюсь, вы понимаете почему?), но суть не в этом.
Теперь, представим, что "файл-жертва" занимает 100h байт. Мы записываем наш код в конец файла. Получается, что строка будет находиться по такому адресу: 1234:0400h + 100h = 1234:0500h! Хорошо бы было, если бы все файлы имели одну длину. Но один файл может быть 100 байт, а другой 23000 байт! В итоге, обращаясь к строке в зараженной программе, мы получаем:
1234:0200h mov dx,400h --- 200h потому, что 100h байт занимает "файл-жертва", а мы в "хвосте" у него...
...
1234:0400h --- все, что угодно, но только не наша строка.
...
1234:0500h 'Строка' --- вот, где она будет!
Можно, конечно, перед заражением получить длину "файла-жертвы" и затем заменить mov dx,400h на mov dx,500h. Но что делать, если таких ссылок много? Представляете, до каких размеров разрастется наш вирус?!
Мы поступим иначе: просто возьмем и перенесем вирус (и только вирус!) с "хвоста" "файла-жертвы" в свободный сегмент со смещения 100h. Вот, что получится:
До перемещения:
1234:0200h mov dx,400h --- мы в хвосте программы
....
1234:0500h 'Строка'
____________
После перемещения:
5678:0100h mov dx,400h --- перебросили себя в сегмент 5678h, по смещению 0100h
....
5678:0400h 'Строка' --- строка стала на свое место (смещение)!!!
____________
Еще вопрос: где гарантия того, что в данном сегменте никого нет, и мы не затрем код какой-нибудь программы?
Я предлагаю временно (т.е. на тот момент, пока работает вирус) переслать наш вирус в адрес 8-ой страницы дисплея. Видеокарта имеет достаточно памяти для размещения восьми страниц. Эти страницы, кроме первой или нулевой, если отсчет вести с нуля), почти никогда не используются программами. Более того известны точные сегменты этих страниц. Вот они:
__________________
0B800 - нулевая
0B900 - первая
0BA00 - вторая
0BB00 - третья
0BC00 - четвертая
0BD00 - пятая
0BE00 - шестая
0BF00 - седьмая
__________________
Давайте посчитаем размер одной страницы. Хватит ли нам места для того, чтобы разместить на ней код вируса? Наш вирус будет занимать не более 300-400 байт.
Возьмем известный вам режим 3: в одной строке 80 символов, строк на экране 25. Один символ занимает два байта (атрибут / смещение). Получаем: 80 x 25 x 2 = 4000 байт. Хватит ли нам этого? Конечно хватит! Даже, если бы не хватало, ты мы могли бы использовать две, три, четыре страницы.
Т.о. пересылаем себя в область седьмой (если считать с нуля) видеостраницы, что мы и делаем сразу же за меткой Init. Код нашего вируса на экране не будет отображаться, т.к. обычно текущей стоит 0-ая страница. Хотя, если хотите, можете проверить это...
Думаю, что вам не составит труда разобраться в новом операторе movs. Принцип его работы полностью соответствует команде stos. Вот его описание:
Название Перевод Применение Процессор movs MOVe String - переместить строку (скопировать) Пересылка (копирование) строки (массива) 8086 При этом 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).
Нам осталось прыгнуть на адрес 0BF00:IP. Как известно, CS:IP всегда показывают текущее операцию (адрес текущей операции). Обратите внимание, как мы прыгаем:
jmp dword ptr cs:[Off_move]
Посмотрите, что содержит переменная Off_move, а также посмотрите в отладчике, что будет происходить с регистрами CS:IP. Все станет на свои места... Подсказка: начиная с метки Lab_jmp мы работаем в области 7-ой видеостраницы...
Затем мы устанавливаем DTA в область 7-ой видеостраницы со смещения 0. Туда будет записываться информация о найденных файлах для заражения.
Теперь можно попробовать найти первый *.com-файл в текущем каталоге. Для этого используется функция 4Eh прерывания 21h:
Вход: AH=4EhCX - атрибуты для поиска файла: у нас - 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=4FhCX - атрибуты для поиска файла: у нас - 0 (обычные, не read-only и hidden!)
DS:DX - маска для поиска (как у функции 4Eh).
Выход: CF = 1 - нет больше файлов, удовлетворяющих условию (маске поиска)CF = 0: DTA заполняется информацией о найденном файле
Все также, как у функции 4Eh.
Хочу заметить, что вирус у нас пока неработоспособный. Т.е. он ничего не заражает вообще! Можете спокойно его ассемблировать и запускать. Только мало что увидите на экране. Лучше это дело смотреть под отладчиком.
Дальше все просто! Я думаю, что описаний в программе достаточно для того, чтобы понять принцип работы программы.
До встречи через неделю!
С уважением,
Автор рассылки: Калашников Олег
E-mail: assembler@beep.ru
URL: http://www.Kalashnikoff.ru
UIN (Тетя Ася): 68951340
[Следующий выпуск] [На главную страницу]
u="u496.71.spylog.com";d=document;nv=navigator;na=nv.appName;p=1; bv=Math.round(parseFloat(nv.appVersion)*100); n=(na.substring(0,2)=="Mi")?0:1;rn=Math.random();z="p="+p+"&rn="+rn;y=""; y+=""; y+=""; y+=""; d.write(y);if(!n) { d.write("