[Из песочницы] Удаление Whitelist в bios ноутбуков на примере Lenovo X230

Недавно понадобилось поставить новую wifi карточку стандарта ac в свой ноутбук Lenovo x230, в котором есть whitelest для wlan карточек. Ниже опишу свои изыскания по отключению whitelist’а.4ca102f8bd78add2695368b2490cef73.jpgДля начала нам надо слить дамп нашего биоса, сделать это можно с помощью утилиты FPTfpt -d bios.rom -BIOSДалее нам понадобится утилита PhoenixTool 2.52. Запускаем её, выбираем наш bios.rom и ждём, пока она его распакует, далее в поле Manufacturer выбираем Lenovo и жмём кнопку Advanced, там ставим галочки «Allow user to modify other modules» и «No SLIC»

c02ba34d446aed5e0367add3043a673f.png

Нажимаем «Done» и «Go», когда откроется окошкоea83090dddbb5691a31fcdee698346ae.pngничего не нажимаем и идём в папку DUMP, куда распакован наш биос. Далее нужно найти файл отвечающий за whitelist. Ищем просто по тексту ошибки (в кодировке UTF-16), которая выводится на экран при вставленном модуле не из вайтлиста »1802: Unauthorized network card is plugged in»

4159741b65a9b308f5af674e9587dc22.png

Находим файл 79E0EDD7–9D1D-4F41-AE1A-F896169E5216_2207.ROM — это модуль биоса для вайтлиста.Далее грузим его в IDA, смотрим код и ищем нашу строку »1802: Unauthorized network card is plugged in»

c2d360752c68ae7a273b63732ef6ef63.png

К этой строке идёт обращение в процедуре Sub_A0C.Т. е. процедура Sub_A0C предположительно занимается выводом ошибки на экран, смотрим откуда она вызывается (кликаем по имени процедуры и нажимем клавишу X на клавиатуре)

c616027f9339cd110af3ea5f4e13c0fd.png

Видим что это процедура Sub_B20. Идём в эту процедуру и нажимаем пробел для перехода к схематичному представления кода.

74d501419169a2601a91055052d79996.png

Видим что процедура Sub_A0C вызывается из блока кода на метке Loc_BDD. Далее можно проследить условные переходы к этой метке и т.д. Но я решил, чтобы лучше понять код работы этой процедуры, пройти код от начала процедуры.Итак, первое условное ветвление проверяет регистр edx на ноль

test edx, edx jz Loc_C6E т.к. регистр edx выше в этой процедуре нигде не инициализируется, то понятно, что ему должно присваиваться значение перед вызовом процедуры Sub_B20. Это можно увидеть в кодеffbfe7cb6fa1ccb052e6bc34b4ed34f4.png и 9d98642dc71b40d9bbee396ec68b659a.pngЧто означает значение в регистре edx я не понял, поэтому пройдёмся по обоим веткам ветвления.Пойдём для начала по правой веке, на Loc_C6Ef9ccf146e4c7155b30c3063d29236716.png

В eax кладётся адрес данных qword_270, двойным щелчком по qword_270 переходим к просмотру этой записи, далее переходим на вкладку Hex View-A. Это и есть наш whitelist, он идёт с адреса 270h до 3FFh. С форматом тоже всё просто, каждая запись длинной в 16 байт (4 слова по 32bit) соответствует одному устройству: первое слово — какой-то флаг, принимающий значение 0, 1, 5 или 6, второе слово — это system id, третье — subsystem id, четвёртое — ещё один флаг, имеющий значение 0 или 1. Предполагаю что первый флаг определяет тип устройства: 0 — wifi карточка, 1 — модем, 5 — ?, 6 — конец списка.

884b83d0298592378655a166ff556907.png

Вернёмся к коду. Сравниваем eax с шестёркой, а шестёрка у нас — это конец вайтлиста, т.е. если вайтлист получается пустой, то идём сразу на Loc_BDD, которая у нас вызывает ошибку. Это условие нам не интересно, т.к. вайтлист у нас не пустой, и условие не выполнится. Далее кладём адрес qword_270 в регистр rdx, проверяем eax (первый флаг записи в вайтлисте) на ноль, если флаг отличный от нуля, переходим к ошибке. Это условие нас тоже не интересует. Это же условие является началом цикла обхода вайтлиста.Дальше командами

movzx ecx, word ptr [r8+rdx+6] movzx eax, word ptr [r8+rdx+4] shl ecx, 10h or ecx, eax Помещаем system id из вайтлиста в регистр ecx. Регистр r8 здесь выступает в роли инкремента в цикле, изначально он равен нулю.Далее сравниваем ecx (system id из вайтлиста) и значение в памяти по адресу в регистре rdi. cmp [rdi], ecx Несложно догадаться, что по адресу в регистре rdi у нас лежит идентификатор нашей вставленной wifi карточки, а в начале процедуры в регистр rdi мы кладём r8, т.е. процедуре Sub_B20 в качестве параметра использется регистр r8, где должен лежать адрес ячейки памяли с идентификатором нашей карточки.Если идентификатор не совпал, то идём на Loc_CBA, там мы увеличиваем инкрементный регистр r8 на 10h (для этого в регистре r13w у нас заранее должна лежать еденица) loc_CBA: add r9w, r13w movzx r8d, r9w shl r8, 4 и проверяем, не в конце ли мы вайтлиста mov eax, [r8+rdx] cmp eax, 6 jz loc_BDD Если в конце, то выходим из цикла и выдаём ошибку, если не в конце, то идём в начало цикла.Понятно, что для обхода вайлиста, нам надо убрать условный переход при сравнении system id, т.е. заменить jnz short loc_CBA на jmp $+2.Далее, если system id совпал, идёт аналогичный код для сравнения subsystem id movzx ecx, word ptr [r8+rdx+0Ah] movzx eax, word ptr [r8+rdx+8] shl ecx, 10h or ecx, eax cmp [rdi+4], ecx jz short loc_CD5 Если subsystem id не совпал, то перебираем по циклу идентификаторы дальше. Тут нам тоже необходимо поправить условные переход на безусловный jz short loc_CD5 на jmp short loc_CD5.Дальше по коду уже нет переходов на ошибку, но есть интересный код, проверяющий второй флаг в записи вайтлиста, про который я писал ранее, он сравнивается с регистром r13d, и если совпадает, то выполняется некий дополнительный кусок кода. Что делает этот код понять трудно, по анализу вайтлиста можно заметить, что этот флаг стоит только у карточек фирмы Intel.Так, с правой веткой разобрались, теперь пройдёмся по левой ветке.Там у нас код работы с вайтлистом начинается с метки Loc_C18. Аналогично проверяется, не пустой ли whitelist:

loc_C18: mov eax, dword ptr cs: qword_270 xor r9w, r9w cmp eax, 6 jz short loc_BDD Далее сравнивается eax (первый флаг) и r13d (что за параметр лежит в r13d я так и не разобрался, в начале процедуры него кладётся значение по адресу [rbx+1]), далее в зависимости от выполнения этого условия, попадаем сразу на код проверки system id, либо выполняем интересное сравнение cmp eax, 5 jnz short loc_C54 Проверяем первый флаг в записи вайтлиста на 5, если условие выполняется, то пропускаем эту запись вайтлиста (т.е. игнорируем wifi карточку) и идём далее по циклу проверки.Чтобы понять что же это за такой интересный флаг, надо понимать, что передаётся в процедуру Sub_B20. Если помните, в правой ветке кода, если этот флаг был отличный от нуля, то выдавалась ошибка о неподдерживаемой карте. Т.е. чтобы карточка с флагом 5 загрузилась, должны выполниться следующие условия вызова процедуры Sub_B20: регистр edx должен быть отличным от нуля, а регистр r13d не должен быть равен пяти (cmp eax, r13d, а в eax у нас лежит наш флаг равный пяти). Можно лишь догадаться, что для запуска карточки с таким флагом, требуется ещё какое-то условие, кроме нахождения её в вайтлисте. Дальше выполнять анализ для меня было довольно сложно, поэтому, что же это за условие, узнать не удалось.Далее по коду, мы аналогично правой ветке, проверяем в цикле system id

loc_C3B: movzx ecx, word ptr [r8+rdx+6] movzx eax, word ptr [r8+rdx+4] shl ecx, 10h or ecx, eax cmp [rdi], ecx jz loc_DF3 Здесь нам надо также заменить условный переход jz loc_DF3 на безусловный jmp loc_DF3.Что интересно, далее в левой ветке нет проверки subsystem id, т.е. достаточно совпадения system id. Из вышеизложенного можно предположить, что правая ветка — проверка wifi карточек, а левая проверка модемов. А в регистре edx при вызове функции содержится тип устройства: 0 — wifi, 1 — модем. Но тут тоже непонятка, т.к. каточка 0087:8086 с флагом 5 — это wifi+wimax, а не модем, да и в edx может быть больше единицы, т.к. из edx вычитается r13d, а потом сравнивается с четвёркой: sub edx, r13d jz short loc_B4F cmp edx, 4 jz short loc_B4F Собственно на этом анализ можно заканчивать. Нужные места для патча мы нашли.Переводим команды в опкоды и делаем замены в hex редакторе, в итоге получаем такой патч: C4E: 0F84→90E9 (jz to jmp) CA3: 16→00 (jnz loc_CBA to jnz $+2) CB8: 74→EB (jnz to jmp) Сохраняем пропатченый файл 79E0EDD7–9D1D-4F41-AE1A-F896169E5216_2207.ROM и нажимеам в окне PhoenixTool кнопку Ok.PhoenixTool соберёт новый биос с именем bios_SLIC.rom.Осталось дело за малым, необходимо прошить новый биос. В свежих ноутбуках Lenovo, включая мой x230, изменённый bios нельзя прошить программно, поэтому шьём его программатором. Фото процесса прошивки через программатор к сожалению не делал. Биос находится в микросхеме MX25L3206E рядом с разъёмом ExpressCard. Эта микросхема представляет из себя обычный SPI EEPROM 25ой серии, простой программатор для которой стоит 300р.

На этом всё, наслаждаемся работой новой wifi карточки.

Использовались материалы с форума bios-mods.comwww.bios-mods.com/forum/Thread-TUTORIAL-Lenovo-X230-Tablet-BIOS-Whitelist-Removal-Hardware-Flashwww.bios-mods.com/forum/Thread-REQUEST-Whitelist-wifi-removal-for-T430-got-hardware-flash-programmer? page=4

© Habrahabr.ru