Memory allocation in firmware is basically not the same as one we would find on applications running in an OS because it's an "OS-free" environment. Therefore, the the benefits of OS protection for "memory allocation gone wild" is virtually non-existent. This puts codes running as part of the firmware execution at more risk compared to code running inside an OS. I have yet to put more scrutiny on the TianoCore (UEFI) implementation for memory allocation functions. Probably, it's much better than those in legacy BIOS modules or other related firmware predating it.
I have particular notes on routines akin to C language malloc(), free() and circular buffer handling functions. Calls to malloc() function in firmware level code is usually quite safe because several malloc() implementations that I read, implements a sort of rudimentary exception handling which would bail out one module execution if not enough space is found when code in the "requesting" module asks for heap memory. However, there are still lingering possible of error when the module lost a reference to allocated memory due to pointer reassignment. I have yet to see bad behaving code like this. But it seems, the assumption on the malloc() implementation is that these things never happened!
As for circular buffers, this kind of thing is in use mostly to talk to storage devices and other "block" devices which transfers quite large amount of bytes in "block"s. Circular buffer implementations could use contiguous memory space if the code that initialize it found one such an available area. However, it could also be implemented as circular linked-list of fragmented chunks which are not necessarily adjacent in the physical memory. This is where things get interesting. A logic bug in function calling the one of the circular buffer function could result to access in the wrong physical memory address. That could happen if a calling function assumes that the circular buffer is implemented as contiguous physical memory chunks instead of a linked memory chunks (not necessarily contiguous in physical memory addresses). In this case, the developer who code the function calling the circular buffer implementation should be blamed as he/she didn't foresee an impending chaos he/she created. Unfortunately, I have yet to see "exception handling" on firmware-level code dealing with such things.
Welcome to the dark corner of BIOS reverse engineering, code injection and various modification techniques only deemed by those immensely curious about BIOS
Sunday, February 17, 2013
Friday, February 8, 2013
Some BIOS/Firmware-related utilities are running in DOS "extender" mode, i.e. 32-bit Flat Protected mode. Reversing this kind of executable is not quite as straight forward as other DOS programs. Some of them "bind" the DOS "extender" binary with the core application executable into one "integrated" executable. A further optimization that you might find is executable compression before "bind"ing the executable to the DOS "extender". How would you deal with this kind of binary? Well, to be honest. It's not quite easy, but I found these steps help:
- Unbind the DOS "extender" from the "integrated" executable. For this, you can use the SUNSYS Bind Utility which is part of the DOS32A DOS extender. It's freely available at http://dos32a.narechk.net/index_en.html. Using the SUNSYS Bind utility, you can obtain the real executable. Usually in the form of LE executable.
- (This step is optional, depending on the condition of the "unbound" executable). If the LE executable is compressed with UPX, you can use the UPX utility to decompress the executable to obtain the real executable. The UPX utility supports decompressing executables packed with UPX, with the -d command.