Recently, it was necessary to put a new wifi standard ac card in your Lenovo x230 laptop, which has a whitelist for wlan cards. Below I will describe my research on how to turn off whitelist.

First we need to merge our bios dump, this can be done using the
FPT utility
fpt -d bios.rom -BIOS
Next we need the utility
PhoenixTool 2.52 . We launch it, select our bios.rom and wait for it to unpack it, then select Lenovo in the Manufacturer field and click the Advanced button, then tick the “Allow user to modify other modules” and “No SLIC” checkboxes.

')
Click "Done" and "Go" when the window opens

We do not press anything and go to the DUMP folder where our bios is unpacked. Next you need to find the file responsible for whitelist. We are just looking for the text of the error (in UTF-16 encoding), which is displayed on the screen when the module is inserted from a non-whitelist "1802: Unauthorized network card is plugged in"

Find the file 79E0EDD7-9D1D-4F41-AE1A-F896169E5216_2207.ROM is a bios module for the whitelist.
Next we load it into IDA, look at the code and look for our line “1802: Unauthorized network card is plugged in”

This line is addressed in the procedure Sub_A0C. Those. Sub_A0C procedure is supposedly engaged in displaying an error on the screen, we’ll see where it comes from (click on the procedure name and press the X key on the keyboard)

We see that this is a procedure Sub_B20. Go to this procedure and press the spacebar to go to the schematic representation of the code.

We see that the Sub_A0C procedure is called from the code block on the Loc_BDD tag. Then you can follow the conditional transitions to this label, etc. But I decided, in order to better understand the code of this procedure, to go through the code from the beginning of the procedure.
So the first conditional branch checks the edx register for zero
test edx, edx jz Loc_C6E
because Since the edx register is not initialized anywhere in this procedure, it is clear that it must be assigned a value before calling the Sub_B20 procedure. This can be seen in the code.

and

What does the value in the edx register mean I did not understand, so let's go through both branches of the branch.
Let's go for a start on the right eyelid, on Loc_C6E

In eax put the address of the data qword_270, double-click on qword_270 go to view this record, then go to the Hex View-A tab. This is our whitelist, it goes from address 270h to 3FFh. With the format, too, everything is simple, each record is 16 bytes long (4 words over 32bit) corresponds to one device: the first word is a flag that takes the value 0, 1, 5 or 6, the second word is system id, the third is subsystem id, the fourth - another flag that has a value of 0 or 1. I suppose that the first flag determines the type of device: 0 - wifi card, 1 - modem, 5 -?, 6 - end of list.

Let's go back to the code. We compare eax with the six, and the six with us is the end of the whitelist, i.e. if the whitelist turns out to be empty, then go immediately to Loc_BDD, which in our case causes an error. This condition is not interesting to us, since our whitelist is not empty and the condition is not fulfilled. Next, put the address qword_270 in the register rdx, check eax (the first flag of the entry in the whitlist) to zero, if the flag is different from zero, go to the error. This condition also does not interest us. The same condition is the beginning of the whitelist bypass cycle.
Next teams
movzx ecx, word ptr [r8+rdx+6] movzx eax, word ptr [r8+rdx+4] shl ecx, 10h or ecx, eax
We place the system id from the whitelist into the ecx register. The register r8 here acts as an increment in the cycle, initially it is equal to zero.
Next, compare ecx (system id from the whitelist) and the value in memory at the address in the register rdi.
cmp [rdi], ecx
It is easy to guess that at the address in the rdi register we have the identifier of our inserted wifi card, and at the beginning of the procedure we put r8 in the rdi register, i.e. Sub_B20 uses the r8 register as a parameter, where the memory address of the memory card with our card identifier should be located.
If the identifier does not match, then go to Loc_CBA, where we increase the incremental register r8 by 10h (for this, we must have one in the register r13w)
loc_CBA: add r9w, r13w movzx r8d, r9w shl r8, 4
and check to see if we are at the whitlist
mov eax, [r8+rdx] cmp eax, 6 jz loc_BDD
If at the end, we exit the cycle and give an error, if not at the end, then we go to the beginning of the cycle.
It is clear that in order to bypass the WAlist, we need to remove the conditional transition when comparing the system id, i.e. replace
jnz short loc_CBA
with
jmp $+2
.
Further, if the system id matches, there is a similar code for comparing 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
If subsystem id does not match, then loop through the identifiers further. Here we also need to correct the conditional transition to the unconditional
jz short loc_CD5
to
jmp short loc_CD5
.
Further on the code there are no more transitions to the error, but there is an interesting code that checks the second flag in the whitelist record, about which I wrote earlier, it is compared with the register r13d, and if it matches, then some additional piece of code is executed. What makes this code difficult to understand, according to the analysis of the whitelist, you can see that this flag stands only on Intel cards.
So, we figured out the right branch, now let's go through the left branch. There we have the code for working with the whistler starts with the label Loc_C18. Similarly, it is checked whether the whitelist is empty:
loc_C18: mov eax, dword ptr cs:qword_270 xor r9w, r9w cmp eax, 6 jz short loc_BDD
Next, eax (the first flag) and r13d are compared (which parameter lies in r13d, I didn’t figure it out, at the beginning of the procedure, the value is put at [rbx + 1]), then, depending on the fulfillment of this condition, we immediately get to the verification code system id, or perform an interesting comparison
cmp eax, 5 jnz short loc_C54
We check the first flag in the whitelist record for 5, if the condition is met, then skip this whitelist record (i.e. ignore the wifi card) and go further along the verification cycle.
To understand what kind of an interesting flag it is, you need to understand what is passed to the Sub_B20 procedure. If you remember, in the right branch of the code, if this flag was different from zero, then an error about an unsupported card was generated. Those. for the card with flag 5 to load, the following conditions for calling the Sub_B20 procedure must be met: the edx register must be nonzero, and the r13d register must not be five (
cmp eax, r13d
, and in eax we have our flag equal to five). One can only guess that launching a card with such a flag requires some other condition besides finding it in the whitlist. It was quite difficult for me to perform further analysis, therefore, it was not possible to find out what the condition was.
Further along the code, we are similar to the right branch, check in the system id loop
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
Here we also need to replace the conditional transition
jz loc_DF3
with unconditional
jmp loc_DF3
.
Interestingly, there is no subsystem id check in the left branch, i.e. enough system id matches. From the above, we can assume that the right branch is a check of wifi cards, and a left check of modems. And in the register edx when calling a function contains the type of device: 0 - wifi, 1 - modem. But here, too, neponyatka, because 0087: 8086 with flag 5 is wifi + wimax, not a modem, and in edx it can be more than one, because r13d is subtracted from edx, and then compared to the four:
sub edx, r13d jz short loc_B4F cmp edx, 4 jz short loc_B4F
Actually this analysis can be completed. We found the right places for the patch.
We translate the commands into opcodes and make replacements in the hex editor, as a result we get the following patch:
C4E: 0F84->90E9 (jz to jmp) CA3: 16->00 (jnz loc_CBA to jnz $+2) CB8: 74->EB (jnz to jmp)
Save the patched file 79E0EDD7-9D1D-4F41-AE1A-F896169E5216_2207.ROM and click the Ok button in the PhoenixTool window.
PhoenixTool will collect a new bios with the name bios_SLIC.rom.
It remains the case for small, you need to flash a new BIOS. In fresh Lenovo laptops, including my x230, the modified bios cannot be flashed programmatically, so we sew it with a programmer. Unfortunately, I did not do the photo of the firmware process through the programmer. The BIOS is located on the MX25L3206E chip next to the ExpressCard slot. This chip is a regular 25th series SPI EEPROM, a simple programmer for which costs 300r.
That's it, enjoy the work of the new wifi card.
Used materials from the forum bios-mods.com
www.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