Консультация № 109152
13.11.2007, 03:18
0.00 руб.
0 2 2
Здравствуйте, уважаемые эксперты. Не могу разобрать начало инициализации вируса из главы 13 программы Virus13.
1. Непонятен синтаксис строки mov cx,offset Finish-100h, где Finish equ $. Что значит $? В предыдущих программах $ была в конце строки, выводимой на экран, но в Virus13 таких строк нет. Но если всё же $ здесь и означает конец кода нашего вируса, то зачем к $ приписывать -100h. Всё равно ведь программа будет записана до $, а не до 100h. Отладчик же показывает cx 0084, а не 100h. Наверное, 0084h и есть размер нашего вируса.
2. К строке mov si,100h автор даёт комментарий: «DS:SI откуда перемещать будем нашу программу …» А каким образом в DS:SI попала наша программа, она же находится в DS:DX. Получается, что DX = SI. Всегда ли регистры DS:SI показывают содержание любой текущей программы или это касается только этой?
3. При выполнении команды jmp dword ptr cs:[Off_move], где Off_move dw offset Lab_jmp, изменяется регистр CS. Решив сократить код, т.е. написать не две строки как у автора, а одну, я переделал так: jmp dword ptr cs:[offset Lab_jmp], т.е. сразу указал на метку Lab_jmp, а не через переменную Off_move. Однако при выполнении этой команды регистр CS не изменился. Почему? Ведь в авторской строке и в моей фактически указан один и тот же адрес.
Заранее спасибо.


Приложение:
jmp Init ; --- Общие данные---Off_move dw offset Lab_jmp Seg_move dw 0BF00h ………………………………………………………Init: mov es,Seg_move ;ES – сегмент, куда будем ;перемещать код вируса mov di,100h ;DI - смещение mov cx,offset Finish-100h mov si,100h ;DS:SI откуда перемещать будем rep movsb ;перебрасываем нашу программу в ;область 7 видеостраницы jmp dword ptr cs:[Off_move] Lab_jmp:………………………………………………………Finish equ $ ;Метка в конце программы-вируса

Обсуждение

давно
Посетитель
7438
7205
13.11.2007, 10:52
общий
это ответ
Здравствуйте, Masada!
Давай по порядку...
0. Сначала давай разберем, как программа грузится в память.
а) ДОС выделяет (если возможно) всю оставшуюся память и строит в ней MCB,
т.е. оформляет ее как блок памяти
б) адрес сегмента этого блока памяти заносится в DS и ES
в) в начале сегмента длиной 100h строит так называемый блок PSP
г) загружает в память, начиная с DS:100h программу
д) для COM делает jmp PSP:100h (такой команды нет, это для понимания)
е) для EXE делается настройка адресов по таблице из заголовка и переход на адрес опять же из заголовка
1. Теперь о $.
Как правильно заметил, символом ‘$‘ в 9-й функции отмечается конец строки
Этот символ отрабатывается самой функцией во время выполнения программы
Кроме этого знак ‘$‘ используется ассемблером для указания адреса команды, следующей за текущей.
Заметь: во время ассемблирования! В самом коде доллара мы не найдем!
Например: jmp $ фактически ничего не делает (передает управление на следующую команду)
В нашем случае: командой finish equ $ мы запоминаем адрес конца программы как finish ($ стоит в конце программы...)
А mov cx, offset Finish-100h дает нам длину программы (разницу между концом и адресом загрузки!)
2. Командой mov si, 100h мы иницилизируем регистр si началом программы
Программа не попадала в DS:SI - она загружена в DS:100h.
Мы сами настраиваем регистры, как нам надо.
И вообще, откуда взял, что DS:DX - адрес программы? После загрузки программы
все регистры в общем случае неопределены.
3. Команда jmp dword ptr cs:[Off_move] предполагает, что надо сделать длинный переход
по адресу, хранящемуся в длинном слове Off_move.
Что мы и имеем в программе.
Твоя же модификация заставляет интерпретировать как длинный адрес двойное слово по адресу Lab_jmp.
Подумай сам, это одно ли тоже?
Мы же хотим перейти в сегмент 0BF00h, на тоже смещение...
А вообще, молодец, что пытаешься сам разобраться, пусть неправильно, но расуждаешь.
Удачи!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
16.11.2007, 09:53
общий
это ответ
Здравствуйте, Masada!
Ответ на вопрос 1. $ - счетчик текущего адреса, показывает смещение от начала сегмента до самого знака $. Пример:
data segment
metka1=$ ; metka1=0, так как от начала сегмента до $ (metka1) ноль байт
mes1 db ‘abcd’
metka2=$ ; metka2=4, так как от начала сегмента до $ (metka2) четыре байта
mes2 db ‘12345’
metka3=$-mes2 ; metka3=9-4=5, так как от начала сегмента до $ (metka3) девять байт (4 байта это mes2 и 5 байтов это mes3) смещение mes3 в сегменте data составляет 4, поэтому metka3 имеет значение 5 (сам знак $ в сегменте имеет нулевую длину, только не путать с ‘$’ – это 1 байт).
Аналогично $ работает и в сегменте команд (определяет длину программы от начало сегмента команд до знака $).
Строка mov cx,offset Finish-100h, эту строку можно было записать так mov cx, Finish-100h, где Finish equ $.
В этих двух случаях в cx заносится длина кода (в байтах) программы до Finish.

Ответ на вопрос 2. Строка mov si,100h определяет начало программного кода в сегменте CS, но так как вирус пишется в COM исполнении, то все сегменты cs, ds, ss, es имеют один и тот же адрес (директива assume), а то что код начинается с адреса 100h это требование COM – формата.
Адрес DS:DX – нужен для реализации например функции 09h прерывания 21h.
Далее в программе есть строка
mov es, Seg_move ;где Seg_move dw 0bf00h
mov di, 100h
эти строки необходимы для адреса приемника ES:DI
строка
rep movsb
это строковая операция которая копирует бай находящейся по адресу DS:SI (это код программы) в область памяти расположенной по адресу ES:DI, rep число повторений (число раз копирований) определяет регистр cx.

Ответ на вопрос 3. При выполнении команды jmp dword ptr cs:[Off_move], будет сформирован адрес состоящий из двух слов. Первое слово (младшее) будет считано по адресу cs:[Off_move], второе (старшее) слово будет считано по адресу cs:[Seg_move], и будет совершен межсегментный переход.
При выполнение команды jmp dword ptr cs:[offset Lab_jmp] будет сформирован адрес перехода на метку Lab_jmp, так как явно указываем текущей сегмент и адрес метки в этом сегменте. Компоновщик компонуя программу вычислит длину адреса, а она окажется меньше 64K поэтому он заменит код перехода на короткий или внутрисегментный. Поэтому команда jmp dword ptr cs:[offset Lab_jmp] равносильно команде jmp Lab_jmp.

Удачи
Форма ответа