Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Ассемблер? Это просто! Учимся программировать Выпуск N 013


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

Доброго здоровья, дорогие мои!


Выпуск N 013

Там, дзе вечар на зямлю сыпле зор манiсты,

Я злаyлю, цябе злаyлю, выпуск наравiсты.

Праз палеткi i лясы, праз лугi, паляны,

Ты нясi, яго нясi, Iнэт незацугляны.

Ты нясi, яго нясi, Iнэт незацугляны.


Что у нас сегодня?


Информация для новеньких.

Пожалуйста, возьмите предыдущие выпуски по следующему адресу:

http://www.oleg77.newmail.ru (здесь также можно найти все необходимое программное обеспечение для работы с Ассемблером).

Если у Вас нет доступа в Сеть, то напишите мне письмо с просьбой выслать тот или иной выпуск либо все вместе: assembler@beep.ru?Subject=Issues

Если в поле "Тема" Вы укажите слово Issues, то ВСЕ предыдущие выпуски будут высланы Вам автоматически; это существенно ускорит ответ. Обратите внимание, что у меня изменился электронный адрес, а также адрес сайта, что не было исправлено в предыдущих выпусках!


Ваши письма

Спасибо всем, кто посетил наш сайт и оставил в Гостевой книге информацию! Многие жалуются, что страница стала загружаться дольше. Что ж, я "ужал" все, что можно было.

Ко мне приходит много писем с просьбой подсказать где найти ту или иную информацию. Друзья мои! Ну не знаю я, где можно все найти. Могу подсказать два адреса (один из которых был опубликован в предыдущем выпуске):

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.oleg77.newmail.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=1Ah

DS: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=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.

Хочу заметить, что вирус у нас пока неработоспособный. Т.е. он ничего не заражает вообще! Можете спокойно его ассемблировать и запускать. Только мало что увидите на экране. Лучше это дело смотреть под отладчиком.

Дальше все просто! Я думаю, что описаний в программе достаточно для того, чтобы понять принцип работы программы.

До встречи через неделю!


С уважением,

Автор рассылки: Калашников Олег

E-mail: assembler@beep.ru

URL: http://www.oleg77.newmail.ru

UIN (Тетя Ася): 68951340



http://subscribe.ru/
E-mail: ask@subscribe.ru

В избранное