Всем доброго дня! Ребят, заинтересовался исследованием BIOS, почитал разную литературу, но так и не смог найти ответ на свой вопрос :(.
Вопрос вот в чем:
Экспериментирую с прошивкой (AMIBIOS 8) для материнской платы MSI G31TM-P35. Поскольку часть прошивки хранится в сжатом виде, то для распаковки использую MMTOOL. Получил 22 модуля. Можно дизассемблировать каждый модуль по отдельности, но тогда не понятно как они друг с другом взаимодействуют. Вот и встал вопрос, как собрать все модули в один файл, чтобы его можно было бы загрузить в Иду и проанализировать? Знаю, что надо создавать новые сегменты и грузить в них код, но возникает новый вопрос: по каким адресам загружать каждый из модулей?
Чувствую, что вопросы не новы, но, к сожалению, поиск решений не увенчался успехом.
Что посоветуете?
обычно когда делают jmp di или jmp si, то где-то рядом есть таблица адресов переходов. IMHO. И, соответственно, в комментах ее повторять не надо.
К примеру:
seg005:16E4 ; --------------------------------------------------------------------------- seg005:16E4 seg005:16E4 loc_F16E4: ; CODE XREF: seg005:02B6j seg005:16E4 invd seg005:16E6 movd mm7, edi seg005:16E9 mov eax, esp seg005:16EC jmp loc_F20A5 seg005:16EF ; ---------------------------------------------------------------------------тут в регистр mm7 записывается значение edi, а используется через 7 jmp:
seg005:17B4 movd edi, mm7 seg005:17B7 jmp di seg005:17B9 ; ---------------------------------------------------------------------------А комментарии такого вида приходится делать, чтоб не потерять значение, так как в моем случае встречается многократное исполнение одного кода, а возврат в разные места:
seg005:1BF7 ; --------------------------------------------------------------------------- seg005:1BF7 ; START OF FUNCTION CHUNK FOR sub_F1C41 seg005:1BF7 seg005:1BF7 loc_F1BF7: ; CODE XREF: seg005:034Aj seg005:1BF7 ; seg005:16F2j ... seg005:1BF7 mov eax, cr0 seg005:1BFA or eax, 60000000h seg005:1C00 mov cr0, eax seg005:1C03 wbinvd seg005:1C05 mov ecx, 2FFh seg005:1C0B rdmsr seg005:1C0D and ax, 0F3FFh seg005:1C10 wrmsr seg005:1C12 wbinvd seg005:1C14 mov eax, cr4 seg005:1C17 and al, 7Fh seg005:1C19 mov cr4, eax seg005:1C1C mov eax, cr3 seg005:1C1F mov cr3, eax seg005:1C22 jmp di ; di, 16F5h seg005:1C22 ; END OF FUNCTION CHUNK FOR sub_F1C41 ; di, 1C48h seg005:1C22 ; seg005:1C24 ; ---------------------------------------------------------------------------все - понял о чем речь. О вызовах с возвратами обратно, когда в функцию передается указатель на блок кода, который нужно выполнить :-)
так Вы неправильно рассматриваете код. Все с seg005:1BF7 до seg005:1C22 выгодно объявить отдельной функцией. И рассматривать картину с бОльшей высоты - на уровне вызовов различных процедур. Ведь тот код, который вызывает seg005:1BF7 и задает содержимое регистра DI!
б) Не открою тайну: ММХ-регистры в примере выше используются в отсутствие стека как временные хранилища
в) Все-равно нужно отслеживать вызовы функции из разных точек. Все-равно это приходится делать комментариями, и это трудоемко и неудобно.
P.S. Лучше выложить бинарный код исследуемого BIOS и дизассемблированный файл IDA. Я понимаю, что не хочется выставлять на показ черновики. Возможно и польза будет мизерная. Но это облегчает понимание и помогает общению.
Если есть желание покопаться в коде, то могу выложить образ и код ИДЫ. Кстати, я там собрал в один файл всё кроме куска с упакованными модулями, так как не знаю по каким адресам их размещать.
Есть два вопроса:
1. какие чаще всего встречаются jmp (di, cx, dx, ax итд)?
Это для понимания того, получится ли некоторую часть дизассемблировать не проходя все ветки...
Примерно так получается:
F0000:41A8 ; --------------------------------------------------------------------------- F0000:41A8 stosb F0000:41A9 inc cx F0000:41AA dec al F0000:41AC xchg al, ah F0000:41AE mov sp, 41B4h F0000:41B1 jmp loc_F3394 F0000:41B4 ; --------------------------------------------------------------------------- F0000:41B4 mov dh, 41h ; 'A' F0000:41B6 jmp loc_F3E82 F0000:41B9 ; ---------------------------------------------------------------------------а вот и loc_F3394
F0000:3394 ; --------------------------------------------------------------------------- F0000:3394 F0000:3394 loc_F3394: ; CODE XREF: F0000:41B1j F0000:3394 ; F0000:41CBj F0000:3394 out 72h, al F0000:3396 jmp short $+2 F0000:3398 xchg al, ah F0000:339A out 73h, al F0000:339C jmp short $+2 F0000:339E xchg al, ah F0000:33A0 retn ; sp, 41B4h F0000:33A0 ; F0000:33A0 ; ---------------------------------------------------------------------------И если не переходить на loc_F3394, а сразу перейти на 41B4h ну и нажать "С" получаем кусок кода.
А смысл в том, что не всегда получается (лично у меня) проследить откуда берется значение, вот пропущу где-нибудь xchg или bswap и потерял значение в DX =)
2. кто-нибудь пробовал дизассемблировать при помощи 16-битного отладчика?
Пробовал прикрутить некоторые, но они пожимали плечами и говорили, - что не могут 16-битный, тока 32.
Вопрос обсуждался 3 года назад
https://rom.by/forum/Dizassemblirovanie_BIOS_1
2. Не совсем понял.
a) Дизассемблирует (т.е. заменяет бинарный код на текст) - дизассемблер.
b) Отладчик - отлаживает в рантайм, т.е. идет контролируемое выполнение кода.
Как часть отладчик может включать в себя дизассемблер для визуализации. Дизассемблер не может включать в себя отладчик.
Вам что надо?
В итоге, дизассемблирование заметно ускорится, когда будет наглядно видно что в регистрах.
ЗЫ
Думаю не всё так гладко, как кажется.
Так как, это начальный этап и требуется не сконфигурированное оборудование (северный мост, южный и т. д.).
Вот, собственно, как-то так.