View Full Version : Develop your master boot record and debug it with IDA Pro and the Bochs debugger plug

Hex Blog
September 10th, 2009, 15:19
Writing boot code is useful for many reasons, whether you are:

Developing your own operating system
Developing disk encryption systems
Experimenting and researchingOr even writing a bootkit
While developing the IDA Bochs plugin at Hex-Rays, we had to write a small MBR and we needed a nice and fast way to compile and debug our code.
In the beginning, we were using bochsdbg.exe to debug our code and little by little once we coded the "Bochs Disk Image loader" part we could debug the MBR with IDA and Bochs plugin.
Now you may be wondering: How can I use IDA Bochs plugin to debug my MBR?
For a quick answer, here are the needed steps:

Prepare a Bochs disk image
Prepare a bochsrc file
Insert your MBR into the disk image
Open bochsrc file with IDAStart debugging
In case you did not know, bochsrc files (though they are text files) are handled by the bochsrc.ldw (IDA Loader). The loader parses the bochsrc file looking for the first "ata" keyword then it locates its "path" attribute.
In the following example, bochsrc loader will detect "c.img".

romimage: file=$BXSHARE/BIOS-bochs-latest
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
megs: 16
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="c.img", mode=flat, cylinders=20, heads=16, spt=63
boot: disk

After finding the disk image file, the loader will simply create a new segment at 0x7C00 containing the first sector of that file only and then it selects the Bochs debugger (in Disk Image loader mode). Once the loader is finished you can press F9 and start debugging.
As simple as this sounds, this process is really limited:

What if the MBR loads more code from different sectors? (MBR with 2 or more sectors of code)
What about symbol names?What if we want to customize and control the MBR loading process?
Fortunately, IDA Pro provides a rich API (with the SDK or scripting) that will allow us to tackle all these issues. Preparing a Bochs disk image

If you don't have a Bochs image ready, please use the bximage.exe tool to create a disk image.
http://hexblog.com/ida_pro/pix/mbr_dskimg.jpg Preparing bochsrc file

Edit your bochsrc file and add the ata0 (generated by bximage tool) line to it, and finally run bochsdbg.exe to verify that you can run Bochs properly (outside of IDA).
If you see the Bochs debugger prompt, you can press "c" to continue execution but Bochs will complain because our disk image is not bootable. (As a new disk image, It lacks the 55AA signature at the end of the first sector) Inserting the MBR into the disk image

For your convenience, we included a sample mbr.asm file ready for you to compile.
nasmw -f bin mbr.asm
To insert the mbr into the disk image, we can write a small Python function:

def UpdateImage(imgfile, mbrfile):
Write the MBR code into the disk image

# open image file
f = open(imgfile, "r+b"
if not f:
print "Could not open image file!"
return False
# open MBR file
f2 = open(mbrfile, "rb"
if not f2:
print "Could not open mbr file!"
return False

# read whole MBR file
mbr = f2.read()

# update image file

return True

Loading bochsrc with IDA

As discussed previously, loading the bochsrc file into IDA is not enough (see above) so we need to write another script that acts like a loader:

def MbrLoader():
This small routine loads the MBR into IDA
It acts as a custom file loader (written with a script)
import idaapi;
import idc;


# wait till end of analysis

# adjust segment

# load the rest of the MBR

# Make code
idc.AnalyzeArea(BOOT_START, BOOT_END)

What we did is simply extend the segment from 512 to 1024 (our sample MBR is 1024 bytes long) and load into IDA the rest of the MBR code from the compiled mbr.asm binary. Importing symbols into IDA

When we assemble mbr.asm, a map file will also be generated. We will write a simple parser to extract the addresses and names from the map file and copy them to IDA:

def ParseMap(map_file):
Opens and parses a map file
Returns a list of tuples (addr, addr_name) or an empty list on failure
ret = []
f = open(map_file)
if not f:
return ret
# look for the beginning of symbols
for line in f:
if line.startswith("Real":
return ret
# Prepare RE for the line of the following form:
# 7C1F 7C1F io_error
r = re.compile('\s*(\w+)\s*(\w+)\s*(\w*)')

for line in f:
m = r.match(line.strip())
if not m:
ret.append((int(m.group(2), 16), m.group(3)))
return ret

def ApplySymbols():
This function tries to apply the symbol names in the database
If it succeeds it prints how many symbol names were applied
global MBRNAME
map_file = MBRNAME + ".map"
if not os.path.exists(map_file):
syms = ParseMap(map_file)
if not len(syms):

for sym in syms:
MakeNameEx(sym[0], sym[1], SN_CHECK|SN_NOWARN)

print "Applied %d symbol(s)" % len(syms)

Putting it all together

Now that we addressed all of the issues previously mentioned, let us glue everything with a batch file: [CODE]
rem Assemble the MBR if exist mbr del mbr nasmw -f bin mbr.asm if not exist mbr goto end rem Update the image file python mbr.py update if not errorlevel 0 goto end rem Run IDA to load the file idaw -c -A -OIDAPython:mbr.py bochsrc rem database was not created if not exist bochsrc.idb goto end if exist mbr del mbr if exist mbr.map del mbr.map rem delete old database if exist mbr.idb del mbr.idb rem rename to mbr ren bochsrc.idb mbr.idb rem Start idag (without debugger) rem start idag mbr rem Start IDAG with debugger directly start idag -rbochs mbr echo Ready to debug with IDA Bochs :end
If you noticed, we run IDA twice: the first time we run it and pass our script name to IDAPython; the script will continue the custom loading process and symbol propagation for us.
The second time we run IDA with the "-rbochs" switch telling IDA to open the database and directly run the debugger.
You can still run IDA just once: "start idag -c -A -OIDAPython:mbr.py bochsrc" however you do not call Exit() and you turn off batch mode (with Batch()). http://hexblog.com/ida_pro/pix/mbr_final.jpg
And last but not least, how do you debug your MBR code? Please download the files from here ("http://hexblog.com/ida_pro/files/mbr_bochs.zip"). Comments and suggestions are welcome.