Welcome to the dark corner of BIOS reverse engineering, code injection and various modification techniques only deemed by those immensely curious about BIOS
Sunday, January 29, 2012
x86 Segment Descriptor Cache
Saturday, November 12, 2011
BIOS/UEFI-related Full-scale and Module-level Reverse Engineering with IDA Pro
Over the past several months, I've been intensively researching BIOS-related binaries. The primary tool I used is still IDA Pro. However, I noted that the speed at which my understanding of the binary evolves still nowhere near what it should be. Therefore, I have been evaluating my method for a while and come-up with these steps:
- Make sure you know the context at which the certain part(s) of the BIOS/UEFI binary executes. This way, you can maximize the presence of documentations or specifications related to that particular part of the binary.
- Mark "alleged" data structures (arrays, structures, etc.) with readable names. Do not worry about changing the names later as long as you keep track of where they are located if they are global variables.
- Create IDA Pro structures which would help improve readability of your disassembly. Again, do not worry too much about correctness at this point because you will know it further down the line. The bottom line is reverse code engineering consists of repeated refinement steps which improves the understanding of the code along the way. The point is you needto create clues for further refinement steps.
- Zoom-out function graph (not function call-graph but the single function graph) to get the "big picture" of the function elements especially to recognize loops and branches. This way, it's faster to understand the function. Refine the "alleged" data structure as needed, as you go through the function analysis. Also don't forget to give meaningful name to the function.
- (Optional). If you think writing C/C++ code as representation for the function could help, then do so. In my case, it helps tremendously, especially because th binary I'm working with is compiled with C compiler (evident from the stack and parameter usage).
- Making standardized information in the anterior line of the first function instruction helps tremendously. I think at least these information should be there:
- Function name, preferably along with its starting address. The address is important because name could change as our understanding evolves during the reverse engineering activity. It's particularly important because the documentation generated from the reverse engineering surely refers to several key functions.
- Function description, i.e. what it does in general sense.
- Function parameters (input and output).
- Data structures and global variables modified by the function.
- Kris Kaspersky-style commenting is rather useful for me. He places a lengthy (but enlightening comment) below specific lines. For example:
main proc near ; CODE XREF: start+AF?p push esi push 8 call ??2@YAPAXI@Z ; operator new(unit) ; Using the new operator, we allocate 8 bytes for the instance of ; some object. Generally, it's not very certain at all that memory ; is allocated for an object (there might be something like ; char *x = new char[8]), so let's not, consider this assertion ; as dogma, and accept it as a working hypothesis. ; Further analysis will show how matters actually stand. mov esi, eax add esp, 4I found that this commenting style helps especially when we have just starting with the reverse engineering task. - The use of virtual machine could help because it enables us to debug certain BIOS/UEFI part(s). For example: pci option rom debugging with seabios.
- The remaining thing which I'm still not used to is: How to use the function call graphs effectively?
Thursday, November 3, 2011
BIOS Disassembly Ninjutsu Uncovered 2nd Edition Works/Research Update
It's been "dormant" months on this front for a couple of months. Well, actually I'm working on BIOS and middleware stuff and keeping-up with real life.
Now, into the BIOS Disassembly Uncovered 2nd Edition matters. After working on BIOS related research and stuff these last few months I realized that there are a lot of research and works need to be done before I could continue writing stuff for the book. You may ask why? Well, first and foremost. The first book is an important hallmark in my life. Therefore, I won't just "write another book" for the second edition. I prefer it to be "groundbreaking", rather than just mediocre. A lot of subjects still needs research, particularly in the area of Coreboot, UEFI and cryptographic stuff related to BIOS/UEFI and other firmware in general. I found it rather surprising that after the publication of the first book, there has been quite a "surge" in BIOS-related protection out there (at least judging from patent applications). I know it has been researched prior to the first book. But, perhaps, its publication accelerates some of them.
Ok. So now, I would reiterate that I'm more than merely enthusiastic about the second edition book. But, after reflecting on present condition and the current state of the research I don't want to be rushed and produce a mediocre book. I actually want it to be much better than the first because back then I was newbie. I even barely able to use IDA Pro properly despite being able to write several not so complex IDA Pro plugin.
If you have any inquiries, especially in cryptographic-related BIOS stuff. Let me know. Perhaps, you have a link to sample binary out there I haven't know of?
Thanks..
Monday, October 17, 2011
PCI "Generic" Option ROM Debugging with SeaBIOS, Coreboot and IDA Pro
- Configure and build SeaBIOS.
- Run make menuconfig in SeaBIOS root source directory. If you’re downloading SeaBIOS as Coreboot payload, it’s located at <coreboot_source_path>/payloads/external/SeaBIOS/seabios.
- Enable CONFIG_OPTIONROMS, CONFIG_PMM, CONFIG_COREBOOT_FLASH when you run make menuconfig.
- Configure debug level to 8 (CONFIG_DEBUG_LEVEL)
- Save your changes and quit from the configuration menu (make menuconfig).
- Build SeaBIOS by invoking make.
- Configure and build Coreboot.
- Run make menuconfig in Coreboot root source directory.
- Disable both CONFIG_VGA_ROM_RUN and CONFIG_PCI_ROM_RUN as either of these options will confuse the virtual machine (Qemu) and possibly modify the contents of the PCI option ROM at runtime (debugging). Producing unwanted side effects.
- Configure SeaBIOS binary not as ordinary payload, but as an ELF payload. Configure CONFIG_PAYLOAD_FILE to point to the SeaBIOS ELF file, i.e.
<seabios_source_path>/out/bios.bin.elf . - Save your changes and quit from configuration menu (make menuconfig).
- Build Coreboot by invoking make.
- Insert TEST.ROM as CBFS component to Coreboot ROM file. The following are the steps to insert the PCI option ROM (the steps could be scripted):
- Combine TEST.ROM as CBFS component to Coreboot ROM with this command (invoked from Coreboot source code root directory):
./build/cbfstool build/coreboot.rom add <path_to_TEST_ROM> genroms/test.rom raw - Check whether everything is OK with this command:
./build/cbfstool build/coreboot.rom print
- Combine TEST.ROM as CBFS component to Coreboot ROM with this command (invoked from Coreboot source code root directory):
- Run Qemu utilizing the newly built Coreboot ROM file as its BIOS (configured to stop and wait for the GDB connection).
qemu –m 128 –bios <path_to_coreboot_rom> -hda linux.img –net none –nographic –s –S
The –net none option disables gPXE option ROM from Qemu to load. The gPXE option ROM complicates the analysis a bit. Therefore, it’s better to get rid of it.
NOTE: If Qemu gPXE option ROM is enabled (default), the TEST.ROM option ROM would always be loaded at C980h segment. If Qemu gPXE option ROM is disabled, the TEST.ROM option ROM would always be loaded at C900h segment. - Run IDA Pro and connect via GDB remote debugging.
- Configure IDA Pro debugger to run in x86 16-bit mode.
- Attach to the qemu machine via Debugger|Attach|Remote GDB Debugger menu. Configure the IP address of your virtual or physical target machine there (which runs Qemu) and set the debugger specific option to run 16-bit code.
- When stopped at reset vector (FFFF:FFF0), create your required memory regions (Debugger|Debugger Options…|Set Specific Options|Memory Map)
- Configure breakpoints as needed.
- Run (press F9) and debug.
