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 ?
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:
Backup first
dd if=/dev/sda of=~/windows_bootloader.bin bs=512 count=1
Disassemble the bootloader
ndisasm -b16 -o7C00h ~/windows_bootloader.bin > ~/windows_bootloader.asm
Make your modifications and reassemble
nasm ~/windows_bootloader.asm -f bin ~/modified_bootloader.bin
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.
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.
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.
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.
I found a similar question which may help:
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.
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:
- Backup actual MBR, eg
dd if=/dev/sda3 of=/home/you/mbr−backup count=1
- Edit code in a file: boot.asm
- Compile with nasm:
nasm boot.asm -o boot.bin -f bin
correcting if errors - Copy the freshly created MBR to drive:
dd if=boot.bin of=/dev/sda3
- Reboot.
- Choose TESTMBR in the menu.
- 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.
If you can make a floppy, cd or memory stick that will boot to a MS command prompt, and have a matching version of MS debug, you can read and write to the MBR as below. A machine running win95 or win98 should be able to create a boot floppy for you. Just copy debug from the windows\command directory to the floppy.
inside debug: use the r command to change register values. set ax to 0201 for read, or 0301 for write. set es:bx to the starting address of the memory (buffer) you wish to use. 0000:7C00 might work, as this is typically the area that your next sector gets read to in the boot process. set cx to 0001 to read / write one sector of 512 bytes. set dx to 0080 for first physical hard drive.
use the "a" command to assemble the one line of code: INT 13h
use the "p" command to proceed. The data will be read or written, based on your choice of AX.
You could read to memory, "n" to name a file, "w" to write the file, and then edit a copy of the mbr in some other program. Once complete, use debug's "n" and "L" to name and load the edited MBR file, and call int 13h using ax= 0301h to write the image to the correct sector.
Are you sure you need to write the MBR? I a disk with partitions, you can also modify the partition's VBR (Volume Boot Record). That may be easier/safer, as you don't need to touch the MBR and your machine will still able to boot to other partitions (and OS), even if you totally destroy your test partition.
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.
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.
Windows has an undocumented utility "debug" which allows to:1) load any sector (including mbr) of hdd to ram. 2)view that code as binary or assemby. 3) Assemble some code in ram.4) write that code to any sector (to mbr also). To start this utilty, type debug at command promt, hit enter. The prompt changes to "-" .then type "help". you get informstion abot how to use it,
来源:https://stackoverflow.com/questions/568359/write-mbr-code