tags:

views:

2414

answers:

8
+4  Q: 

Write MBR Code

I am an electrical engineer who has recently discovered the need to modify the code in the MBR. Basically I need the ability to execute code on the HDD before, the OS starts up and takes over.

I fully understand that this will need to be written in Assembly and given the 446 bytes or so of code space in the MBR I just expect to call other code outside of the MBR. My question is what's the best way to write into the MBR ? If I want to alter the MBR of lets say disk HDD_1... Is it better to slave HDD_1 into another machine and then write to it, or write to it directly (outside of windows) in the current machine. Basically I figure I'll insert a call and leave the rest of the MBR alone.

Any suggestions would be appreciated

Chris

I am well aware that this is going to be difficult. My QUESTION is what's the best way to put an instruction in the MBR ? It goes without saying Windows doesn't allow direct access to the disk. How would you suggest I write instructions into the MBR ? Is maybe booting a live CD of *nix and writing to the MBR from there ?

+5  A: 

The BIOS boots the computer from the hard drive (or floppy drive) by reading the first sector (512 bytes) of each boot device and checking for a specific set of signature bytes. If those bytes are found, the 512 byte sector is copied to ram (at a specific position) and BIOS jumps to run it.

Other then the signature bytes, 446 bytes in the sector are available for you to use as your boot program, but the boot program must fit entirely in that sector! Since 446 bytes isn't very large, you will have to make BIOS calls to copy other sectors off the hard drive (or floppy drive, or whatever) into ram to run those.

Once you've loaded enough into ram to run your program, jump to it and you're good to go.

That is how an operating system literally "pulls itself up by it's own bootstraps"

See http://en.wikipedia.org/wiki/Master_boot_record

Now, there's no reason you couldn't write the boot code in C or C++ (or most anything else) except that with assembly, you know exactly what code will be generated and it's easy to make BIOS calls.

I would suggest you write a 512 byte disk drive to ram copier that loads your program from the disk into ram, and then jumps to the start address of your program. You can then write your program in any language you want. Keep in mind that when your boot code starts running, those 512 bytes are the only thing you can count on as in the ram. (Well, the BIOS is there you can make BIOS calls. The BIOS will also place some system information at certain places in ram...) If you want to call any functions you've written that are outside that sector, you have to load them into ram yourself.

Also, the easiest way to test your code will probablly be to put it on a floppy disk and boot off that.

To answer your original question, you could keep a backup copy of the old MBR somewhere, and your new MBR could load your function into ram, run it, then load the original MBR and run that, allowing windows to continue booting.

Also, Michael Burr is right, getting what you want done is going to be a nightmare.

In answer to your comment about how to actually write this on the hard drive, there are several "raw write" programs that can copy to a sector on the disk. Also, you could just boot off a linux live cd and use dd to write your data to the sector of your choice on the block device of your choice. -- Simple as pie that part.

James Caccese
+1  A: 

I found a similar question which may help:

http://stackoverflow.com/questions/39503/modifying-the-mbr-of-windows

However, you may want to elaborate on what you plan to do. As I have found out myself bootloader code can be quite tedious to work with. Also, I would certainly test this with a floppy if possible.

As far as actually doing this all from Windows, I am a bit clueless. Just about all of my programming experience to this point has been under a Unix environment.

TURBOxSPOOL
+4  A: 

Basically I figure I'll insert a call and leave the rest of the MBR alone

What will be called by this subroutine call? The only code in memory at that point is whatever is in the MBR or ROM.

Please think carefully about whether you really need this or that's there's not a better alternative before you spend too much time on it. Third-party code written to an MBR (other than the MBR that the OS loader puts in there) is often not well received by users because:

  • antivirus programs often flag it as suspicious code, because it's a technique viruses have used to gain control of machines
  • programs have used the technique of inserting themselves into an MBR and storing additional code and data in 'reserved' sectors of the disc (because there's really not much one can do and store in an MBR). Unfortunately, since there's no good, standard way to actually reserve those sectors, this technique (sometimes used for copy protection) can cause corruption of data structures on the disk (ie., all data on the drive goes bye-bye). Users really hate that. I believe at one point Quicken used a protection scheme that did something like this and faced a pretty big backlash.

So if you do decide to continue on this path, please tread carefully and be prepared for headaches.

Michael Burr
In fact boot sector virus code may be a good starting point. It's fairly harmless anyway since as soon as windows takes over it kills anything running in real mode (Real mode? whatever non-protected below the 640K limit is called) so there is no of infecting the computer.
Scott Herbert
+2  A: 

Why does it go without saying that Windows doesn't allow direct access to the disk? The MSDN page for CreateFile() says this:

Direct access to the disk or to a volume is restricted. For more information, see "Changes to the file system and to the storage stack to restrict direct disk access and direct volume access in Windows Vista and in Windows Server 2008" in the Help and Support Knowledge Base at http://support.microsoft.com/kb/942448.

Windows Server 2003 and Windows XP/2000: Direct access to the disk or to a volume is not restricted in this manner.

KB942448 explains the restrictions, and they seem to allow a process with sufficient privileges to write to the MBR or to a partition boot sector.

bk1e
+1  A: 

You could look into GRUB. I am by no means an expert at MBR code and it's been a long while since I ran a *nix OS, but I remember that the bootloader worked in stages and loaded the stages from the disk before the OS started. You could write your own stage to do the work you need done before the OS loads and then boot the OS. I'm not sure how practical this option is, particularly since the code seems to be in the middle of a rewrite because the "legacy" version was unmaintainable according to the documentation.

Ben Robbins
+2  A: 

There are various ways of writing to the boot sector of a drive, and there is a general reference I used back when I was experimenting with homebrew OS development: http://wiki.osdev.org/

I personally just boot under linux and use dd:

  1. Backup first

    dd if=/dev/sda of=~/windows_bootloader.bin bs=512 count=1

  2. Disassemble the bootloader

    ndisasm -b16 -o7C00h ~/windows_bootloader.bin > ~/windows_bootloader.asm

  3. Make your modifications and reassemble

    nasm ~/windows_bootloader.asm -f bin ~/modified_bootloader.bin

  4. Overwrite the bootloader

    dd if=~/modified_bootloader.bin of=/dev/sda bs=512 count=1

This assumes your that 'sda' is the correct block device. And note that the step 4 doesn't just copy the file to /dev/sda (which it could, but then you might overwrite more than just the first sector if the output binary > 512 Bytes )

Obviously you're not going to want to debug this approach on a live system. It will save you a lot of headaches to use some kind of x86 emulator like bochs, qemu or VMWare Server.

However as Michael Burr has stated, this will probably be a bad idea. Modifying the Windows bootloader, will probably leave you with little or no room for your own code.

Yannick M.
Upvoted for the link to wiki.osdev... Just spent an hour there instead of coding!
Computer Guru
A: 

The editing of the MBR is perfectly possible from within Windows(XP). For this is used the HxD hex editor, you can literily copy-paste a hex file over the MBR, even on your active system drive (use with caution ! :)) http://mh-nexus.de/en/hxd/

As a starting point a would get the MBR of which the source is available, for instance Grub. (So let grub do the botoing to Windows) With this you have a good starting point to do the changes to your MBR. Editing the MBR shouldn't be too hard, as this little piece of software is pretty basic. Some 16bit (DOS) assembler skills are needed though. An other way is to let grub run some extra payload and not changing the MBR at all, but I'm 100% sure if this is possible; please refer to Grub manuals.

A: 

I think your best way is with linux, it has nasm for compiling, dd for cluster copying (which means MBR as well), and even a boot loader menu (lilo for example) if you don't want to mess with your actual partitions.

I had to make my own boot sequence last year. Basically, I had this:

LILO boot menu:
    -> WindowsXP
    -> linux

I wanted to do something seperately on an MBR, without affecting the actual install, so I created a new (small) partition and added that to the LILO list (omitting details here), which gave this:

LILO boot menu:
    -> WindowsXP
    -> linux
    -> TESTMBR

That way, since every partition has its own MBR as well, I could put any whacky code I wanted in there without the risk of locking myself out (which is a little annoying to fix).

To actually change that MBR I did this:

  1. Backup actual MBR, eg dd if=/dev/sda3 of=/home/you/mbr−backup count=1
  2. Edit code in a file: boot.asm
  3. Compile with nasm: nasm boot.asm -o boot.bin -f bin correcting if errors
  4. Copy the freshly created MBR to drive: dd if=boot.bin of=/dev/sda3
  5. Reboot.
  6. Choose TESTMBR in the menu.
  7. See how it goes.

Sure, you can do that directly on the drive's MBR instead of the partition's MBR like I did here, but for my own case it was more practical.

Concerning the actual code-jumping-out-of-MBR, you'll need to use the INT 13,42 interruption, which loads any cluster on a disk. For the purpose of my test I just had to display its contents, but I can take a closer look if you want.

Hope that could help, sorry for the long reply.

SK.