Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #93, СЕНТЯБРЬ 2006 г.

Жесткий кодинг

Крис Касперски

Хакер, номер #093, стр. 093-136-2


В тот момент, когда BIOS получает управление, практически все имеющееся оборудование к работе еще не готово. Нет даже оперативной памяти, поскольку DRAM-контроллер не настроен и не инициализирован. Короче, как дальше жить! Поэтому, первым делом boot-блок проводит первичную инициализацию важнейших узлов, после чего считывает основной код BIOS'а и распаковывает его в оперативную память. На этом работа boot-блока закачивается и всю дальнейшую инициализацию системы выполняет распакованный им код.

Помимо инициализации, BIOS так же управляет оборудованием (например, выключает жесткие диски по прошествии определенного времени, следит за показанием датчиков напряжения и температуры, регулируя частоту процессора и оперативной памяти), а так же предоставляет в распоряжение программиста обширную библиотеку функций, абстрагирующую его от конкретного железа и доступную через вектора прерываний. В частности, за дисковую подсистему отвечает прерывание 13h, но вернемся к нашим баранам, то есть к голому железу.

Обычно, boot-блок располагается в последних 4 Кбайтах файла прошивки, а по смещению 10h от его конца находится точка входа в BIOS, представляющая собой jmp на подлинную точку входа:

0007FFF0: EA5BE000F0 jmp 0F000:0E05B

Остальной код прошивки, как правило, упакован, поэтому непосредственно внедряться можно только в последние 4 Кбайта, т. е. в промежуток между F000:EFFF и F000:FFFF.

Внедряемый код должен быть либо полностью перемещаемым (т. е. сохранять свою работоспособность независимо от базового адреса загрузки), либо в начало ассемблерного листинга необходимо воткнуть директиву "ORG 0XXXXh", где 0XXXXh равно разнице конца boot-блока (лежащего по смещению FFFFh) и размеру внедряемого кода.

Последние два байта boot-блока занимает контрольная сумма, рассчитываемая по следующему алгоритму (сохранившемуся еще со времен первых BIOS'ов): мы просто складываем все байты друг с другом и находим остаток от деления на 100h, что в псевдокоде занимается так: sum = (sum + next_byte) & 0xFF. Контрольная сумма всего boot-блока должна равняться нулю, следовательно, последний байт блока равен: (100h – sum) & 0xFF.

Работа с шиной PCI

Шина PCI является основной шиной, через которую к процессору подключаются все остальные контроллеры и устройства, поэтому, чтобы научиться программировать голое железо, нам прежде всего необходимо разобраться как программировать саму шину PCI. Это легко. Достаточно выучить всего пару регистров: CF8h и CFCh.

Назад на стр. 093-136-1  Содержание  Вперед на стр. 093-136-3