Инфицирование 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] |