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