Current location - Quotes Website - Signature design - How to extract code from BIOS firmware
How to extract code from BIOS firmware
2 Reverse System Management Interrupt (SMI) Handle

Some people may think that "hardware analyzer" should be used to participate in our grand plan, but this is actually a misunderstanding. SMI handler is a part of BIOS firmware, which can be disassembled from it like ordinary BIOS code. Pinczakko's two books "Secrets of BIOS Disassembly Endurance" and "Guide to Reverse Engineering of Award BIOS" describe the details of the reverse of Award and AMI BIOS, and interested readers can refer to them here. Here, we have two ways to dump SMI handler from BIOS.

1. Find the vulnerability, enter SMRAM from protected mode, and dump all the contents in SMRAM, especially areas such as TSEG, Gao SMRAM, 0xA0000-0xBFFFF. If the BIOS does not lock the D_LCK bit, it can be dumped by modifying the SMRAMC PCI configuration register introduced by Duflot and BSDaemon. In the case that the BIOS locks SMRAM and the BIOS firmware looks impeccable, the only way is to modify the BIOS so that it will not set the D_LCK bit. Brush the modified program back to the ROM of BIOS, so that SMRAM will not be locked when starting. However, to do this, we must first make sure that BIOS does not need digital signature, and at present, almost no motherboard will use firmware with digital signature other than EFIBIOS.

I think it is necessary to mention the method of setting D_LCK bit in BIOS. Generally, BIOS tends to use 0xCF8/0xCFC ports to set relevant PCI configuration registers through legal I/O access. The BIOS first writes 0x8000009C to the address port of 0xCF8, then writes the value 0x 1A to the data port of 0xcf8, and sets the SMRAMC register to lock the SMRAM.

2. There is another method, which is simpler than the former and does not need to access SMRAM data at runtime.

2. 1 Download the latest from the website of the BIOS developer, or use the Flash programmer to extract the binary code of the firmware from the rom of the BIOS. The ASUS P5Q motherboard we are targeting is to download P5Q- ASUS -Pro- 16 13. ROM file.

2.2 Most BIOS firmware contains the main BIOS module, in which the compressed SMI processing handle is located. Open the main BIOS module using the decompression tool provided by the developer. Because ASUS BIOS is based on AMI BIOS, we use the BIOS module operation utility of AMI BIOS and MMTool.exe to extract the main module from it. Open the downloaded. ROM file is in MMTool, click the "single chain Arch BIOS" extraction module (ID= 1Bh), then check the "uncompressed form" option, and finally save it to get the main BIOS module containing SMI processing handle.

2.3 After extracting the main BIOS module, we can use tools such as HIEW or IDA Pro to start our SMI disassembly journey.

Remove SMI handle.

We noticed that a set of structures were used in ASUS/AMI BIOS to describe the processing function of SMI. Each entry in the array is marked with "$SMIxx", where the "xx" character represents a specific SMI handler. Figure 1 is SMI scheduling table data used by AMIBIOS 8 based on P45 chipset ASUS P5Q SE motherboard.

Decomposition SMI distribution function

There is a special SMI allocation function in BIOS, which we call "dispatch_smi". It will traverse all the entries in the allocation table and call the processing function pointed by handle_smi_ptr. If no handler can respond to the current SMI interrupt signal, it will call the last $DEF routine. The following code is the Handle_SMI BIOS function that we disassembled from ASUS P5Q motherboard.

Hook SMI processing function

Based on the above discussion, there are many ways to hook SMI handlers. You can add a new SMI handler or patch an existing handler and add a new function. There is not much difference between the two methods in essence, so we will make necessary introductions in both cases.

1. Add our own SMI handler to the SMI allocation table.

To add a new function, we must first create a new entry in the allocation table, which we call "$SMIaa", as shown in Figure 3.

This entry contains a pointer to the default SMI handler, which we will modify later. Or we can find a free area in SMRAM, put a section of shellcode, and replace the pointer to the default handle with a pointer to shellcode. Finally, it should be noted that when new processing functions are added to the allocation table, the SMI code count value stored in the SMRAM data section should also be increased by 1 accordingly, so as to keep the consistency of the number of SMI processing functions.

The "debug" handler mentioned above only did one thing, that is, copied the SMI allocation table from 0x0B428:[si] to 0x0000: [Di]. It seems that we can safely hook it up with our own SMI code. Subsequently, we will implement a keylogger and inject it into this processing function. However, before we start a new chapter, it is necessary to review the related technologies that users can use to call recorders when they hit keys.

1. Use I/O APIC to direct the keyboard hardware interrupt (IRQ #0 1) to SMI. Shawn Embleton and Sherri Sparks use an I/O advanced programmable interrupt controller, which directs the IRQ #0 1 interrupt of the keyboard to SMI, and captures keystroke events in the SMI handler.

2. Use the I/O trap mechanism when accessing the data port of the keyboard controller.

I/O trap technology different from the former is adopted in this paper. This technology was originally used by BIOS to simulate PS/2 keyboard, and we will explain its working principle in detail in the next chapter.

3 SMM keyboard recorder

3. 1 hardware I/O trap mechanism

One of the ways to realize the kernel-level keyboard recorder is to hook the debug trap #DB handler in the interrupt descriptor table (IDT), set the debug registers DR0-DR3, and capture the system keystroke events with the data port 0x60. Similarly, we can also use the method of entering SMI through keyboard I/O port 60/64. We refer to the design white paper "USB Support for AMIBIOS 8" of AMI BIOS, which contains such a narrative.

"2.5.4 60/64 port emulation (emulation)

This option can turn the trap function of the 60h/64h port on or off. The 60h/64h port trap allows the BIOS to provide full PS/2-based support for USB keyboards and mice, which is especially useful in Microsoft Windows NT operating systems and keyboards that support multiple languages. This option also provides PS/2 keyboard functions such as keyboard locking, password setting and scan code selection for USB keyboard. "

This mechanism is completed by the hardware system, so it depends on the specific hardware configuration. Fortunately, both Intel and AMD's CPU have mechanisms related to I/O traps. "SMM I/o Trap and I/O Restart" in AMD Athlon 64 and AMD Opteron Processor Developer's Guide in AMD Development Manual BIOS and Kernel, and "I/O Status Realization and I/O Instruction Restart" in Intel ia-32 Architecture Software Developer's Manual.

I/O trap mechanism allows input and output instructions to access any I/O port of the system inside SMI handler after being captured by SMI. The purpose of designing this mechanism is to power on some equipment through I/O port when power is cut off. In addition, I/O traps can also be used to simulate 60h/64h keyboard ports in SMI handles. To some extent, it is similar to the debugging trap mechanism mentioned above. It uses traps to capture the access to I/O ports, but instead of calling the debugging trap handling handle of the operating system kernel, it generates an SMI interrupt to let the CPU enter SMM mode and perform the SMI handling function of I/O traps.

When the processor is trapped in I/O instruction and enters SMM mode, all the information trapped in I/O instruction will be saved in the I/O status field of SMM storage status diagram, which is located in SMBASE+0x8000+0x7FA4. Figure 4 shows the data distribution in this area, which will be used by our recording program later.

-IO_SMI (bit 0) is set, indicating that it is currently an I/O trap SMI.

-I/O length flag (bit [1:3]) indicates that I/O access is one of byte (00 1b), word (0 10b) or doubleword (100b).

-I/O type flag (bits [4:7]) indicates the type of I/O instruction, such as in imm( 100 1b) and DX(000 1b).

-I/O port (bits [16:3 1]), which contains the currently accessed I/O port number.

If the current access to the 0x60 port is through IN DX instruction and byte width, and IO_SMI is set, the SMM keylogger needs to first detect and update the EAX field in the SMM storage state mapping area, and then detect whether the value of the I/O state field at 0x7FA4 is 0x006000 13.

mov esi,SMBASE

mov ecx,dword ptr fs:[esi + 0xFFA4]

cmp ecx,0x006000 13

jnz _not_io_smi

The above is a simplified form of detection. SMM keylogger also needs to detect other signs, such as I/Otype and I/O length in the I/O status field. Because we are recording the purpose of the keyboard, we only care about the I/O trap, not the related settings of I/O restart. I/O restart and I/O trap constitute a complete SMI I/O processing mode. When SMI execution in SMM is completed, I/O restart allows input or output instructions to resume from SMI interrupt and continue execution.

I/O trap mechanism allows us to fall into SMI's processing routine when the software and hardware of any I/O port read and write interactively. Now we only care about the 0x60 data port. The specific steps to realize I/O falling into keyboard keys are as follows:

1. When the keystroke event occurs, the keyboard controller generates a hardware interrupt, and I/O APIC directs the IRQ 1 interrupt signal to the processing handle of SMI.

2. After receiving the keyboard interrupt, APIC calls IDT's keyboard interrupt handler, which is the interrupt vector 0x93 of PS/2 keyboard.

3. The keyboard interrupt handler reads the key scan code from the buffer of the keyboard controller through port 0x60. Usually, the scan code will be cleared and displayed on the screen.

4. At this point, the chipset causes the read trap of port 0x60 and generates a signal to inform the I/O trap SMI.

5. In SMM mode, the SMI handling handle of the keyboard recorder responds to SMI interrupt and handles the I/O trap SMI.

6. When exiting SMM, the SMI processing handle of the keyboard recorder returns the result (current scan code) to the read instruction of the 0x60 port, which is handed over to the interrupt handle of the kernel for further processing.

Under I/O trap and I/O APIC, the operation of step 6 above (returning the scan code to the keyboard interrupt handler of the operating system) is different. If APIC is used to trigger SMI, SMI keyboard recorder must fill the scanning code into the buffer of keyboard controller again, so that the operating system can read the code again for further processing.

Under the I/O trap, another method is adopted. The "IN al, 0x60" INstruction used by the operating system keyboard interrupt handler will cause the I/O of SMM keyboard recorder to fall into a loop, because the in instruction will never be recovered from SMM and continue to be executed. At this point, the SMI handle only needs to save the reading result of the in instruction to the AL/AX/EAX register, as if the in instruction had never been captured.

Under IA32 system, the EAX register is located at the location offset 0x7FD0 in the storage status area of SMRAM, namely SMBASE +0x8000+0x7FD0, and under IA64, it is SMBASE+0x8000+0x7F5C. Therefore, when setting the above IO_SMI, SMM keylogger needs to update the scan code read from 0x60 port to EAX domain. The following is a code snippet to update the EAX domain:

; 1. When reading 0x60 port, verify the setting of IO_SMI bit.

; 2. Update EAX domain of SMM storage status area (SMBASE+0x8000+0x7FD0).

mov esi,SMBASE

mov ecx,dword ptr fs:[esi + 0xFFA4]

cmp ecx,0x006000 13

jnz _not_io_smi

Mov byte pointer fs:[esi+0xFFD0], al

3.5 Keylogger Description under Multiprocessor

Our keylogger has updated the EAX(RAX) register in the SMRAM storage state mapping area of the system. What should I do if I encounter a multiprocessor system? When multiple logical processors enter SMM mode at the same time, they all have their own SMM storage state mapping area in SMRAM, which will be properly solved by assigning different SMRAM base addresses to each processor through BIOS, so this technology is also called "SMBASE redirection".

For example, in a dual-processor system, two logical processors have different SMBASE, SMBASE0 and SMBASE0+0x300; They are; The SMI processing handle of the first processor will be executed from EIP = SMBASE0+0x8000, and the second processor will be executed from EIP = SMBASE0+0x8000+0x300; Similarly, their respective storage state mapping areas are located at (SMBASE0+0x8000+0x7F00) and (SMBASE0+0x8000+0x7F00+0x300) respectively.

Not only 0x300, but also other SMBASE incremental offsets will be set by the BIOS for other processors. Although the incremental offset is variable, its calculation process is not complicated. There is an SMM version ID (version ID) at the offset of 0x7EFC in the SMM storage state mapping area, which is the same value for each processor. For example, the correction ID of SMM may be 0x30 100. Find the correction ID of each processor in SMRAM, calculate the difference between them, and get the relative displacement between SMBASE.

Below we show the EAX update code of SMM keyboard recorder on dual-processor system. It will check whether the I/O status field matches the I/O trap of the processor in turn, and if so, update the EAX value in its SMM storage status mapping area.

; Updating EAX on a Dual Processor System

mov esi,SMBASE

Lea ecx, dword ptr [esi+SMM map IO status information]

cmp ecx,IOSMI_IN_60_BYTE

jne _skip_proc0:

Move byte pointer [ESI+SMM _ map _EAX], al

_skip_proc0:

Lea ecx, dword ptr [esi+SMM map IO status information+0x300]

cmp ecx,IOSMI_IN_60_BYTE

jne _skip_proc 1:

Mov byte pointer [ESI+SMM _ map _EAX+0x300], al

_skip_proc 1:

Four suggested detection methods

4. 1 I/O trap mechanism detection

4.2 Timing detection