ZF

                Инфицирование Windows-программ
                             от
                    Qark и Quantum [VLAD]

       ( Фрагмент. Вольный перевод - (с) DrMad, 1999 )

    ***>( Прим.  переводчика:  данное описание соответствует  NEформату
исполнимых  файлов,  используемому  в Windows 3.x,  но не PE-формату из
Windows 9x/NT. Тем не менее, NE-программы, инфицированные этим методом,
будут нормально выполняться во всех версиях Windows.) <***

    Этот документ  пытается  объяснить технику инфицирования NewExe для
вирусописателей. Это не предназначено для новичков и вы должны понимать
инфицирование ДОСовских ЕХЕ-программ.

    Инфицирование описано   здесь   в  деталях  и  соответствут  вирусу
WinSurfer,  хотя  существуют  и  другие  методы,  котороые  могут  быть
использованы,  но это не наше дело (в ваших силах придумать свой код!).

    Вам захочется   заиметь  информацию  о  заголовке  NewExe,  которая
содержится в Ralf Brown Interrupt List под Int21h AH=4Bh, копия которой
содержится в конце данной статьи.

    Вот карта того. что мы попытались здесь описать:

       До инфицирования                   После инфицирования

     0h---------------------           0h---------------------
       |                   |             |                   |
       | заголовок DOS EXE |             | заголовок DOS EXE |
       |                   |             |                   |
       ---------------------             ---------------------
       |                   |             |                   |
       |  код DOS          |             |  код DOS          |
       |                   |             |                   |
       |                   |         3F8h---------------------
   400h---------------------             |                   |
       |                   | <- Сместите |Новый EXE-заголовок|
       |Новый EXE-заголовок|    это      |и некоторые таблицы|
       |и некоторые таблицы|    верх     |                   |
       |                   |             | ----------------- |
       | ----------------- |             |   Таблица         |
       |   Таблица         |             |   Сегментов       |
       |   Сегментов       |             |                   |
       |                   |             |                   |
       |                   | Вставьте -> | ----------------- | Вхождение
       | ----------------- |  сюда       | ----------------- | в вирусный
       | Некоторые         |             | Некоторые         | сегмент
       | другие            |             | другие            |
       | таблицы           |             | таблицы           |
       x                   x             x                   x
       x                   x             x                   x
       x                   x             x                   x
 CS:IP ---------------------             ---------------------
       |                   |             |                   |
       |   Код Windows     |             |   Код Windows     |
       |   и другие сег-   |             |   и другие сег-   |
       |   менты           |             |   менты           |
       |                   |             |                   |
 Конец ---------------------       CS:IP ---------------------
                                         | Сегмент ыирусного |
                          Вставьте все   | кода и пр.        |
                            сюда ->      |                   |
                                         --------------------- Вхождения
                                         |                   | вирусных
                                 Конец   --------------------- релокейшенов


 Теория инфицирования:
 ---------------------

    Проверьте, что  данный ЕХЕ-файл предназначен для Windows и
что NE расположен по смещению 1024.
    Уменьшьте NE-указатель по смещению 3Ch на восемь.
    Умешьшьте ДОСовский указатель стека на 8.
    Некоторые NE-смещения,  смещения  которых  больше,  чем  смещения в
таблице сегментов, должны быть увеличены на восемь.
    Увеличьте на 1 счетчик количества сегментов.
    Сохраните CS:IP.
    Укажите при помощи CS:IP на точку входа в новый сегмент.
    Рассчитайте позицию конца таблицы сегментов,  сдвиньте все
данные, включая таблицу сегментов, вверх на 8 байтов.
    Добавьте точку входа в новый сегмент
    Припишите вирус к концу файла
    Запишите таблицу перемещения в конец файла
    ---

    Это было очень общий обзор того, чего хотелось бы сделать.

    Общая идея  всего  этого - перемещение NE-заголовка вперед
для того,  чтобы добавить новую строку к таблице сегментов,  и
изменение CS:IP так, чтобы они указывали на нее.

    Хорошо, теперь рассмотрим все этапы шаг за шагом.

    Проверка на Windows-программу
    -----------------------------

    NewEXE-файл всегда начинается с DOS-заголовка и некоторого
исполнимого в DOS кода. Для Windows-программы:

    Слово по смещению 0 есть 'MZ'.
    Слово по смещению 18h есть 40h или больше.
    Приняв во  внимание  все  эти  условия,  поставим  еще одно:  чтобы
указатель на NE-заголовок был равен 400.  Причина этому - необходимость
пустого пространства для сдвига NE-заголовка вперед на 8.

    Переписывание DOS-заголовка
    ---------------------------

    Перед переписыванием   DOS-заголовка,  уменьшьте  поле  SP
(10h) на 8, поскольку стек указывает на конец секции DOS-кода,
а должен  указывать на начало NE-заголовка.  (Но на самом деле
этого не требуется). Указатель на NE-заголовок по смещению 3Ch
должен быть уменьшен на 8, так как мы собираемся перемещать NE
-заголовок вперед на эту позицию.

    Модифицирование NE-заголовка
    ----------------------------

    С этого момента мы ссылаемся на смещения в NE-заголовке.

    Смещение до таблицы сегментов есть  22h.  Если  некоторые  из  этих
указателей есть 24h,  26h,  28h,  2Ah (т.е. больше [22h]), то увеличьте
этот указатель на 8.  Причиной этому то, что мы все еще вставляем новую
строку  в  таблицу  сегментов,  и  все  лежащие за ней таблицы будут на
восемь байтов дальше от начала заголовка.

    Счетчик сегментов есть слово по  смещению  1Ch.  Увеличьте
его на один,  поскольку мы все еще добавляем новый сегмент,  и
мы должны отметить этот факт в заголовке.

    По смещению  14h  размещается двойное слово - указатель на
точку входа в программу CS:IP,  где CS есть количество строк в
таблице сегментов.  Сохраните  этот  указатель в вашей таблице
размещения (которая будет рассмотрена позже).  Теперь  укажите
CS:IP на мегмент вируса.  Сделайте это записью необходимого IP
в поле по адресу 14h (по смещению точки входа в ваш  сегмент )
и указателя  сегмента в поле по адресу 16h (поскольку вирусный
сегмент - последний в таблице сегментов, и общее их количество
должно соответствовать величине, которую мы инкрементировали).

    Вы можете потом сами проверить, но все, что Вам сейчас надо сделать
- это передвинуть текущий NE-заголовок с таблицей сегментов вперед на 8
байт, но не данные за ним. Вот расчетная формула:

            ((segmentcounter-1)*8)+word ptr [22h]


    Непосредственно за этой позицией тока, куда можно вставить
новую строку-описание сегмента.

 Описание вирусного сегмента
 ---------------------------

    Формат записи о сегменте в NE-программе:

    00h WORD смещение в файле
    02h WORD длина образа файла (0000h=64K)
    04h WORD сегментные атрибуты (см. ниже)
    06h WORD количество байтов под сегмент (0000h=64K)

    Значение в смещениях 2 и 6  в  записи  о  сегменте  как  раз  длина
вируса. По смещению 4 лежит сегментный атрибут, мы используем 180h, это
признак кодового сегмента с релокейшенами (настраиваемыми словами).

    Вычисления значения по смещению 0 более  сложно.  Необходимо  взять
длину  файла  и  сдвинуть вправо на величину выравнивания,  сохраненную
ранее.  Мне было влом сдвигать двойное слово,  поэтому я делал  это  по
частям.

    Длина файла в DX:AX :
       mov     ax,4202h
       xor     cx,cx
       cwd
       int     21h
    Сдвигаем вправо DX:AX на выравнивающее смещение:
       mov     cl,byte ptr alignment_shift
       push    bx
       mov     bx,1
       shl     bx,cl
       mov     cx,bx
       pop     bx
       div     cx
    AX=содержит искомое значение для 0-го смещения

    Запишите эти восемь байтов вслед за сдвинутым заголовком.

    Запись вируса
    -------------

    Переместитесь на конец программы и припишите вирус.

    Запись в таблицу размещения (таблицу релокейшенов)
    --------------------------------------------------

    Вам потребуется точка входа  в  таблицу  размещений,  поскольку  вы
можете вернуть управление оригинальной программе после того,  как вирус
сделал   свое   грязное   дело.   Таблица   размещения    располагается
непосредственно в следующем сегменте.

    Формат таблицы размещений:

    Смещение Размер Описание
    00     WORD     Количество релокейшенов
    00     BYTE     Тип релокейшена
    01     BYTE     Флаги релокейшена
    02     WORD     Смещение в сегменте
    04     WORD     Сегмент описываемого адреса
    06     WORD     Смещение описываемого адреса

    Первое слово  будет равно 1,  потому что у нас только один
релокейшен. Первый  байт  есть  3,  чтобы  сигнализировать   о
32-битном указателе (дальний переход).  Второй байт есть 4 для
сигнализирования об аддитивном релокейшене (без этого работать
не будет).  Слово  по  смещению  2 это смещение двойного слова
после кода команды 'far jmp'. Слово по смещению 4 это CS точки
входа в  оригинальную  программу.  Слово  по смещению 6 это IP
точки входа в оригинальную программу.

    Пример:

                db      0eah    ; Код команды JMP FAR PTR
    ret_ip      dw      0
                dw      0ffffh

    relocation  dw      1       ; Один релокейшен
                db      3       ; Тип - 32-битовый указатель
                db      4       ; Тип - аддитивный релокейшен
                dw      offset ret_ip ; Смещение релокейшена
                                      ; в сегменте
    hostcs      dw      0       ; CS:IP того места, куда
    hostip      dw      0       ; релокейшен указывает

    Замечание: в адресе  релокейшена  данные  (ret_ip)  _обязаны_  быть
FFFF:0000 как сказано ниже, т.к. Windows рассматривает их как связанный
список.  Если вы не поняли,  не волнуйтесь и просто  делайте,  как  вам
сказано.  Просто  по  другому  не  будет работать.  Важно,  чтобы перед
записью  вирусного  тела  в  программу  вы  установили  этот  адрес  на
FFFF:0000, чтобы эта программа установилась корректно.

    Допишите релокейшен к концу файла.

    Windows разрешает  обычные  вызовы  Int 21 (с минимальными
изменениями),  так что все файловые манипуляции о преждему  до
смешного просты.

    ....

    ***> (Прим. переводчика: часть текста пропущена) <***

    Ne-формат (Извлечено из Ralf Browns Interrupt List)
    ---------------------------------------------------

    NE-файлы стартуют со следующим изначениями регистров:

       AX = сегмент среды        (Брехня! AX=0)
       BX = смещение хвоста команды в сегменте среды
       CX = размер автоматического сегмента данных (0000h = 64K)
       ES,BP = 0000h             (Брехня! ES=PSP)
       DS = автоматический сегмент данных
       SS:SP = начальное положение стека

    хвост команды  соответствует PSP:0081h с ДОС-овских EXE-шниках,  за
исключением того, что вместо 0Dh теперь используется NUL (00h); в новом
формате программ нет PSP (Все брехня).

Формат заголовка .EXE-файла:

Смещ.   Размер   Описание

 00h    2 BYTEs  EXE-сигнатура, "MZ" или "ZM" (5A4Dh или 4D5Ah)
 02h    WORD     количество байтов в последнем 512-байтнике
 04h    WORD     количество 512-байтников (включая последний,
                 заполненный частично)
 06h    WORD     количество релокейшенов
 08h    WORD     размер заголовка в 16-байтных параграфах
 0Ah    WORD     минимальное количество параграфов памяти,
                 добавляемое к длине программы
 0Ch    WORD     максимальное -"-
 0h     WORD     начальное значение SS относительно стартового
                 сегмента программы
 10h    WORD     начальное значение SP
 12h    WORD     контрольная сумма
 14h    DWORD    начальное значение CS:IP
 18h    WORD     смещение внутри заголовка таблицы размещения
                 (таблицы релокейшенов)
                 >40h для  новых форматов программ (NE,LE,LX,PE...)
 1Ah    WORD     номер оверлея (обычно 0 для главной программы)

---NE-формат---

 1Ch  4 BYTEs   ???
 20h    WORD    биты поведения
 22h 26 BYTEs   зарезервировано для описания поведения
 3Ch    DWORD   смещение для NE-заголовка в дисковом файле,
                или 00000000h в обычной MZ-программе

Формат NE-заголовка

Смещ. Размер    Описание

 00h  2 BYTEs   сигнатура "NE" (4Eh 45h)
 02h  2 BYTEs   версия линкера (старш. и младш.)
 04h    WORD    смещение от начала заголовка до таблицы вхождений
 06h    WORD    длина таблицы вхождений в байтах
 08h    DWORD   контрольная сумма (Borland TPW ставит 0)
 0Ch    BYTE    флаги программы
 0Dh    BYTE    флаги приложения
 0Eh    WORD    индекс автоматического сегмента данных
 10h    WORD    начальный размер локальной области динамич. памяти
 12h    WORD    начальный размер стека (добавляется к сегменту данных,
                0000h если SS <> DS)
 14h    DWORD   точка входа в программу (CS:IP),
                "CS" - это индекс в таблице сегментов
 18h    DWORD    начальное положение стека (SS:SP),
                "SS" - это индекс сегмента
                 если  SS=автоматический сегмент данных
                 и SP=0000h, то указатель стека ставится на вершину
                 автоматического сегмента данных, прямо перед областью
                 динамической памяти
 1Ch    WORD     счетчик сегментов
 1Eh    WORD     счетчик ссылок на модуль
 20h    WORD     длина в байтах таблицы нерезидентных имен
 22h    WORD     смещение от начала заголовка до таблицы сегментов
 24h    WORD     смещение от начала заголовка до таблицы ресурсов
 26h    WORD     смещение от начала заголовка до таблицы резидентных
                 имен
 28h    WORD     смещение от начала заголовка до таблицы ссылок на
                 модули
 2Ah    WORD     смещение от начала заголовка до таблицы импорта
                 (массив строк, завершающийся строкой 0-й длины )
 2Ch    DWORD    смещение от начала фала до таблицы
                 нерезидентных имен
 30h    WORD     счетчик перемещаемых точек входа в таблице вхождений
 32h    WORD     счетчик сдвига выравнивания размера файла
                 0 аналогичен 9 (по умолчанию 512-байтовые странички)
 34h    WORD     количество вхождений в таблицу ресурсов
 36h    BYTE     операционная система
                 00h неизвестно
                 01h OS/2
                 02h Windows
                 03h Европейский MS-DOS 4.x
                 04h Windows 386
                 05h BOSS (Borland Operating System Services)
 37h    BYTE     прочие EXE-флаги
                 бит 0: поддержка длинных имен файлов
                 бит 1: защищенный режим 2.X
                 бит 2: пропорциональный шрифт 2.X
                 бит 3: gangload area
 38h    WORD     offset to return thunks or start of
                 gangload area
 3Ah    WORD     offset to segment reference thunks or length of
                 gangload area
 3Ch    WORD     минимальный размер свопаемого кода
 3Eh  2 BYTEs    ожиданмая версия Windows (сначала младш.)

Примечание:      Этот заголовок детально описан в Windows 3.1 SDK
                 Programmer's Reference, Vol 4.

Битовые поля для NE-флагов программы:

Бит(ы)  Описание

 0-1    тип DGROUP
         0 = нет
         1 = единый разделяемый
         2 = множественный (неразделяемый)
         3 = (null)
 2      глобальная инициализация
 3      только в защмщенном режиме
 4      команды 8086
 5      команды 80286
 6      команды 80386
 7      команды 80x87

Битовые поля для NE-флагов приложения:

Бит(ы)  Описание

 0-2    тип приложения
        001 полноэкранное (нет в Windows/P.M. API)
        010 совместимое с Windows/P.M. API
        011 использует Windows/P.M. API
 3      Family Application (OS/2)
 5      0=исполнимое, 1=с ошибками
 6      несовместимая программа (допустимый стек не поддерживается)
 7      DLL or драйвер, а не приложение
        (SS:SP неверно,  CS:IP указывает на дальнюю процедуру,
        вызываемую с AX=хэндл модуля, которая возвращает AX=0000h
        при ошибке, AX ненулевое при удачной инициализации)

    Формат записи в таблице сегментов

 00h WORD смещение в файле
          (сдвиньте влево  на выравнивающий сдвиг для получения
           смещения в байтах)
 02h WORD длина файлового образа (0000h = 64K)
 04h WORD атрибуты сегмента
 06h WORD количество байтов под сегмент (0000h = 64K)

    Примечание: у первого в таблице сегмента номер равен 1.

Битовые поля для атрибутов сегмента:

Бит(ы)  Описание
 0      Сегмент данных, а не сегмент кода
 1      Не используется???
 2      реальный режим
 3      итеративный
 4      перемещаемый
 5      разделяемый
 6      предварительно загруженный, а не отдельно подгружаемый
 7      только исполняемый (для кода) или только читаемый
        (для данных)
 8      релокейшены (прямо следуют за кодом сегмента)
 9      присутствует отладочная информация
 10,11  биты 80286 DPL
 12     отменяемый
 13-15  приоритет отмены

    Фомат данных о релокейшене (непосредственно следуют за об-
разом сегмента)

Смещ.   Размер  Описание

 00h    WORD    количество релокейшенов
 02h 8N BYTEs   собственно релокейшены
              Смещ.   Размер  Описание
               00h    BYTE    Тип релокейшена
                              00h LOBYTE
                              02h BASE
                              03h PTR
                              05h OFFS
                              0Bh PTR48
                              0Dh OFFS32
               01h    BYTE    флаги
                               бит 2: добавляемый
               02h    WORD    смещение в сегменте
               04h    WORD    сегмент указуемого сегмента
               06h    WORD    смещение указуемого сегмента

              [end]



(C) NF, 1998-2004